diff --git a/rtengine/curves.cc b/rtengine/curves.cc index ee772a61e..e257a0eff 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -396,7 +396,7 @@ namespace rtengine { //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void CurveFactory::complexLCurve (double br, double contr, const std::vector& curvePoints, \ - LUTu & histogram, LUTf & outCurve, \ + LUTu & histogram, LUTu & histogramCropped, LUTf & outCurve, \ LUTu & outBeforeCCurveHistogram, int skip) { // curve without contrast @@ -422,21 +422,21 @@ namespace rtengine { std::vector brightcurvePoints; brightcurvePoints.push_back((double)((CurveType)DCT_NURBS)); - brightcurvePoints.push_back(0); //black point. Value in [0 ; 1] range - brightcurvePoints.push_back(0); //black point. Value in [0 ; 1] range + brightcurvePoints.push_back(0); // black point. Value in [0 ; 1] range + brightcurvePoints.push_back(0); // black point. Value in [0 ; 1] range - if(br>0) { - brightcurvePoints.push_back(0.1); //toe point + if (br>0) { + brightcurvePoints.push_back(0.1); // toe point brightcurvePoints.push_back(0.1+br/150.0); //value at toe point - brightcurvePoints.push_back(0.7); //shoulder point + brightcurvePoints.push_back(0.7); // shoulder point brightcurvePoints.push_back(MIN(1.0,0.7+br/300.0)); //value at shoulder point } else { - brightcurvePoints.push_back(0.1-br/150.0); //toe point - brightcurvePoints.push_back(0.1); //value at toe point + brightcurvePoints.push_back(0.1-br/150.0); // toe point + brightcurvePoints.push_back(0.1); // value at toe point - brightcurvePoints.push_back(MIN(1.0,0.7-br/300.0)); //shoulder point - brightcurvePoints.push_back(0.7); //value at shoulder point + brightcurvePoints.push_back(MIN(1.0,0.7-br/300.0)); // shoulder point + brightcurvePoints.push_back(0.7); // value at shoulder point } brightcurvePoints.push_back(1); // white point brightcurvePoints.push_back(1); // value at white point @@ -444,7 +444,7 @@ namespace rtengine { DiagonalCurve* brightcurve = new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS/skip); // Actually, CURVES_MIN_POLY_POINTS = 1000, //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - for (int i=0; i<32768; i++) {//L values range up to 32767, higher values are for highlight overflow + 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; @@ -478,14 +478,14 @@ namespace rtengine { std::vector contrastcurvePoints; contrastcurvePoints.push_back((double)((CurveType)DCT_NURBS)); - contrastcurvePoints.push_back(0); //black point. Value in [0 ; 1] range - contrastcurvePoints.push_back(0); //black point. Value in [0 ; 1] range + contrastcurvePoints.push_back(0); // black point. Value in [0 ; 1] range + contrastcurvePoints.push_back(0); // black point. Value in [0 ; 1] range - contrastcurvePoints.push_back(avg-avg*(0.6-contr/250.0)); //toe point - contrastcurvePoints.push_back(avg-avg*(0.6+contr/250.0)); //value at toe point + contrastcurvePoints.push_back(avg-avg*(0.6-contr/250.0)); // toe point + contrastcurvePoints.push_back(avg-avg*(0.6+contr/250.0)); // value at toe point - contrastcurvePoints.push_back(avg+(1-avg)*(0.6-contr/250.0)); //shoulder point - contrastcurvePoints.push_back(avg+(1-avg)*(0.6+contr/250.0)); //value at shoulder point + contrastcurvePoints.push_back(avg+(1-avg)*(0.6-contr/250.0)); // shoulder point + contrastcurvePoints.push_back(avg+(1-avg)*(0.6+contr/250.0)); // value at shoulder point contrastcurvePoints.push_back(1); // white point contrastcurvePoints.push_back(1); // value at white point @@ -502,7 +502,7 @@ namespace rtengine { } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - for (int i=0; i<32768; i++) {//L values go up to 32767, last stop is for highlight overflow + for (int i=0; i<32768; i++) { // L values go up to 32767, last stop is for highlight overflow float val; // apply custom/parametric/NURBS curve, if any @@ -510,7 +510,7 @@ namespace rtengine { if (outBeforeCCurveHistogram) { float hval = dcurve[i]; int hi = (int)(255.0*CLIPD(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 9688f2d0f..75597e14a 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -209,7 +209,8 @@ class CurveFactory { 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); + static void complexLCurve (double br, double contr, const std::vector& curvePoints, LUTu & histogram, LUTu & histogramCropped, + LUTf & outCurve, LUTu & outBeforeCCurveHistogram, int skip); }; class Curve { diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc index 0f0eda49a..d4f92c91f 100644 --- a/rtengine/imagefloat.cc +++ b/rtengine/imagefloat.cc @@ -237,7 +237,7 @@ Imagefloat::to16() const } -void Imagefloat::CalcCroppedHistogram(const ProcParams ¶ms, float scale, LUTu & hist) { +void Imagefloat::calcCroppedHistogram(const ProcParams ¶ms, float scale, LUTu & hist) { hist.clear(); // Set up factors to calc the lightness @@ -249,18 +249,13 @@ void Imagefloat::CalcCroppedHistogram(const ProcParams ¶ms, float scale, LUT // 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)); - } + int x1, x2, y1, y2; + params.crop.mapToResized(width, height, scale, x1, x2, y1, y2); #pragma omp parallel for - for (int y=hy1; y65535) i=65535; hist[i]++; diff --git a/rtengine/imagefloat.h b/rtengine/imagefloat.h index b601cb445..011378ed0 100644 --- a/rtengine/imagefloat.h +++ b/rtengine/imagefloat.h @@ -89,7 +89,7 @@ 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 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 cd7b1edd5..40d48f8e3 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -44,7 +44,7 @@ ImProcCoordinator::ImProcCoordinator () satcurve(65536,0); vhist16(65536); - lhist16(65536); + lhist16(65536); lhist16Cropped(65536); histCropped(65536); histRed(256); histRedRaw(256); @@ -189,7 +189,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases); if ((todo & M_RGBCURVE) || todo==CROP) { - if (hListener) oprevi->CalcCroppedHistogram(params, scale, histCropped); + 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, \ @@ -201,18 +201,30 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { // 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 + int x1, y1, x2, y2, pos; + params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); + + lhist16.clear(); lhist16Cropped.clear(); + for (int x=0; xL[x][y])); + lhist16[pos]++; + + if (y>=y1 && y=x1 && xhistogramChanged (histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve, histRedRaw, histGreenRaw, histBlueRaw); } @@ -386,7 +391,10 @@ if (settings->verbose) printf ("setscale before lock\n"); } -void ImProcCoordinator::updateHistograms (int x1, int y1, int x2, int y2) { +void ImProcCoordinator::updateLRGBHistograms () { + + int x1, y1, x2, y2; + params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); histRed.clear(); histGreen.clear(); diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index fac8fd025..660107778 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -75,7 +75,7 @@ class ImProcCoordinator : public StagedImageProcessor { LUTf satcurve; LUTu vhist16; - LUTu lhist16; + LUTu lhist16,lhist16Cropped; LUTu histCropped; LUTu histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve, bcabhist; @@ -98,7 +98,7 @@ class ImProcCoordinator : public StagedImageProcessor { void progress (Glib::ustring str, int pr); void reallocAll (); - void updateHistograms (int x1, int y1, int x2, int y2); + void updateLRGBHistograms (); void setScale (int prevscale); void updatePreviewImage (int todo, Crop* cropCall= NULL); diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index a583a97e7..e7ec3764f 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -37,6 +37,17 @@ namespace procparams { const char *RAWParams::methodstring[RAWParams::numMethods]={"eahd", "hphd", "vng4", "dcb", "amaze", "ahd", "fast" }; const char *RAWParams::ff_BlurTypestring[RAWParams::numFlatFileBlurTypes]={/*"Parametric",*/ "Area Flatfield", "Vertical Flatfield", "Horizontal Flatfield", "V+H Flatfield"}; +// Maps crop to resized width (e.g. smaller previews) +void CropParams::mapToResized(int resizedWidth, int resizedHeight, int scale, int &x1, int &x2, int &y1, int &y2) const { + x1 = 0, x2 = resizedWidth, y1 = 0, y2 = resizedHeight; + if (enabled) { + x1 = MIN(resizedWidth-1, MAX(0, x / scale)); + y1 = MIN(resizedHeight-1, MAX(0, y / scale)); + x2 = MIN(resizedWidth, MAX(0, (x+w) / scale)); + y2 = MIN(resizedHeight, MAX(0, (y+h) / scale)); + } +} + ProcParams::ProcParams () { setDefaults (); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index f91e790b4..3d16e86ba 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -209,6 +209,8 @@ class CropParams { Glib::ustring ratio; Glib::ustring orientation; Glib::ustring guide; + + void mapToResized(int resizedWidth, int resizedHeight, int scale, int &x1, int &x2, int &y1, int &y2) const; }; /** diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index cf5420def..75d0b6502 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -739,7 +739,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei hist16[(int)(2*(labView->L[i][j]))]++; // luminance processing - CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, hist16, curve, dummy, 16); + CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, + hist16, hist16, curve, dummy, 16); ipf.luminanceCurve (labView, labView, curve); CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.enable_saturationlimiter, params.labCurve.saturationlimit, \ params.labCurve.acurve, params.labCurve.bcurve, curve1, curve2, satcurve, 16); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 77d0fda1e..7394ee3a5 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -169,7 +169,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p hist16[CLIP((int)((labView->L[i][j])))]++; // luminance processing - CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, hist16, curve, dummy, 1); + CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, hist16, hist16, curve, dummy, 1); ipf.luminanceCurve (labView, labView, curve); CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.enable_saturationlimiter, params.labCurve.saturationlimit, \ params.labCurve.acurve, params.labCurve.bcurve, curve1, curve2, satcurve, 1);