diff --git a/rtengine/curves.cc b/rtengine/curves.cc index 2e82d0330..ee772a61e 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -188,7 +188,7 @@ namespace rtengine { void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, double hlcomprthresh, \ double shcompr, double br, double contr, double gamma_, bool igamma_, \ - const std::vector& curvePoints, LUTu & histogram, \ + const std::vector& curvePoints, LUTu & histogram, LUTu & histogramCropped, \ LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, \ LUTu & outBeforeCCurveHistogram, int skip) { @@ -361,13 +361,13 @@ namespace rtengine { // apply custom/parametric/NURBS curve, if any if (tcurve) { - if (outBeforeCCurveHistogram) { + if (outBeforeCCurveHistogram && histogramCropped) { float fi=i; float hval = dcurve[shCurve[hlCurve[i]*fi]*fi]; //if (needigamma) // hval = igamma2 (hval); int hi = (int)(255.0*(hval)); - outBeforeCCurveHistogram[hi]+=histogram[i] ; + outBeforeCCurveHistogram[hi] += histogramCropped[i] ; } val = tcurve->getVal (dcurve[i]); } else { diff --git a/rtengine/curves.h b/rtengine/curves.h index b8878442e..9688f2d0f 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -205,7 +205,8 @@ class CurveFactory { } public: - static void complexCurve (double ecomp, double black, double hlcompr, double hlcomprthresh, double shcompr, double br, double contr, double gamma_, bool igamma_, const std::vector& curvePoints, LUTu & histogram,LUTf & hlCurve, LUTf & shCurve,LUTf & outCurve, LUTu & outBeforeCCurveHistogram, int skip=1); + static void complexCurve (double ecomp, double black, double hlcompr, double hlcomprthresh, double shcompr, double br, double contr, double gamma_, bool igamma_, const std::vector& curvePoints, + LUTu & histogram, LUTu & histogramCropped, LUTf & hlCurve, LUTf & shCurve,LUTf & outCurve, LUTu & outBeforeCCurveHistogram, int skip=1); static void complexsgnCurve (double saturation, bool satlimit, double satlimthresh, const std::vector& acurvePoints, \ const std::vector& bcurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, int skip=1); static void complexLCurve (double br, double contr, const std::vector& curvePoints, LUTu & histogram, LUTf & outCurve, LUTu & outBeforeCCurveHistogram, int skip); diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc index 8d6b89c08..0f0eda49a 100644 --- a/rtengine/imagefloat.cc +++ b/rtengine/imagefloat.cc @@ -22,6 +22,7 @@ #include #include #include +#include using namespace rtengine; @@ -235,6 +236,38 @@ Imagefloat::to16() const return img16; } + +void Imagefloat::CalcCroppedHistogram(const ProcParams ¶ms, float scale, LUTu & hist) { + hist.clear(); + + // Set up factors to calc the lightness + TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); + + float facRed = wprof[1][0]; + float facGreen = wprof[1][1]; + float facBlue = wprof[1][2]; + + + // calc pixel size + int hx1 = 0, hx2 = width, hy1 = 0, hy2 = height; + if (params.crop.enabled) { + hx1 = MIN(width-1,MAX(0,params.crop.x / scale)); + hy1 = MIN(height-1,MAX(0,params.crop.y / scale)); + hx2 = MIN(width,MAX(0,(params.crop.x+params.crop.w) / scale)); + hy2 = MIN(height,MAX(0,(params.crop.y+params.crop.h) / scale)); + } + + #pragma omp parallel for + for (int y=hy1; y65535) i=65535; + hist[i]++; + } + } +} + // Parallized transformation; create transform with cmsFLAGS_NOCACHE! void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform, bool safe) { if (safe) { diff --git a/rtengine/imagefloat.h b/rtengine/imagefloat.h index 544e442f2..b601cb445 100644 --- a/rtengine/imagefloat.h +++ b/rtengine/imagefloat.h @@ -24,10 +24,9 @@ #include #include -//#include namespace rtengine { - + using namespace procparams; //enum TypeInterpolation { TI_Nearest, TI_Bilinear }; class Image8; @@ -90,6 +89,8 @@ class Imagefloat : public ImageIO, public IImagefloat { virtual float** getGPlane () { return g; } virtual float** getBPlane () { return b; } + void CalcCroppedHistogram(const ProcParams ¶ms, float scale, LUTu & hist); + void ExecCMSTransform(cmsHTRANSFORM hTransform, bool safe); }; }; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 6a53b02c0..dceda03a7 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -45,6 +45,7 @@ ImProcCoordinator::ImProcCoordinator () vhist16(65536); lhist16(65536); + histCropped(65536); histRed(65536); histGreen(65536); @@ -185,19 +186,26 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { } progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases); - if (todo & M_RGBCURVE) { + if ((todo & M_RGBCURVE) || todo==CROP) { + if (hListener) oprevi->CalcCroppedHistogram(params, scale, histCropped); + + // complexCurve also calculated pre-curves histogram dependend on crop CurveFactory::complexCurve (params.toneCurve.expcomp, params.toneCurve.black/65535.0, \ params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, \ params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, \ imgsrc->getGamma(), true, params.toneCurve.curve, \ - vhist16, hltonecurve, shtonecurve, tonecurve, histToneCurve, scale==1 ? 1 : 1); - ipf.rgbProc (oprevi, oprevl, hltonecurve, shtonecurve, tonecurve, shmap, params.toneCurve.saturation); + vhist16, histCropped, hltonecurve, shtonecurve, tonecurve, histToneCurve, scale==1 ? 1 : 1); + + // if it's just crop we just need the histogram, no image updates + if ( todo!=CROP ) { + ipf.rgbProc (oprevi, oprevl, hltonecurve, shtonecurve, tonecurve, shmap, params.toneCurve.saturation); - // compute L channel histogram - lhist16.clear(); - for (int i=0; iL[i][j]))]++; + // compute L channel histogram + lhist16.clear(); + for (int i=0; iL[i][j]))]++; + } } readyphase++; diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 5f1ef3c15..0126ea6c8 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -78,6 +78,7 @@ class ImProcCoordinator : public StagedImageProcessor { LUTu vhist16; LUTu lhist16; + LUTu histCropped; LUTu histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve, bcabhist; diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index aaf67e0e7..d24747751 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -123,7 +123,8 @@ void ImProcFunctions::setScale (double iscale) { scale = iscale; } -void ImProcFunctions::firstAnalysis_ (Imagefloat* original, Glib::ustring wprofile, unsigned int* histogram, int row_from, int row_to) { +// Called from several threads +void ImProcFunctions::firstAnalysisThread (Imagefloat* original, Glib::ustring wprofile, unsigned int* histogram, int row_from, int row_to) { TMatrix wprof = iccStore->workingSpaceMatrix (wprofile); @@ -193,12 +194,12 @@ void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* par int blk = H/nthreads; if (tidheight); + firstAnalysisThread (original, wprofile, hist[0], 0, original->height); #endif histogram.clear(); @@ -212,6 +213,7 @@ void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* par } +// Process RGB image and convert to LAB space void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, SHMap* shmap, int sat) { int h_th, s_th; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index dc6367362..84d4964cf 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -48,7 +48,7 @@ class ImProcFunctions { void transformNonSep (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH); void transformSep (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH); void sharpenHaloCtrl (LabImage* lab, float** blurmap, float** base, int W, int H); - void firstAnalysis_ (Imagefloat* original, Glib::ustring wprofile, unsigned int* histogram, int row_from, int row_to); + void firstAnalysisThread(Imagefloat* original, Glib::ustring wprofile, unsigned int* histogram, int row_from, int row_to); void dcdamping (float** aI, float** aO, float damping, int W, int H); bool needsCA (); diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 9efe072bf..0bd856994 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -733,7 +733,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei LUTf satcurve (65536); LUTu dummy; - CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, isRaw ? 2.2 : 0, true, params.toneCurve.curve, hist16, curve1, curve2, curve, dummy, 16); + CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, isRaw ? 2.2 : 0, true, params.toneCurve.curve, + hist16, dummy, curve1, curve2, curve, dummy, 16); LabImage* labView = new LabImage (fw,fh); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 4732b361d..65534c394 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -150,7 +150,8 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p LUTf satcurve (65536,0); LUTu dummy; - CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getGamma(), true, params.toneCurve.curve, hist16, curve1, curve2, curve, dummy); + CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getGamma(), true, params.toneCurve.curve, + hist16, dummy, curve1, curve2, curve, dummy); LabImage* labView = new LabImage (fw,fh);