diff --git a/rtengine/LUT.h b/rtengine/LUT.h index 76bcf0ccd..6203cfb92 100644 --- a/rtengine/LUT.h +++ b/rtengine/LUT.h @@ -215,7 +215,7 @@ public: * For a LUT(500), it will return 500 * @return number of element in the array */ - int getSize() + unsigned int getSize() const { return size; } @@ -274,6 +274,20 @@ public: return *this; } + // mutliply all elements of LUT with a constant float value + LUT & operator*=(float factor) + { +#ifdef _OPENMP + #pragma omp simd +#endif + + for(unsigned int i = 0; i < this->size; i++) { + data[i] *= factor; + } + + return *this; + } + // use with integer indices T& operator[](int index) const { @@ -526,79 +540,59 @@ public: upperBound = 0; maxs = 0; } -}; - - -// TODO: HOMBRE: HueLUT is actually unused, could we delete this class now that LUT::getVal01 has been created? - - -/** @brief LUT subclass handling hue values specifically. - The array has a fixed size of float values and have to be in the [0.; 1.] range in both axis (no error checking implemented) */ -class HueLUT : public LUTf -{ -public: - HueLUT() : LUTf() {} - explicit HueLUT(bool createArray) : LUTf() + // create an identity LUT (LUT(x) = x) or a scaled identity LUT (LUT(x) = x / divisor) + void makeIdentity(float divisor = 1.f) { - if (createArray) { - this->operator () (501, LUT_CLIP_BELOW | LUT_CLIP_ABOVE); - } - } - - void create() - { - this->operator () (501, LUT_CLIP_BELOW | LUT_CLIP_ABOVE); - } - - // use with integer indices - float& operator[](int index) const - { - return data[ rtengine::LIM(index, 0, upperBound) ]; - } - - // use with float indices in the [0.;1.] range - float operator[](float index) const - { - int idx = int(index * 500.f); // don't use floor! The difference in negative space is no problems here - - if (index < 0.f) { - return data[0]; - } else if (index > 1.f) { - return data[upperBound]; - } - - float balance = index - float(idx / 500.f); - float h1 = data[idx]; - float h2 = data[idx + 1]; - - if (h1 == h2) { - return h1; - } - - if ((h1 > h2) && (h1 - h2 > 0.5f)) { - h1 -= 1.f; - float value = h1 + balance * (h2 - h1); - - if (value < 0.f) { - value += 1.f; + if(divisor == 1.f) { + for(unsigned int i = 0; i < size; i++) { + data[i] = i; } - - return value; - } else if (h2 - h1 > 0.5f) { - h2 -= 1.f; - float value = h1 + balance * (h2 - h1); - - if (value < 0.f) { - value += 1.f; - } - - return value; } else { - return h1 + balance * (h2 - h1); + for(unsigned int i = 0; i < size; i++) { + data[i] = i / divisor; + } } } -}; + // compress a LUT with size y into a LUT with size y (y &dest, unsigned int numVals) const + { + numVals = std::min(numVals, size); + float divisor = numVals - 1; + float mult = (dest.size - 1) / divisor; + + for (unsigned int i = 0; i < numVals; i++) { + int hi = (int)(mult * i); + dest.data[hi] += this->data[i] ; + } + } + + // compress a LUT with size y into a LUT with size y (y &dest, unsigned int numVals, const LUT &passThrough) const + { + if(passThrough) { + numVals = std::min(numVals, size); + numVals = std::min(numVals, passThrough.getSize()); + float mult = dest.size - 1; + + for (int i = 0; i < numVals; i++) { + int hi = (int)(mult * passThrough[i]); + dest[hi] += this->data[i] ; + } + } + } + + void makeConstant(float value, unsigned int numVals = 0) + { + numVals = numVals == 0 ? size : numVals; + numVals = std::min(numVals, size); + for(unsigned int i = 0; i < numVals; i++) { + data[i] = value; + } + } + + +}; #endif /* LUT_H_ */ diff --git a/rtengine/curves.cc b/rtengine/curves.cc index 6792df50d..e8a1bc88e 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -43,7 +43,7 @@ using namespace std; namespace rtengine { -Curve::Curve () : N(0), x(NULL), y(NULL), ypp(NULL), hashSize(1000 /* has to be initialized to the maximum value */ ) {} +Curve::Curve () : N(0), x(nullptr), y(nullptr), ypp(nullptr), hashSize(1000 /* has to be initialized to the maximum value */ ) {} void Curve::AddPolygons () { @@ -155,11 +155,9 @@ void Curve::getControlPoint(int cpNum, double &x, double &y) const const double CurveFactory::sRGBGamma = 2.2; const double CurveFactory::sRGBGammaCurve = 2.4; -SSEFUNCTION void fillCurveArray(DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed) +void fillCurveArray(DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed) { - if (needed) { - LUTf lutCurve (65536); for (int i = 0; i <= 0xffff; i += i < 0xffff - skip ? skip : 1 ) { // change to [0,1] range @@ -167,307 +165,139 @@ SSEFUNCTION void fillCurveArray(DiagonalCurve* diagCurve, LUTf &outCurve, int sk // apply custom/parametric/NURBS curve, if any val = diagCurve->getVal (val); // store result in a temporary array - lutCurve[i] = (val); + outCurve[i] = val; } // if skip>1, let apply linear interpolation in the skipped points of the curve if (skip > 1) { - int prev = 0; + float skipmul = 1.f / (float) skip; - for (int i = 1; i <= 0xffff - skip; i++) { - if (i % skip == 0) { - prev += skip; - continue; + 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; } - - lutCurve[i] = ( lutCurve[prev] * (skip - i % skip) + lutCurve[prev + skip] * (i % skip) ) / skip; } } - for (int i = 0; i <= 0xffff; i++) { - outCurve[i] = (65535.f * lutCurve[i]); - } + outCurve *= 65535.f; } else { -#ifdef __SSE2__ - __m128 fourv = _mm_set1_ps(4.f); - __m128 iv = _mm_set_ps(3.f, 2.f, 1.f, 0.f); - - for (int i = 0; i <= 0xfffc; i += 4) { - _mm_storeu_ps(&outCurve[i], iv); - iv += fourv; - } - -#else - - for (int i = 0; i <= 0xffff; i++) { - outCurve[i] = (float)i; - } - -#endif - } - -} - -void CurveFactory::updatechroma ( - const std::vector& cccurvePoints, - LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma - int skip) -{ - LUTf dCcurve(65536, 0); - float val; - - for (int i = 0; i < 48000; i++) { //32768*1.414 + ... - val = (double)i / 47999.0; - dCcurve[i] = CLIPD(val); - } - - outBeforeCCurveHistogramC.clear(); - bool histNeededC = false; - - - if (!cccurvePoints.empty() && cccurvePoints[0] != 0) { - if (outBeforeCCurveHistogramC /*&& histogramCropped*/) { - histNeededC = true; - } - } - - for (int i = 0; i < 48000; i++) { //32768*1.414 + ... - float val; - - if (histNeededC) { - float hval = dCcurve[i]; - int hi = (int)(255.0 * CLIPD(hval)); // - outBeforeCCurveHistogramC[hi] += histogramC[i] ; - } + outCurve.makeIdentity(); } } - -void CurveFactory::curveLightBrightColor ( - procparams::ColorAppearanceParams::eTCModeId curveMode1, const std::vector& curvePoints1, - procparams::ColorAppearanceParams::eTCModeId curveMode2, const std::vector& curvePoints2, - procparams::ColorAppearanceParams::eCTCModeId curveMode3, const std::vector& curvePoints3, - LUTu & histogram, LUTu & histogramCropped, LUTu & outBeforeCCurveHistogram,//for Luminance - LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma - ColorAppearance & customColCurve1, - ColorAppearance & customColCurve2, - ColorAppearance & customColCurve3, - int skip) +void CurveFactory::curveLightBrightColor (const std::vector& curvePoints1, const std::vector& curvePoints2, const std::vector& curvePoints3, + const LUTu & histogram, LUTu & outBeforeCCurveHistogram,//for Luminance + const LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma + ColorAppearance & customColCurve1, ColorAppearance & customColCurve2, ColorAppearance & customColCurve3, int skip) { outBeforeCCurveHistogram.clear(); outBeforeCCurveHistogramC.clear(); - bool histNeededC = false; - bool histNeeded = false; - DiagonalCurve* tcurve = NULL; customColCurve3.Reset(); if (!curvePoints3.empty() && curvePoints3[0] > DCT_Linear && curvePoints3[0] < DCT_Unchanged) { - tcurve = new DiagonalCurve (curvePoints3, CURVES_MIN_POLY_POINTS / skip); + DiagonalCurve tcurve(curvePoints3, CURVES_MIN_POLY_POINTS / skip); if (outBeforeCCurveHistogramC /*&& histogramCropped*/) { - histNeededC = true; + histogramC.compressTo(outBeforeCCurveHistogramC, 48000); } - } - - if (tcurve) { - if (tcurve->isIdentity()) { - delete tcurve; - tcurve = NULL; - } else { + if (!tcurve.isIdentity()) { customColCurve3.Set(tcurve); } - - delete tcurve; - tcurve = NULL; } + customColCurve2.Reset(); if (!curvePoints2.empty() && curvePoints2[0] > DCT_Linear && curvePoints2[0] < DCT_Unchanged) { - tcurve = new DiagonalCurve (curvePoints2, CURVES_MIN_POLY_POINTS / skip); + DiagonalCurve tcurve(curvePoints2, CURVES_MIN_POLY_POINTS / skip); if (outBeforeCCurveHistogram /*&& histogramCropped*/) { histNeeded = true; } - } - - if (tcurve) { - if (tcurve->isIdentity()) { - delete tcurve; - tcurve = NULL; - } else { + if (!tcurve.isIdentity()) { customColCurve2.Set(tcurve); } - - delete tcurve; - tcurve = NULL; } + // create first curve if needed customColCurve1.Reset(); if (!curvePoints1.empty() && curvePoints1[0] > DCT_Linear && curvePoints1[0] < DCT_Unchanged) { - tcurve = new DiagonalCurve (curvePoints1, CURVES_MIN_POLY_POINTS / skip); + DiagonalCurve tcurve(curvePoints1, CURVES_MIN_POLY_POINTS / skip); if (outBeforeCCurveHistogram /*&& histogramCropped*/) { histNeeded = true; } - } - - if (tcurve) { - if (tcurve->isIdentity()) { - delete tcurve; - tcurve = NULL; - } else { + if (!tcurve.isIdentity()) { customColCurve1.Set(tcurve); - delete tcurve; - tcurve = NULL; } } if (histNeeded) { - for (int i = 0; i < 32768; i++) { - double hval = CLIPD((double)i / 32767.0); - int hi = (int)(255.0 * hval); - outBeforeCCurveHistogram[hi] += histogram[i] ; - } - } - - if (histNeededC) { - for (int i = 0; i < 48000; i++) { //32768*1.414 + ... - double hval = CLIPD((double)i / 47999.0); - int hi = (int)(255.0 * hval); // - outBeforeCCurveHistogramC[hi] += histogramC[i] ; - } - } - - if (tcurve) { - delete tcurve; - } - -} -// add curve Denoise : C=f(C) -void CurveFactory::denoiseCC ( bool & ccdenoiseutili, const std::vector& cccurvePoints, LUTf & NoiseCCcurve, int skip) -{ - bool needed; - DiagonalCurve* dCurve = NULL; - LUTf dCcurve(65536, 0); - - float val; - - for (int i = 0; i < 48000; i++) { - dCcurve[i] = (float)i / 47999.0; - } - - needed = false; - - if (!cccurvePoints.empty() && cccurvePoints[0] != 0) { - dCurve = new DiagonalCurve (cccurvePoints, CURVES_MIN_POLY_POINTS / skip); - - if (dCurve && !dCurve->isIdentity()) { - needed = true; - ccdenoiseutili = true; - } - } - - fillCurveArray(dCurve, NoiseCCcurve, skip, needed); - //NoiseCCcurve.dump("Noise"); - - if (dCurve) { - delete dCurve; - dCurve = NULL; + histogram.compressTo(outBeforeCCurveHistogram, 32768); } } - -void CurveFactory::curveBW ( - const std::vector& curvePointsbw, const std::vector& curvePointsbw2, - LUTu & histogrambw, LUTu & outBeforeCCurveHistogrambw,//for Luminance - ToneCurve & customToneCurvebw1, ToneCurve & customToneCurvebw2, int skip) +void CurveFactory::curveBW ( const std::vector& curvePointsbw, const std::vector& curvePointsbw2, + const LUTu & histogrambw, LUTu & outBeforeCCurveHistogrambw,//for Luminance + ToneCurve & customToneCurvebw1, ToneCurve & customToneCurvebw2, int skip) { const float gamma_ = Color::sRGBGammaCurve; - const float start = expf(gamma_ * logf( -0.055 / ((1.0 / gamma_ - 1.0) * 1.055 ))); - const float slope = 1.055 * powf (start, 1.0 / gamma_ - 1) - 0.055 / start; - const float mul = 1.055; - const float add = 0.055; + constexpr float mul = 1.055; + constexpr float add = 0.055; + const float start = expf(gamma_ * logf( -add / ((1.0 / gamma_ - 1.0) * mul ))); + const float slope = mul * powf (start, 1.0 / gamma_ - 1) - add / start; outBeforeCCurveHistogrambw.clear(); bool histNeeded = false; - DiagonalCurve* tcurve = NULL; customToneCurvebw2.Reset(); if (!curvePointsbw2.empty() && curvePointsbw2[0] > DCT_Linear && curvePointsbw2[0] < DCT_Unchanged) { - tcurve = new DiagonalCurve (curvePointsbw2, CURVES_MIN_POLY_POINTS / skip); + DiagonalCurve tcurve(curvePointsbw2, CURVES_MIN_POLY_POINTS / skip); if (outBeforeCCurveHistogrambw /*&& histogramCropped*/) { histNeeded = true; } - } - - if (tcurve) { - if (!tcurve->isIdentity()) { + if (!tcurve.isIdentity()) { customToneCurvebw2.Set(tcurve, gamma_, start, slope, mul, add); } - - delete tcurve; - tcurve = NULL; } + customToneCurvebw1.Reset(); if (!curvePointsbw.empty() && curvePointsbw[0] > DCT_Linear && curvePointsbw[0] < DCT_Unchanged) { - tcurve = new DiagonalCurve (curvePointsbw, CURVES_MIN_POLY_POINTS / skip); + DiagonalCurve tcurve(curvePointsbw, CURVES_MIN_POLY_POINTS / skip); if (outBeforeCCurveHistogrambw /*&& histogramCropped*/) { histNeeded = true; } - } - - if (tcurve) { - if (!tcurve->isIdentity()) { + if (!tcurve.isIdentity()) { customToneCurvebw1.Set(tcurve, gamma_, start, slope, mul, add); } - - delete tcurve; - tcurve = NULL; } + // create first curve if needed if (histNeeded) { - LUTf dcurve(65536, 0); - - float val; - - for (int i = 0; i < 32768; i++) { - val = (float)i / 32767.f; - dcurve[i] = CLIPD(val); - } - - for (int i = 0; i < 32768; i++) { - float hval = dcurve[i]; - int hi = (int)(255.0 * CLIPD(hval)); - outBeforeCCurveHistogrambw[hi] += histogrambw[i] ; - } + histogrambw.compressTo(outBeforeCCurveHistogrambw, 32768); } - - if (tcurve) { - delete tcurve; - } - } + // add curve Lab : C=f(L) -void CurveFactory::curveCL ( bool & clcutili, const std::vector& clcurvePoints, LUTf & clCurve, LUTu & histogramcl, LUTu & outBeforeCLurveHistogram, int skip) +void CurveFactory::curveCL ( bool & clcutili, const std::vector& clcurvePoints, LUTf & clCurve, const LUTu & histogramcl, LUTu & outBeforeCLurveHistogram, int skip) { - bool needed; - DiagonalCurve* dCurve = NULL; + bool needed = false; + DiagonalCurve* dCurve = nullptr; if (outBeforeCLurveHistogram) { outBeforeCLurveHistogram.clear(); @@ -475,8 +305,6 @@ void CurveFactory::curveCL ( bool & clcutili, const std::vector& clcurve bool histNeededCL = false; - needed = false; - if (!clcurvePoints.empty() && clcurvePoints[0] != 0) { dCurve = new DiagonalCurve (clcurvePoints, CURVES_MIN_POLY_POINTS / skip); @@ -490,25 +318,21 @@ void CurveFactory::curveCL ( bool & clcutili, const std::vector& clcurve } } - if(histNeededCL) - for (int i = 0; i < 50000; i++) { //32768*1.414 + ... - int hi = (int)(255.0 * CLIPD((float)i / 49999.0)); // - outBeforeCLurveHistogram[hi] += histogramcl[i] ; - } - + if(histNeededCL) { + histogramcl.compressTo(outBeforeCLurveHistogram, 50000); + } fillCurveArray(dCurve, clCurve, skip, needed); if (dCurve) { delete dCurve; - dCurve = NULL; } } -void CurveFactory::mapcurve ( bool & mapcontlutili, const std::vector& mapcurvePoints, LUTf & mapcurve, int skip, LUTu & histogram, LUTu & outBeforeCurveHistogram) +void CurveFactory::mapcurve ( bool & mapcontlutili, const std::vector& mapcurvePoints, LUTf & mapcurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram) { bool needed = false; - DiagonalCurve* dCurve = NULL; + DiagonalCurve* dCurve = nullptr; outBeforeCurveHistogram.clear(); bool histNeeded = false; @@ -526,28 +350,20 @@ void CurveFactory::mapcurve ( bool & mapcontlutili, const std::vector& m } if (histNeeded) { - for (int i = 0; i < 32768; i++) { - double hval = CLIPD((double)i / 32767.0); - int hi = (int)(255.0 * hval); - outBeforeCurveHistogram[hi] += histogram[i] ; - } + histogram.compressTo(outBeforeCurveHistogram, 32768); } fillCurveArray(dCurve, mapcurve, skip, needed); if (dCurve) { delete dCurve; - dCurve = NULL; } } - - - -void CurveFactory::curveDehaContL ( bool & dehacontlutili, const std::vector& dehaclcurvePoints, LUTf & dehaclCurve, int skip, LUTu & histogram, LUTu & outBeforeCurveHistogram) +void CurveFactory::curveDehaContL ( bool & dehacontlutili, const std::vector& dehaclcurvePoints, LUTf & dehaclCurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram) { bool needed = false; - DiagonalCurve* dCurve = NULL; + DiagonalCurve* dCurve = nullptr; outBeforeCurveHistogram.clear(); bool histNeeded = false; @@ -565,37 +381,24 @@ void CurveFactory::curveDehaContL ( bool & dehacontlutili, const std::vector& wavclcurvePoints, LUTf & wavclCurve, /*LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,*/int skip) { - bool needed; - DiagonalCurve* dCurve = NULL; - - // if (outBeforeWavCLurveHistogram) - // outBeforeWavCLurveHistogram.clear(); - bool histNeededCL = false; - - needed = false; + bool needed = false; + DiagonalCurve* dCurve = nullptr; if (!wavclcurvePoints.empty() && wavclcurvePoints[0] != 0) { dCurve = new DiagonalCurve (wavclcurvePoints, CURVES_MIN_POLY_POINTS / skip); - // if (outBeforeWavCLurveHistogram) - // histNeededCL = true; if (dCurve && !dCurve->isIdentity()) { needed = true; @@ -603,112 +406,47 @@ void CurveFactory::curveWavContL ( bool & wavcontlutili, const std::vector& clcurvePoints, LUTf & clToningCurve, int skip) +// add curve Colortoning : C=f(L) and CLf(L) +void CurveFactory::curveToning ( const std::vector& curvePoints, LUTf & ToningCurve, int skip) { - bool needed; - DiagonalCurve* dCurve = NULL; + bool needed = false; + DiagonalCurve* dCurve = nullptr; - needed = false; - - if (!clcurvePoints.empty() && clcurvePoints[0] != 0) { - dCurve = new DiagonalCurve (clcurvePoints, CURVES_MIN_POLY_POINTS / skip); + if (!curvePoints.empty() && curvePoints[0] != 0) { + dCurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip); if (dCurve && !dCurve->isIdentity()) { needed = true; - clctoningutili = true; } } - fillCurveArray(dCurve, clToningCurve, skip, needed); - - // clToningCurve.dump("CLToning"); - if (dCurve) { - delete dCurve; - dCurve = NULL; - } -} - -// add curve Colortoning : CLf(L) -void CurveFactory::curveToningLL ( bool & llctoningutili, const std::vector& llcurvePoints, LUTf & llToningCurve, int skip) -{ - bool needed; - DiagonalCurve* dCurve = NULL; - - needed = false; - - if (!llcurvePoints.empty() && llcurvePoints[0] != 0) { - dCurve = new DiagonalCurve (llcurvePoints, CURVES_MIN_POLY_POINTS / skip); - - if (dCurve && !dCurve->isIdentity()) { - needed = true; - llctoningutili = true; - } - } - - fillCurveArray(dCurve, llToningCurve, skip, needed); -// llToningCurve.dump("LLToning"); + fillCurveArray(dCurve, ToningCurve, skip, needed); if (dCurve) { delete dCurve; - dCurve = NULL; } } + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void CurveFactory::complexsgnCurve (float adjustr, bool & autili, bool & butili, bool & ccutili, bool & cclutili, double saturation, double rstprotection, const std::vector& acurvePoints, const std::vector& bcurvePoints, const std::vector& cccurvePoints, const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve, - LUTu & histogramC, LUTu & histogramLC, LUTu & outBeforeCCurveHistogram, LUTu & outBeforeLCurveHistogram, //for chroma + const LUTu & histogramC, const LUTu & histogramLC, LUTu & outBeforeCCurveHistogram, LUTu & outBeforeLCurveHistogram, //for chroma int skip) { - - //----------------------------------------------------- - - bool needed; - DiagonalCurve* dCurve = NULL; - LUTf dCcurve(65536, 0); + bool needed = false; + DiagonalCurve* dCurve = nullptr; int k = 48000; //32768*1.41 - if(outBeforeCCurveHistogram || outBeforeLCurveHistogram) { - for (int i = 0; i < k * adjustr; i++) { //# 32768*1.414 approximation maxi for chroma - dCcurve[i] = (float)i / (k * adjustr - 1); - } - } - - if (outBeforeCCurveHistogram) { - outBeforeCCurveHistogram.clear(); - } - - bool histNeededC = false; - - if (outBeforeLCurveHistogram) { - outBeforeLCurveHistogram.clear(); - } - - bool histNeededLC = false; - - //----------------------------------------------------- - - needed = false; - // create a curve if needed if (!acurvePoints.empty() && acurvePoints[0] != 0) { dCurve = new DiagonalCurve (acurvePoints, CURVES_MIN_POLY_POINTS / skip); @@ -720,11 +458,10 @@ void CurveFactory::complexsgnCurve (float adjustr, bool & autili, bool & butili } fillCurveArray(dCurve, aoutCurve, skip, needed); - //if(autili) aoutCurve.dump("acurve"); if (dCurve) { delete dCurve; - dCurve = NULL; + dCurve = nullptr; } //----------------------------------------------------- @@ -744,17 +481,21 @@ void CurveFactory::complexsgnCurve (float adjustr, bool & autili, bool & butili if (dCurve) { delete dCurve; - dCurve = NULL; + dCurve = nullptr; } //----------------------------------------------- needed = false; + if (outBeforeCCurveHistogram) { + outBeforeCCurveHistogram.clear(); + } + if (!cccurvePoints.empty() && cccurvePoints[0] != 0) { dCurve = new DiagonalCurve (cccurvePoints, CURVES_MIN_POLY_POINTS / skip); - if (outBeforeCCurveHistogram /*&& histogramCropped*/) { - histNeededC = true; + if (outBeforeCCurveHistogram) { + histogramC.compressTo(outBeforeCCurveHistogram, k * adjustr); } if (dCurve && !dCurve->isIdentity()) { @@ -763,29 +504,25 @@ void CurveFactory::complexsgnCurve (float adjustr, bool & autili, bool & butili } } - if (histNeededC) { - for (int i = 0; i < k * adjustr; i++) { //32768*1.414 + ... - float hval = dCcurve[i]; - int hi = (int)(255.0 * CLIPD(hval)); // - outBeforeCCurveHistogram[hi] += histogramC[i] ; - } - } - fillCurveArray(dCurve, satCurve, skip, needed); if (dCurve) { delete dCurve; - dCurve = NULL; + dCurve = nullptr; } //---------------------------- needed = false; + if (outBeforeLCurveHistogram) { + outBeforeLCurveHistogram.clear(); + } + if (!lccurvePoints.empty() && lccurvePoints[0] != 0) { dCurve = new DiagonalCurve (lccurvePoints, CURVES_MIN_POLY_POINTS / skip); - if (outBeforeLCurveHistogram /*&& histogramCropped*/) { - histNeededLC = true; + if (outBeforeLCurveHistogram) { + histogramLC.compressTo(outBeforeLCurveHistogram, k * adjustr); } if (dCurve && !dCurve->isIdentity()) { @@ -794,22 +531,11 @@ void CurveFactory::complexsgnCurve (float adjustr, bool & autili, bool & butili } } - if (histNeededLC) { - for (int i = 0; i < k * adjustr; i++) { //32768*1.414 + ... - float hval = dCcurve[i]; - int hi = (int)(255.0 * CLIPD(hval)); // - outBeforeLCurveHistogram[hi] += histogramLC[i] ; - } - } - - fillCurveArray(dCurve, lhskCurve, skip, needed); if (dCurve) { delete dCurve; - dCurve = NULL; } - } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -817,15 +543,15 @@ void CurveFactory::complexsgnCurve (float adjustr, bool & autili, bool & butili //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, double hlcomprthresh, - double shcompr, double br, double contr, - procparams::ToneCurveParams::eTCModeId curveMode, const std::vector& curvePoints, - procparams::ToneCurveParams::eTCModeId curveMode2, const std::vector& curvePoints2, - LUTu & histogram, LUTu & histogramCropped, - LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, - LUTu & outBeforeCCurveHistogram, - ToneCurve & customToneCurve1, - ToneCurve & customToneCurve2, - int skip) + double shcompr, double br, double contr, + procparams::ToneCurveParams::eTCModeId curveMode, const std::vector& curvePoints, + procparams::ToneCurveParams::eTCModeId curveMode2, const std::vector& curvePoints2, + LUTu & histogram, LUTu & histogramCropped, + LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, + LUTu & outBeforeCCurveHistogram, + ToneCurve & customToneCurve1, + ToneCurve & customToneCurve2, + int skip) { // the curve shapes are defined in sRGB gamma, but the output curves will operate on linear floating point data, @@ -846,7 +572,7 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double // tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - DiagonalCurve* brightcurve = NULL; + DiagonalCurve* brightcurve = nullptr; // check if brightness curve is needed if (br > 0.00001 || br < -0.00001) { @@ -885,28 +611,47 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double float scale = 65536.0; float comp = (max(0.0, ecomp) + 1.0) * hlcompr / 100.0; float shoulder = ((scale / max(1.0f, exp_scale)) * (hlcomprthresh / 200.0)) + 0.1; - //printf("shoulder = %e\n",shoulder); - //printf ("exp_scale= %f comp= %f def_mul=%f a= %f \n",exp_scale,comp,def_mul,a); - if (comp <= 0.0f) - for (int i = 0; i < 0x10000; i++) { - hlCurve[i] = exp_scale; - } - else { - for (int i = 0; i <= shoulder; i++) { - hlCurve[i] = exp_scale; - } + if (comp <= 0.0f) { + hlCurve.makeConstant(exp_scale); + } else { + hlCurve.makeConstant(exp_scale, shoulder + 1); float scalemshoulder = scale - shoulder; - for (int i = shoulder + 1; i < 0x10000; i++) { +#ifdef __SSE2__ + int i = shoulder + 1; + if(i&1) { // original formula, slower than optimized formulas below but only used once or none, so I let it as is for reference // change to [0,1] range float val = (float)i - shoulder; float R = val * comp / (scalemshoulder); hlCurve[i] = xlog(1.0 + R * exp_scale) / R; // don't use xlogf or 1.f here. Leads to errors caused by too low precision + i++; } - } + vdouble onev = _mm_set1_pd(1.0); + vdouble Rv = _mm_set_pd((i+1-shoulder) * (double)comp/ scalemshoulder,(i-shoulder) * (double)comp/ scalemshoulder); + vdouble incrementv = _mm_set1_pd(2.0 * comp / scalemshoulder); + vdouble exp_scalev = _mm_set1_pd(exp_scale); + for (; i < 0x10000; i+=2) { + // change to [0,1] range + vdouble resultv = xlog(onev + Rv * exp_scalev) / Rv; + vfloat resultfv = _mm_cvtpd_ps(resultv); + _mm_store_ss(&hlCurve[i], resultfv); + resultfv = PERMUTEPS(resultfv, _MM_SHUFFLE(1,1,1,1)); + _mm_store_ss(&hlCurve[i+1], resultfv); + Rv += incrementv; + } +#else + float R = comp / scalemshoulder; + float increment = R; + for (int i = shoulder + 1; i < 0x10000; i++) { + // change to [0,1] range + hlCurve[i] = xlog(1.0 + R * exp_scale) / R; // don't use xlogf or 1.f here. Leads to errors caused by too low precision + R += increment; + } +#endif + } // curve without contrast LUTf dcurve(0x10000); @@ -915,7 +660,7 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double // 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. float val = 1.f / 65535.f; - float val2 = simplebasecurve (val, black, 0.015 * shcompr); + float val2 = simplebasecurve (val, black, 0.015 * shcompr); shCurve[0] = CLIPD(val2) / val; val = 0.0; // gamma correction @@ -929,11 +674,11 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double // store result in a temporary array dcurve[0] = CLIPD(val); - #pragma omp parallel for + + #pragma omp parallel for //schedule(dynamic,2048) for (int i = 1; i < 0x10000; i++) { - float val; - val = (float)i / 65535.0f; + float val = i / 65535.f; float val2 = simplebasecurve (val, black, 0.015 * shcompr); shCurve[i] = CLIPD(val2) / val; @@ -965,18 +710,13 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double unsigned int sum = 0; float avg = 0; - //double sqavg = 0; for (int i = 0; i <= 0xffff; i++) { - float fi = i; - fi *= hlCurve[i]; + float fi = i * hlCurve[i]; avg += dcurve[(int)(shCurve[fi] * fi)] * histogram[i]; - //sqavg += dcurve[i]*dcurve[i] * histogram[i]; sum += histogram[i]; } avg /= sum; - //sqavg /= sum; - //double stddev = sqrt(sqavg-avg*avg); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% std::vector contrastcurvePoints; @@ -995,41 +735,35 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double contrastcurvePoints.at(7) = 1.; // white point contrastcurvePoints.at(8) = 1.; // value at white point - DiagonalCurve* contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip); + DiagonalCurve contrastcurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // apply contrast enhancement for (int i = 0; i <= 0xffff; i++) { - dcurve[i] = contrastcurve->getVal (dcurve[i]); + dcurve[i] = contrastcurve.getVal (dcurve[i]); } - delete contrastcurve; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // create second curve if needed bool histNeeded = false; - DiagonalCurve* tcurve = NULL; + DiagonalCurve* tcurve = nullptr; customToneCurve2.Reset(); if (!curvePoints2.empty() && curvePoints2[0] > DCT_Linear && curvePoints2[0] < DCT_Unchanged) { - tcurve = new DiagonalCurve (curvePoints2, CURVES_MIN_POLY_POINTS / skip); + DiagonalCurve tcurve(curvePoints2, CURVES_MIN_POLY_POINTS / skip); + + if (!tcurve.isIdentity()) { + customToneCurve2.Set(tcurve, gamma_, start, slope, mul, add); + } if (outBeforeCCurveHistogram /*&& histogramCropped*/) { histNeeded = true; } } - if (tcurve) { - if (!tcurve->isIdentity()) { - customToneCurve2.Set(tcurve, gamma_, start, slope, mul, add); - } - - delete tcurve; - tcurve = NULL; - } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1038,90 +772,53 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double customToneCurve1.Reset(); if (!curvePoints.empty() && curvePoints[0] > DCT_Linear && curvePoints[0] < DCT_Unchanged) { - tcurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip); + DiagonalCurve tcurve(curvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (!tcurve.isIdentity()) { + customToneCurve1.Set(tcurve, gamma_, start, slope, mul, add); + } if (outBeforeCCurveHistogram /*&& histogramCropped*/) { histNeeded = true; } } - if (tcurve) { - if (!tcurve->isIdentity()) { - customToneCurve1.Set(tcurve, gamma_, start, slope, mul, add); - } + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - delete tcurve; - tcurve = NULL; +#ifdef __SSE2__ + vfloat gamma_v = F2V(gamma_); + vfloat startv = F2V(start); + vfloat slopev = F2V(slope); + vfloat mulv = F2V(mul); + vfloat addv = F2V(add); + vfloat c65535v = F2V(65535.f); + for (int i = 0; i <= 0xffff; i+=4) { + vfloat valv = LVFU(dcurve[i]); + valv = igamma (valv, gamma_v, startv, slopev, mulv, addv); + STVFU(outCurve[i],c65535v * valv); } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // create curve bw - // curve 2 - /* DiagonalCurve* tbwcurve = NULL; - customToneCurvebw2.Reset(); - - if (!curvePointsbw2.empty() && curvePointsbw2[0]>DCT_Linear && curvePointsbw2[0]isIdentity()) { - delete tbwcurve; - tbwcurve = NULL; - } - else - customToneCurvebw2.Set(tbwcurve); - delete tbwcurve; - tbwcurve = NULL; - } - - customToneCurvebw1.Reset(); - - if (!curvePointsbw.empty() && curvePointsbw[0]>DCT_Linear && curvePointsbw[0]isIdentity()) { - delete tbwcurve; - tbwcurve = NULL; - } - else if (curveModeb != procparams::BlackWhiteParams::TC_MODE_STD_BW) { - customToneCurvebw1.Set(tbwcurve); - delete tbwcurve; - tbwcurve = NULL; - } - } - */ - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - +#else for (int i = 0; i <= 0xffff; i++) { float val = dcurve[i]; - - if (histNeeded) { - float fi = i; - float hval = hlCurve[i] * fi; - hval = dcurve[shCurve[hval] * hval]; - //if (needigamma) - // hval = igamma2 (hval); - int hi = (int)(255.0 * (hval)); - outBeforeCCurveHistogram[hi] += histogram/*Cropped*/[i] ; - } - val = igamma (val, gamma_, start, slope, mul, add); outCurve[i] = (65535.f * val); } +#endif + + if (histNeeded) { + for (int i = 0; i <= 0xffff; i++) { + float fi = i; + float hval = hlCurve[i] * fi; + hval = dcurve[shCurve[hval] * hval]; + int hi = (int)(255.f * (hval)); + outBeforeCCurveHistogram[hi] += histogram[i] ; + } + } if (tcurve) { delete tcurve; } - /*if (outBeforeCCurveHistogram) { - for (int i=0; i<256; i++) printf("i= %d bchist= %d \n",i,outBeforeCCurveHistogram[i]); - }*/ } @@ -1130,12 +827,11 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void CurveFactory::complexLCurve (double br, double contr, const std::vector& curvePoints, - LUTu & histogram, LUTu & histogramCropped, LUTf & outCurve, + const LUTu & histogram, LUTu & histogramCropped, LUTf & outCurve, LUTu & outBeforeCCurveHistogram, int skip, bool & utili) { - // curve without contrast - LUTf dcurve(65536, 0); + LUTf dcurve(32768, 0); // clear array that stores histogram valid before applying the custom curve if (outBeforeCCurveHistogram) { @@ -1174,7 +870,7 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vectorgetVal (val); + val = brightcurve.getVal (val); // store result in a temporary array dcurve[i] = CLIPD(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; - } + dcurve.makeIdentity(32767.f); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1206,27 +898,21 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vector 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]; } + std::vector contrastcurvePoints; + if(sum) { avg /= sum; - //sqavg /= sum; - //float stddev = sqrt(sqavg-avg*avg); - // printf("avg=%f\n",avg); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - std::vector contrastcurvePoints; contrastcurvePoints.resize(9); contrastcurvePoints.at(0) = double(DCT_NURBS); @@ -1242,12 +928,10 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vector contrastcurvePoints; contrastcurvePoints.resize(5); contrastcurvePoints.at(0) = double(DCT_NURBS); @@ -1257,22 +941,22 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vectorgetVal (dcurve[i]); + dcurve[i] = contrastcurve.getVal (dcurve[i]); } - delete contrastcurve; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // create a curve if needed - DiagonalCurve* tcurve = NULL; + DiagonalCurve* tcurve = nullptr; bool histNeeded = false; if (!curvePoints.empty() && curvePoints[0] != 0) { @@ -1285,7 +969,7 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vectorisIdentity()) { delete tcurve; - tcurve = NULL; + tcurve = nullptr; } if (tcurve) { @@ -1297,14 +981,14 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vectorgetVal (dcurve[i]); - outCurve[i] = (32767.0 * val); + outCurve[i] = (32767.f * val); } } else { // Skip the slow getval method if no curve is used (or an identity curve) @@ -1312,25 +996,21 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vector& curvePoints, LUTf & outCurve, int skip) { - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // create a curve if needed - DiagonalCurve* tcurve = NULL; + DiagonalCurve* tcurve = nullptr; if (!curvePoints.empty() && curvePoints[0] != 0) { tcurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip); @@ -1352,7 +1029,7 @@ void CurveFactory::RGBCurve (const std::vector& curvePoints, LUTf & outC if (tcurve && tcurve->isIdentity()) { delete tcurve; - tcurve = NULL; + tcurve = nullptr; } if (tcurve) { @@ -1362,23 +1039,16 @@ void CurveFactory::RGBCurve (const std::vector& curvePoints, LUTf & outC for (int i = 0; i < 65536; i++) { // apply custom/parametric/NURBS curve, if any - // RGB curves are defined with sRGB gamma, but operate on linear data - float val = float(i) / 65535.f; - val = CurveFactory::gamma2 (val); + float val = Color::gamma2curve[i] / 65535.f; val = tcurve->getVal(val); - val = CurveFactory::igamma2 (val); - //float val = tcurve->getVal ((float)i/65536.0f); - outCurve[i] = (65536.0f * val); + outCurve[i] = Color::igammatab_srgb[val * 65535.f]; } delete tcurve; - } - // let the LUTf empty for identity curves - else { + } else { // let the LUTf empty for identity curves outCurve.reset(); } - } @@ -1388,12 +1058,12 @@ void ColorAppearance::Reset() } // Fill a LUT with X/Y, ranged 0xffff -void ColorAppearance::Set(Curve *pCurve) +void ColorAppearance::Set(const Curve &pCurve) { lutColCurve(65536); for (int i = 0; i < 65536; i++) { - lutColCurve[i] = pCurve->getVal(double(i) / 65535.) * 65535.; + lutColCurve[i] = pCurve.getVal(double(i) / 65535.) * 65535.; } } @@ -1436,20 +1106,20 @@ void ToneCurve::Reset() } // Fill a LUT with X/Y, ranged 0xffff -void ToneCurve::Set(Curve *pCurve, float gamma, float start, float slope, float mul, float add) +void ToneCurve::Set(const Curve &pCurve, float gamma, float start, float slope, float mul, float add) { lutToneCurve(65536); if (gamma <= 0.0 || gamma == 1.) { for (int i = 0; i < 65536; i++) { - lutToneCurve[i] = (float)pCurve->getVal(float(i) / 65535.f) * 65535.f; + lutToneCurve[i] = (float)pCurve.getVal(float(i) / 65535.f) * 65535.f; } } else { // apply gamma, that is 'pCurve' is defined with the given gamma and here we convert it to a curve in linear space for (int i = 0; i < 65536; i++) { float val = float(i) / 65535.f; val = CurveFactory::gamma (val, gamma, start, slope, mul, add); - val = pCurve->getVal(val); + val = pCurve.getVal(val); val = CurveFactory::igamma (val, gamma, start, slope, mul, add); lutToneCurve[i] = val * 65535.f; } @@ -1479,7 +1149,7 @@ void OpacityCurve::Set(const Curve *pCurve) void OpacityCurve::Set(const std::vector &curvePoints, bool &opautili) { - FlatCurve* tcurve = NULL; + FlatCurve* tcurve = nullptr; if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { tcurve = new FlatCurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2); @@ -1490,7 +1160,7 @@ void OpacityCurve::Set(const std::vector &curvePoints, bool &opautili) Set(tcurve); opautili = true; delete tcurve; - tcurve = NULL; + tcurve = nullptr; } } @@ -1863,7 +1533,7 @@ void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3], void ColorGradientCurve::SetXYZ(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin) { - FlatCurve* tcurve = NULL; + FlatCurve* tcurve = nullptr; if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { tcurve = new FlatCurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2); @@ -1872,7 +1542,7 @@ void ColorGradientCurve::SetXYZ(const std::vector &curvePoints, const do if (tcurve) { SetXYZ(tcurve, xyz_rgb, rgb_xyz, satur, lumin); delete tcurve; - tcurve = NULL; + tcurve = nullptr; } } @@ -1964,7 +1634,7 @@ void ColorGradientCurve::SetRGB(const Curve *pCurve, const double xyz_rgb[3][3], void ColorGradientCurve::SetRGB(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3]) { - FlatCurve* tcurve = NULL; + FlatCurve* tcurve = nullptr; if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { tcurve = new FlatCurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2); @@ -1973,7 +1643,7 @@ void ColorGradientCurve::SetRGB(const std::vector &curvePoints, const do if (tcurve) { SetRGB(tcurve, xyz_rgb, rgb_xyz); delete tcurve; - tcurve = NULL; + tcurve = nullptr; } } diff --git a/rtengine/curves.h b/rtengine/curves.h index b0e9d691f..cac839827 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -159,7 +159,9 @@ protected: static inline double simplebasecurve (double x, double b, double sr) { // a = 1, D = 1, hr = 0 (unused for a = D = 1) - if (b < 0) { + if (b == 0.0) { + return x; + } else if (b < 0) { double m = 0.5;//midpoint double slope = 1.0 + b; //slope of straight line between (0,-b) and (1,1) double y = -b + m * slope; //value at midpoint @@ -175,7 +177,7 @@ protected: double y = (m - b) * slope; if (x <= m) { - return b == 0 ? x * slope : clower (x / m, slope * m / y, sr) * y; + return clower (x / m, slope * m / y, sr) * y; } else { return y + (x - m) * slope; } @@ -238,13 +240,18 @@ public: } static inline float gamma (float x, float gamma, float start, float slope, float mul, float add) { - return (x <= start ? x*slope : expf(logf(x) / gamma) * mul - add); + return (x <= start ? x*slope : xexpf(xlogf(x) / gamma) * mul - add); } static inline float igamma (float x, float gamma, float start, float slope, float mul, float add) { - return (x <= start * slope ? x / slope : expf(logf((x + add) / mul) * gamma) ); + return (x <= start * slope ? x / slope : xexpf(xlogf((x + add) / mul) * gamma) ); } - +#ifdef __SSE2__ + static inline vfloat igamma (vfloat x, vfloat gamma, vfloat start, vfloat slope, vfloat mul, vfloat add) + { + return (x <= start * slope ? x / slope : xexpf(xlogf((x + add) / mul) * gamma) ); + } +#endif static inline float hlcurve (const float exp_scale, const float comp, const float hlrange, float level) { if (comp > 0.0) { @@ -276,37 +283,30 @@ public: LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, LUTu & outBeforeCCurveHistogram, ToneCurve & outToneCurve, ToneCurve & outToneCurve2, int skip = 1); - static void curveBW (const std::vector& curvePointsbw, const std::vector& curvePointsbw2, LUTu & histogrambw, LUTu & outBeforeCCurveHistogrambw, + static void curveBW (const std::vector& curvePointsbw, const std::vector& curvePointsbw2, const LUTu & histogrambw, LUTu & outBeforeCCurveHistogrambw, ToneCurve & customToneCurvebw1, ToneCurve & customToneCurvebw2, int skip); - static void curveCL ( bool & clcutili, const std::vector& clcurvePoints, LUTf & clCurve, LUTu & histogramcl, LUTu & outBeforeCLurveHistogram, int skip); + static void curveCL ( bool & clcutili, const std::vector& clcurvePoints, LUTf & clCurve, const LUTu & histogramcl, LUTu & outBeforeCLurveHistogram, int skip); static void curveWavContL ( bool & wavcontlutili, const std::vector& wavclcurvePoints, LUTf & wavclCurve,/* LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,*/int skip); - static void curveDehaContL ( bool & dehacontlutili, const std::vector& dehaclcurvePoints, LUTf & dehaclCurve, int skip, LUTu & histogram, LUTu & outBeforeCurveHistogram); - static void mapcurve ( bool & mapcontlutili, const std::vector& mapcurvePoints, LUTf & mapcurve, int skip, LUTu & histogram, LUTu & outBeforeCurveHistogram); + static void curveDehaContL ( bool & dehacontlutili, const std::vector& dehaclcurvePoints, LUTf & dehaclCurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram); + static void mapcurve ( bool & mapcontlutili, const std::vector& mapcurvePoints, LUTf & mapcurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram); - static void curveToningCL ( bool & clctoningutili, const std::vector& clcurvePoints, LUTf & clToningCurve, int skip); - static void curveToningLL ( bool & llctoningutili, const std::vector& llcurvePoints, LUTf & llToningCurve, int skip); - static void denoiseCC ( bool & ccdenoiseutili, const std::vector& cccurvePoints, LUTf & NoiseCCcurve, int skip); + static void curveToning ( const std::vector& curvePoints, LUTf & ToningCurve, int skip); static void complexsgnCurve ( float adjustr, bool & autili, bool & butili, bool & ccutili, bool & clcutili, double saturation, double rstprotection, const std::vector& acurvePoints, const std::vector& bcurvePoints, const std::vector& cccurvePoints, const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve, - LUTu & histogramC, LUTu & histogramLC, LUTu & outBeforeCCurveHistogram, LUTu & outBeforeLCurveHistogram, ///for chroma + const LUTu & histogramC, const LUTu & histogramLC, LUTu & outBeforeCCurveHistogram, LUTu & outBeforeLCurveHistogram, ///for chroma int skip = 1); - static void complexLCurve (double br, double contr, const std::vector& curvePoints, LUTu & histogram, LUTu & histogramCropped, + static void complexLCurve (double br, double contr, const std::vector& curvePoints, const LUTu & histogram, LUTu & histogramCropped, LUTf & outCurve, LUTu & outBeforeCCurveHistogram, int skip, bool & utili); - static void updatechroma ( - const std::vector& cccurvePoints, - LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma - int skip = 1); - static void curveLightBrightColor ( - procparams::ColorAppearanceParams::eTCModeId curveMode, const std::vector& curvePoints, - procparams::ColorAppearanceParams::eTCModeId curveMode2, const std::vector& curvePoints2, - procparams::ColorAppearanceParams::eCTCModeId curveMode3, const std::vector& curvePoints3, - LUTu & histogram, LUTu & histogramCropped, LUTu & outBeforeCCurveHistogram, - LUTu & histogramC, LUTu & outBeforeCCurveHistogramC, + const std::vector& curvePoints, + const std::vector& curvePoints2, + const std::vector& curvePoints3, + const LUTu & histogram, LUTu & outBeforeCCurveHistogram, + const LUTu & histogramC, LUTu & outBeforeCCurveHistogramC, ColorAppearance & outColCurve1, ColorAppearance & outColCurve2, ColorAppearance & outColCurve3, @@ -358,11 +358,11 @@ protected: } static inline double p01 (double x, double prot) { - return x <= 0.5 ? CurveFactory::clower (x * 2, 2.0, prot) / 2.0 : 0.5 + CurveFactory::cupper ((x - 0.5) * 2, 2.0, prot) / 2.0; + return x <= 0.5 ? CurveFactory::clower (x * 2, 2.0, prot) * 0.5 : 0.5 + CurveFactory::cupper ((x - 0.5) * 2, 2.0, prot) * 0.5; } static inline double p10 (double x, double prot) { - return x <= 0.5 ? CurveFactory::cupper (x * 2, 2.0, prot) / 2.0 : 0.5 + CurveFactory::clower ((x - 0.5) * 2, 2.0, prot) / 2.0; + return x <= 0.5 ? CurveFactory::cupper (x * 2, 2.0, prot) * 0.5 : 0.5 + CurveFactory::clower ((x - 0.5) * 2, 2.0, prot) * 0.5; } static inline double pfull (double x, double prot, double sh, double hl) { @@ -464,7 +464,7 @@ public: virtual ~ToneCurve() {}; void Reset(); - void Set(Curve *pCurve, float gamma = 0, float start = 0, float slope = 0, float mul = 0, float add = 0); + void Set(const Curve &pCurve, float gamma = 0, float start = 0, float slope = 0, float mul = 0, float add = 0); operator bool (void) const { return lutToneCurve; @@ -688,7 +688,7 @@ public: virtual ~ColorAppearance() {}; void Reset(); - void Set(Curve *pCurve); + void Set(const Curve &pCurve); operator bool (void) const { return lutColCurve; diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index c05230738..8e6ce6728 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -1011,7 +1011,7 @@ DCPProfile::DCPProfile(Glib::ustring fname) // Create the curve DiagonalCurve rawCurve(cPoints, CURVES_MIN_POLY_POINTS); - toneCurve.Set((Curve*)&rawCurve); + toneCurve.Set(rawCurve); hasToneCurve = true; } } else if (tag == NULL) { @@ -1031,7 +1031,7 @@ DCPProfile::DCPProfile(Glib::ustring fname) } DiagonalCurve rawCurve(cPoints, CURVES_MIN_POLY_POINTS); - toneCurve.Set((Curve*)&rawCurve); + toneCurve.Set(rawCurve); hasToneCurve = true; } } diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index c6d66e4bf..72f801bab 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -1414,10 +1414,7 @@ SSEFUNCTION void RawImageSource::lmmse_interpolate_omp(int winw, int winh, int i gamtab = &(Color::gammatab_24_17a); } else { gamtab = new LUTf(65536, LUT_CLIP_ABOVE | LUT_CLIP_BELOW); - - for(int i = 0; i < 65536; i++) { - (*gamtab)[i] = (float)i / 65535.f; - } + gamtab->makeIdentity(65535.f); } diff --git a/rtengine/diagonalcurves.cc b/rtengine/diagonalcurves.cc index f09eb3459..4b41c2c29 100644 --- a/rtengine/diagonalcurves.cc +++ b/rtengine/diagonalcurves.cc @@ -301,10 +301,10 @@ double DiagonalCurve::getVal (double t) const } // do a binary search for the right interval: - int k_lo = 0, k_hi = N - 1; + unsigned int k_lo = 0, k_hi = N - 1; while (k_hi - k_lo > 1) { - int k = (k_hi + k_lo) / 2; + unsigned int k = (k_hi + k_lo) / 2; if (x[k] > t) { k_hi = k; @@ -323,7 +323,7 @@ double DiagonalCurve::getVal (double t) const else { // if (kind==Spline) { double a = (x[k_hi] - t) / h; double b = (t - x[k_lo]) / h; - double r = a * y[k_lo] + b * y[k_hi] + ((a * a * a - a) * ypp[k_lo] + (b * b * b - b) * ypp[k_hi]) * (h * h) / 6.0; + double r = a * y[k_lo] + b * y[k_hi] + ((a * a * a - a) * ypp[k_lo] + (b * b * b - b) * ypp[k_hi]) * (h * h) * 0.1666666666666666666666666666666; return CLIPD(r); } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 2f14c1ded..ccee4328b 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -40,7 +40,7 @@ ImProcCoordinator::ImProcCoordinator () tonecurve(65536, 0), //,1); chaut(0.f), redaut(0.f), blueaut(0.f), maxredaut(0.f), maxblueaut(0.f), minredaut(0.f), minblueaut(0.f), nresi(0.f), chromina(0.f), sigma(0.f), lumema(0.f), - lumacurve(65536, 0), + lumacurve(32770, 0), // lumacurve[32768] and lumacurve[32769] will be set to 32768 and 32769 later to allow linear interpolation chroma_acurve(65536, 0), chroma_bcurve(65536, 0), satcurve(65536, 0), @@ -53,7 +53,7 @@ ImProcCoordinator::ImProcCoordinator () NoiseCCcurve(65536, 0), vhist16(65536), vhist16bw(65536), lhist16(65536), lhist16Cropped(65536), - lhist16CAM(65536), lhist16CroppedCAM(65536), + lhist16CAM(65536), lhist16CCAM(65536), lhist16RETI(65536), histCropped(65536), @@ -465,12 +465,11 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) opautili = false; params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili); - bool clctoningutili = false; - bool llctoningutili = false; - CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16); - // clToningcurve.dump("CLToning3"); - CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16); - + if(params.colorToning.enabled) { + CurveFactory::curveToning(params.colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16); + // clToningcurve.dump("CLToning3"); + CurveFactory::curveToning(params.colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16); + } CurveFactory::curveBW (params.blackwhite.beforeCurve, params.blackwhite.afterCurve, vhist16bw, histToneCurveBW, beforeToneCurveBW, afterToneCurveBW, scale == 1 ? 1 : 1); @@ -698,39 +697,24 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) if(params.colorappearance.enabled) { //L histo and Chroma histo for ciecam // histogram well be for Lab (Lch) values, because very difficult to do with J,Q, M, s, C - int x1, y1, x2, y2, pos, posc; + int x1, y1, x2, y2; params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); lhist16CAM.clear(); - lhist16CroppedCAM.clear(); lhist16CCAM.clear(); - for (int x = 0; x < pH; x++) - for (int y = 0; y < pW; y++) { - pos = CLIP((int)(nprevl->L[x][y])); - - if(!params.colorappearance.datacie) { - posc = CLIP((int)sqrt(nprevl->a[x][y] * nprevl->a[x][y] + nprevl->b[x][y] * nprevl->b[x][y])); + if(!params.colorappearance.datacie) { + for (int x = 0; x < pH; x++) + for (int y = 0; y < pW; y++) { + int pos = CLIP((int)(nprevl->L[x][y])); + int posc = CLIP((int)sqrt(nprevl->a[x][y] * nprevl->a[x][y] + nprevl->b[x][y] * nprevl->b[x][y])); lhist16CAM[pos]++; lhist16CCAM[posc]++; - } - - if (y >= y1 && y < y2 && x >= x1 && x < x2) { - lhist16CroppedCAM[pos]++; - } } + } - LUTu dummy; - CurveFactory::curveLightBrightColor ( - params.colorappearance.curveMode, params.colorappearance.curve, - params.colorappearance.curveMode2, params.colorappearance.curve2, - params.colorappearance.curveMode3, params.colorappearance.curve3, - lhist16CAM, lhist16CroppedCAM, histLCAM, - lhist16CCAM, histCCAM, - customColCurve1, - customColCurve2, - customColCurve3, - scale == 1 ? 1 : 1 - ); + CurveFactory::curveLightBrightColor (params.colorappearance.curve, params.colorappearance.curve2, params.colorappearance.curve3, + lhist16CAM, histLCAM, lhist16CCAM, histCCAM, + customColCurve1, customColCurve2, customColCurve3, 1); float fnum = imgsrc->getMetaData()->getFNumber (); // F number float fiso = imgsrc->getMetaData()->getISOSpeed () ; // ISO float fspeed = imgsrc->getMetaData()->getShutterSpeed () ; // Speed diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 4d442482e..e138de925 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -108,7 +108,7 @@ protected: LUTu vhist16, vhist16bw; LUTu lhist16, lhist16Cropped; - LUTu lhist16CAM, lhist16CroppedCAM; + LUTu lhist16CAM; LUTu lhist16CCAM; LUTu lhist16RETI; LUTu histCropped; diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 989d9c6a7..74c750ccc 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -37,7 +37,8 @@ #include "improccoordinator.h" #include "clutstore.h" #include "ciecam02.h" - +#define BENCHMARK +#include "StopWatch.h" #ifdef _OPENMP #include #endif @@ -1722,27 +1723,28 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int LUTu hist16Q; if (needJ) { - hist16J (65536); + hist16J (32768); hist16J.clear(); } if (needQ) { - hist16Q (65536); + hist16Q (32768); hist16Q.clear(); } - #pragma omp parallel + const int numThreads = min(max(width*height / 65536,1),omp_get_max_threads()); + #pragma omp parallel num_threads(numThreads) if(numThreads>1) { LUTu hist16Jthr; LUTu hist16Qthr; if (needJ) { - hist16Jthr (65536); + hist16Jthr (32768); hist16Jthr.clear(); } if (needQ) { - hist16Qthr(65536); + hist16Qthr(32768); hist16Qthr.clear(); } @@ -1751,37 +1753,48 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) { //rough correspondence between L and J float currL = lab->L[i][j] / 327.68f; - float koef = 1.0f; //rough correspondence between L and J + float koef; //rough correspondence between L and J -// if (currL>95.f) koef=1.f; - if(currL > 85.f) { - koef = 0.97f; - } else if(currL > 80.f) { - koef = 0.93f; - } else if(currL > 70.f) { - koef = 0.87f; - } else if(currL > 60.f) { - koef = 0.85f; - } else if(currL > 50.f) { - koef = 0.8f; - } else if(currL > 40.f) { - koef = 0.75f; + if(currL > 50.f) { + if(currL > 70.f) { + if(currL > 80.f) { + if(currL > 85.f) { + koef = 0.97f; + } else { + koef = 0.93f; + } + } else { + koef = 0.87f; + } + } else { + if (currL > 60.f) { + koef = 0.85f; + } else { + koef = 0.8f; + } + } + } else { + if(currL > 10.f) { + if(currL > 20.f) { + if(currL > 40.f) { + koef = 0.75f; + } else { + koef = 0.7f; + } + } else { + koef = 0.9f; + } + } else { + koef = 1.0; + } } -// else if(currL>30.f) koef=0.7f; - else if(currL > 20.f) { - koef = 0.7f; - } else if(currL > 10.f) { - koef = 0.9f; - } - -// else if(currL>0.f) koef=1.0f; if (needJ) { - hist16Jthr[CLIP((int)((koef * lab->L[i][j])))]++; //evaluate histogram luminance L # J + hist16Jthr[(int)((koef * lab->L[i][j]))]++; //evaluate histogram luminance L # J } if (needQ) { - hist16Qthr[CLIP((int) (sqrtf((koef * (lab->L[i][j])) * 32768.f)))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L + hist16Qthr[(int) (sqrtf((koef * (lab->L[i][j])) * 32768.f))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L } sum += koef * lab->L[i][j]; //evaluate mean J to calculate Yb @@ -1790,14 +1803,10 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int #pragma omp critical { if(needJ) - for(int i = 0; i < 65536; i++) { - hist16J[i] += hist16Jthr[i]; - } + hist16J += hist16Jthr; if(needQ) - for(int i = 0; i < 65536; i++) { - hist16Q[i] += hist16Qthr[i]; - } + hist16Q += hist16Qthr; } } @@ -3077,7 +3086,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf) { - LUTf fGammaLUTf; Imagefloat *tmpImage = NULL; // NOTE: We're getting all 3 pointers here, but this function may not need them all, so one could optimize this @@ -3373,13 +3381,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer } bool hasgammabw = gammabwr != 1.f || gammabwg != 1.f || gammabwb != 1.f; - fGammaLUTf(65535); - #pragma omp parallel for - - for (int i = 0; i < 65536; i++) { - fGammaLUTf[i] = CurveFactory::gamma2 (float(i) / 65535.f) * 65535.f; - } - if (hasColorToning || blackwhite || (params->dirpyrequalizer.cbdlMethod == "bef" && params->dirpyrequalizer.enabled)) { tmpImage = new Imagefloat(working->width, working->height); } @@ -3387,15 +3388,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer int W = working->width; int H = working->height; - - - - - - - - - #define TS 112 #ifdef _OPENMP @@ -3592,9 +3584,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer if (editID == EUID_ToneCurve1) { // filling the pipette buffer for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { - editIFloatTmpR[ti * TS + tj] = CLIP(fGammaLUTf[rtemp[ti * TS + tj]] / 65535.f); - editIFloatTmpG[ti * TS + tj] = CLIP(fGammaLUTf[gtemp[ti * TS + tj]] / 65535.f); - editIFloatTmpB[ti * TS + tj] = CLIP(fGammaLUTf[btemp[ti * TS + tj]] / 65535.f); + editIFloatTmpR[ti * TS + tj] = Color::gamma2curve[rtemp[ti * TS + tj]] / 65535.f; + editIFloatTmpG[ti * TS + tj] = Color::gamma2curve[gtemp[ti * TS + tj]] / 65535.f; + editIFloatTmpB[ti * TS + tj] = Color::gamma2curve[btemp[ti * TS + tj]] / 65535.f; } } } @@ -3663,9 +3655,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer if (editID == EUID_ToneCurve2) { // filling the pipette buffer for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { - editIFloatTmpR[ti * TS + tj] = CLIP(fGammaLUTf[rtemp[ti * TS + tj]] / 65535.f); - editIFloatTmpG[ti * TS + tj] = CLIP(fGammaLUTf[gtemp[ti * TS + tj]] / 65535.f); - editIFloatTmpB[ti * TS + tj] = CLIP(fGammaLUTf[btemp[ti * TS + tj]] / 65535.f); + editIFloatTmpR[ti * TS + tj] = Color::gamma2curve[rtemp[ti * TS + tj]] / 65535.f; + editIFloatTmpG[ti * TS + tj] = Color::gamma2curve[gtemp[ti * TS + tj]] / 65535.f; + editIFloatTmpB[ti * TS + tj] = Color::gamma2curve[btemp[ti * TS + tj]] / 65535.f; } } } @@ -3722,19 +3714,19 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer if (editID == EUID_RGB_R) { for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { - editWhateverTmp[ti * TS + tj] = fGammaLUTf[rtemp[ti * TS + tj]] / 65536.f; + editWhateverTmp[ti * TS + tj] = Color::gamma2curve[rtemp[ti * TS + tj]] / 65536.f; } } } else if (editID == EUID_RGB_G) { for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { - editWhateverTmp[ti * TS + tj] = fGammaLUTf[gtemp[ti * TS + tj]] / 65536.f; + editWhateverTmp[ti * TS + tj] = Color::gamma2curve[gtemp[ti * TS + tj]] / 65536.f; } } } else if (editID == EUID_RGB_B) { for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { - editWhateverTmp[ti * TS + tj] = fGammaLUTf[btemp[ti * TS + tj]] / 65536.f; + editWhateverTmp[ti * TS + tj] = Color::gamma2curve[btemp[ti * TS + tj]] / 65536.f; } } } @@ -4167,9 +4159,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer if (editID == EUID_BlackWhiteBeforeCurve) { for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { - editIFloatTmpR[ti * TS + tj] = CLIP(fGammaLUTf[rtemp[ti * TS + tj]] / 65535.f); - editIFloatTmpG[ti * TS + tj] = CLIP(fGammaLUTf[gtemp[ti * TS + tj]] / 65535.f); - editIFloatTmpB[ti * TS + tj] = CLIP(fGammaLUTf[btemp[ti * TS + tj]] / 65535.f); + editIFloatTmpR[ti * TS + tj] = Color::gamma2curve[rtemp[ti * TS + tj]] / 65535.f; + editIFloatTmpG[ti * TS + tj] = Color::gamma2curve[gtemp[ti * TS + tj]] / 65535.f; + editIFloatTmpB[ti * TS + tj] = Color::gamma2curve[btemp[ti * TS + tj]] / 65535.f; } } } else if (editID == EUID_BlackWhiteLuminance) { @@ -4402,9 +4394,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer float fx, fy, fz; - fx = (x < 65535.0f ? Color::cachef[std::max(x, 0.f)] : 327.68f * std::cbrt(x / MAXVALF)); - fy = (y < 65535.0f ? Color::cachef[std::max(y, 0.f)] : 327.68f * std::cbrt(y / MAXVALF)); - fz = (z < 65535.0f ? Color::cachef[std::max(z, 0.f)] : 327.68f * std::cbrt(z / MAXVALF)); + fx = (x < 65535.0f ? Color::cachef[x] : 327.68f * std::cbrt(x / MAXVALF)); + fy = (y < 65535.0f ? Color::cachef[y] : 327.68f * std::cbrt(y / MAXVALF)); + fz = (z < 65535.0f ? Color::cachef[z] : 327.68f * std::cbrt(z / MAXVALF)); lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; lab->a[i][j] = (500.0f * (fx - fy) ); @@ -4560,7 +4552,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer for (int i = 0; i < tH; i++) { for (int j = 0; j < tW; j++) { - editWhatever->v(i, j) = CLIP(fGammaLUTf[tmpImage->r(i, j)] / 65535.f); // assuming that r=g=b + editWhatever->v(i, j) = Color::gamma2curve[tmpImage->r(i, j)] / 65535.f; // assuming that r=g=b } } } @@ -5527,6 +5519,7 @@ void ImProcFunctions::luminanceCurve (LabImage* lold, LabImage* lnew, LUTf & cur SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve, LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) { + int W = lold->W; int H = lold->H; // lhskcurve.dump("lh_curve"); diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc index f9f6c12a1..7103cadd4 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -120,15 +120,8 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext rtengine::Image8 *output = NULL; const unsigned char *data = NULL; int fw, fh; - LUTf cdcurve; - bool dehacontlutili = false; procparams::ProcParams params; - /*rtengine::RAWParams raw; - rtengine::LensProfParams lensProf; - rtengine::procparams::ToneCurveParams toneCurve; - rtengine::procparams::ColorManagementParams icm; - rtengine::CoarseTransformParams coarse;*/ ColorTemp wb = rawImage.getWB (); rawImage.getFullSize (fw, fh, TR_NONE); PreviewProps pp (0, 0, fw, fh, 1); diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 1a4e0dbb5..7d9dd0bf3 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -4311,7 +4311,7 @@ BENCHFUN #pragma omp parallel #endif { - LUTu tmphistogram(65536 >> histcompr); + LUTu tmphistogram(histogram.getSize()); tmphistogram.clear(); #ifdef _OPENMP #pragma omp for nowait @@ -4366,17 +4366,18 @@ BENCHFUN const bool fourColours = ri->getSensorType() == ST_BAYER && ((mult[1] != mult[3] || cblacksom[1] != cblacksom[3]) || FC(0,0) == 3 || FC(0,1) == 3 || FC(1,0) == 3 || FC(1,1) == 3); + constexpr int histoSize = 65536; LUTu hist[4]; - hist[0](65536); + hist[0](histoSize); hist[0].clear(); if (ri->get_colors() > 1) { - hist[1](65536); + hist[1](histoSize); hist[1].clear(); - hist[2](65536); + hist[2](histoSize); hist[2].clear(); } if (fourColours) { - hist[3](65536); + hist[3](histoSize); hist[3].clear(); } @@ -4391,15 +4392,15 @@ BENCHFUN { // we need one LUT per color and thread, which corresponds to 1 MB per thread LUTu tmphist[4]; - tmphist[0](65536); + tmphist[0](histoSize); tmphist[0].clear(); if (ri->get_colors() > 1) { - tmphist[1](65536); + tmphist[1](histoSize); tmphist[1].clear(); - tmphist[2](65536); + tmphist[2](histoSize); tmphist[2].clear(); if (fourColours) { - tmphist[3](65536); + tmphist[3](histoSize); tmphist[3].clear(); } } diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index e20efdbdd..5f09bb74a 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -38,6 +38,8 @@ #include "../rtgui/ppversion.h" #include "improccoordinator.h" #include +#define BENCHMARK +#include "StopWatch.h" extern Options options; @@ -798,6 +800,7 @@ IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, std::string camName, double focalLen, double focalLen35mm, float focusDist, float shutter, float fnumber, float iso, std::string expcomp_, double& myscale) { + BENCHFUN // check if the WB's equalizer value has changed if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4)) { wbEqual = params.wb.equal; @@ -923,7 +926,6 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei } else { StdImageSource::colorSpaceConversion (baseImg, params.icm, embProfile, thumbImg->getSampleFormat()); } - int fw = baseImg->width; int fh = baseImg->height; //ColorTemp::CAT02 (baseImg, ¶ms) ;//perhaps not good! @@ -972,7 +974,6 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei int black = params.toneCurve.black; int hlcompr = params.toneCurve.hlcompr; int hlcomprthresh = params.toneCurve.hlcomprthresh; - if (params.toneCurve.autoexp && aeHistogram) { ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, expcomp, bright, contr, black, hlcompr, hlcomprthresh); //ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, params.toneCurve.expcomp, params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr); @@ -981,11 +982,13 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei LUTf curve1 (65536); LUTf curve2 (65536); LUTf curve (65536); + LUTf satcurve (65536); LUTf lhskcurve (65536); + LUTf lumacurve(32770, 0); // lumacurve[32768] and lumacurve[32769] will be set to 32768 and 32769 later to allow linear interpolation LUTf clcurve (65536); - LUTf clToningcurve (65536); - LUTf cl2Toningcurve (65536); + LUTf clToningcurve; + LUTf cl2Toningcurve; LUTf rCurve (65536); LUTf gCurve (65536); @@ -1003,7 +1006,6 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei ColorAppearance customColCurve3; ToneCurve customToneCurvebw1; ToneCurve customToneCurvebw2; - CurveFactory::complexCurve (expcomp, black / 65535.0, hlcompr, hlcomprthresh, params.toneCurve.shcompr, bright, contr, params.toneCurve.curveMode, params.toneCurve.curve, @@ -1013,7 +1015,6 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, 16); CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, 16); CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, 16); - TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); double wp[3][3] = { {wprof[0][0], wprof[0][1], wprof[0][2]}, @@ -1030,13 +1031,14 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili); //params.dirpyrDenoise.getCurves(dnNoisCurve, lldenoisutili); - bool clctoningutili = false; - bool llctoningutili = false; - CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16); - CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16); + if(params.colorToning.enabled) { + clToningcurve (65536); + cl2Toningcurve (65536); + CurveFactory::curveToning(params.colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16); + CurveFactory::curveToning(params.colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16); + } CurveFactory::curveBW (params.blackwhite.beforeCurve, params.blackwhite.afterCurve, hist16, dummy, customToneCurvebw1, customToneCurvebw2, 16); - double rrm, ggm, bbm; float autor, autog, autob; float satLimit = float(params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f; @@ -1066,7 +1068,6 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei LabImage* labView = new LabImage (fw, fh); DCPProfile *dcpProf = NULL; - if (isRaw) { cmsHPROFILE dummy; RawImageSource::findInputProfile(params.icm.input, NULL, camName, &dcpProf, dummy); @@ -1075,7 +1076,6 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei dcpProf->setStep2ApplyState(params.icm.working, params.icm.toneCurve, params.icm.applyLookTable, params.icm.applyBaselineExposureOffset); } } - ipf.rgbProc (baseImg, labView, NULL, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf); // freeing up some memory @@ -1100,7 +1100,6 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei hist16[CLIP((int)((labView->L[i][j])))]++; hist16C[CLIP((int)sqrt(labView->a[i][j]*labView->a[i][j] + labView->b[i][j]*labView->b[i][j]))]++; } - // luminance processing // ipf.EPDToneMap(labView,0,6); @@ -1110,9 +1109,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei bool ccutili = false; bool cclutili = false; bool clcutili = false; - CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, - hist16, hist16, curve, dummy, 16, utili); + hist16, hist16, lumacurve, dummy, 16, utili); CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, hist16C, dummy, 16); @@ -1123,7 +1121,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei //ipf.luminanceCurve (labView, labView, curve); - ipf.chromiLuminanceCurve (NULL, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, curve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy, dummy, dummy); + ipf.chromiLuminanceCurve (NULL, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy, dummy, dummy); ipf.vibrance(labView); @@ -1133,18 +1131,18 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei //if(!params.colorappearance.enabled){ipf.EPDToneMap(labView,5,6);} - CurveFactory::curveLightBrightColor ( - params.colorappearance.curveMode, params.colorappearance.curve, - params.colorappearance.curveMode2, params.colorappearance.curve2, - params.colorappearance.curveMode3, params.colorappearance.curve3, - hist16, hist16, dummy, - hist16C, dummy, - customColCurve1, - customColCurve2, - customColCurve3, - 16); if(params.colorappearance.enabled) { + CurveFactory::curveLightBrightColor ( + params.colorappearance.curve, + params.colorappearance.curve2, + params.colorappearance.curve3, + hist16, dummy, + hist16C, dummy, + customColCurve1, + customColCurve2, + customColCurve3, + 16); int begh = 0, endh = labView->H; bool execsharp = false; float d; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index c03addb42..b7d1f3b61 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -771,10 +771,10 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p LUTf curve (65536, 0); LUTf satcurve (65536, 0); LUTf lhskcurve (65536, 0); - LUTf lumacurve(65536, 0); + LUTf lumacurve(32770, 0); // lumacurve[32768] and lumacurve[32769] will be set to 32768 and 32769 later to allow linear interpolation LUTf clcurve (65536, 0); - LUTf clToningcurve (65536, 0); - LUTf cl2Toningcurve (65536, 0); + LUTf clToningcurve; + LUTf cl2Toningcurve; LUTf wavclCurve (65536, 0); LUTf rCurve (65536, 0); @@ -814,11 +814,12 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p bool opautili = false; params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili); - bool clctoningutili = false; - CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve, 1); - bool llctoningutili = false; - CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve, 1); - + if(params.colorToning.enabled) { + clToningcurve (65536, 0); + CurveFactory::curveToning(params.colorToning.clcurve, clToningcurve, 1); + cl2Toningcurve (65536, 0); + CurveFactory::curveToning(params.colorToning.cl2curve, cl2Toningcurve, 1); + } LabImage* labView = new LabImage (fw, fh); @@ -894,10 +895,10 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p if(params.labCurve.contrast != 0) { //only use hist16 for contrast #ifdef _OPENMP - #pragma omp parallel shared(hist16,labView, fh, fw) + #pragma omp parallel #endif { - LUTu hist16thr (65536); // one temporary lookup table per thread + LUTu hist16thr (hist16.getSize()); // one temporary lookup table per thread hist16thr.clear(); #ifdef _OPENMP #pragma omp for schedule(static) nowait @@ -906,19 +907,14 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p for (int i = 0; i < fh; i++) for (int j = 0; j < fw; j++) { - hist16thr[CLIP((int)((labView->L[i][j])))]++; + hist16thr[(int)((labView->L[i][j]))]++; } #pragma omp critical { - for(int i = 0; i < 65536; i++) - { - hist16[i] += hist16thr[i]; - } + hist16 += hist16thr; } } - - } bool utili = false; @@ -935,7 +931,6 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve, params.labCurve.lccurve, curve1, curve2, satcurve, lhskcurve, hist16C, hist16C, dummy, dummy, 1); -// ipf.MSR(labView, labView->W, labView->H, 1); ipf.chromiLuminanceCurve (NULL, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy, dummy, dummy); @@ -1025,10 +1020,10 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p begh = 0; endh = fh; CurveFactory::curveLightBrightColor ( - params.colorappearance.curveMode, params.colorappearance.curve, - params.colorappearance.curveMode2, params.colorappearance.curve2, - params.colorappearance.curveMode3, params.colorappearance.curve3, - hist16, hist16, dummy, + params.colorappearance.curve, + params.colorappearance.curve2, + params.colorappearance.curve3, + hist16, dummy, hist16C, dummy, customColCurve1, customColCurve2, diff --git a/rtengine/sleef.c b/rtengine/sleef.c index c7b3fb486..2377aea79 100644 --- a/rtengine/sleef.c +++ b/rtengine/sleef.c @@ -58,7 +58,9 @@ __inline double ldexpk(double x, int q) { m = (((m + q) >> 9) - m) << 7; q = q - (m << 2); u = longBitsToDouble(((int64_t)(m + 0x3ff)) << 52); - x = x * u * u * u * u; + double u2 = u*u; + u2 = u2 * u2; + x = x * u2; u = longBitsToDouble(((int64_t)(q + 0x3ff)) << 52); return x * u; } @@ -1197,7 +1199,7 @@ __inline float xexpf(float d) { int q = (int)xrintf(d * R_LN2f); float s, u; - + s = mlaf(q, -L2Uf, d); s = mlaf(q, -L2Lf, s); @@ -1246,7 +1248,7 @@ __inline float xdivf( float d, int n){ uflint.intval -= n << 23; // add n to the exponent } return uflint.floatval; -} +}