From 9bf2ff00791c8ab28c99994c7a74b5f976195840 Mon Sep 17 00:00:00 2001 From: Emil Martinec Date: Sun, 7 Nov 2010 11:34:15 -0600 Subject: [PATCH] Added RGB saturation slider. Fixed coding error in RGB contrast curve. --- rtdata/languages/default | 6 +- rtdata/profiles/crisp.pp3 | 3 +- rtdata/profiles/default.pp3 | 3 +- rtdata/profiles/neutral.pp3 | 354 +++++++++++++++++----------------- rtengine/curves.cc | 27 ++- rtengine/dcrop.cc | 2 +- rtengine/green_equil_RT.cc | 19 +- rtengine/improccoordinator.cc | 2 +- rtengine/improcfun.cc | 69 ++++++- rtengine/improcfun.h | 5 +- rtengine/procevents.h | 3 +- rtengine/procparams.cc | 6 +- rtengine/procparams.h | 1 + rtengine/refreshmap.cc | 3 +- rtengine/rtthumbnail.cc | 2 +- rtengine/simpleprocess.cc | 2 +- rtgui/addsetids.h | 4 +- rtgui/batchtoolpanelcoord.cc | 2 +- rtgui/paramsedited.cc | 5 +- rtgui/paramsedited.h | 3 +- rtgui/preferences.cc | 1 + rtgui/tonecurve.cc | 31 ++- rtgui/tonecurve.h | 6 +- 23 files changed, 325 insertions(+), 234 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 88db8c9b6..fc7887a97 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -219,8 +219,8 @@ HISTORY_MSG_83;High quality shadows/highlights HISTORY_MSG_84;Perspective correction HISTORY_MSG_85;Wavelet coefficients HISTORY_MSG_86;Wavelet equalizer -HISTORY_MSG_87;Spot noise reduction -HISTORY_MSG_88;Spot NR threshold +HISTORY_MSG_87;Salt&pepper noise reduction +HISTORY_MSG_88;Salt&pepper NR threshold HISTORY_MSG_89;Noise reduction HISTORY_MSG_8;Exposure Compensation HISTORY_MSG_90;NR - luminance @@ -234,6 +234,7 @@ HISTORY_MSG_97;'b' curve HISTORY_MSG_98;Demozaicing HISTORY_MSG_99;Preprocessing HISTORY_MSG_9;Highlight Compression +HISTORY_MSG_100;RGB saturation HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOTAS;As... HISTORY_NEWSSDIALOGLABEL;Label of the snapshot: @@ -622,6 +623,7 @@ TP_EXPOSURE_CONTRAST;Contrast TP_EXPOSURE_CURVEEDITOR;Tone Curve TP_EXPOSURE_EXPCOMP;Exp. Comp. TP_EXPOSURE_LABEL;Exposure +TP_EXPOSURE_SATURATION;Saturation TP_HLREC_CIELAB;CIELab Blending TP_HLREC_COLOR;Color Propagation TP_HLREC_LABEL;Highlight Reconstruction diff --git a/rtdata/profiles/crisp.pp3 b/rtdata/profiles/crisp.pp3 index 77c88a570..e8dd5e060 100644 --- a/rtdata/profiles/crisp.pp3 +++ b/rtdata/profiles/crisp.pp3 @@ -4,10 +4,11 @@ Version=484 [Exposure] Auto=true -Clip=0.001 +Clip=0.01 Compensation=0 Brightness=0 Contrast=12 +Saturation=0 Black=0 HighlightCompr=70 ShadowCompr=50 diff --git a/rtdata/profiles/default.pp3 b/rtdata/profiles/default.pp3 index 3302d68c8..05ad0c117 100644 --- a/rtdata/profiles/default.pp3 +++ b/rtdata/profiles/default.pp3 @@ -4,10 +4,11 @@ Version=484 [Exposure] Auto=true -Clip=0.001 +Clip=0.01 Compensation=0 Brightness=0 Contrast=0 +Saturation=0 Black=0 HighlightCompr=70 ShadowCompr=50 diff --git a/rtdata/profiles/neutral.pp3 b/rtdata/profiles/neutral.pp3 index cbbfadbe1..dec3ff071 100644 --- a/rtdata/profiles/neutral.pp3 +++ b/rtdata/profiles/neutral.pp3 @@ -1,177 +1,177 @@ - -[Version] -Version=20101019 - -[Exposure] -Auto=false -Clip=0.001 -Compensation=0 -Brightness=0 -Contrast=0 -Black=0 -HighlightCompr=0 -ShadowCompr=0 -Curve=0; - -[Channel Mixer] -Red=100;0;0; -Green=0;100;0; -Blue=0;0;100; - -[Luminance Curve] -Brightness=0 -Contrast=0 -Saturation=0 -LCurve=0; -aCurve=0; -bCurve=0; - -[Sharpening] -Enabled=false -Method=usm -Radius=0.80000000000000004 -Amount=120 -Threshold=512 -OnlyEdges=false -EdgedetectionRadius=1.8999999999999999 -EdgeTolerance=1800 -HalocontrolEnabled=false -HalocontrolAmount=85 -DeconvRadius=0.75 -DeconvAmount=75 -DeconvDamping=20 -DeconvIterations=30 - -[Color Boost] -Amount=0 -AvoidColorClipping=false -SaturationLimiter=false -SaturationLimit=75 - -[White Balance] -Setting=Camera -Temperature=3737 -Green=0.90500000000000003 - -[Color Shift] -ChannelA=0 -ChannelB=0 - -[Impulse Denoising] -Enabled=false -Threshold=50 - -[Directional Pyramid Denoising] -Enabled=false -Luma=10 -Chroma=10 -Gamma=2 - -[Luminance Denoising] -Enabled=false -Radius=2.5 -EdgeTolerance=1500 - -[Chrominance Denoising] -Enabled=false -Amount=20 - -[Shadows & Highlights] -Enabled=false -HighQuality=false -Highlights=0 -HighlightTonalWidth=80 -Shadows=0 -ShadowTonalWidth=80 -LocalContrast=0 -Radius=30 - -[Crop] -Enabled=false -X=0 -Y=0 -W=4276 -H=2836 -FixedRatio=false -Ratio=3:2 -Orientation=Landscape -Guide=None - -[Coarse Transformation] -Rotate=0 -HorizontalFlip=false -VerticalFlip=false - -[Common Properties for Transformations] -AutoFill=true - -[Rotation] -Degree=0 - -[Distortion] -Amount=0 -UseLensFun=false - -[Perspective] -Horizontal=0 -Vertical=0 - -[CACorrection] -Red=0 -Blue=0 - -[Vignetting Correction] -Amount=0 -Radius=50 -Strength=1 -CenterX=0 -CenterY=0 - -[HLRecovery] -Enabled=false -Method=CIELab blending - -[Resize] -Enabled=false -Scale=1 -Method=Bicubic -DataSpecified=0 -Width=4276 -Height=2836 - -[Color Management] -InputProfile=(camera) -ApplyGammaBeforeInputProfile=false -WorkingProfile=sRGB -OutputProfile=No ICM: sRGB output - -[Equalizer] -Enabled=false -C0=0 -C1=0 -C2=0 -C3=0 -C4=0 -C5=0 -C6=0 -C7=0 - -[Directional Pyramid Equalizer] -Enabled=false -Mult0=1 -Mult1=1 -Mult2=1 -Mult3=1 -Mult4=0 - -[RAW] -DarkFrame= -DarkFrameAuto=false -CA=false -HotDeadPixels=false -LineDenoise=0 -GreenEqThreshold=0 -CcSteps=1 -Method=amaze -DCBIterations=2 -DCBEnhance=false +[Version] +Version=20101019 + +[Exposure] +Auto=false +Clip=0.001 +Compensation=0 +Brightness=0 +Contrast=0 +Saturation=0 +Black=0 +HighlightCompr=0 +ShadowCompr=0 +Curve=0; + +[Channel Mixer] +Red=100;0;0; +Green=0;100;0; +Blue=0;0;100; + +[Luminance Curve] +Brightness=0 +Contrast=0 +Saturation=0 +LCurve=0; +aCurve=0; +bCurve=0; + +[Sharpening] +Enabled=false +Method=usm +Radius=0.8 +Amount=120 +Threshold=512 +OnlyEdges=false +EdgedetectionRadius=1.9 +EdgeTolerance=1800 +HalocontrolEnabled=false +HalocontrolAmount=85 +DeconvRadius=0.75 +DeconvAmount=75 +DeconvDamping=20 +DeconvIterations=30 + +[Color Boost] +Amount=0 +AvoidColorClipping=false +SaturationLimiter=false +SaturationLimit=75 + +[White Balance] +Setting=Camera +Temperature=5200 +Green=1.0 + +[Color Shift] +ChannelA=0 +ChannelB=0 + +[Impulse Denoising] +Enabled=false +Threshold=50 + +[Directional Pyramid Denoising] +Enabled=false +Luma=10 +Chroma=10 +Gamma=2 + +[Luminance Denoising] +Enabled=false +Radius=2.5 +EdgeTolerance=1500 + +[Chrominance Denoising] +Enabled=false +Amount=20 + +[Shadows & Highlights] +Enabled=false +HighQuality=false +Highlights=0 +HighlightTonalWidth=80 +Shadows=0 +ShadowTonalWidth=80 +LocalContrast=0 +Radius=30 + +[Crop] +Enabled=false +X=0 +Y=0 +W=4276 +H=2836 +FixedRatio=false +Ratio=3:2 +Orientation=Landscape +Guide=None + +[Coarse Transformation] +Rotate=0 +HorizontalFlip=false +VerticalFlip=false + +[Common Properties for Transformations] +AutoFill=true + +[Rotation] +Degree=0 + +[Distortion] +Amount=0 +UseLensFun=false + +[Perspective] +Horizontal=0 +Vertical=0 + +[CACorrection] +Red=0 +Blue=0 + +[Vignetting Correction] +Amount=0 +Radius=50 +Strength=1 +CenterX=0 +CenterY=0 + +[HLRecovery] +Enabled=false +Method=CIELab blending + +[Resize] +Enabled=false +Scale=1 +Method=Bicubic +DataSpecified=0 +Width=4276 +Height=2836 + +[Color Management] +InputProfile=(camera) +ApplyGammaBeforeInputProfile=false +WorkingProfile=sRGB +OutputProfile=No ICM: sRGB output + +[Equalizer] +Enabled=false +C0=0 +C1=0 +C2=0 +C3=0 +C4=0 +C5=0 +C6=0 +C7=0 + +[Directional Pyramid Equalizer] +Enabled=false +Mult0=1 +Mult1=1 +Mult2=1 +Mult3=1 +Mult4=0 + +[RAW] +DarkFrame= +DarkFrameAuto=false +CA=false +HotDeadPixels=false +LineDenoise=0 +GreenEqThreshold=0 +CcSteps=1 +Method=amaze +DCBIterations=2 +DCBEnhance=false diff --git a/rtengine/curves.cc b/rtengine/curves.cc index f03d76752..7fb025de2 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -691,7 +691,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou brightcurve = new Curve (brightcurvePoints, CURVES_MIN_POLY_POINTS/skip); // Actually, CURVES_MIN_POLY_POINTS = 1000, //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - for (int i=0; i<=0xffff; i+= i<0xffff-skip ? skip : 1 ) { + for (int i=0; i<=0xffff; i++) { // change to [0,1] range double val = (double)i / 65535.0; @@ -713,10 +713,13 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou val = basecurve (val, 1, black, def_mul, 1, 1.5*shcompr/100.0); shCurve[i] = (int) (65535.0 * CLIPD(val)); + } //%%%%%%%%%%%%%%%%%%%%%%%%%% + for (int i=0; i<=0xffff; i+= i<0xffff-skip ? skip : 1 ) { + // change to [0,1] range - val = (double)i / 65535.0; + double val = (double)i / 65535.0; // gamma correction if (gamma_>0) @@ -729,7 +732,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou // apply custom/parametric/NURBS curve, if any if (tcurve) { if (outBeforeCCurveHistogram) { - double hval = val; + double hval = brightcurve->getVal (shCurve[hlCurve[(int)val]]); //if (needigamma) // hval = igamma2 (hval); int hi = (int)(255.0*CLIPD(hval)); @@ -757,8 +760,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou prev+=skip; continue; } - hlCurve[i] = ( hlCurve[prev] * (skip - i%skip) + hlCurve[prev+skip] * (i%skip) ) / skip; - shCurve[i] = ( shCurve[prev] * (skip - i%skip) + shCurve[prev+skip] * (i%skip) ) / skip; dcurve[i] = ( dcurve[prev] * (skip - i%skip) + dcurve[prev+skip] * (i%skip) ) / skip; } @@ -768,29 +769,26 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou double avg = 0; //double sqavg = 0; for (int i=0; i<=0xffff; i++) { - avg += dcurve[i] * histogram[i]; + avg += dcurve[shCurve[hlCurve[i]]] * histogram[i]; //sqavg += dcurve[i]*dcurve[i] * histogram[i]; sum += histogram[i]; } avg /= sum; //sqavg /= sum; //double stddev = sqrt(sqavg-avg*avg); - float contrslope = (50)/(50-0.25*contr); + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% std::vector contrastcurvePoints; contrastcurvePoints.push_back((double)((CurveType)NURBS)); contrastcurvePoints.push_back(0); //black point. Value in [0 ; 1] range contrastcurvePoints.push_back(0); //black point. Value in [0 ; 1] range - - contrastcurvePoints.push_back(avg*(1-1/contrslope)); //toe point - contrastcurvePoints.push_back(0); //value at toe point - contrastcurvePoints.push_back(avg); //mid point - contrastcurvePoints.push_back(avg); //value at mid 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)/contrslope); // shoulder point - contrastcurvePoints.push_back(1); // 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 @@ -807,6 +805,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou val = igamma2 (val); outCurve[i] = (int) (65535.0 * CLIPD(val)); } + delete contrastcurve; } else for (int i=0; i<=0xffff; i++) diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index b272728ec..9776f606c 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -167,7 +167,7 @@ void Crop::update (int todo, bool internal) { // shadows & highlights & tone curve & convert to cielab if (todo & M_RGBCURVE) - parent->ipf.rgbProc (baseCrop, laboCrop, parent->hltonecurve, parent->shtonecurve, parent->tonecurve, cshmap); + parent->ipf.rgbProc (baseCrop, laboCrop, parent->hltonecurve, parent->shtonecurve, parent->tonecurve, cshmap, params.toneCurve.saturation); // apply luminance operations diff --git a/rtengine/green_equil_RT.cc b/rtengine/green_equil_RT.cc index e7f5a00e2..c4bbf1481 100644 --- a/rtengine/green_equil_RT.cc +++ b/rtengine/green_equil_RT.cc @@ -1,31 +1,18 @@ // CFA pixel cleaning via directional average -// by Emil Martinec +// © Emil Martinec // 2/18/2010 #define TS 256 // Tile size -#define CLASS -/*#define ushort UshORt - typedef unsigned char uchar; - typedef unsigned short ushort;*/ - -#include -#include -#include -#include -#include #include -#include -#include #include -#include #include #define SQR(x) ((x)*(x)) -//void CLASS green_equilibrate()//for dcraw implementation -void CLASS RawImageSource::green_equilibrate(float thresh) +//void green_equilibrate()//for dcraw implementation +void RawImageSource::green_equilibrate(float thresh) { // local variables static const int border=8; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 09f1c2227..0f92783c5 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -167,7 +167,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases); if (todo & M_RGBCURVE) { CurveFactory::complexCurve (params.toneCurve.expcomp, params.toneCurve.black/65535.0, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getDefGain(), imgsrc->getGamma(), true, params.toneCurve.curve, vhist16, hltonecurve, shtonecurve, tonecurve, bcrgbhist, scale==1 ? 1 : 1); - ipf.rgbProc (oprevi, oprevl, hltonecurve, shtonecurve, tonecurve, shmap); + ipf.rgbProc (oprevi, oprevl, hltonecurve, shtonecurve, tonecurve, shmap, params.toneCurve.saturation); // recompute luminance histogram memset (lhist16, 0, 65536*sizeof(int)); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index f1c36b898..466528b12 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -245,7 +245,7 @@ void ImProcFunctions::firstAnalysis (Image16* original, const ProcParams* params delete [] hist; } -void ImProcFunctions::rgbProc (Image16* working, LabImage* lab, int* hltonecurve, int* shtonecurve, int* tonecurve, SHMap* shmap) { +void ImProcFunctions::rgbProc (Image16* working, LabImage* lab, int* hltonecurve, int* shtonecurve, int* tonecurve, SHMap* shmap, int sat) { int h_th, s_th; if (shmap) { @@ -281,6 +281,7 @@ void ImProcFunctions::rgbProc (Image16* working, LabImage* lab, int* hltonecurve int tW = working->width; int tH = working->height; int r, g, b; + float h, s, v; #pragma omp parallel for private(r, g, b,factor,mapval) if (multiThread) for (int i=0; i0.5) { + rgb2hsv(r,g,b,h,s,v); + if (sat>0) { + s = (1-(float)sat/100)*s+(float)sat/100*(1-SQR(SQR(1-s))); + } else { + s *= 1+(float)sat/100; + } + hsv2rgb(h,s,v,r,g,b); + } int x = (toxyz[0][0] * r + toxyz[1][0] * g + toxyz[2][0] * b) >> 15; int y = (toxyz[0][1] * r + toxyz[1][1] * g + toxyz[2][1] * b) >> 15; @@ -574,5 +585,61 @@ void ImProcFunctions::getAutoExp (unsigned int* histogram, int histcompr, doubl if (br<0) br = 0; } + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void ImProcFunctions::rgb2hsv (int r, int g, int b, float &h, float &s, float &v) { + + double var_R = r / 65535.0; + double var_G = g / 65535.0; + double var_B = b / 65535.0; + + double var_Min = MIN(MIN(var_R,var_G),var_B); + double var_Max = MAX(MAX(var_R,var_G),var_B); + double del_Max = var_Max - var_Min; + v = var_Max; + if (fabs(del_Max)<0.00001) { + h = 0; + s = 0; + } + else { + s = del_Max/var_Max; + + if ( var_R == var_Max ) h = (var_G - var_B)/del_Max; + else if ( var_G == var_Max ) h = 2.0 + (var_B - var_R)/del_Max; + else if ( var_B == var_Max ) h = 4.0 + (var_R - var_G)/del_Max; + h /= 6.0; + + if ( h < 0 ) h += 1; + if ( h > 1 ) h -= 1; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void ImProcFunctions::hsv2rgb (float h, float s, float v, int &r, int &g, int &b) { + + float h1 = h*6; // sector 0 to 5 + int i = floor( h1 ); + float f = h1 - i; // fractional part of h + + float p = v * ( 1 - s ); + float q = v * ( 1 - s * f ); + float t = v * ( 1 - s * ( 1 - f ) ); + + float r1,g1,b1; + + if (i==0) {r1 = v; g1 = t; b1 = p;} + if (i==1) {r1 = q; g1 = v; b1 = p;} + if (i==2) {r1 = p; g1 = v; b1 = t;} + if (i==3) {r1 = p; g1 = q; b1 = v;} + if (i==4) {r1 = t; g1 = p; b1 = v;} + if (i==5) {r1 = v; g1 = p; b1 = q;} + + r = (int)((r1)*65535); + g = (int)((g1)*65535); + b = (int)((b1)*65535); +} + } diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index b8dc328ad..84c6dc99e 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -79,7 +79,7 @@ class ImProcFunctions { bool needsTransform (); void firstAnalysis (Image16* working, const ProcParams* params, unsigned int* vhist16, double gamma); - void rgbProc (Image16* working, LabImage* lab, int* hltonecurve, int* shtonecurve, int* tonecurve, SHMap* shmap); + void rgbProc (Image16* working, LabImage* lab, int* hltonecurve, int* shtonecurve, int* tonecurve, SHMap* shmap, int sat); void luminanceCurve (LabImage* lold, LabImage* lnew, int* curve, int row_from, int row_to); void chrominanceCurve (LabImage* lold, LabImage* lnew, int channel, int* curve, int row_from, int row_to); void colorCurve (LabImage* lold, LabImage* lnew); @@ -116,6 +116,9 @@ class ImProcFunctions { bool transCoord (int W, int H, std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1); void getAutoExp (unsigned int* histogram, int histcompr, double expcomp, double clip, double& br, int& bl); double getTransformAutoFill (int oW, int oH); + + void rgb2hsv (int r, int g, int b, float &h, float &s, float &v); + void hsv2rgb (float h, float s, float v, int &r, int &g, int &b); }; } #endif diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 9f2a2208e..f4bfc7420 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -121,7 +121,8 @@ enum ProcEvent { EvLbCurve=96, EvDemosaic=97, EvPreProcess=98, - NUMOFEVENTS=99 + EvSaturation=99, + NUMOFEVENTS=100 }; } #endif diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 30d59dd0a..44faaf8d4 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -52,6 +52,7 @@ void ProcParams::setDefaults () { toneCurve.expcomp = 0; toneCurve.brightness = 0; toneCurve.contrast = 0; + toneCurve.saturation = 0; toneCurve.black = 0; toneCurve.hlcompr = 70; toneCurve.shcompr = 25; @@ -214,6 +215,7 @@ int ProcParams::save (Glib::ustring fname) const { keyFile.set_double ("Exposure", "Compensation", toneCurve.expcomp); keyFile.set_integer ("Exposure", "Brightness", toneCurve.brightness); keyFile.set_integer ("Exposure", "Contrast", toneCurve.contrast); + keyFile.set_integer ("Exposure", "Saturation", toneCurve.saturation); keyFile.set_integer ("Exposure", "Black", toneCurve.black); keyFile.set_integer ("Exposure", "HighlightCompr", toneCurve.hlcompr); keyFile.set_integer ("Exposure", "ShadowCompr", toneCurve.shcompr); @@ -443,7 +445,8 @@ if (keyFile.has_group ("Exposure")) { if (keyFile.has_key ("Exposure", "Compensation")) toneCurve.expcomp = keyFile.get_double ("Exposure", "Compensation"); if (keyFile.has_key ("Exposure", "Brightness")) toneCurve.brightness = keyFile.get_integer ("Exposure", "Brightness"); if (keyFile.has_key ("Exposure", "Contrast")) toneCurve.contrast = keyFile.get_integer ("Exposure", "Contrast"); - if (keyFile.has_key ("Exposure", "Black")) toneCurve.black = keyFile.get_integer ("Exposure", "Black"); + if (keyFile.has_key ("Exposure", "Saturation")) toneCurve.saturation = keyFile.get_integer ("Exposure", "Saturation"); + if (keyFile.has_key ("Exposure", "Black")) toneCurve.black = keyFile.get_integer ("Exposure", "Black"); if (keyFile.has_key ("Exposure", "HighlightCompr")) toneCurve.hlcompr = keyFile.get_integer ("Exposure", "HighlightCompr"); if (toneCurve.hlcompr > 100) toneCurve.hlcompr = 100; // older pp3 files can have values above 100. if (keyFile.has_key ("Exposure", "ShadowCompr")) toneCurve.shcompr = keyFile.get_integer ("Exposure", "ShadowCompr"); @@ -746,6 +749,7 @@ bool ProcParams::operator== (const ProcParams& other) { && toneCurve.brightness == other.toneCurve.brightness && toneCurve.black == other.toneCurve.black && toneCurve.contrast == other.toneCurve.contrast + && toneCurve.saturation == other.toneCurve.saturation && toneCurve.shcompr == other.toneCurve.shcompr && toneCurve.hlcompr == other.toneCurve.hlcompr && toneCurve.autoexp == other.toneCurve.autoexp diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 3b10d032a..095eae1d0 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -38,6 +38,7 @@ class ToneCurveParams { int brightness; int black; int contrast; + int saturation; int shcompr; int hlcompr; }; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 500e3757c..cd31c28df 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -118,6 +118,7 @@ DIRPYREQUALIZER, // EvDirPyrEqualizer, DIRPYREQUALIZER, // EvDirPyrEqlEnabled, LUMINANCECURVE, // EvLSaturation, LUMINANCECURVE, // EvLaCurve, -LUMINANCECURVE, // EvLbCurve +LUMINANCECURVE, // EvLbCurve, +RGBCURVE, // EvSaturation, }; diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index f60f7a37a..f2b12b8c6 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -406,7 +406,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, logDefGain, isRaw ? 2.2 : 0, true, params.toneCurve.curve, hist16, curve1, curve2, curve, NULL, 16); LabImage* labView = new LabImage (baseImg); - ipf.rgbProc (baseImg, labView, curve1, curve2, curve, shmap); + ipf.rgbProc (baseImg, labView, curve1, curve2, curve, shmap, params.toneCurve.saturation); if (shmap) delete shmap; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index d102a0101..0f28e868b 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -135,7 +135,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getDefGain(), imgsrc->getGamma(), true, params.toneCurve.curve, hist16, curve1, curve2, curve, NULL); LabImage* labView = new LabImage (baseImg); - ipf.rgbProc (baseImg, labView, curve1, curve2, curve, shmap); + ipf.rgbProc (baseImg, labView, curve1, curve2, curve, shmap, params.toneCurve.saturation); if (shmap) delete shmap; diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 80d23c3b1..e28a366e5 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -23,9 +23,9 @@ #define ADDSET_CA 19 #define ADDSET_VIGN_AMOUNT 20 #define ADDSET_LC_SATURATION 21 +#define ADDSET_TC_SATURATION 22 // When adding items, make sure to update ADDSET_PARAM_NUM -#define ADDSET_PARAM_NUM 22 // THIS IS USED AS A DELIMITER!! - +#define ADDSET_PARAM_NUM 23 // THIS IS USED AS A DELIMITER!! #endif diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index a4fe97d94..5a3bb7167 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -120,7 +120,7 @@ void BatchToolPanelCoordinator::initSession () { pparams = selected[0]->getProcParams (); coarse->initBatchBehavior (); - curve->setAdjusterBehavior (options.baBehav[ADDSET_TC_EXPCOMP], options.baBehav[ADDSET_TC_BRIGHTNESS], options.baBehav[ADDSET_TC_BLACKLEVEL], options.baBehav[ADDSET_TC_CONTRAST]); + curve->setAdjusterBehavior (options.baBehav[ADDSET_TC_EXPCOMP], options.baBehav[ADDSET_TC_BRIGHTNESS], options.baBehav[ADDSET_TC_BLACKLEVEL], options.baBehav[ADDSET_TC_CONTRAST], options.baBehav[ADDSET_TC_SATURATION]); lcurve->setAdjusterBehavior (options.baBehav[ADDSET_LC_BRIGHTNESS], options.baBehav[ADDSET_LC_CONTRAST], options.baBehav[ADDSET_LC_SATURATION]); whitebalance->setAdjusterBehavior (options.baBehav[ADDSET_WB_TEMPERATURE], options.baBehav[ADDSET_WB_GREEN]); vignetting->setAdjusterBehavior (options.baBehav[ADDSET_VIGN_AMOUNT]); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 1e11e93bb..763cae160 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -32,6 +32,7 @@ void ParamsEdited::set (bool v) { toneCurve.brightness = v; toneCurve.black = v; toneCurve.contrast = v; + toneCurve.saturation = v; toneCurve.shcompr = v; toneCurve.hlcompr = v; toneCurve.autoexp = v; @@ -163,7 +164,8 @@ void ParamsEdited::initFrom (const std::vector toneCurve.brightness = toneCurve.brightness && p.toneCurve.brightness == other.toneCurve.brightness; toneCurve.black = toneCurve.black && p.toneCurve.black == other.toneCurve.black; toneCurve.contrast = toneCurve.contrast && p.toneCurve.contrast == other.toneCurve.contrast; - toneCurve.shcompr = toneCurve.shcompr && p.toneCurve.shcompr == other.toneCurve.shcompr; + toneCurve.saturation = toneCurve.saturation && p.toneCurve.saturation == other.toneCurve.saturation; + toneCurve.shcompr = toneCurve.shcompr && p.toneCurve.shcompr == other.toneCurve.shcompr; toneCurve.hlcompr = toneCurve.hlcompr && p.toneCurve.hlcompr == other.toneCurve.hlcompr; toneCurve.autoexp = toneCurve.autoexp && p.toneCurve.autoexp == other.toneCurve.autoexp; toneCurve.clip = toneCurve.clip && p.toneCurve.clip == other.toneCurve.clip; @@ -295,6 +297,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (toneCurve.brightness) toEdit.toneCurve.brightness = options.baBehav[ADDSET_TC_BRIGHTNESS] ? toEdit.toneCurve.brightness + mods.toneCurve.brightness : mods.toneCurve.brightness; if (toneCurve.black) toEdit.toneCurve.black = options.baBehav[ADDSET_TC_BLACKLEVEL] ? toEdit.toneCurve.black + mods.toneCurve.black : mods.toneCurve.black; if (toneCurve.contrast) toEdit.toneCurve.contrast = options.baBehav[ADDSET_TC_CONTRAST] ? toEdit.toneCurve.contrast + mods.toneCurve.contrast : mods.toneCurve.contrast; + if (toneCurve.saturation) toEdit.toneCurve.saturation = options.baBehav[ADDSET_TC_SATURATION] ? toEdit.toneCurve.saturation + mods.toneCurve.saturation : mods.toneCurve.saturation; if (toneCurve.shcompr) toEdit.toneCurve.shcompr = mods.toneCurve.shcompr; if (toneCurve.hlcompr) toEdit.toneCurve.hlcompr = mods.toneCurve.hlcompr; if (toneCurve.autoexp) toEdit.toneCurve.autoexp = mods.toneCurve.autoexp; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 4e7f745c8..a70f26886 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -31,7 +31,8 @@ class ToneCurveParamsEdited { bool brightness; bool black; bool contrast; - bool shcompr; + bool saturation; + bool shcompr; bool hlcompr; bool autoexp; bool clip; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index cceb47ed2..ba297680e 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -133,6 +133,7 @@ Gtk::Widget* Preferences::getBatchProcPanel () { appendBehavList (mi, M("TP_EXPOSURE_BRIGHTNESS"), ADDSET_TC_BRIGHTNESS, false); appendBehavList (mi, M("TP_EXPOSURE_BLACKLEVEL"), ADDSET_TC_BLACKLEVEL, false); appendBehavList (mi, M("TP_EXPOSURE_CONTRAST"), ADDSET_TC_CONTRAST, false); + appendBehavList (mi, M("TP_EXPOSURE_SATURATION"), ADDSET_TC_SATURATION, false); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_SHADOWSHLIGHTS_LABEL")); diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index 01359dde3..5fae69720 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -67,7 +67,8 @@ ToneCurve::ToneCurve () : ToolPanel(), expAdd(false), blackAdd(false), brAdd(fal pack_start (*brightness); contrast = Gtk::manage (new Adjuster (M("TP_EXPOSURE_CONTRAST"), -100, 100, 1, 0)); pack_start (*contrast); - + saturation = Gtk::manage (new Adjuster (M("TP_EXPOSURE_SATURATION"), -100, 100, 1, 0)); + pack_start (*saturation); //----------- Curve ------------------------------ pack_start (*Gtk::manage (new Gtk::HSeparator())); @@ -91,6 +92,7 @@ ToneCurve::ToneCurve () : ToolPanel(), expAdd(false), blackAdd(false), brAdd(fal hlcompr->setAdjusterListener (this); shcompr->setAdjusterListener (this); contrast->setAdjusterListener (this); + saturation->setAdjusterListener (this); } void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { @@ -104,7 +106,8 @@ void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { shcompr->setEditedState (pedited->toneCurve.shcompr ? Edited : UnEdited); brightness->setEditedState (pedited->toneCurve.brightness ? Edited : UnEdited); contrast->setEditedState (pedited->toneCurve.contrast ? Edited : UnEdited); - autolevels->set_inconsistent (!pedited->toneCurve.autoexp); + saturation->setEditedState (pedited->toneCurve.saturation ? Edited : UnEdited); + autolevels->set_inconsistent (!pedited->toneCurve.autoexp); clipDirty = pedited->toneCurve.clip; shape->setUnChanged (!pedited->toneCurve.curve); } @@ -121,7 +124,8 @@ void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { shcompr->setValue (pp->toneCurve.shcompr); brightness->setValue (pp->toneCurve.brightness); contrast->setValue (pp->toneCurve.contrast); - shape->setCurve (pp->toneCurve.curve); + saturation->setValue (pp->toneCurve.saturation); + shape->setCurve (pp->toneCurve.curve); enableListener (); } @@ -136,6 +140,7 @@ void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) { pp->toneCurve.shcompr = (int)shcompr->getValue (); pp->toneCurve.brightness = (int)brightness->getValue (); pp->toneCurve.contrast = (int)contrast->getValue (); + pp->toneCurve.saturation = (int)saturation->getValue (); pp->toneCurve.curve = shape->getCurve (); if (pedited) { @@ -145,7 +150,8 @@ void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) { pedited->toneCurve.shcompr = shcompr->getEditedState (); pedited->toneCurve.brightness = brightness->getEditedState (); pedited->toneCurve.contrast = contrast->getEditedState (); - pedited->toneCurve.autoexp = !autolevels->get_inconsistent(); + pedited->toneCurve.saturation = saturation->getEditedState (); + pedited->toneCurve.autoexp = !autolevels->get_inconsistent(); pedited->toneCurve.clip = clipDirty; pedited->toneCurve.curve = !shape->isUnChanged (); } @@ -159,6 +165,7 @@ void ToneCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pe hlcompr->setDefault (defParams->toneCurve.hlcompr); shcompr->setDefault (defParams->toneCurve.shcompr); contrast->setDefault (defParams->toneCurve.contrast); + saturation->setDefault (defParams->toneCurve.saturation); if (pedited) { expcomp->setDefaultEditedState (pedited->toneCurve.expcomp ? Edited : UnEdited); @@ -167,6 +174,7 @@ void ToneCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pe shcompr->setDefaultEditedState (pedited->toneCurve.shcompr ? Edited : UnEdited); brightness->setDefaultEditedState (pedited->toneCurve.brightness ? Edited : UnEdited); contrast->setDefaultEditedState (pedited->toneCurve.contrast ? Edited : UnEdited); + saturation->setDefaultEditedState (pedited->toneCurve.saturation ? Edited : UnEdited); } else { expcomp->setDefaultEditedState (Irrelevant); @@ -175,6 +183,7 @@ void ToneCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pe shcompr->setDefaultEditedState (Irrelevant); brightness->setDefaultEditedState (Irrelevant); contrast->setDefaultEditedState (Irrelevant); + saturation->setDefaultEditedState (Irrelevant); } } @@ -209,6 +218,8 @@ void ToneCurve::adjusterChanged (Adjuster* a, double newval) { listener->panelChanged (EvBlack, costr); else if (a==contrast) listener->panelChanged (EvContrast, costr); + else if (a==saturation) + listener->panelChanged (EvSaturation, costr); else if (a==hlcompr) listener->panelChanged (EvHLCompr, costr); else if (a==shcompr) @@ -272,6 +283,7 @@ void ToneCurve::waitForAutoExp () { hlcompr->setEnabled (false); shcompr->setEnabled (false); contrast->setEnabled (false); + saturation->setEnabled (false); curveEditorG->set_sensitive (false); } @@ -301,6 +313,7 @@ void ToneCurve::enableAll () { hlcompr->setEnabled (true); shcompr->setEnabled (true); contrast->setEnabled (true); + saturation->setEnabled (true); curveEditorG->set_sensitive (true); } @@ -329,11 +342,12 @@ void ToneCurve::setBatchMode (bool batchMode) { shcompr->showEditedCB (); brightness->showEditedCB (); contrast->showEditedCB (); - + saturation->showEditedCB (); + curveEditorG->setBatchMode (batchMode); } -void ToneCurve::setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, bool contradd) { +void ToneCurve::setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, bool contradd, bool satadd) { if ((!expAdd && expadd) || (expAdd && !expadd)) expcomp->setLimits (-5, 5, 0.01, 0); @@ -345,11 +359,14 @@ void ToneCurve::setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, boo brightness->setLimits (-100, 100, 1, 0); if ((!contrAdd && contradd) || (contrAdd && !contradd)) contrast->setLimits (-100, 100, 1, 0); - + if ((!satAdd && satadd) || (satAdd && !satadd)) + saturation->setLimits (-100, 100, 1, 0); + expAdd = expadd; blackAdd = blackadd; brAdd = bradd; contrAdd = contradd; + satAdd = satadd; } void ToneCurve::updateCurveBackgroundHistogram (unsigned* hist) { diff --git a/rtgui/tonecurve.h b/rtgui/tonecurve.h index 6af309cc1..0f3ed8eff 100644 --- a/rtgui/tonecurve.h +++ b/rtgui/tonecurve.h @@ -38,7 +38,9 @@ class ToneCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, p Adjuster* hlcompr; Adjuster* shcompr; Adjuster* contrast; - bool expAdd, blackAdd, brAdd, contrAdd, clipDirty, lastAuto; + Adjuster* saturation; + + bool expAdd, blackAdd, brAdd, contrAdd, satAdd, clipDirty, lastAuto; sigc::connection autoconn; CurveEditorGroup* curveEditorG; CurveEditor* shape; @@ -53,7 +55,7 @@ class ToneCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, p void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); void setBatchMode (bool batchMode); - void setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, bool contradd); + void setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, bool contradd, bool satadd); void adjusterChanged (Adjuster* a, double newval); void autolevels_toggled ();