diff --git a/rtdata/languages/default b/rtdata/languages/default index aa0be0a9f..54742eea6 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1338,10 +1338,22 @@ HISTORY_MSG_HLBL;Color propagation - blur HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D HISTORY_MSG_ICM_OUTPUT_TYPE;Output - Type -HISTORY_MSG_ICM_WORKING_GAMMA;Working - Gamma -HISTORY_MSG_ICM_WORKING_SLOPE;Working - Slope -HISTORY_MSG_ICM_WORKING_TRC_METHOD;Working - TRC method +HISTORY_MSG_ICM_WORKING_GAMMA;TRC - Gamma +HISTORY_MSG_ICM_WORKING_SLOPE;TRC - Slope +HISTORY_MSG_ICM_WORKING_TRC_METHOD;TRC method +HISTORY_MSG_ICM_WORKING_ILLUM_METHOD;Illuminant method +HISTORY_MSG_ICM_WORKING_PRIM_METHOD;Primaries method +HISTORY_MSG_ICM_REDX;Primaries Red X +HISTORY_MSG_ICM_REDY;Primaries Red Y +HISTORY_MSG_ICM_GREX;Primaries Green X +HISTORY_MSG_ICM_GREY;Primaries Green Y +HISTORY_MSG_ICM_BLUX;Primaries Blue X +HISTORY_MSG_ICM_BLUY;Primaries Blue Y +HISTORY_MSG_ICL_LABGRIDCIEXY;Cie xy +HISTORY_MSG_ICM_AINTENT;Abstract profile intent HISTORY_MSG_ILLUM;Illuminant +HISTORY_MSG_ICM_FBW;Black and White +HISTORY_MSG_ICM_PRESER;Preserve neutral HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness HISTORY_MSG_LOCALCONTRAST_ENABLED;Local Contrast @@ -2402,10 +2414,14 @@ TP_ICM_APPLYHUESATMAP;Base table TP_ICM_APPLYHUESATMAP_TOOLTIP;Employ the embedded DCP base table (HueSatMap). The setting is only available if the selected DCP has one. TP_ICM_APPLYLOOKTABLE;Look table TP_ICM_APPLYLOOKTABLE_TOOLTIP;Employ the embedded DCP look table. The setting is only available if the selected DCP has one. +TP_ICM_BLUFRAME;Blue Primaries TP_ICM_BPC;Black Point Compensation TP_ICM_DCPILLUMINANT;Illuminant TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolated TP_ICM_DCPILLUMINANT_TOOLTIP;Select which embedded DCP illuminant to employ. Default is "interpolated" which is a mix between the two based on white balance. The setting is only available if a dual-illuminant DCP with interpolation support is selected. +TP_ICM_FBW;Black-and-White +TP_ICM_GREFRAME;Green Primaries +TP_ICM_ILLUMPRIM_TOOLTIP;Choose the illuminant closest to the shooting conditions.\nChanges can only be made when the ‘Destination primaries’ selection is set to ‘Custom (sliders)’. TP_ICM_INPUTCAMERA;Camera standard TP_ICM_INPUTCAMERAICC;Auto-matched camera profile TP_ICM_INPUTCAMERAICC_TOOLTIP;Use RawTherapee's camera-specific DCP or ICC input color profiles. These profiles are more precise than simpler matrix ones. They are not available for all cameras. These profiles are stored in the /iccprofiles/input and /dcpprofiles folders and are automatically retrieved based on a file name matching to the exact model name of the camera. @@ -2418,22 +2434,66 @@ TP_ICM_INPUTEMBEDDED_TOOLTIP;Use color profile embedded in non-raw files. TP_ICM_INPUTNONE;No profile TP_ICM_INPUTNONE_TOOLTIP;Use no input color profile at all.\nUse only in special cases. TP_ICM_INPUTPROFILE;Input Profile -TP_ICM_LABEL;Color Management +TP_ICM_LABEL;Color Management +TP_ICM_LABGRID_CIEXY;R(x)=%1 R(y)=%2\nG(x)=%3 G(y)=%4\nB(x)=%5 B(y)=%6 TP_ICM_NOICM;No ICM: sRGB Output TP_ICM_OUTPUTPROFILE;Output Profile +TP_ICM_OUTPUTPROFILE_TOOLTIP;By default all RTv4 or RTv2 profiles are with TRC - sRGB: g=2.4 s=12.92\n\nWith 'ICC Profile Creator' you can generate v4 or v2 profiles with the following choices;\n-Primaries: Aces AP0, Aces AP1, AdobeRGB, Prophoto, Rec2020, sRGB, Widegamut, BestRGB, BetaRGB, BruceRGB, Custom\n-TRC: BT709, sRGB, linear, standard g=2.2, standard g=1.8, Custom\n-Illuminant: D41, D50, D55, D60, D65, D80, stdA 2856K +TP_ICM_PRIMRED_TOOLTIP;Primaries Red:\nsRGB x=0.64 y=0.33\nAdobe x=0.64 y=0.33\nWidegamut x=0.735 y=0.265\nRec2020 x=0.708 y=0.292\nACES P1 x=0.713 y= 0.293\nACES P0 x=0.7347 y=0.2653\nProphoto x=0.7347 y=0.2653\nBruceRGB x=0.64 y=0.33\nBeta RGB x=0.688 y=0.3112\nBestRGB x=0.7347 y=0.2653 +TP_ICM_PRIMGRE_TOOLTIP;Primaries Green:\nsRGB x=0.3 y=0.6\nAdobe x=0.21 y=0.71\nWidegamut x=0.115 y=0.826\nRec2020 x=0.17 y=0.797\nACES P1 x=0.165 y= 0.83\nACES P0 x=0.0 y=1.0\nProphoto x=0.1596 y=0.8404\nBruceRGB x=0.28 y=0.65\nBeta RGB x=0.1986 y=0.7551\nBest RGB x=0.2150 0.7750 +TP_ICM_PRIMBLU_TOOLTIP;Primaries Blue:\nsRGB x=0.15 y=0.06\nAdobe x=0.15 y=0.06\nWidegamut x=0.157 y=0.018\nRec2020 x=0.131 y=0.046\nACES P1 x=0.128 y= 0.044\nACES P0 x=0.0001 y=-0.077\nProphoto x=0.0366 y=0.0001\nBruceRGB x=0.15 y=0.06\nBeta RGB x=0.1265 y=0.0352\nBestRGB x=0.131 y=0.046 TP_ICM_PROFILEINTENT;Rendering Intent +TP_ICM_REDFRAME;Custom Primaries TP_ICM_SAVEREFERENCE;Save Reference Image TP_ICM_SAVEREFERENCE_APPLYWB;Apply white balance TP_ICM_SAVEREFERENCE_APPLYWB_TOOLTIP;Generally, apply the white balance when saving images to create ICC profiles, and do not apply the white balance to create DCP profiles. TP_ICM_SAVEREFERENCE_TOOLTIP;Save the linear TIFF image before the input profile is applied. The result can be used for calibration purposes and generation of a camera profile. TP_ICM_TONECURVE;Tone curve TP_ICM_TONECURVE_TOOLTIP;Employ the embedded DCP tone curve. The setting is only available if the selected DCP has a tone curve. +TP_ICM_TRCFRAME;Abstract Profile +TP_ICM_TRCFRAME_TOOLTIP;Also known as ‘synthetic’ or ‘virtual’ profiles, which are applied at the end of the processing pipeline (prior to ciecam) allowing you to create custom image effects.\nYou can make changes to the:\n ‘Tone response curve’, which modifies the tones of the image.\n ‘Illuminant’ : which allows you to change the profile primaries to adapt them to the shooting conditions.\n ‘Destination primaries’: which allows you to change the destination primaries with two main uses - channel mixer and calibration.\nNote: Abstract profiles take into account the built-in Working profiles without modifying them. They do not work with custom Working profiles. +TP_ICM_WORKING_CIEDIAG;CIE xy diagram TP_ICM_WORKINGPROFILE;Working Profile +TP_ICM_WORKING_PRESER;Preserves Pastel tones TP_ICM_WORKING_TRC;Tone response curve: +TP_ICM_WORKING_TRC_BT709;BT709 g=2.22 s=4.5 +TP_ICM_WORKING_TRC_SRGB;sRGB g=2.4 s=12.92 +TP_ICM_WORKING_TRC_22;Adobe g=2.2 +TP_ICM_WORKING_TRC_18;Prophoto g=1.8 +TP_ICM_WORKING_TRC_LIN;Linear g=1 TP_ICM_WORKING_TRC_CUSTOM;Custom TP_ICM_WORKING_TRC_GAMMA;Gamma TP_ICM_WORKING_TRC_NONE;None TP_ICM_WORKING_TRC_SLOPE;Slope +TP_ICM_TRC_TOOLTIP;Allows you to change the default sRGB ‘Tone response curve’ in RT (g=2.4 s=12.92).\nThis TRC modifies the tones of the image. The RGB and Lab values, histogram and output (screen, TIF, JPG) are changed:\n-Gamma acts mainly on light tones -Slope acts mainly on dark tones.\nYou can choose any pair of 'gamma and slope' (values >1) and the algorithm will ensure that there is continuity between the linear and parabolic parts of the curve.\nA selection other than 'none' activates the 'Illuminant' and 'Destination primaries' menus. +TP_ICM_WORKING_ILLU;Illuminant +TP_ICM_WORKING_ILLU_NONE;Default +TP_ICM_WORKING_ILLU_D41;D41 +TP_ICM_WORKING_ILLU_D50;D50 +TP_ICM_WORKING_ILLU_D55;D55 +TP_ICM_WORKING_ILLU_D60;D60 +TP_ICM_WORKING_ILLU_D65;D65 +TP_ICM_WORKING_ILLU_D80;D80 +TP_ICM_WORKING_ILLU_D120;D120 +TP_ICM_WORKING_ILLU_STDA;stdA 2875K +TP_ICM_WORKING_ILLU_2000;Tungsten 2000K +TP_ICM_WORKING_ILLU_1500;Tungsten 1500K +TP_ICM_WORKING_PRIM;Destination primaries +TP_ICM_PRIMILLUM_TOOLTIP;You can change an image from its original mode (‘working profile’) to a different mode (‘destination primaries’). When you choose a different color mode for an image, you permanently change the color values in the image.\n\nChanging the ‘primaries’ is quite complex and difficult to use. It requires a lot of experimenting.\n It is capable of making exotic color adjustments as Channel Mixer primaries.\n Allows you to modify the camera calibration with Custom (sliders). +TP_ICM_WORKING_PRIM_NONE;Default +TP_ICM_WORKING_PRIM_SRGB;sRGB +TP_ICM_WORKING_PRIM_ADOB;Adobe RGB +TP_ICM_WORKING_PRIM_PROP;ProPhoto +TP_ICM_WORKING_PRIM_REC;Rec2020 +TP_ICM_WORKING_PRIM_ACE;ACESp1 +TP_ICM_WORKING_PRIM_WID;WideGamut +TP_ICM_WORKING_PRIM_AC0;ACESp0 +TP_ICM_WORKING_PRIM_BRU;BruceRGB +TP_ICM_WORKING_PRIM_BET;Beta RGB +TP_ICM_WORKING_PRIM_BST;BestRGB +TP_ICM_WORKING_PRIM_CUS;Custom (sliders) +TP_ICM_WORKING_PRIM_CUSGR;Custom (CIE xy Diagram) +TP_ICM_WORKING_PRIMFRAME_TOOLTIP;When ‘Custom CIE xy diagram’ is selected in ‘Destination- primaries’’ combobox, you can modify the values of the 3 primaries directly on the graph.\nNote that in this case, the white point position on the graph will not be updated. TP_ICM_WORKING_TRC_TOOLTIP;Only for built-in profiles. TP_IMPULSEDENOISE_LABEL;Impulse Noise Reduction TP_IMPULSEDENOISE_THRESH;Threshold @@ -3299,6 +3359,12 @@ TP_PREPROCWB_LABEL;Preprocess White Balance TP_PREPROCWB_MODE;Mode TP_PREPROCWB_MODE_AUTO;Auto TP_PREPROCWB_MODE_CAMERA;Camera +TC_PRIM_BLUX;Bx +TC_PRIM_BLUY;By +TC_PRIM_GREX;Gx +TC_PRIM_GREY;Gy +TC_PRIM_REDX;Rx +TC_PRIM_REDY;Ry TP_PRSHARPENING_LABEL;Post-Resize Sharpening TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. TP_RAWCACORR_AUTO;Auto-correction diff --git a/rtengine/color.cc b/rtengine/color.cc index 3fcd44eb8..d6c35208d 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -944,6 +944,7 @@ void Color::xyz2Prophoto (float x, float y, float z, float &r, float &g, float & g = ((prophoto_xyz[1][0] * x + prophoto_xyz[1][1] * y + prophoto_xyz[1][2] * z)) ; b = ((prophoto_xyz[2][0] * x + prophoto_xyz[2][1] * y + prophoto_xyz[2][2] * z)) ; } + void Color::Prophotoxyz (float r, float g, float b, float &x, float &y, float &z) { x = ((xyz_prophoto[0][0] * r + xyz_prophoto[0][1] * g + xyz_prophoto[0][2] * b)) ; diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 852ba0ba7..2641f8885 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -19,9 +19,11 @@ */ #include "cieimage.h" +#include "color.h" #include "curves.h" #include "dcp.h" #include "dcrop.h" +#include "guidedfilter.h" #include "image8.h" #include "imagefloat.h" #include "improccoordinator.h" @@ -30,9 +32,9 @@ #include "procparams.h" #include "refreshmap.h" #include "rt_math.h" -#include "color.h" +#include "utils.h" + #include "../rtgui/editcallbacks.h" -#include "guidedfilter.h" #pragma GCC diagnostic warning "-Wall" #pragma GCC diagnostic warning "-Wextra" @@ -278,7 +280,7 @@ void Crop::update(int todo) crW = 250; } - // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview + // if (settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview if (settings->leveldnv == 2) { crW = int (tileWskip / 2); } @@ -402,7 +404,7 @@ void Crop::update(int todo) crH = 250; } - // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview + // if (settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview if (settings->leveldnv == 2) { crW = int (tileWskip / 2); crH = int (tileHskip / 2); @@ -607,7 +609,7 @@ void Crop::update(int todo) //end evaluate noise } - // if(params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto + // if (params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { //reinit origCrop after Auto PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip); parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw); @@ -975,7 +977,7 @@ void Crop::update(int todo) double hlcomprthresh = params.locallab.spots.at(sp).hlcomprthresh; double shcompr = params.locallab.spots.at(sp).shcompr; double br = params.locallab.spots.at(sp).lightness; - if(black < 0. && params.locallab.spots.at(sp).expMethod == "pde" ) { + if (black < 0. && params.locallab.spots.at(sp).expMethod == "pde" ) { black *= 1.5; } @@ -1053,7 +1055,7 @@ void Crop::update(int todo) parent->previewDeltaE, parent->locallColorMask, parent->locallColorMaskinv, parent->locallExpMask, parent->locallExpMaskinv, parent->locallSHMask, parent->locallSHMaskinv, parent->locallvibMask, parent->localllcMask, parent->locallsharMask, parent->locallcbMask, parent->locallretiMask, parent->locallsoftMask, parent->localltmMask, parent->locallblMask, parent->localllogMask, parent->locall_Mask, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, meantme, stdtme, meanretie, stdretie); - if(parent->previewDeltaE || parent->locallColorMask == 5 || parent->locallvibMask == 4 || parent->locallExpMask == 5 || parent->locallSHMask == 4 || parent->localllcMask == 4 || parent->localltmMask == 4 || parent->localllogMask == 4 || parent->locallsoftMask == 6 || parent->localllcMask == 4) { + if (parent->previewDeltaE || parent->locallColorMask == 5 || parent->locallvibMask == 4 || parent->locallExpMask == 5 || parent->locallSHMask == 4 || parent->localllcMask == 4 || parent->localltmMask == 4 || parent->localllogMask == 4 || parent->locallsoftMask == 6 || parent->localllcMask == 4) { params.blackwhite.enabled = false; params.colorToning.enabled = false; params.rgbCurves.enabled = false; @@ -1137,20 +1139,6 @@ void Crop::update(int todo) if (todo & M_RGBCURVE) { Imagefloat *workingCrop = baseCrop; -/* - if (params.icm.workingTRC == "Custom") { //exec TRC IN free - const Glib::ustring profile = params.icm.workingProfile; - if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") { - const int cw = baseCrop->getWidth(); - const int ch = baseCrop->getHeight(); - workingCrop = new Imagefloat(cw, ch); - //first put gamma TRC to 1 - parent->ipf.workingtrc(baseCrop, workingCrop, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310, parent->getCustomTransformIn(), true, false, true); - //adjust gamma TRC - parent->ipf.workingtrc(workingCrop, workingCrop, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope, parent->getCustomTransformOut(), false, true, true); - } - } -*/ double rrm, ggm, bbm; DCPProfileApplyState as; DCPProfile *dcpProf = parent->imgsrc->getDCP(params.icm, as); @@ -1228,7 +1216,7 @@ void Crop::update(int todo) int minwin = min(labnCrop->W, labnCrop->H); int maxlevelcrop = 10; - // if(cp.mul[9]!=0)maxlevelcrop=10; + // if (cp.mul[9]!=0)maxlevelcrop=10; // adap maximum level wavelet to size of crop if (minwin * skip < 1024) { maxlevelcrop = 9; //sampling wavelet 512 @@ -1314,7 +1302,7 @@ void Crop::update(int todo) bool proton = WaveParams.exptoning; bool pronois = WaveParams.expnoise; - if(WaveParams.showmask) { + if (WaveParams.showmask) { // WaveParams.showmask = false; // WaveParams.expclari = true; } @@ -1441,7 +1429,7 @@ void Crop::update(int todo) } float indic = 1.f; - if(WaveParams.showmask){ + if (WaveParams.showmask){ mL0 = mC0 = -1.f; indic = -1.f; mL = fabs(mL); @@ -1476,6 +1464,50 @@ void Crop::update(int todo) parent->ipf.softLight(labnCrop, params.softlight); + if (params.icm.workingTRC != ColorManagementParams::WorkingTrc::NONE) { + const int GW = labnCrop->W; + const int GH = labnCrop->H; + std::unique_ptr provis; + const float pres = 0.01f * params.icm.preser; + if (pres > 0.f && params.icm.wprim != ColorManagementParams::Primaries::DEFAULT) { + provis.reset(new LabImage(GW, GH)); + provis->CopyFrom(labnCrop); + } + + const std::unique_ptr tmpImage1(new Imagefloat(GW, GH)); + + parent->ipf.lab2rgb(*labnCrop, *tmpImage1, params.icm.workingProfile); + + const float gamtone = parent->params->icm.workingTRCGamma; + const float slotone = parent->params->icm.workingTRCSlope; + + int illum = rtengine::toUnderlying(params.icm.will); + const int prim = rtengine::toUnderlying(params.icm.wprim); + + Glib::ustring prof = params.icm.workingProfile; + + cmsHTRANSFORM dummy = nullptr; + int ill = 0; + parent->ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false); + parent->ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, 5, prof, gamtone, slotone, illum, prim, dummy, false, true, true); + + parent->ipf.rgb2lab(*tmpImage1, *labnCrop, params.icm.workingProfile); + //labnCrop and provis + if (provis) { + parent->ipf.preserv(labnCrop, provis.get(), GW, GH); + } + if (params.icm.fbw) { +#ifdef _OPENMP + #pragma omp parallel for +#endif + for (int x = 0; x < GH; x++) + for (int y = 0; y < GW; y++) { + labnCrop->a[x][y] = 0.f; + labnCrop->b[x][y] = 0.f; + } + } + } + if (params.colorappearance.enabled) { float fnum = parent->imgsrc->getMetaData()->getFNumber(); // F number float fiso = parent->imgsrc->getMetaData()->getISOSpeed() ; // ISO @@ -1519,6 +1551,8 @@ void Crop::update(int todo) // all pipette buffer processing should be finished now PipetteBuffer::setReady(); + + // Computing the preview image, i.e. converting from lab->Monitor color space (soft-proofing disabled) or lab->Output profile->Monitor color space (soft-proofing enabled) parent->ipf.lab2monitorRgb(labnCrop, cropImg); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 71468fd8f..b3913103e 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -17,6 +17,7 @@ * along with RawTherapee. If not, see . */ #include + #include #include "improccoordinator.h" @@ -27,6 +28,7 @@ #include "colortemp.h" #include "curves.h" #include "dcp.h" +#include "guidedfilter.h" #include "iccstore.h" #include "image8.h" #include "imagefloat.h" @@ -35,7 +37,7 @@ #include "lcp.h" #include "procparams.h" #include "refreshmap.h" -#include "guidedfilter.h" +#include "utils.h" #include "../rtgui/options.h" @@ -600,16 +602,16 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) float max_r[nbw*nbh]; float max_b[nbw*nbh]; - if(denoiseParams.Lmethod == "CUR") { - if(noiseLCurve) + if (denoiseParams.Lmethod == "CUR") { + if (noiseLCurve) denoiseParams.luma = 0.5f; else denoiseParams.luma = 0.0f; - } else if(denoiseParams.Lmethod == "SLI") + } else if (denoiseParams.Lmethod == "SLI") noiseLCurve.Reset(); - if(noiseLCurve || noiseCCurve){//only allocate memory if enabled and scale=1 + if (noiseLCurve || noiseCCurve){//only allocate memory if enabled and scale=1 // we only need image reduced to 1/4 here calclum = new Imagefloat ((pW+1)/2, (pH+1)/2);//for luminance denoise curve for(int ii=0;iiicm.workingTRC == "Custom") { //exec TRC IN free - if (oprevi == orig_prev) { - oprevi = new Imagefloat(pW, pH); - orig_prev->copyData(oprevi); - } - const Glib::ustring profile = params->icm.workingProfile; - - if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") { - const int cw = oprevi->getWidth(); - const int ch = oprevi->getHeight(); - - // put gamma TRC to 1 - if (customTransformIn) { - cmsDeleteTransform(customTransformIn); - customTransformIn = nullptr; - } - - ipf.workingtrc(oprevi, oprevi, cw, ch, -5, params->icm.workingProfile, 2.4, 12.92310, customTransformIn, true, false, true); - - //adjust TRC - if (customTransformOut) { - cmsDeleteTransform(customTransformOut); - customTransformOut = nullptr; - } - - ipf.workingtrc(oprevi, oprevi, cw, ch, 5, params->icm.workingProfile, params->icm.workingTRCGamma, params->icm.workingTRCSlope, customTransformOut, false, true, true); - } - } - */ - } - - // if ((todo & (M_LUMINANCE + M_COLOR)) || (todo & M_AUTOEXP)) { - // if (todo & M_RGBCURVE) { - if (((todo & (M_AUTOEXP | M_RGBCURVE)) || (todo & M_CROP)) && params->locallab.enabled && !params->locallab.spots.empty()) { + if ((todo & (M_AUTOEXP | M_RGBCURVE | M_CROP)) && params->locallab.enabled && !params->locallab.spots.empty()) { ipf.rgb2lab(*oprevi, *oprevl, params->icm.workingProfile); @@ -920,11 +888,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) for (int sp = 0; sp < (int)params->locallab.spots.size(); sp++) { - if(params->locallab.spots.at(sp).equiltm && params->locallab.spots.at(sp).exptonemap) { + if (params->locallab.spots.at(sp).equiltm && params->locallab.spots.at(sp).exptonemap) { savenormtm.reset(new LabImage(*oprevl, true)); } - if(params->locallab.spots.at(sp).equilret && params->locallab.spots.at(sp).expreti) { + if (params->locallab.spots.at(sp).equilret && params->locallab.spots.at(sp).expreti) { savenormreti.reset(new LabImage(*oprevl, true)); } // Set local curves of current spot to LUT @@ -1034,7 +1002,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) float yend = 1.f; float xsta = 0.f; float xend = 1.f; - if(istm || isreti) { + if (istm || isreti) { locx = params->locallab.spots.at(sp).loc.at(0) / 2000.0; locy = params->locallab.spots.at(sp).loc.at(2) / 2000.0; locxl= params->locallab.spots.at(sp).loc.at(1) / 2000.0; @@ -1054,10 +1022,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) int yys = ysta * hh; int yye = yend * hh; - if(istm) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt + if (istm) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt ipf.mean_sig (nprevl->L, meantme, stdtme, xxs, xxe, yys, yye); } - if(isreti) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt + if (isreti) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt ipf.mean_sig (nprevl->L, meanretie, stdretie,xxs, xxe, yys, yye) ; } @@ -1146,20 +1114,20 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) - if(istm) { //calculate mean and sigma on full image for use by normalize_mean_dt + if (istm) { //calculate mean and sigma on full image for use by normalize_mean_dt float meanf = 0.f; float stdf = 0.f; - ipf.mean_sig (savenormtm.get()->L, meanf, stdf, xxs, xxe, yys, yye); + ipf.mean_sig (savenormtm->L, meanf, stdf, xxs, xxe, yys, yye); //using 2 unused variables noiselumc and softradiustm params->locallab.spots.at(sp).noiselumc = (int) meanf; params->locallab.spots.at(sp).softradiustm = stdf ; } - if(isreti) { //calculate mean and sigma on full image for use by normalize_mean_dt + if (isreti) { //calculate mean and sigma on full image for use by normalize_mean_dt float meanf = 0.f; float stdf = 0.f; - ipf.mean_sig (savenormreti.get()->L, meanf, stdf,xxs, xxe, yys, yye ); + ipf.mean_sig (savenormreti->L, meanf, stdf,xxs, xxe, yys, yye ); //using 2 unused variables sensihs and sensiv params->locallab.spots.at(sp).sensihs = (int) meanf; params->locallab.spots.at(sp).sensiv = (int) stdf; @@ -1334,7 +1302,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) lhist16.clear(); #ifdef _OPENMP const int numThreads = min(max(pW * pH / (int)lhist16.getSize(), 1), omp_get_max_threads()); - #pragma omp parallel num_threads(numThreads) if(numThreads>1) + #pragma omp parallel num_threads(numThreads) if (numThreads>1) #endif { LUTu lhist16thr(lhist16.getSize()); @@ -1414,7 +1382,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) bool proton = WaveParams.exptoning; bool pronois = WaveParams.expnoise; - if(WaveParams.showmask) { + if (WaveParams.showmask) { // WaveParams.showmask = false; // WaveParams.expclari = true; } @@ -1540,7 +1508,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } float indic = 1.f; - if(WaveParams.showmask){ + if (WaveParams.showmask){ mL0 = mC0 = -1.f; indic = -1.f; mL = fabs(mL); @@ -1611,6 +1579,134 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) ipf.softLight(nprevl, params->softlight); + if (params->icm.workingTRC != ColorManagementParams::WorkingTrc::NONE) { + const int GW = nprevl->W; + const int GH = nprevl->H; + std::unique_ptr provis; + const float pres = 0.01f * params->icm.preser; + if (pres > 0.f && params->icm.wprim != ColorManagementParams::Primaries::DEFAULT) { + provis.reset(new LabImage(GW, GH)); + provis->CopyFrom(nprevl); + } + + std::unique_ptr tmpImage1(new Imagefloat(GW, GH)); + + ipf.lab2rgb(*nprevl, *tmpImage1, params->icm.workingProfile); + + const float gamtone = params->icm.workingTRCGamma; + const float slotone = params->icm.workingTRCSlope; + + int illum = toUnderlying(params->icm.will); + const int prim = toUnderlying(params->icm.wprim); + + Glib::ustring prof = params->icm.workingProfile; + cmsHTRANSFORM dummy = nullptr; + int ill = 0; + ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false); + ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, 5, prof, gamtone, slotone, illum, prim, dummy, false, true, true); + + ipf.rgb2lab(*tmpImage1, *nprevl, params->icm.workingProfile); + //nprevl and provis + if (provis) { + ipf.preserv(nprevl, provis.get(), GW, GH); + } + if (params->icm.fbw) { +#ifdef _OPENMP + #pragma omp parallel for +#endif + for (int x = 0; x < GH; x++) + for (int y = 0; y < GW; y++) { + nprevl->a[x][y] = 0.f; + nprevl->b[x][y] = 0.f; + } + } + + tmpImage1.reset(); + + if (prim == 12) {//pass red gre blue xy in function of area dats Ciexy + float redgraphx = params->icm.labgridcieALow; + float redgraphy = params->icm.labgridcieBLow; + float blugraphx = params->icm.labgridcieAHigh; + float blugraphy = params->icm.labgridcieBHigh; + float gregraphx = params->icm.labgridcieGx; + float gregraphy = params->icm.labgridcieGy; + float redxx = 0.55f * (redgraphx + 1.f) - 0.1f; + redxx = rtengine::LIM(redxx, 0.41f, 1.f); + float redyy = 0.55f * (redgraphy + 1.f) - 0.1f; + redyy = rtengine::LIM(redyy, 0.f, 0.7f); + float bluxx = 0.55f * (blugraphx + 1.f) - 0.1f; + bluxx = rtengine::LIM(bluxx, -0.1f, 0.5f); + float bluyy = 0.55f * (blugraphy + 1.f) - 0.1f; + bluyy = rtengine::LIM(bluyy, -0.1f, 0.5f); + + float grexx = 0.55f * (gregraphx + 1.f) - 0.1f; + grexx = rtengine::LIM(grexx, -0.1f, 0.4f); + float greyy = 0.55f * (gregraphy + 1.f) - 0.1f; + greyy = rtengine::LIM(greyy, 0.5f, 1.f); + + if (primListener) { + primListener->primChanged (redxx, redyy, bluxx, bluyy, grexx, greyy); + } + } else {//all other cases - pass Cie xy to update graph Ciexy + float r_x = params->icm.redx; + float r_y = params->icm.redy; + float b_x = params->icm.blux; + float b_y = params->icm.bluy; + float g_x = params->icm.grex; + float g_y = params->icm.grey; + //printf("rx=%f ry=%f \n", (double) r_x, (double) r_y); + float wx = 0.33f; + float wy = 0.33f; + + switch (illum) { + case 1://D41 + wx = 0.37798f; + wy = 0.38123f; + break; + case 2://D50 + wx = 0.3457f; + wy = 0.3585f; + break; + case 3://D55 + wx = 0.3324f; + wy = 0.3474f; + break; + case 4://D60 + wx = 0.3217f; + wy = 0.3377f; + break; + case 5://D65 + wx = 0.3127f; + wy = 0.3290f; + break; + case 6://D80 + wx = 0.2937f; + wy = 0.3092f; + break; + case 7://D120 + wx = 0.2697f; + wy = 0.2808f; + break; + case 8://stdA + wx = 0.4476f; + wy = 0.4074f; + break; + case 9://2000K + wx = 0.5266f; + wy = 0.4133f; + break; + case 10://1500K + wx = 0.5857f; + wy = 0.3932f; + break; + } + + if (primListener) { + primListener->iprimChanged (r_x, r_y, b_x, b_y, g_x, g_y, wx, wy); + } + } + } + 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 @@ -1718,6 +1814,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } } + // if (todo & (M_AUTOEXP | M_RGBCURVE)) { + // Update the monitor color transform if necessary if ((todo & M_MONITOR) || (lastOutputProfile != params->icm.outputProfile) || lastOutputIntent != params->icm.outputIntent || lastOutputBPC != params->icm.outputBPC) { lastOutputProfile = params->icm.outputProfile; diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 9735f8be8..796895125 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -190,6 +190,7 @@ protected: ImageTypeListener *imageTypeListener; FilmNegListener *filmNegListener; AutoColorTonListener* actListener; + AutoprimListener* primListener; AutoChromaListener* adnListener; WaveletListener* awavListener; RetinexListener* dehaListener; @@ -501,6 +502,10 @@ public: { actListener = bwct; } + void setAutoprimListener (AutoprimListener* pri) override + { + primListener = pri; + } void setAutoChromaListener (AutoChromaListener* adn) override { adnListener = adn; diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 047f045e2..c421f72d1 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -3582,21 +3582,13 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer } if (sCurveEnabled) { - delete sCurve; + delete sCurve; } if (vCurveEnabled) { delete vCurve; } - // shadowsHighlights(lab); - // shadowsHighlights(lab, params->sh.enabled, params->sh.lab,params->sh.highlights ,params->sh.shadows, params->sh.radius, scale, params->sh.htonalwidth, params->sh.stonalwidth); -/* - if (params->localContrast.enabled) { - // Alberto's local contrast - localContrast(lab, lab->L, params->localContrast, false, scale); - } - */ } /** diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index c11f0810b..5020b36f2 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -477,7 +477,8 @@ enum class BlurType { void rgb2lab(const Image8 &src, int x, int y, int w, int h, float L[], float a[], float b[], const procparams::ColorManagementParams &icm, bool consider_histogram_settings = true) const; Imagefloat* lab2rgbOut(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm); // CieImage *ciec; - void workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, const Glib::ustring &profile, double gampos, double slpos, cmsHTRANSFORM &transform, bool normalizeIn = true, bool normalizeOut = true, bool keepTransForm = false) const; + void workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, Glib::ustring &profile, double gampos, double slpos, int &illum, int prim, cmsHTRANSFORM &transform, bool normalizeIn = true, bool normalizeOut = true, bool keepTransForm = false) const; + void preserv(LabImage *nprevl, LabImage *provis, int cw, int ch); bool transCoord(int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr) const; bool transCoord(int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr) const; diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 81a304fd3..f07601c45 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -16,18 +16,20 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#include "rtengine.h" -#include "image8.h" -#include "imagefloat.h" -#include "labimage.h" -#include "improcfun.h" #include -#include "iccstore.h" -#include "iccmatrices.h" -#include "settings.h" + #include "alignedbuffer.h" #include "color.h" +#include "iccmatrices.h" +#include "iccstore.h" +#include "image8.h" +#include "imagefloat.h" +#include "improcfun.h" +#include "labimage.h" #include "procparams.h" +#include "rtengine.h" +#include "settings.h" +#include "utils.h" namespace rtengine { @@ -120,6 +122,19 @@ inline void copyAndClamp(const LabImage *src, unsigned char *dst, const double r } // namespace + +float gammalog(float x, float p, float s, float g3, float g4) +{ + return x <= g3 ? x * s : (1.f + g4) * xexpf(xlogf(x) / p) - g4;//continuous +} + +#ifdef __SSE2__ +vfloat gammalog(vfloat x, vfloat p, vfloat s, vfloat g3, vfloat g4) +{ + return vself(vmaskf_le(x, g3), x * s, (F2V(1.f) + g4) * xexpf(xlogf(x) / p) - g4);//continuous +} +#endif + // Used in ImProcCoordinator::updatePreviewImage (rtengine/improccoordinator.cc) // Crop::update (rtengine/dcrop.cc) // Thumbnail::processImage (rtengine/rtthumbnail.cc) @@ -373,8 +388,31 @@ Imagefloat* ImProcFunctions::lab2rgbOut(LabImage* lab, int cx, int cy, int cw, i return image; } +void ImProcFunctions::preserv(LabImage *nprevl, LabImage *provis, int cw, int ch) +{//avoid too strong in middle values chroma when changing primaries + float pres = 0.01f * params->icm.preser; + float neutral = 2000000000.f;//if a2 + b2 < 200000000 scale 0..100 a and b about : 140 > a & b > -140 decrease effect + float medneutral = 10000000.f;//plein effect 10 > a & b > -10 + float aaneu = 1.f / (medneutral - neutral); + float bbneu = - aaneu * neutral; +#ifdef _OPENMP + #pragma omp for schedule(dynamic, 16) nowait +#endif + for (int i = 0; i < ch; ++i) + for (int j = 0; j < cw; ++j) { + float neu = SQR(provis->a[i][j]) + SQR(provis->b[i][j]); + if (neu < medneutral) {//plein effect + nprevl->a[i][j] = intp(pres, provis->a[i][j], nprevl->a[i][j]); + nprevl->b[i][j] = intp(pres, provis->b[i][j], nprevl->b[i][j]); + } else if (neu < neutral) {//decrease effect + float presred = aaneu * neu + bbneu; + nprevl->a[i][j] = intp(pres * presred, provis->a[i][j], nprevl->a[i][j]); + nprevl->b[i][j] = intp(pres * presred, provis->b[i][j], nprevl->b[i][j]); + } + } +} -void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, const Glib::ustring &profile, double gampos, double slpos, cmsHTRANSFORM &transform, bool normalizeIn, bool normalizeOut, bool keepTransForm) const +void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, Glib::ustring &profile, double gampos, double slpos, int &illum, int prim, cmsHTRANSFORM &transform, bool normalizeIn, bool normalizeOut, bool keepTransForm) const { const TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); @@ -394,6 +432,163 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, } }; + if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") { + if (settings->verbose) { + printf("Profile=%s\n", profile.c_str()); + } + } else { + if (settings->verbose) { + printf("profile not accepted\n"); + } + return; + } + + if (mul == -5 && gampos == 2.4 && slpos == 12.92310) {//must be change if we change settings RT sRGB + //only in this case we can shortcut..all process..no gamut control..because we reduce...leads to very small differences, but big speedup +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) if (multiThread) +#endif + + for (int i = 0; i < ch; ++i) + for (int j = 0; j < cw; ++j) { + float r = src->r(i, j); + float g = src->g(i, j); + float b = src->b(i, j); + r = (Color::igammatab_srgb[r]) / 65535.f; + g = (Color::igammatab_srgb[g]) / 65535.f; + b = (Color::igammatab_srgb[b]) / 65535.f; + dst->r(i, j) = r; + dst->g(i, j) = g; + dst->b(i, j) = b; + } + return; + + } + + if (mul == 1 ||(params->icm.wprim == ColorManagementParams::Primaries::DEFAULT && params->icm.will == ColorManagementParams::Illuminant::DEFAULT)) {//shortcut and speedup when no call primaries and illuminant - no gamut control...in this case be carefull + GammaValues g_a; //gamma parameters + double pwr = 1.0 / static_cast(gampos); + Color::calcGamma(pwr, slpos, g_a); // call to calcGamma with selected gamma and slope + +#ifdef _OPENMP +# pragma omp parallel for schedule(dynamic,16) if (multiThread) +#endif + for (int y = 0; y < ch; ++y) { + int x = 0; +#ifdef __SSE2__ + for (; x < cw - 3; x += 4) { + STVFU(dst->r(y,x), F2V(65536.f) * gammalog(LVFU(src->r(y,x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4]))); + STVFU(dst->g(y,x), F2V(65536.f) * gammalog(LVFU(src->g(y,x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4]))); + STVFU(dst->b(y,x), F2V(65536.f) * gammalog(LVFU(src->b(y,x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4]))); + } +#endif + for (; x < cw; ++x) { + dst->r(y,x) = 65536.f * gammalog(src->r(y,x), gampos, slpos, g_a[3], g_a[4]); + dst->g(y,x) = 65536.f * gammalog(src->g(y,x), gampos, slpos, g_a[3], g_a[4]); + dst->b(y,x) = 65536.f * gammalog(src->b(y,x), gampos, slpos, g_a[3], g_a[4]); + } + } + return; + } + + + float redxx = params->icm.redx; + float redyy = params->icm.redy; + float bluxx = params->icm.blux; + float bluyy = params->icm.bluy; + float grexx = params->icm.grex; + float greyy = params->icm.grey; + + if (prim == 12) {//convert datas area to xy + float redgraphx = params->icm.labgridcieALow; + float redgraphy = params->icm.labgridcieBLow; + float blugraphx = params->icm.labgridcieAHigh; + float blugraphy = params->icm.labgridcieBHigh; + float gregraphx = params->icm.labgridcieGx; + float gregraphy = params->icm.labgridcieGy; + redxx = 0.55f * (redgraphx + 1.f) - 0.1f; + redxx = rtengine::LIM(redxx, 0.41f, 1.f);//limit values for xy (arbitrary) + redyy = 0.55f * (redgraphy + 1.f) - 0.1f; + redyy = rtengine::LIM(redyy, 0.f, 0.7f); + bluxx = 0.55f * (blugraphx + 1.f) - 0.1f; + bluxx = rtengine::LIM(bluxx, -0.1f, 0.5f); + bluyy = 0.55f * (blugraphy + 1.f) - 0.1f; + bluyy = rtengine::LIM(bluyy, -0.1f, 0.5f); + grexx = 0.55f * (gregraphx + 1.f) - 0.1f; + grexx = rtengine::LIM(grexx, -0.1f, 0.4f); + greyy = 0.55f * (gregraphy + 1.f) - 0.1f; + greyy = rtengine::LIM(greyy, 0.5f, 1.f); + } + + switch (ColorManagementParams::Primaries(prim)) { + case ColorManagementParams::Primaries::DEFAULT: { + break; + } + + case ColorManagementParams::Primaries::SRGB: { + profile = "sRGB"; + break; + } + + case ColorManagementParams::Primaries::ADOBE_RGB: { + profile = "Adobe RGB"; + break; + } + + case ColorManagementParams::Primaries::PRO_PHOTO: { + profile = "ProPhoto"; + break; + } + + case ColorManagementParams::Primaries::REC2020: { + profile = "Rec2020"; + break; + } + + case ColorManagementParams::Primaries::ACES_P1: { + profile = "ACESp1"; + break; + } + + case ColorManagementParams::Primaries::WIDE_GAMUT: { + profile = "WideGamut"; + break; + } + + case ColorManagementParams::Primaries::ACES_P0: { + profile = "ACESp0"; + break; + } + + case ColorManagementParams::Primaries::BRUCE_RGB: { + profile = "BruceRGB"; + break; + } + + case ColorManagementParams::Primaries::BETA_RGB: { + profile = "Beta RGB"; + break; + } + + case ColorManagementParams::Primaries::BEST_RGB: { + profile = "BestRGB"; + break; + } + + case ColorManagementParams::Primaries::CUSTOM: { + profile = "Custom"; + break; + } + + case ColorManagementParams::Primaries::CUSTOM_GRID: { + profile = "Custom"; + break; + } + } + + if (settings->verbose && prim != 0) { + printf("prim=%i Profile Destination=%s\n", prim, profile.c_str()); + } cmsHTRANSFORM hTransform = nullptr; if (transform) { hTransform = transform; @@ -418,8 +613,7 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, D60 = 6005 // for ACES AP0 and AP1 }; - ColorTemp temp = ColorTemp::D50; - + double tempv4 = 5003.; float p[6]; //primaries //primaries for 10 working profiles ==> output profiles @@ -430,6 +624,7 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, p[3] = 0.8260; p[4] = 0.1570; p[5] = 0.0180; + illum = toUnderlying(ColorManagementParams::Illuminant::D50); } else if (profile == "Adobe RGB") { p[0] = 0.6400; //Adobe primaries p[1] = 0.3300; @@ -437,7 +632,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, p[3] = 0.7100; p[4] = 0.1500; p[5] = 0.0600; - temp = ColorTemp::D65; + tempv4 = 6504.; + illum = toUnderlying(ColorManagementParams::Illuminant::D65); } else if (profile == "sRGB") { p[0] = 0.6400; // sRGB primaries p[1] = 0.3300; @@ -445,7 +641,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, p[3] = 0.6000; p[4] = 0.1500; p[5] = 0.0600; - temp = ColorTemp::D65; + tempv4 = 6504.; + illum = toUnderlying(ColorManagementParams::Illuminant::D65); } else if (profile == "BruceRGB") { p[0] = 0.6400; // Bruce primaries p[1] = 0.3300; @@ -453,14 +650,16 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, p[3] = 0.6500; p[4] = 0.1500; p[5] = 0.0600; - temp = ColorTemp::D65; - } else if (profile == "Beta RGB") { + tempv4 = 6504.; + illum = toUnderlying(ColorManagementParams::Illuminant::D65); + } else if (profile == "Beta RGB") { p[0] = 0.6888; // Beta primaries p[1] = 0.3112; p[2] = 0.1986; p[3] = 0.7551; p[4] = 0.1265; p[5] = 0.0352; + illum = toUnderlying(ColorManagementParams::Illuminant::D50); } else if (profile == "BestRGB") { p[0] = 0.7347; // Best primaries p[1] = 0.2653; @@ -468,6 +667,7 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, p[3] = 0.7750; p[4] = 0.1300; p[5] = 0.0350; + illum = toUnderlying(ColorManagementParams::Illuminant::D50); } else if (profile == "Rec2020") { p[0] = 0.7080; // Rec2020 primaries p[1] = 0.2920; @@ -475,7 +675,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, p[3] = 0.7970; p[4] = 0.1310; p[5] = 0.0460; - temp = ColorTemp::D65; + tempv4 = 6504.; + illum = toUnderlying(ColorManagementParams::Illuminant::D65); } else if (profile == "ACESp0") { p[0] = 0.7347; // ACES P0 primaries p[1] = 0.2653; @@ -483,7 +684,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, p[3] = 1.0; p[4] = 0.0001; p[5] = -0.0770; - temp = ColorTemp::D60; + tempv4 = 6004.; + illum = toUnderlying(ColorManagementParams::Illuminant::D60); } else if (profile == "ACESp1") { p[0] = 0.713; // ACES P1 primaries p[1] = 0.293; @@ -491,7 +693,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, p[3] = 0.830; p[4] = 0.128; p[5] = 0.044; - temp = ColorTemp::D60; + tempv4 = 6004.; + illum = toUnderlying(ColorManagementParams::Illuminant::D60); } else if (profile == "ProPhoto") { p[0] = 0.7347; //ProPhoto and default primaries p[1] = 0.2653; @@ -499,6 +702,14 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, p[3] = 0.8404; p[4] = 0.0366; p[5] = 0.0001; + illum = toUnderlying(ColorManagementParams::Illuminant::D50); + } else if (profile == "Custom") { + p[0] = redxx; + p[1] = redyy; + p[2] = grexx; + p[3] = greyy; + p[4] = bluxx; + p[5] = bluyy; } else { p[0] = 0.7347; //default primaries always unused p[1] = 0.2653; @@ -528,27 +739,145 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, // 7 parameters for smoother curves cmsCIExyY xyD; - cmsWhitePointFromTemp(&xyD, (double)temp); - if (profile == "ACESp0") { - xyD = {0.32168, 0.33767, 1.0};//refine white point to avoid differences + Glib::ustring ills = "D50"; + switch (ColorManagementParams::Illuminant(illum)) { + case ColorManagementParams::Illuminant::DEFAULT: + case ColorManagementParams::Illuminant::STDA: + case ColorManagementParams::Illuminant::TUNGSTEN_2000K: + case ColorManagementParams::Illuminant::TUNGSTEN_1500K: { + break; + } + + case ColorManagementParams::Illuminant::D41: { + tempv4 = 4100.; + ills = "D41"; + break; + } + + case ColorManagementParams::Illuminant::D50: { + tempv4 = 5003.; + ills = "D50"; + break; + } + + case ColorManagementParams::Illuminant::D55: { + tempv4 = 5500.; + ills = "D55"; + break; + } + + case ColorManagementParams::Illuminant::D60: { + tempv4 = 6004.; + ills = "D60"; + break; + } + + case ColorManagementParams::Illuminant::D65: { + tempv4 = 6504.; + ills = "D65"; + break; + } + + case ColorManagementParams::Illuminant::D80: { + tempv4 = 8000.; + ills = "D80"; + break; + } + + case ColorManagementParams::Illuminant::D120: { + tempv4 = 12000.; + ills = "D120"; + break; + } } + cmsWhitePointFromTemp(&xyD, tempv4); + + switch (ColorManagementParams::Illuminant(illum)) { + case ColorManagementParams::Illuminant::DEFAULT: + case ColorManagementParams::Illuminant::D55: + case ColorManagementParams::Illuminant::D80: { + break; + } + + case ColorManagementParams::Illuminant::D41: { + break; + } + + case ColorManagementParams::Illuminant::D50: { + xyD = {0.3457, 0.3585, 1.0}; // near LCMS values but not perfect... it's a compromise!! + break; + } + + case ColorManagementParams::Illuminant::D60: { + xyD = {0.32168, 0.33767, 1.0}; + break; + } + + case ColorManagementParams::Illuminant::D65: { + xyD = {0.312700492, 0.329000939, 1.0}; + break; + } + + case ColorManagementParams::Illuminant::D120: { + xyD = {0.269669, 0.28078, 1.0}; + break; + } + + case ColorManagementParams::Illuminant::STDA: { + xyD = {0.447573, 0.407440, 1.0}; + ills = "stdA 2875K"; + break; + } + + case ColorManagementParams::Illuminant::TUNGSTEN_2000K: { + xyD = {0.526591, 0.41331, 1.0}; + ills = "Tungsten 2000K"; + break; + } + + case ColorManagementParams::Illuminant::TUNGSTEN_1500K: { + xyD = {0.585703, 0.393157, 1.0}; + ills = "Tungsten 1500K"; + break; + } + } + + //D41 0.377984 0.381229 + //D55 0.332424 0.347426 + //D80 0.293755 0.309185 + //D75 0.299021 0.314852 cmsToneCurve* GammaTRC[3]; GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, five, gammaParams);//5 = more smoother than 4 + cmsHPROFILE oprofdef = nullptr; const cmsCIExyYTRIPLE Primaries = { {p[0], p[1], 1.0}, // red {p[2], p[3], 1.0}, // green {p[4], p[5], 1.0} // blue }; - const cmsHPROFILE oprofdef = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC); - cmsFreeToneCurve(GammaTRC[0]); + oprofdef = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC); + cmsWriteTag(oprofdef, cmsSigRedTRCTag, GammaTRC[0]); + cmsWriteTag(oprofdef, cmsSigGreenTRCTag, GammaTRC[1]); + cmsWriteTag(oprofdef, cmsSigBlueTRCTag, GammaTRC[2]); + //to read XYZ values and illuminant + if (rtengine::settings->verbose) { + cmsCIEXYZ *redT = static_cast(cmsReadTag(oprofdef, cmsSigRedMatrixColumnTag)); + cmsCIEXYZ *greenT = static_cast(cmsReadTag(oprofdef, cmsSigGreenMatrixColumnTag)); + cmsCIEXYZ *blueT = static_cast(cmsReadTag(oprofdef, cmsSigBlueMatrixColumnTag)); + printf("Illuminant=%s\n", ills.c_str()); + printf("rX=%f gX=%f bX=%f\n", redT->X, greenT->X, blueT->X); + printf("rY=%f gY=%f bY=%f\n", redT->Y, greenT->Y, blueT->Y); + printf("rZ=%f gZ=%f bZ=%f\n", redT->Z, greenT->Z, blueT->Z); + } + + cmsFreeToneCurve(GammaTRC[0]); if (oprofdef) { - constexpr cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE; + constexpr cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE | cmsFLAGS_BLACKPOINTCOMPENSATION | cmsFLAGS_GAMUTCHECK; const cmsHPROFILE iprof = ICCStore::getInstance()->getXYZProfile(); lcmsMutex->lock(); - hTransform = cmsCreateTransform(iprof, TYPE_RGB_FLT, oprofdef, TYPE_RGB_FLT, params->icm.outputIntent, flags); + hTransform = cmsCreateTransform(iprof, TYPE_RGB_FLT, oprofdef, TYPE_RGB_FLT, params->icm.aRendIntent, flags); lcmsMutex->unlock(); } } diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index 35df6d350..00b379271 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -5069,7 +5069,7 @@ void ImProcFunctions::maskcalccol(bool invmask, bool pde, int bfw, int bfh, int if (delt) { const std::unique_ptr> rdEBuffer(new JaggedArray(bfw, bfh)); - float** rdE = *(rdEBuffer.get()); + float** rdE = *rdEBuffer; deltaEforMask(rdE, bfw, bfh, bufreserv.get(), hueref, chromaref, lumaref, maxdE, mindE, maxdElim, mindElim, iterat, limscope, scope, lp.balance, lp.balanceh); #ifdef _OPENMP @@ -6080,13 +6080,16 @@ void ImProcFunctions::InverseColorLight_Local(bool tonequ, bool tonecurv, int sp const std::unique_ptr tmpImage(new Imagefloat(GW, GH)); lab2rgb(*temp, *tmpImage, params->icm.workingProfile); - + Glib::ustring prof = params->icm.workingProfile; if (tonecurv) { //Tone response curve : does nothing if gamma=2.4 and slope=12.92 ==> gamma sRGB const float gamtone = params->locallab.spots.at(sp).gamSH; const float slotone = params->locallab.spots.at(sp).sloSH; + int ill = 0; cmsHTRANSFORM dummy = nullptr; - workingtrc(tmpImage.get(), tmpImage.get(), GW, GH, -5, params->icm.workingProfile, 2.4, 12.92310, dummy, true, false, false); - workingtrc(tmpImage.get(), tmpImage.get(), GW, GH, 5, params->icm.workingProfile, gamtone, slotone, dummy, false, true, true); + workingtrc(tmpImage.get(), tmpImage.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false); + // workingtrc(tmpImage.get(), tmpImage.get(), GW, GH, 5, prof, gamtone, slotone, illum, 0, dummy, false, true, true);//to keep if we want improve with illuminant and primaries + workingtrc(tmpImage.get(), tmpImage.get(), GW, GH, 1, prof, gamtone, slotone, ill, 0, dummy, false, true, true);//be carefull no gamut control + } if (tonequ) { @@ -11559,7 +11562,7 @@ void ImProcFunctions::Lab_Local( } } - rgb2lab(*(tmpImage.get()), *bufexpfin, params->icm.workingProfile); + rgb2lab(*tmpImage, *bufexpfin, params->icm.workingProfile); tmpImageorig.reset(); tmpImage.reset(); @@ -12341,7 +12344,7 @@ void ImProcFunctions::Lab_Local( ImProcFunctions::impulse_nr(bufwv.get(), threshold); } - DeNoise_Local(call, lp, originalmaskbl.get(), levred, huerefblur, lumarefblur, chromarefblur, original, transformed, *(bufwv.get()), cx, cy, sk); + DeNoise_Local(call, lp, originalmaskbl.get(), levred, huerefblur, lumarefblur, chromarefblur, original, transformed, *bufwv, cx, cy, sk); if (lp.recur) { original->CopyFrom(transformed, multiThread); @@ -12753,7 +12756,7 @@ void ImProcFunctions::Lab_Local( const float refb = chromaref * sin(hueref); const std::unique_ptr> reducDEBuffer(new JaggedArray(Wd, Hd)); - float** reducDE = *(reducDEBuffer.get()); + float** reducDE = *reducDEBuffer; float ade = 0.01f * raddE; float bde = 100.f - raddE; @@ -12769,10 +12772,10 @@ void ImProcFunctions::Lab_Local( } const std::unique_ptr> origBuffer(new JaggedArray(Wd, Hd)); - float** orig = *(origBuffer.get()); + float** orig = *origBuffer; const std::unique_ptr> origBuffer1(new JaggedArray(Wd, Hd)); - float** orig1 = *(origBuffer1.get()); + float** orig1 = *origBuffer1; #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) if (multiThread) @@ -13100,7 +13103,7 @@ void ImProcFunctions::Lab_Local( const float refb = chromaref * sin(hueref); const std::unique_ptr> reducDEBuffer(new JaggedArray(Wd, Hd)); - float** reducDE = *(reducDEBuffer.get()); + float** reducDE = *reducDEBuffer; float ade = 0.01f * raddE; float bde = 100.f - raddE; float sensibefore = ade * lp.sensh + bde;//we can change sensitivity 0.1 90 or 0.3 70 or 0.4 60 @@ -13116,10 +13119,10 @@ void ImProcFunctions::Lab_Local( } const std::unique_ptr> origBuffer(new JaggedArray(Wd, Hd)); - float** orig = *(origBuffer.get()); + float** orig = *origBuffer; const std::unique_ptr> origBuffer1(new JaggedArray(Wd, Hd)); - float** orig1 = *(origBuffer1.get()); + float** orig1 = *origBuffer1; LabImage *tmpl = nullptr; @@ -13952,13 +13955,16 @@ void ImProcFunctions::Lab_Local( Imagefloat *tmpImage = nullptr; tmpImage = new Imagefloat(bfw, bfh); lab2rgb(*bufexpfin, *tmpImage, params->icm.workingProfile); + Glib::ustring prof = params->icm.workingProfile; if (tonecurv) { //Tone response curve : does nothing if gamma=2.4 and slope=12.92 ==> gamma sRGB - const float gamtone = params->locallab.spots.at(sp).gamSH; - const float slotone = params->locallab.spots.at(sp).sloSH; - cmsHTRANSFORM dummyTransForm = nullptr; - workingtrc(tmpImage, tmpImage, bfw, bfh, -5, params->icm.workingProfile, 2.4, 12.92310, dummyTransForm, true, false, false); - workingtrc(tmpImage, tmpImage, bfw, bfh, 5, params->icm.workingProfile, gamtone, slotone, dummyTransForm, false, true, true); + float gamtone = params->locallab.spots.at(sp).gamSH; + float slotone = params->locallab.spots.at(sp).sloSH; + cmsHTRANSFORM dummy = nullptr; + int ill =0; + workingtrc(tmpImage, tmpImage, bfw, bfh, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false); + // workingtrc(tmpImage, tmpImage, bfw, bfh, 5, prof, gamtone, slotone, 0, 0, dummy, false, true, true); //to keep if we want improve with illuminant and primaries + workingtrc(tmpImage, tmpImage, bfw, bfh, 1, prof, gamtone, slotone, ill, 0, dummy, false, true, true);//be carefull no gamut control } if (tonequ) { @@ -14941,13 +14947,13 @@ void ImProcFunctions::Lab_Local( //const float sigm = 1.f; //params->locallab.spots.at(sp).fatlevel; //const float mean = 1.f;// params->locallab.spots.at(sp).fatanchor; const std::unique_ptr tmpImagefat(new Imagefloat(bfwr, bfhr)); - lab2rgb(*bufexpfin, *(tmpImagefat.get()), params->icm.workingProfile); + lab2rgb(*bufexpfin, *tmpImagefat, params->icm.workingProfile); int alg = 0; if(fatParams.anchor == 50.f) { alg = 1; } ToneMapFattal02(tmpImagefat.get(), fatParams, 3, 0, nullptr, 0, 0, alg);//last parameter = 1 ==>ART algorithm - rgb2lab(*(tmpImagefat.get()), *bufexpfin, params->icm.workingProfile); + rgb2lab(*tmpImagefat, *bufexpfin, params->icm.workingProfile); } @@ -15358,7 +15364,7 @@ void ImProcFunctions::Lab_Local( usergb = true; const std::unique_ptr tmpImage(new Imagefloat(bfw, bfh)); - lab2rgb(*buftemp, *(tmpImage.get()), params->icm.workingProfile); + lab2rgb(*buftemp, *tmpImage, params->icm.workingProfile); #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) if (multiThread) #endif @@ -15425,7 +15431,7 @@ void ImProcFunctions::Lab_Local( } } - rgb2lab(*(tmpImage.get()), *buftemp, params->icm.workingProfile); + rgb2lab(*tmpImage, *buftemp, params->icm.workingProfile); // end rgb curves } @@ -15742,7 +15748,7 @@ void ImProcFunctions::Lab_Local( } const std::unique_ptr> rdEBuffer(new JaggedArray(bfw, bfh)); - float** rdE = *(rdEBuffer.get()); + float** rdE = *rdEBuffer; deltaEforMask(rdE, bfw, bfh, bufreser.get(), hueref, chromaref, lumaref, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, mercol, lp.balance, lp.balanceh); @@ -15904,11 +15910,11 @@ void ImProcFunctions::Lab_Local( //prepare RGB values in 0 1(or more)for current image and reserved std::unique_ptr tmpImageorig(new Imagefloat(bfw, bfh)); - lab2rgb(*bufcolfin, *(tmpImageorig.get()), params->icm.workingProfile); + lab2rgb(*bufcolfin, *tmpImageorig, params->icm.workingProfile); tmpImageorig->normalizeFloatTo1(); std::unique_ptr tmpImagereserv(new Imagefloat(bfw, bfh)); - lab2rgb(*bufcolreserv, *(tmpImagereserv.get()), params->icm.workingProfile); + lab2rgb(*bufcolreserv, *tmpImagereserv, params->icm.workingProfile); tmpImagereserv->normalizeFloatTo1(); float minR = tmpImagereserv->r(0, 0); diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc index 67db52e55..491e17cb9 100644 --- a/rtengine/ipretinex.cc +++ b/rtengine/ipretinex.cc @@ -397,7 +397,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e } std::unique_ptr> srcBuffer(new JaggedArray(W_L, H_L)); - float** src = *(srcBuffer.get()); + float** src = *srcBuffer; #ifdef _OPENMP #pragma omp parallel for @@ -1238,7 +1238,7 @@ void ImProcFunctions::MSRLocal(int call, int sp, bool fftw, int lum, float** red const int H_L = height; const int W_L = width; std::unique_ptr> srcBuffer(new JaggedArray(W_L, H_L)); - float** src = *(srcBuffer.get()); + float** src = *srcBuffer; #ifdef _OPENMP diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 5768f9c3e..317b34893 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2216,9 +2216,28 @@ ColorManagementParams::ColorManagementParams() : applyHueSatMap(true), dcpIlluminant(0), workingProfile("ProPhoto"), - workingTRC("none"), - workingTRCGamma(2.4), - workingTRCSlope(12.92310), + workingTRC(WorkingTrc::NONE), + will(Illuminant::DEFAULT), + wprim(Primaries::DEFAULT), + workingTRCGamma(2.4),//gamma sRGB + workingTRCSlope(12.92), + redx(0.64), + redy(0.33), + grex(0.21), + grey(0.71), + blux(0.15), + bluy(0.06), + preser(0.), + fbw(false), + labgridcieALow(0.51763),//Prophoto red = (0.7347+0.1) * 1.81818 - 1 + labgridcieBLow(-0.33582), + labgridcieAHigh(-0.75163),//Prophoto blue + labgridcieBHigh(-0.8180), + labgridcieGx(-0.69164),//Prophoto green 0.1596 + labgridcieGy(-0.70909),//0.84 + labgridcieWx(-0.18964),//D50 0.3457, 0.3585, + labgridcieWy(-0.16636),// + aRendIntent(RI_RELATIVE), outputProfile(options.rtSettings.srgb), outputIntent(RI_RELATIVE), outputBPC(true) @@ -2236,8 +2255,27 @@ bool ColorManagementParams::operator ==(const ColorManagementParams& other) cons && dcpIlluminant == other.dcpIlluminant && workingProfile == other.workingProfile && workingTRC == other.workingTRC + && will == other.will + && wprim == other.wprim && workingTRCGamma == other.workingTRCGamma && workingTRCSlope == other.workingTRCSlope + && redx == other.redx + && redy == other.redy + && grex == other.grex + && grey == other.grey + && blux == other.blux + && bluy == other.bluy + && labgridcieALow == other.labgridcieALow + && labgridcieBLow == other.labgridcieBLow + && labgridcieAHigh == other.labgridcieAHigh + && labgridcieBHigh == other.labgridcieBHigh + && labgridcieGx == other.labgridcieGx + && labgridcieGy == other.labgridcieGy + && labgridcieWx == other.labgridcieWx + && labgridcieWy == other.labgridcieWy + && preser == other.preser + && fbw == other.fbw + && aRendIntent == other.aRendIntent && outputProfile == other.outputProfile && outputIntent == other.outputIntent && outputBPC == other.outputBPC; @@ -3979,6 +4017,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : // Log encoding visilog(false), explog(false), + complexlog(0), autocompute(false), sourceGray(10.), sourceabs(2000.), @@ -6493,10 +6532,97 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->icm.applyHueSatMap, "Color Management", "ApplyHueSatMap", icm.applyHueSatMap, keyFile); saveToKeyfile(!pedited || pedited->icm.dcpIlluminant, "Color Management", "DCPIlluminant", icm.dcpIlluminant, keyFile); saveToKeyfile(!pedited || pedited->icm.workingProfile, "Color Management", "WorkingProfile", icm.workingProfile, keyFile); - saveToKeyfile(!pedited || pedited->icm.workingTRC, "Color Management", "WorkingTRC", icm.workingTRC, keyFile); + saveToKeyfile( + !pedited || pedited->icm.workingTRC, + "Color Management", + "WorkingTRC", + { + {ColorManagementParams::WorkingTrc::NONE, "none"}, + {ColorManagementParams::WorkingTrc::CUSTOM, "Custom"}, + {ColorManagementParams::WorkingTrc::BT709, "bt709"}, + {ColorManagementParams::WorkingTrc::SRGB, "srgb"}, + {ColorManagementParams::WorkingTrc::GAMMA_2_2, "22"}, + {ColorManagementParams::WorkingTrc::GAMMA_1_8, "18"}, + {ColorManagementParams::WorkingTrc::LINEAR, "lin"} + }, + icm.workingTRC, + keyFile + ); + saveToKeyfile( + !pedited || pedited->icm.will, + "Color Management", + "Will", + { + {ColorManagementParams::Illuminant::DEFAULT, "def"}, + {ColorManagementParams::Illuminant::D41, "D41"}, + {ColorManagementParams::Illuminant::D50, "D50"}, + {ColorManagementParams::Illuminant::D55, "D55"}, + {ColorManagementParams::Illuminant::D60, "D60"}, + {ColorManagementParams::Illuminant::D65, "D65"}, + {ColorManagementParams::Illuminant::D80, "D80"}, + {ColorManagementParams::Illuminant::D120, "D120"}, + {ColorManagementParams::Illuminant::STDA, "stda"}, + {ColorManagementParams::Illuminant::TUNGSTEN_2000K, "2000"}, + {ColorManagementParams::Illuminant::TUNGSTEN_1500K, "1500"} + }, + icm.will, + keyFile + ); + saveToKeyfile( + !pedited || pedited->icm.wprim, + "Color Management", + "Wprim", + { + {ColorManagementParams::Primaries::DEFAULT, "def"}, + {ColorManagementParams::Primaries::SRGB, "srgb"}, + {ColorManagementParams::Primaries::ADOBE_RGB, "adob"}, + {ColorManagementParams::Primaries::PRO_PHOTO, "prop"}, + {ColorManagementParams::Primaries::REC2020, "rec"}, + {ColorManagementParams::Primaries::ACES_P1, "aces"}, + {ColorManagementParams::Primaries::WIDE_GAMUT, "wid"}, + {ColorManagementParams::Primaries::ACES_P0, "ac0"}, + {ColorManagementParams::Primaries::BRUCE_RGB, "bru"}, + {ColorManagementParams::Primaries::BETA_RGB, "bet"}, + {ColorManagementParams::Primaries::BEST_RGB, "bst"}, + {ColorManagementParams::Primaries::CUSTOM, "cus"}, + {ColorManagementParams::Primaries::CUSTOM_GRID, "cusgr"} + }, + icm.wprim, + keyFile + ); saveToKeyfile(!pedited || pedited->icm.workingTRCGamma, "Color Management", "WorkingTRCGamma", icm.workingTRCGamma, keyFile); saveToKeyfile(!pedited || pedited->icm.workingTRCSlope, "Color Management", "WorkingTRCSlope", icm.workingTRCSlope, keyFile); + saveToKeyfile(!pedited || pedited->icm.redx, "Color Management", "Redx", icm.redx, keyFile); + saveToKeyfile(!pedited || pedited->icm.redy, "Color Management", "Redy", icm.redy, keyFile); + saveToKeyfile(!pedited || pedited->icm.grex, "Color Management", "Grex", icm.grex, keyFile); + saveToKeyfile(!pedited || pedited->icm.grey, "Color Management", "Grey", icm.grey, keyFile); + saveToKeyfile(!pedited || pedited->icm.blux, "Color Management", "Blux", icm.blux, keyFile); + saveToKeyfile(!pedited || pedited->icm.bluy, "Color Management", "Bluy", icm.bluy, keyFile); + saveToKeyfile(!pedited || pedited->icm.labgridcieALow, "Color Management", "LabGridcieALow", icm.labgridcieALow, keyFile); + saveToKeyfile(!pedited || pedited->icm.labgridcieBLow, "Color Management", "LabGridcieBLow", icm.labgridcieBLow, keyFile); + saveToKeyfile(!pedited || pedited->icm.labgridcieAHigh, "Color Management", "LabGridcieAHigh", icm.labgridcieAHigh, keyFile); + saveToKeyfile(!pedited || pedited->icm.labgridcieBHigh, "Color Management", "LabGridcieBHigh", icm.labgridcieBHigh, keyFile); + saveToKeyfile(!pedited || pedited->icm.labgridcieGx, "Color Management", "LabGridcieGx", icm.labgridcieGx, keyFile); + saveToKeyfile(!pedited || pedited->icm.labgridcieGy, "Color Management", "LabGridcieGy", icm.labgridcieGy, keyFile); + saveToKeyfile(!pedited || pedited->icm.labgridcieWx, "Color Management", "LabGridcieWx", icm.labgridcieWx, keyFile); + saveToKeyfile(!pedited || pedited->icm.labgridcieWy, "Color Management", "LabGridcieWy", icm.labgridcieWy, keyFile); + saveToKeyfile(!pedited || pedited->icm.preser, "Color Management", "Preser", icm.preser, keyFile); + saveToKeyfile(!pedited || pedited->icm.fbw, "Color Management", "Fbw", icm.fbw, keyFile); saveToKeyfile(!pedited || pedited->icm.outputProfile, "Color Management", "OutputProfile", icm.outputProfile, keyFile); + saveToKeyfile( + !pedited || pedited->icm.aRendIntent, + "Color Management", + "aIntent", + { + {RI_PERCEPTUAL, "Perceptual"}, + {RI_RELATIVE, "Relative"}, + {RI_SATURATION, "Saturation"}, + {RI_ABSOLUTE, "Absolute"} + }, + icm.aRendIntent, + keyFile + ); + saveToKeyfile( !pedited || pedited->icm.outputIntent, "Color Management", @@ -8455,10 +8581,125 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Color Management", "ApplyHueSatMap", pedited, icm.applyHueSatMap, pedited->icm.applyHueSatMap); assignFromKeyfile(keyFile, "Color Management", "DCPIlluminant", pedited, icm.dcpIlluminant, pedited->icm.dcpIlluminant); assignFromKeyfile(keyFile, "Color Management", "WorkingProfile", pedited, icm.workingProfile, pedited->icm.workingProfile); - assignFromKeyfile(keyFile, "Color Management", "WorkingTRC", pedited, icm.workingTRC, pedited->icm.workingTRC); + if ( + !assignFromKeyfile( + keyFile, + "Color Management", + "WorkingTRC", + pedited, + { + {"none", ColorManagementParams::WorkingTrc::NONE}, + {"Custom", ColorManagementParams::WorkingTrc::CUSTOM}, + {"bt709", ColorManagementParams::WorkingTrc::BT709}, + {"srgb", ColorManagementParams::WorkingTrc::SRGB}, + {"22", ColorManagementParams::WorkingTrc::GAMMA_2_2}, + {"18", ColorManagementParams::WorkingTrc::GAMMA_1_8}, + {"lin", ColorManagementParams::WorkingTrc::LINEAR} + }, + icm.workingTRC, + pedited->icm.workingTRC + ) + ) { + icm.workingTRC = ColorManagementParams::WorkingTrc::NONE; + if (pedited) { + pedited->icm.workingTRC = true; + } + } + if ( + !assignFromKeyfile( + keyFile, + "Color Management", + "Will", + pedited, + { + {"def", ColorManagementParams::Illuminant::DEFAULT}, + {"D41", ColorManagementParams::Illuminant::D41}, + {"D50", ColorManagementParams::Illuminant::D50}, + {"D55", ColorManagementParams::Illuminant::D55}, + {"D60", ColorManagementParams::Illuminant::D60}, + {"D65", ColorManagementParams::Illuminant::D65}, + {"D80", ColorManagementParams::Illuminant::D80}, + {"D120", ColorManagementParams::Illuminant::D120}, + {"stda", ColorManagementParams::Illuminant::STDA}, + {"2000", ColorManagementParams::Illuminant::TUNGSTEN_2000K}, + {"1500", ColorManagementParams::Illuminant::TUNGSTEN_1500K} + }, + icm.will, + pedited->icm.will + ) + ) { + icm.will = ColorManagementParams::Illuminant::DEFAULT; + if (pedited) { + pedited->icm.will = true; + } + } + if ( + !assignFromKeyfile( + keyFile, + "Color Management", + "Wprim", + pedited, + { + {"def", ColorManagementParams::Primaries::DEFAULT}, + {"srgb", ColorManagementParams::Primaries::SRGB}, + {"adob", ColorManagementParams::Primaries::ADOBE_RGB}, + {"prop", ColorManagementParams::Primaries::PRO_PHOTO}, + {"rec", ColorManagementParams::Primaries::REC2020}, + {"aces", ColorManagementParams::Primaries::ACES_P1}, + {"wid", ColorManagementParams::Primaries::WIDE_GAMUT}, + {"ac0", ColorManagementParams::Primaries::ACES_P0}, + {"bru", ColorManagementParams::Primaries::BRUCE_RGB}, + {"bet", ColorManagementParams::Primaries::BETA_RGB}, + {"bst", ColorManagementParams::Primaries::BEST_RGB}, + {"cus", ColorManagementParams::Primaries::CUSTOM}, + {"cusgr", ColorManagementParams::Primaries::CUSTOM_GRID} + }, + icm.wprim, + pedited->icm.wprim + ) + ) { + icm.wprim = ColorManagementParams::Primaries::DEFAULT; + if (pedited) { + pedited->icm.wprim = true; + } + } assignFromKeyfile(keyFile, "Color Management", "WorkingTRCGamma", pedited, icm.workingTRCGamma, pedited->icm.workingTRCGamma); assignFromKeyfile(keyFile, "Color Management", "WorkingTRCSlope", pedited, icm.workingTRCSlope, pedited->icm.workingTRCSlope); + assignFromKeyfile(keyFile, "Color Management", "Redx", pedited, icm.redx, pedited->icm.redx); + assignFromKeyfile(keyFile, "Color Management", "Redy", pedited, icm.redy, pedited->icm.redy); + assignFromKeyfile(keyFile, "Color Management", "Grex", pedited, icm.grex, pedited->icm.grex); + assignFromKeyfile(keyFile, "Color Management", "Grey", pedited, icm.grey, pedited->icm.grey); + assignFromKeyfile(keyFile, "Color Management", "Blux", pedited, icm.blux, pedited->icm.blux); + assignFromKeyfile(keyFile, "Color Management", "Bluy", pedited, icm.bluy, pedited->icm.bluy); + assignFromKeyfile(keyFile, "Color Management", "Preser", pedited, icm.preser, pedited->icm.preser); + assignFromKeyfile(keyFile, "Color Management", "Fbw", pedited, icm.fbw, pedited->icm.fbw); + assignFromKeyfile(keyFile, "Color Management", "LabGridcieALow", pedited, icm.labgridcieALow, pedited->icm.labgridcieALow); + assignFromKeyfile(keyFile, "Color Management", "LabGridcieBLow", pedited, icm.labgridcieBLow, pedited->icm.labgridcieBLow); + assignFromKeyfile(keyFile, "Color Management", "LabGridcieAHigh", pedited, icm.labgridcieAHigh, pedited->icm.labgridcieAHigh); + assignFromKeyfile(keyFile, "Color Management", "LabGridcieBHigh", pedited, icm.labgridcieBHigh, pedited->icm.labgridcieBHigh); + assignFromKeyfile(keyFile, "Color Management", "LabGridcieGx", pedited, icm.labgridcieGx, pedited->icm.labgridcieGx); + assignFromKeyfile(keyFile, "Color Management", "LabGridcieGy", pedited, icm.labgridcieGy, pedited->icm.labgridcieGy); + assignFromKeyfile(keyFile, "Color Management", "LabGridcieWx", pedited, icm.labgridcieWx, pedited->icm.labgridcieWx); + assignFromKeyfile(keyFile, "Color Management", "LabGridcieWy", pedited, icm.labgridcieWy, pedited->icm.labgridcieWy); + if (keyFile.has_key("Color Management", "aIntent")) { + Glib::ustring intent = keyFile.get_string("Color Management", "aIntent"); + + if (intent == "Perceptual") { + icm.aRendIntent = RI_PERCEPTUAL; + } else if (intent == "Relative") { + icm.aRendIntent = RI_RELATIVE; + } else if (intent == "Saturation") { + icm.aRendIntent = RI_SATURATION; + } else if (intent == "Absolute") { + icm.aRendIntent = RI_ABSOLUTE; + } + + if (pedited) { + pedited->icm.aRendIntent = true; + } + } + assignFromKeyfile(keyFile, "Color Management", "OutputProfile", pedited, icm.outputProfile, pedited->icm.outputProfile); if (ppVersion < 341) { if (icm.outputProfile == "RT_Medium_gsRGB") { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index ef14a6e05..f7ca3e0f6 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1701,6 +1701,46 @@ struct ResizeParams { * Parameters of the color spaces used during the processing */ struct ColorManagementParams { + enum class WorkingTrc { + NONE, + CUSTOM, + BT709, + SRGB, + GAMMA_2_2, + GAMMA_1_8, + LINEAR + }; + + enum class Illuminant { + DEFAULT, + D41, + D50, + D55, + D60, + D65, + D80, + D120, + STDA, + TUNGSTEN_2000K, + TUNGSTEN_1500K + }; + + enum class Primaries { + DEFAULT, + SRGB, + ADOBE_RGB, + PRO_PHOTO, + REC2020, + ACES_P1, + WIDE_GAMUT, + ACES_P0, + BRUCE_RGB, + BETA_RGB, + BEST_RGB, + CUSTOM, + CUSTOM_GRID + }; + Glib::ustring inputProfile; bool toneCurve; bool applyLookTable; @@ -1709,9 +1749,28 @@ struct ColorManagementParams { int dcpIlluminant; Glib::ustring workingProfile; - Glib::ustring workingTRC; + WorkingTrc workingTRC; + Illuminant will; + Primaries wprim; double workingTRCGamma; double workingTRCSlope; + double redx; + double redy; + double grex; + double grey; + double blux; + double bluy; + double preser; + bool fbw; + double labgridcieALow; + double labgridcieBLow; + double labgridcieAHigh; + double labgridcieBHigh; + double labgridcieGx; + double labgridcieGy; + double labgridcieWx; + double labgridcieWy; + RenderingIntent aRendIntent; Glib::ustring outputProfile; RenderingIntent outputIntent; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 7ae919e0a..6c4bfd8f9 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1325,7 +1325,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le if (ri->zeroIsBad()) { // mark all pixels with value zero as bad, has to be called before FF and DF. dcraw sets this flag only for some cameras (mainly Panasonic and Leica) bitmapBads.reset(new PixelsMap(W, H)); - totBP = findZeroPixels(*(bitmapBads.get())); + totBP = findZeroPixels(*bitmapBads); if (settings->verbose) { printf("%d pixels with value zero marked as bad pixels\n", totBP); @@ -1469,7 +1469,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le bitmapBads.reset(new PixelsMap(W, H)); } - int nFound = findHotDeadPixels(*(bitmapBads.get()), raw.hotdeadpix_thresh, raw.hotPixelFilter, raw.deadPixelFilter); + int nFound = findHotDeadPixels(*bitmapBads, raw.hotdeadpix_thresh, raw.hotPixelFilter, raw.deadPixelFilter); totBP += nFound; if (settings->verbose && nFound > 0) { @@ -1484,7 +1484,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le bitmapBads.reset(new PixelsMap(W, H)); } - int n = f.mark(rawData, *(bitmapBads.get())); + int n = f.mark(rawData, *bitmapBads); totBP += n; if (n > 0) { @@ -1548,15 +1548,15 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le if (ri->getSensorType() == ST_BAYER) { if (numFrames == 4) { for (int i = 0; i < 4; ++i) { - interpolateBadPixelsBayer(*(bitmapBads.get()), *rawDataFrames[i]); + interpolateBadPixelsBayer(*bitmapBads, *rawDataFrames[i]); } } else { - interpolateBadPixelsBayer(*(bitmapBads.get()), rawData); + interpolateBadPixelsBayer(*bitmapBads, rawData); } } else if (ri->getSensorType() == ST_FUJI_XTRANS) { - interpolateBadPixelsXtrans(*(bitmapBads.get())); + interpolateBadPixelsXtrans(*bitmapBads); } else { - interpolateBadPixelsNColours(*(bitmapBads.get()), ri->get_colors()); + interpolateBadPixelsNColours(*bitmapBads, ri->get_colors()); } } diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 225cef180..451164b8c 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -200,7 +200,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // EvLLCCurve LUMINANCECURVE, // EvLLCredsk ALLNORAW, // EvDPDNLdetail - ALLNORAW, // EvCATEnabled + //ALLNORAW, // EvCATEnabled + LUMINANCECURVE, // EvCATEnabled LUMINANCECURVE, // EvCATDegree LUMINANCECURVE, // EvCATMethodsur LUMINANCECURVE, // EvCATAdapscen diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index c4ffb91f7..142f2751e 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -449,6 +449,15 @@ public: virtual void autoColorTonChanged(int bwct, int satthres, int satprot) = 0; }; +class AutoprimListener +{ +public: + virtual ~AutoprimListener() = default; + virtual void primChanged(float rx, float ry, float bx, float by, float gx, float gy) = 0; + virtual void iprimChanged(float r_x, float r_y, float b_x, float b_y, float g_x, float g_y, float w_x, float w_y) = 0; +}; + + class AutoBWListener { public: @@ -621,6 +630,8 @@ public: virtual void setAutoBWListener (AutoBWListener* l) = 0; virtual void setAutoWBListener (AutoWBListener* l) = 0; virtual void setAutoColorTonListener (AutoColorTonListener* l) = 0; + virtual void setAutoprimListener (AutoprimListener* l) = 0; + virtual void setAutoChromaListener (AutoChromaListener* l) = 0; virtual void setRetinexListener (RetinexListener* l) = 0; virtual void setWaveletListener (WaveletListener* l) = 0; diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 1cc45aef6..8dc998862 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1455,12 +1455,15 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT ipf.labColorCorrectionRegions(labView); + + if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || !params.colorappearance.enabled) { ipf.EPDToneMap (labView, 5, 6); } ipf.softLight(labView, params.softlight); + if (params.colorappearance.enabled) { CurveFactory::curveLightBrightColor ( params.colorappearance.curve, @@ -1508,7 +1511,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT ipf.ciecam_02float (cieView, adap, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, sk, execsharp, d, dj, yb, rtt); delete cieView; } - + + // color processing //ipf.colorCurve (labView, labView); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index a1c1e6d44..9a0d3b90b 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -16,27 +16,31 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ + +#include +#include + #include "cieimage.h" -#include "dcp.h" -#include "imagefloat.h" -#include "labimage.h" -#include "rtengine.h" +#include "clutstore.h" +#include "color.h" #include "colortemp.h" +#include "curves.h" +#include "dcp.h" +#include "guidedfilter.h" +#include "iccstore.h" +#include "imagefloat.h" #include "imagesource.h" #include "improcfun.h" -#include "curves.h" -#include "iccstore.h" -#include "clutstore.h" +#include "labimage.h" +#include "mytime.h" #include "processingjob.h" #include "procparams.h" -#include -#include -#include "../rtgui/options.h" #include "rawimagesource.h" +#include "rtengine.h" +#include "utils.h" + #include "../rtgui/multilangmgr.h" -#include "mytime.h" -#include "guidedfilter.h" -#include "color.h" +#include "../rtgui/options.h" #undef THREAD_PRIORITY_NORMAL @@ -924,21 +928,6 @@ private: ipf.lab2rgb(labcbdl, *baseImg, params.icm.workingProfile); } -/* //gamma TRC working - if (params.icm.workingTRC == "Custom") { //exec TRC IN free - const Glib::ustring profile = params.icm.workingProfile; - - if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") { - const int cw = baseImg->getWidth(); - const int ch = baseImg->getHeight(); - cmsHTRANSFORM dummyTransForm = nullptr; - // put gamma TRC to 1 - ipf.workingtrc(baseImg, baseImg, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310, dummyTransForm, true, false, false); - //adjust TRC - ipf.workingtrc(baseImg, baseImg, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope, dummyTransForm, false, true, false); - } - } -*/ // RGB processing labView = new LabImage(fw, fh); @@ -1371,6 +1360,7 @@ private: ipf.chromiLuminanceCurve(nullptr, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy); + if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) { ipf.EPDToneMap (labView, 0, 1); } @@ -1570,6 +1560,52 @@ private: ipf.softLight(labView, params.softlight); + + if (params.icm.workingTRC != ColorManagementParams::WorkingTrc::NONE) { + const int GW = labView->W; + const int GH = labView->H; + std::unique_ptr provis; + const float pres = 0.01f * params.icm.preser; + if (pres > 0.f && params.icm.wprim != ColorManagementParams::Primaries::DEFAULT) { + provis.reset(new LabImage(GW, GH)); + provis->CopyFrom(labView); + } + + const std::unique_ptr tmpImage1(new Imagefloat(GW, GH)); + + ipf.lab2rgb(*labView, *tmpImage1, params.icm.workingProfile); + + const float gamtone = params.icm.workingTRCGamma; + const float slotone = params.icm.workingTRCSlope; + + int illum = toUnderlying(params.icm.will); + const int prim = toUnderlying(params.icm.wprim); + + Glib::ustring prof = params.icm.workingProfile; + + cmsHTRANSFORM dummy = nullptr; + int ill = 0; + ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false); + ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, 5, prof, gamtone, slotone, illum, prim, dummy, false, true, true); + + ipf.rgb2lab(*tmpImage1, *labView, params.icm.workingProfile); + // labView and provis + if(provis) { + ipf.preserv(labView, provis.get(), GW, GH); + } + if(params.icm.fbw) { +#ifdef _OPENMP + #pragma omp parallel for +#endif + for (int x = 0; x < GH; x++) + for (int y = 0; y < GW; y++) { + labView->a[x][y] = 0.f; + labView->b[x][y] = 0.f; + } + } + + } + //Colorappearance and tone-mapping associated int f_w = 1, f_h = 1; diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 51ca3a4bc..0140c5b62 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -646,7 +646,7 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited) lastLumamode = pp->colorToning.lumamode; - labgrid->setParams(pp->colorToning.labgridALow / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridBLow / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridAHigh / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridBHigh / ColorToningParams::LABGRID_CORR_MAX, false); + labgrid->setParams(pp->colorToning.labgridALow / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridBLow / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridAHigh / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridBHigh / ColorToningParams::LABGRID_CORR_MAX, 0, 0, 0, 0,false); if (pedited && !pedited->colorToning.method) { method->set_active (7); @@ -715,8 +715,10 @@ void ColorToning::write (ProcParams* pp, ParamsEdited* pedited) pp->colorToning.satProtectionThreshold = satProtectionThreshold->getIntValue(); pp->colorToning.saturatedOpacity = saturatedOpacity->getIntValue(); pp->colorToning.strength = strength->getIntValue(); - - labgrid->getParams(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh); + double zerox = 0.; + double zeroy = 0.; + + labgrid->getParams(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh, zerox, zeroy, zerox, zeroy); pp->colorToning.labgridALow *= ColorToningParams::LABGRID_CORR_MAX; pp->colorToning.labgridAHigh *= ColorToningParams::LABGRID_CORR_MAX; pp->colorToning.labgridBLow *= ColorToningParams::LABGRID_CORR_MAX; @@ -832,7 +834,7 @@ void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited* hlColSat->setDefault (defParams->colorToning.hlColSat); shadowsColSat->setDefault (defParams->colorToning.shadowsColSat); strength->setDefault (defParams->colorToning.strength); - labgrid->setDefault(defParams->colorToning.labgridALow / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridBLow / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridAHigh / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridBHigh / ColorToningParams::LABGRID_CORR_MAX); + labgrid->setDefault(defParams->colorToning.labgridALow / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridBLow / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridAHigh / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridBHigh / ColorToningParams::LABGRID_CORR_MAX, 0, 0, 0, 0); if (pedited) { @@ -1430,7 +1432,9 @@ void ColorToning::labRegionGet(int idx) auto &r = labRegionData[idx]; double la, lb; - labRegionAB->getParams(la, lb, r.a, r.b); + double zerox = 0.; + double zeroy = 0.; + labRegionAB->getParams(la, lb, r.a, r.b, zerox, zeroy, zerox, zeroy); r.saturation = labRegionSaturation->getValue(); r.slope = labRegionSlope->getValue(); r.offset = labRegionOffset->getValue(); @@ -1566,9 +1570,9 @@ void ColorToning::labRegionShow(int idx, bool list_only) disableListener(); } rtengine::procparams::ColorToningParams::LabCorrectionRegion dflt; - auto &r = labRegionData[idx]; + auto &r = labRegionData[idx]; if (!list_only) { - labRegionAB->setParams(0, 0, r.a, r.b, false); + labRegionAB->setParams(0, 0, r.a, r.b,0, 0, 0, 0, false); labRegionSaturation->setValue(r.saturation); labRegionSlope->setValue(r.slope); labRegionOffset->setValue(r.offset); diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index e0fd7cd96..6e3b69904 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -22,6 +22,7 @@ #include "eventmapper.h" #include "guiutils.h" +#include "labgrid.h" #include "options.h" #include "pathutils.h" #include "rtimage.h" @@ -29,6 +30,7 @@ #include "../rtengine/dcp.h" #include "../rtengine/iccstore.h" #include "../rtengine/procparams.h" +#include "../rtengine/utils.h" using namespace rtengine; using namespace rtengine::procparams; @@ -45,15 +47,27 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha EvICMpgrey = m->newEvent(GAMMA, "HISTORY_MSG_ICMPGREY"); EvICMpblux = m->newEvent(GAMMA, "HISTORY_MSG_ICMPBLUX"); EvICMpbluy = m->newEvent(GAMMA, "HISTORY_MSG_ICMPBLUY"); - EvICMgamm = m->newEvent(AUTOEXP, "HISTORY_MSG_ICM_WORKING_GAMMA"); - EvICMslop = m->newEvent(AUTOEXP, "HISTORY_MSG_ICM_WORKING_SLOPE"); - EvICMtrcinMethod = m->newEvent(AUTOEXP, "HISTORY_MSG_ICM_WORKING_TRC_METHOD"); - + EvICMgamm = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WORKING_GAMMA"); + EvICMslop = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WORKING_SLOPE"); + EvICMtrcinMethod = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WORKING_TRC_METHOD"); + EvICMwillMethod = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WORKING_ILLUM_METHOD"); + EvICMwprimMethod = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WORKING_PRIM_METHOD"); + EvICMredx = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_REDX"); + EvICMredy = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_REDY"); + EvICMgrex = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_GREX"); + EvICMgrey = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_GREY"); + EvICMblux = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_BLUX"); + EvICMbluy = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_BLUY"); + EvaIntent = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_AINTENT"); + EvICMpreser = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_PRESER"); + EvICMLabGridciexy = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICL_LABGRIDCIEXY"); + EvICMfbw = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_FBW"); isBatchMode = lastToneCurve = lastApplyLookTable = lastApplyBaselineExposureOffset = lastApplyHueSatMap = false; ipDialog = Gtk::manage(new MyFileChooserButton(M("TP_ICM_INPUTDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); ipDialog->set_tooltip_text(M("TP_ICM_INPUTCUSTOM_TOOLTIP")); bindCurrentFolder(*ipDialog, options.lastIccDir); + labgridcie = Gtk::manage(new LabGrid(EvICMLabGridciexy, M("TP_ICM_LABGRID_CIEXY"), true, true)); // ------------------------------- Input profile @@ -184,44 +198,184 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha wProfNames->set_active(0); - // wFrame->add(*wVBox); + wFrame->add(*wProfVBox); //-----------------gamma TRC working + Gtk::Frame *trcFrame = Gtk::manage(new Gtk::Frame(M("TP_ICM_TRCFRAME"))); + trcFrame->set_label_align(0.025, 0.5); + Gtk::Box *trcProfVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); + trcFrame->set_tooltip_text(M("TP_ICM_TRCFRAME_TOOLTIP")); - wTRCHBox = Gtk::manage(new Gtk::Box()); + wTRCBox = Gtk::manage(new Gtk::Box()); - Gtk::Label* wtrclab = Gtk::manage(new Gtk::Label(M("TP_ICM_WORKING_TRC"))); - - wTRCHBox->pack_start(*wtrclab, Gtk::PACK_SHRINK); wTRC = Gtk::manage(new MyComboBoxText()); - wTRCHBox->pack_start(*wTRC, Gtk::PACK_EXPAND_WIDGET); - // wProfVBox->pack_start(*wTRCHBox, Gtk::PACK_EXPAND_WIDGET); + wTRCBox->pack_start(*wTRC, Gtk::PACK_EXPAND_WIDGET); + trcProfVBox->pack_start(*wTRCBox, Gtk::PACK_EXPAND_WIDGET); wTRC->append(M("TP_ICM_WORKING_TRC_NONE")); wTRC->append(M("TP_ICM_WORKING_TRC_CUSTOM")); + wTRC->append(M("TP_ICM_WORKING_TRC_BT709")); + wTRC->append(M("TP_ICM_WORKING_TRC_SRGB")); + wTRC->append(M("TP_ICM_WORKING_TRC_22")); + wTRC->append(M("TP_ICM_WORKING_TRC_18")); + wTRC->append(M("TP_ICM_WORKING_TRC_LIN")); -// wTRC->set_active(0); -// wTRC->set_tooltip_text(M("TP_ICM_WORKING_TRC_TOOLTIP")); + wTRC->set_active(0); + wTRC->set_tooltip_text(M("TP_ICM_TRC_TOOLTIP")); + + wFrame->set_tooltip_text(M("TP_ICM_WORKING_TRC_TOOLTIP")); - wGamma = Gtk::manage(new Adjuster(M("TP_ICM_WORKING_TRC_GAMMA"), 0.40, 15.0, 0.001, 2.4)); - wSlope = Gtk::manage(new Adjuster(M("TP_ICM_WORKING_TRC_SLOPE"), 0., 150., 0.01, 12.92310)); -// wProfVBox->pack_start(*wGamma, Gtk::PACK_SHRINK); -// wGamma->show(); + wGamma = Gtk::manage(new Adjuster(M("TP_ICM_WORKING_TRC_GAMMA"), 0.40, 15.0, 0.001, 2.222)); + wSlope = Gtk::manage(new Adjuster(M("TP_ICM_WORKING_TRC_SLOPE"), 0., 300., 0.01, 4.5)); + trcProfVBox->pack_start(*wGamma, Gtk::PACK_SHRINK); + wGamma->show(); -// wProfVBox->pack_start(*wSlope, Gtk::PACK_SHRINK); -// wSlope->show(); + trcProfVBox->pack_start(*wSlope, Gtk::PACK_SHRINK); + wSlope->show(); + willuBox = Gtk::manage(new Gtk::Box()); + willulab = Gtk::manage(new Gtk::Label(M("TP_ICM_WORKING_ILLU") + ":")); + + willuBox->pack_start(*willulab, Gtk::PACK_SHRINK); + will = Gtk::manage(new MyComboBoxText()); + willuBox->pack_start(*will, Gtk::PACK_EXPAND_WIDGET); + trcProfVBox->pack_start(*willuBox, Gtk::PACK_EXPAND_WIDGET); + will->append(M("TP_ICM_WORKING_ILLU_NONE")); + will->append(M("TP_ICM_WORKING_ILLU_D41")); + will->append(M("TP_ICM_WORKING_ILLU_D50")); + will->append(M("TP_ICM_WORKING_ILLU_D55")); + will->append(M("TP_ICM_WORKING_ILLU_D60")); + will->append(M("TP_ICM_WORKING_ILLU_D65")); + will->append(M("TP_ICM_WORKING_ILLU_D80")); + will->append(M("TP_ICM_WORKING_ILLU_D120")); + will->append(M("TP_ICM_WORKING_ILLU_STDA")); + will->append(M("TP_ICM_WORKING_ILLU_2000")); + will->append(M("TP_ICM_WORKING_ILLU_1500")); + will->set_active(0); + will->set_tooltip_text(M("TP_ICM_ILLUMPRIM_TOOLTIP")); + + + wprimBox = Gtk::manage(new Gtk::Box()); + wprimlab = Gtk::manage(new Gtk::Label(M("TP_ICM_WORKING_PRIM") + ":")); + + wprimBox->pack_start(*wprimlab, Gtk::PACK_SHRINK); + wprim = Gtk::manage(new MyComboBoxText()); + wprimBox->pack_start(*wprim, Gtk::PACK_EXPAND_WIDGET); + fbw = Gtk::manage(new Gtk::CheckButton((M("TP_ICM_FBW")))); + fbw->set_active(true); + trcProfVBox->pack_start(*wprimBox, Gtk::PACK_EXPAND_WIDGET); + trcProfVBox->pack_start(*fbw, Gtk::PACK_EXPAND_WIDGET); + + wprim->append(M("TP_ICM_WORKING_PRIM_NONE")); + wprim->append(M("TP_ICM_WORKING_PRIM_SRGB")); + wprim->append(M("TP_ICM_WORKING_PRIM_ADOB")); + wprim->append(M("TP_ICM_WORKING_PRIM_PROP")); + wprim->append(M("TP_ICM_WORKING_PRIM_REC")); + wprim->append(M("TP_ICM_WORKING_PRIM_ACE")); + wprim->append(M("TP_ICM_WORKING_PRIM_WID")); + wprim->append(M("TP_ICM_WORKING_PRIM_AC0")); + wprim->append(M("TP_ICM_WORKING_PRIM_BRU")); + wprim->append(M("TP_ICM_WORKING_PRIM_BET")); + wprim->append(M("TP_ICM_WORKING_PRIM_BST")); + wprim->append(M("TP_ICM_WORKING_PRIM_CUS")); + wprim->append(M("TP_ICM_WORKING_PRIM_CUSGR")); + wprim->set_active(0); + + wprim->set_tooltip_text(M("TP_ICM_PRIMILLUM_TOOLTIP")); + + + redx = Gtk::manage(new Adjuster(M("TC_PRIM_REDX"), 0.41, 1.0, 0.0001, 0.6400)); + setExpandAlignProperties(redx, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + redy = Gtk::manage(new Adjuster(M("TC_PRIM_REDY"), 0.0, 0.70, 0.0001, 0.3300)); + setExpandAlignProperties(redy, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + grex = Gtk::manage(new Adjuster(M("TC_PRIM_GREX"), -0.1, 0.4, 0.0001, 0.2100)); + setExpandAlignProperties(grex, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + grey = Gtk::manage(new Adjuster(M("TC_PRIM_GREY"), 0.50, 1.0, 0.0001, 0.7100)); + setExpandAlignProperties(grey, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + blux = Gtk::manage(new Adjuster(M("TC_PRIM_BLUX"), -0.1, 0.4, 0.0001, 0.1500)); + setExpandAlignProperties(blux, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + bluy = Gtk::manage(new Adjuster(M("TC_PRIM_BLUY"), -0.1, 0.5, 0.0001, 0.060)); + setExpandAlignProperties(bluy, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + + redx->set_tooltip_text(M("TP_ICM_PRIMRED_TOOLTIP")); + grex->set_tooltip_text(M("TP_ICM_PRIMGRE_TOOLTIP")); + blux->set_tooltip_text(M("TP_ICM_PRIMBLU_TOOLTIP")); + blr = Gtk::manage(new Gtk::Label(M(" "))); + blg = Gtk::manage(new Gtk::Label(M(" "))); + blb = Gtk::manage(new Gtk::Label(M(" "))); + + redBox = Gtk::manage(new Gtk::Box()); + redBox->pack_start(*redx);//, Gtk::PACK_SHRINK); + redBox->pack_start(*blr, Gtk::PACK_SHRINK); + redBox->pack_start(*redy);//, Gtk::PACK_SHRINK); + redFrame = Gtk::manage(new Gtk::Frame(M("TP_ICM_REDFRAME"))); + redFrame->set_label_align(0.025, 0.5); + Gtk::Box *redVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); + redVBox->pack_start(*redBox, Gtk::PACK_EXPAND_WIDGET); + redFrame->set_tooltip_text(M("TP_ICM_WORKING_PRIMFRAME_TOOLTIP")); + + greBox = Gtk::manage(new Gtk::Box()); + greBox->pack_start(*grex);//, Gtk::PACK_SHRINK, 2); + greBox->pack_start(*blg, Gtk::PACK_SHRINK); + greBox->pack_start(*grey);//, Gtk::PACK_SHRINK, 2); + redVBox->pack_start(*greBox, Gtk::PACK_EXPAND_WIDGET); + Gtk::Separator* const separator1 = Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_VERTICAL)); + Gtk::Separator* const separator2 = Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_VERTICAL)); + + bluBox = Gtk::manage(new Gtk::Box()); + bluBox->pack_start(*blux);//, Gtk::PACK_SHRINK); + bluBox->pack_start(*blb, Gtk::PACK_SHRINK); + bluBox->pack_start(*bluy);//, Gtk::PACK_SHRINK); + redVBox->pack_start(*bluBox, Gtk::PACK_EXPAND_WIDGET); + preser = Gtk::manage(new Adjuster(M("TP_ICM_WORKING_PRESER"), 0., 100., 0.5, 0.)); + preser->setAdjusterListener(this); + + preBox = Gtk::manage(new Gtk::Box()); + preBox->pack_start(*preser, Gtk::PACK_SHRINK); + redVBox->pack_start(*separator1, Gtk::PACK_SHRINK); + redVBox->pack_start(*preBox, Gtk::PACK_EXPAND_WIDGET); + redVBox->pack_start(*separator2, Gtk::PACK_SHRINK); + + cielab = Gtk::manage(new Gtk::Label(M("TP_ICM_WORKING_CIEDIAG") + ":")); + + redVBox->pack_start(*cielab, Gtk::PACK_SHRINK); + + redVBox->pack_start(*labgridcie, Gtk::PACK_EXPAND_WIDGET, 4); + + redFrame->add(*redVBox); wGamma->setAdjusterListener(this); + wSlope->setLogScale(16, 0); wSlope->setAdjusterListener(this); + redx->setAdjusterListener(this); + redy->setAdjusterListener(this); + grex->setAdjusterListener(this); + grey->setAdjusterListener(this); + blux->setAdjusterListener(this); + bluy->setAdjusterListener(this); wGamma->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); wSlope->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - wFrame->add(*wProfVBox); + // Rendering intent + riaHBox = Gtk::manage(new Gtk::Box()); + Gtk::Label* abIntentLbl = Gtk::manage(new Gtk::Label(M("TP_ICM_PROFILEINTENT"))); + riaHBox->pack_start(*abIntentLbl, Gtk::PACK_SHRINK); + aRendIntent.reset(new PopUpButton()); + aRendIntent->addEntry("intent-perceptual.png", M("PREFERENCES_INTENT_PERCEPTUAL")); + aRendIntent->addEntry("intent-relative.png", M("PREFERENCES_INTENT_RELATIVE")); + aRendIntent->addEntry("intent-saturation.png", M("PREFERENCES_INTENT_SATURATION")); + aRendIntent->addEntry("intent-absolute.png", M("PREFERENCES_INTENT_ABSOLUTE")); + aRendIntent->setSelected(1); + aRendIntent->show(); + riaHBox->pack_start(*aRendIntent->buttonGroup, Gtk::PACK_EXPAND_PADDING); + + trcFrame->add(*trcProfVBox); pack_start(*wFrame, Gtk::PACK_EXPAND_WIDGET); + pack_start(*trcFrame, Gtk::PACK_EXPAND_WIDGET); + pack_start(*redFrame, Gtk::PACK_EXPAND_WIDGET); // ---------------------------- Output profile @@ -229,6 +383,7 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha Gtk::Frame *oFrame = Gtk::manage(new Gtk::Frame(M("TP_ICM_OUTPUTPROFILE"))); oFrame->set_label_align(0.025, 0.5); + oFrame->set_tooltip_text(M("TP_ICM_OUTPUTPROFILE_TOOLTIP")); Gtk::Box* oProfVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); @@ -303,9 +458,13 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha wprofnamesconn = wProfNames->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::wpChanged)); oprofnamesconn = oProfNames->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::opChanged)); orendintentconn = oRendIntent->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::oiChanged)); + arendintentconn = aRendIntent->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::aiChanged)); dcpillconn = dcpIll->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::dcpIlluminantChanged)); wtrcconn = wTRC->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::wtrcinChanged)); + willconn = will->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::willChanged)); + wprimconn = wprim->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::wprimChanged)); + fbwconn = fbw->signal_toggled().connect(sigc::mem_fun(*this, &ICMPanel::fbwChanged)); obpcconn = obpc->signal_toggled().connect(sigc::mem_fun(*this, &ICMPanel::oBPCChanged)); tcurveconn = ckbToneCurve->signal_toggled().connect(sigc::mem_fun(*this, &ICMPanel::toneCurveChanged)); ltableconn = ckbApplyLookTable->signal_toggled().connect(sigc::mem_fun(*this, &ICMPanel::applyLookTableChanged)); @@ -339,6 +498,13 @@ void ICMPanel::updateRenderingIntent(const Glib::ustring &profile) oRendIntent->setItemSensitivity(1, supportsRelative); oRendIntent->setItemSensitivity(2, supportsSaturation); oRendIntent->setItemSensitivity(3, supportsAbsolute); + + aRendIntent->set_sensitive(true); + aRendIntent->setItemSensitivity(0, supportsPerceptual); + aRendIntent->setItemSensitivity(1, supportsRelative); + aRendIntent->setItemSensitivity(2, supportsSaturation); + aRendIntent->setItemSensitivity(3, supportsAbsolute); + } else { oRendIntent->setItemSensitivity(0, true); oRendIntent->setItemSensitivity(1, true); @@ -346,9 +512,91 @@ void ICMPanel::updateRenderingIntent(const Glib::ustring &profile) oRendIntent->setItemSensitivity(3, true); oRendIntent->set_sensitive(false); oRendIntent->setSelected(1); + + aRendIntent->setItemSensitivity(0, true); + aRendIntent->setItemSensitivity(1, true); + aRendIntent->setItemSensitivity(2, true); + aRendIntent->setItemSensitivity(3, true); + aRendIntent->set_sensitive(false); + aRendIntent->setSelected(1); + } } +ICMPanel::~ICMPanel() +{ + idle_register.destroy(); +} + +void ICMPanel::primChanged (float rx, float ry, float bx, float by, float gx, float gy) +{ //update sliders R G B Ciexy + nextrx = rx; + nextry = ry; + nextbx = bx; + nextby = by; + nextgx = gx; + nextgy = gy; + + idle_register.add( + [this]() -> bool + { + disableListener(); + redx->setValue(nextrx); + redy->setValue(nextry); + blux->setValue(nextbx); + bluy->setValue(nextby); + grex->setValue(nextgx); + grey->setValue(nextgy); + + enableListener(); + return false; + } + ); +} + +void ICMPanel::iprimChanged (float r_x, float r_y, float b_x, float b_y, float g_x, float g_y, float w_x, float w_y) +{//update CIE xy graph + nextrx = r_x; + nextry = r_y; + nextbx = b_x; + nextby = b_y; + nextgx = g_x; + nextgy = g_y; + nextwx = w_x; + nextwy = w_y; + //convert xy datas in datas for labgrid areas + nextrx = 1.81818f * (nextrx + 0.1f) - 1.f; + nextry = 1.81818f * (nextry + 0.1f) - 1.f; + nextbx = 1.81818f * (nextbx + 0.1f) - 1.f; + nextby = 1.81818f * (nextby + 0.1f) - 1.f; + nextgx = 1.81818f * (nextgx + 0.1f) - 1.f; + nextgy = 1.81818f * (nextgy + 0.1f) - 1.f; + nextwx = 1.81818f * (nextwx + 0.1f) - 1.f; + nextwy = 1.81818f * (nextwy + 0.1f) - 1.f; + + idle_register.add( + [this]() -> bool + { + disableListener(); + labgridcie->setParams(nextrx, nextry, nextbx, nextby, nextgx, nextgy, nextwx, nextwy, false); + enableListener(); + return false; + } + ); +} + + +void ICMPanel::setEditProvider(EditDataProvider *provider) +{ + //in case of +} + +void ICMPanel::setListener(ToolPanelListener *tpl) +{//enable listener Toolpanel and Labgridcie + ToolPanel::setListener(tpl); + labgridcie->setListener(tpl); +} + void ICMPanel::updateDCP(int dcpIlluminant, Glib::ustring dcp_name) { ConnectionBlocker dcpillconn_(dcpillconn); @@ -481,6 +729,7 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) disableListener(); ConnectionBlocker obpcconn_(obpcconn); + ConnectionBlocker fbwconn_(fbwconn); ConnectionBlocker ipc_(ipc); ConnectionBlocker tcurveconn_(tcurveconn); ConnectionBlocker ltableconn_(ltableconn); @@ -489,7 +738,11 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) ConnectionBlocker wprofnamesconn_(wprofnamesconn); ConnectionBlocker oprofnamesconn_(oprofnamesconn); ConnectionBlocker orendintentconn_(orendintentconn); + ConnectionBlocker arendintentconn_(arendintentconn); ConnectionBlocker dcpillconn_(dcpillconn); + ConnectionBlocker wtrcconn_(wtrcconn); + ConnectionBlocker willconn_(willconn); + ConnectionBlocker wprimconn_(wprimconn); if (pp->icm.inputProfile.substr(0, 5) != "file:" && !ipDialog->get_filename().empty()) { ipDialog->set_filename(pp->icm.inputProfile); @@ -525,13 +778,15 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) wProfNames->set_active_text(pp->icm.workingProfile); - if (pp->icm.workingTRC == "none") { - wTRC->set_active(0); - } else if (pp->icm.workingTRC == "Custom") { - wTRC->set_active(1); - } + wTRC->set_active(rtengine::toUnderlying(pp->icm.workingTRC)); + + will->set_active(rtengine::toUnderlying(pp->icm.will)); + + wprim->set_active(rtengine::toUnderlying(pp->icm.wprim)); wtrcinChanged(); + willChanged(); + wprimChanged(); if (pp->icm.outputProfile == ColorManagementParams::NoICMString) { oProfNames->set_active_text(M("TP_ICM_NOICM")); @@ -544,8 +799,10 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) } oRendIntent->setSelected(pp->icm.outputIntent); + aRendIntent->setSelected(pp->icm.aRendIntent); obpc->set_active(pp->icm.outputBPC); + fbw->set_active(pp->icm.fbw); ckbToneCurve->set_active(pp->icm.toneCurve); lastToneCurve = pp->icm.toneCurve; ckbApplyLookTable->set_active(pp->icm.applyLookTable); @@ -557,10 +814,19 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) wGamma->setValue(pp->icm.workingTRCGamma); wSlope->setValue(pp->icm.workingTRCSlope); + redx->setValue(pp->icm.redx); + redy->setValue(pp->icm.redy); + grex->setValue(pp->icm.grex); + grey->setValue(pp->icm.grey); + blux->setValue(pp->icm.blux); + bluy->setValue(pp->icm.bluy); + preser->setValue(pp->icm.preser); + labgridcie->setParams(pp->icm.labgridcieALow, pp->icm.labgridcieBLow, pp->icm.labgridcieAHigh, pp->icm.labgridcieBHigh, pp->icm.labgridcieGx, pp->icm.labgridcieGy, pp->icm.labgridcieWx, pp->icm.labgridcieWy, false); if (pedited) { iunchanged->set_active(!pedited->icm.inputProfile); obpc->set_inconsistent(!pedited->icm.outputBPC); + fbw->set_inconsistent(!pedited->icm.fbw); ckbToneCurve->set_inconsistent(!pedited->icm.toneCurve); ckbApplyLookTable->set_inconsistent(!pedited->icm.applyLookTable); ckbApplyBaselineExposureOffset->set_inconsistent(!pedited->icm.applyBaselineExposureOffset); @@ -578,6 +844,10 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) oRendIntent->setSelected(4); } + if (!pedited->icm.aRendIntent) { + aRendIntent->setSelected(4); + } + if (!pedited->icm.dcpIlluminant) { dcpIll->set_active_text(M("GENERAL_UNCHANGED")); } @@ -586,11 +856,206 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) wTRC->set_active_text(M("GENERAL_UNCHANGED")); } + if (!pedited->icm.will) { + will->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->icm.wprim) { + wprim->set_active_text(M("GENERAL_UNCHANGED")); + } + labgridcie->setEdited(pedited->icm.labgridcieALow || pedited->icm.labgridcieBLow || pedited->icm.labgridcieAHigh || pedited->icm.labgridcieBHigh || pedited->icm.labgridcieGx || pedited->icm.labgridcieGy || pedited->icm.labgridcieWx || pedited->icm.labgridcieWy); + wGamma->setEditedState(pedited->icm.workingTRCGamma ? Edited : UnEdited); wSlope->setEditedState(pedited->icm.workingTRCSlope ? Edited : UnEdited); + redx->setEditedState(pedited->icm.redx ? Edited : UnEdited); + redy->setEditedState(pedited->icm.redy ? Edited : UnEdited); + grex->setEditedState(pedited->icm.grex ? Edited : UnEdited); + grey->setEditedState(pedited->icm.grey ? Edited : UnEdited); + blux->setEditedState(pedited->icm.blux ? Edited : UnEdited); + bluy->setEditedState(pedited->icm.bluy ? Edited : UnEdited); + preser->setEditedState(pedited->icm.preser ? Edited : UnEdited); } + switch (ColorManagementParams::WorkingTrc(wTRC->get_active_row_number())) { + case ColorManagementParams::WorkingTrc::NONE: { + wSlope->set_sensitive(false); + wGamma->set_sensitive(false); + will->set_sensitive(false); + willulab->set_sensitive(false); + wprim->set_sensitive(false); + fbw->set_sensitive(false); + wprimlab->set_sensitive(false); + riaHBox->set_sensitive(false); + redFrame->hide(); + break; + } + + case ColorManagementParams::WorkingTrc::CUSTOM: { + will->set_sensitive(false); + willulab->set_sensitive(true); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + if ( + ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM + && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID + ) { + will->set_sensitive(false); + redBox->set_sensitive(false); + greBox->set_sensitive(false); + bluBox->set_sensitive(false); + labgridcie->set_sensitive(false); + + } else { + will->set_sensitive(false); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::CUSTOM) { + will->set_sensitive(true); + } + redBox->set_sensitive(true); + greBox->set_sensitive(true); + bluBox->set_sensitive(true); + labgridcie->set_sensitive(true); + } + + } + riaHBox->set_sensitive(true); + + if (pp->icm.workingTRCGamma <= 1.) { + wGamma->set_sensitive(true); + wSlope->set_sensitive(false); + } else { + wGamma->set_sensitive(true); + wSlope->set_sensitive(true); + } + break; + } + + case ColorManagementParams::WorkingTrc::BT709: + wGamma->setValue(2.222); + wSlope->setValue(4.5); + will->set_sensitive(true); + willulab->set_sensitive(true); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + } + riaHBox->set_sensitive(true); + break; + case ColorManagementParams::WorkingTrc::SRGB: + wGamma->setValue(2.4); + wSlope->setValue(12.92); + will->set_sensitive(true); + willulab->set_sensitive(true); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + riaHBox->set_sensitive(true); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + } + break; + case ColorManagementParams::WorkingTrc::GAMMA_2_2: + wGamma->setValue(2.2); + wSlope->setValue(0.); + will->set_sensitive(true); + willulab->set_sensitive(true); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + redFrame->show(); + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + riaHBox->set_sensitive(true); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + } + break; + case ColorManagementParams::WorkingTrc::GAMMA_1_8: + wGamma->setValue(1.8); + wSlope->setValue(0.); + will->set_sensitive(true); + willulab->set_sensitive(true); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + riaHBox->set_sensitive(true); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + } + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + break; + case ColorManagementParams::WorkingTrc::LINEAR: + wGamma->setValue(1.); + wSlope->setValue(1.); + will->set_sensitive(true); + willulab->set_sensitive(true); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + riaHBox->set_sensitive(true); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + } + break; + } + + switch (ColorManagementParams::Primaries(wprim->get_active_row_number())) { + case ColorManagementParams::Primaries::DEFAULT: + case ColorManagementParams::Primaries::SRGB: + case ColorManagementParams::Primaries::ADOBE_RGB: + case ColorManagementParams::Primaries::PRO_PHOTO: + case ColorManagementParams::Primaries::REC2020: + case ColorManagementParams::Primaries::ACES_P1: + case ColorManagementParams::Primaries::WIDE_GAMUT: + case ColorManagementParams::Primaries::ACES_P0: + case ColorManagementParams::Primaries::BRUCE_RGB: + case ColorManagementParams::Primaries::BETA_RGB: + case ColorManagementParams::Primaries::BEST_RGB: { + labgridcie->set_sensitive(false); + will->set_sensitive(false); + break; + } + + case ColorManagementParams::Primaries::CUSTOM: { + will->set_sensitive(true); + labgridcie->set_sensitive(false); + break; + } + + case ColorManagementParams::Primaries::CUSTOM_GRID: { + labgridcie->set_sensitive(true); + redBox->set_sensitive(false); + greBox->set_sensitive(false); + bluBox->set_sensitive(false); + will->set_sensitive(false); + break; + } + } + enableListener(); } @@ -615,7 +1080,7 @@ void ICMPanel::write(ProcParams* pp, ParamsEdited* pedited) pp->icm.workingProfile = wProfNames->get_active_text(); pp->icm.dcpIlluminant = rtengine::max(dcpIll->get_active_row_number(), 0); - pp->icm.workingTRC = wTRC->get_active_text(); + labgridcie->getParams(pp->icm.labgridcieALow, pp->icm.labgridcieBLow, pp->icm.labgridcieAHigh, pp->icm.labgridcieBHigh, pp->icm.labgridcieGx, pp->icm.labgridcieGy, pp->icm.labgridcieWx, pp->icm.labgridcieWy); if (oProfNames->get_active_text() == M("TP_ICM_NOICM")) { pp->icm.outputProfile = ColorManagementParams::NoICMString; @@ -631,27 +1096,43 @@ void ICMPanel::write(ProcParams* pp, ParamsEdited* pedited) pp->icm.outputIntent = rtengine::RI_RELATIVE; } - if (wTRC->get_active_row_number() == 0) { - pp->icm.workingTRC = "none"; - } else if (wTRC->get_active_row_number() == 1) { - pp->icm.workingTRC = "Custom"; + int aintentVal = aRendIntent->getSelected(); + + if (aintentVal >= 0 && aintentVal < RI__COUNT) { + pp->icm.aRendIntent = static_cast(aintentVal); + } else { + pp->icm.aRendIntent = rtengine::RI_RELATIVE; } + pp->icm.workingTRC = ColorManagementParams::WorkingTrc(wTRC->get_active_row_number()); + pp->icm.will = ColorManagementParams::Illuminant(will->get_active_row_number()); + pp->icm.wprim = ColorManagementParams::Primaries(wprim->get_active_row_number()); + pp->icm.toneCurve = ckbToneCurve->get_active(); pp->icm.applyLookTable = ckbApplyLookTable->get_active(); pp->icm.applyBaselineExposureOffset = ckbApplyBaselineExposureOffset->get_active(); pp->icm.applyHueSatMap = ckbApplyHueSatMap->get_active(); pp->icm.outputBPC = obpc->get_active(); - pp->icm.workingTRCGamma = (double) wGamma->getValue(); - pp->icm.workingTRCSlope = (double) wSlope->getValue(); + pp->icm.fbw = fbw->get_active(); + pp->icm.workingTRCGamma = wGamma->getValue(); + pp->icm.workingTRCSlope = wSlope->getValue(); + pp->icm.redx = redx->getValue(); + pp->icm.redy = redy->getValue(); + pp->icm.grex = grex->getValue(); + pp->icm.grey = grey->getValue(); + pp->icm.blux = blux->getValue(); + pp->icm.bluy = bluy->getValue(); pp->toneCurve.fromHistMatching = false; + pp->icm.preser = preser->getValue(); if (pedited) { pedited->icm.inputProfile = !iunchanged->get_active(); pedited->icm.workingProfile = wProfNames->get_active_text() != M("GENERAL_UNCHANGED"); pedited->icm.outputProfile = oProfNames->get_active_text() != M("GENERAL_UNCHANGED"); pedited->icm.outputIntent = oRendIntent->getSelected() < 4; + pedited->icm.aRendIntent = aRendIntent->getSelected() < 4; pedited->icm.outputBPC = !obpc->get_inconsistent(); + pedited->icm.fbw = !fbw->get_inconsistent(); pedited->icm.dcpIlluminant = dcpIll->get_active_text() != M("GENERAL_UNCHANGED"); pedited->icm.toneCurve = !ckbToneCurve->get_inconsistent(); pedited->icm.applyLookTable = !ckbApplyLookTable->get_inconsistent(); @@ -660,21 +1141,50 @@ void ICMPanel::write(ProcParams* pp, ParamsEdited* pedited) pedited->icm.workingTRCGamma = wGamma->getEditedState(); pedited->icm.workingTRCSlope = wSlope->getEditedState(); pedited->icm.workingTRC = wTRC->get_active_text() != M("GENERAL_UNCHANGED"); - } + pedited->icm.will = will->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->icm.wprim = wprim->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->icm.redx = redx->getEditedState(); + pedited->icm.redy = redy->getEditedState(); + pedited->icm.labgridcieALow = pedited->icm.labgridcieBLow = pedited->icm.labgridcieAHigh = pedited->icm.labgridcieBHigh = pedited->icm.labgridcieGx = pedited->icm.labgridcieGy = pedited->icm.labgridcieWx = pedited->icm.labgridcieWy = labgridcie->getEdited(); + } } void ICMPanel::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited) { wGamma->setDefault(defParams->icm.workingTRCGamma); wSlope->setDefault(defParams->icm.workingTRCSlope); + redx->setDefault(defParams->icm.redx); + redy->setDefault(defParams->icm.redy); + grex->setDefault(defParams->icm.grex); + grey->setDefault(defParams->icm.grey); + blux->setDefault(defParams->icm.blux); + bluy->setDefault(defParams->icm.bluy); + preser->setDefault(defParams->icm.preser); + labgridcie->setDefault(defParams->icm.labgridcieALow, defParams->icm.labgridcieBLow , defParams->icm.labgridcieAHigh, defParams->icm.labgridcieBHigh, defParams->icm.labgridcieGx, defParams->icm.labgridcieGy, defParams->icm.labgridcieWx, defParams->icm.labgridcieWy); if (pedited) { wGamma->setDefaultEditedState(pedited->icm.workingTRCGamma ? Edited : UnEdited); wSlope->setDefaultEditedState(pedited->icm.workingTRCSlope ? Edited : UnEdited); + redx->setDefaultEditedState(pedited->icm.redx ? Edited : UnEdited); + redy->setDefaultEditedState(pedited->icm.redy ? Edited : UnEdited); + grex->setDefaultEditedState(pedited->icm.grex ? Edited : UnEdited); + grey->setDefaultEditedState(pedited->icm.grey ? Edited : UnEdited); + blux->setDefaultEditedState(pedited->icm.blux ? Edited : UnEdited); + bluy->setDefaultEditedState(pedited->icm.bluy ? Edited : UnEdited); + labgridcie->setEdited((pedited->icm.labgridcieALow || pedited->icm.labgridcieBLow || pedited->icm.labgridcieAHigh || pedited->icm.labgridcieBHigh || pedited->icm.labgridcieGx || pedited->icm.labgridcieGy || pedited->icm.labgridcieWx || pedited->icm.labgridcieWy) ? Edited : UnEdited); + preser->setDefaultEditedState(pedited->icm.preser ? Edited : UnEdited); } else { wGamma->setDefaultEditedState(Irrelevant); wSlope->setDefaultEditedState(Irrelevant); + redx->setDefaultEditedState(Irrelevant); + redy->setDefaultEditedState(Irrelevant); + grex->setDefaultEditedState(Irrelevant); + grey->setDefaultEditedState(Irrelevant); + blux->setDefaultEditedState(Irrelevant); + bluy->setDefaultEditedState(Irrelevant); + preser->setDefaultEditedState(Irrelevant); + labgridcie->setEdited(Edited); } } @@ -685,9 +1195,28 @@ void ICMPanel::adjusterChanged(Adjuster* a, double newval) Glib::ustring costr2 = Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), newval); if (a == wGamma) { + if (wGamma->getValue() <= 1.) { + wSlope->set_sensitive(false); + } else { + wSlope->set_sensitive(true); + } listener->panelChanged(EvICMgamm, costr2); } else if (a == wSlope) { listener->panelChanged(EvICMslop, costr2); + } else if (a == redx) { + listener->panelChanged(EvICMredx, costr2); + } else if (a == redy) { + listener->panelChanged(EvICMredy, costr2); + } else if (a == grex) { + listener->panelChanged(EvICMgrex, costr2); + } else if (a == grey) { + listener->panelChanged(EvICMgrey, costr2); + } else if (a == blux) { + listener->panelChanged(EvICMblux, costr2); + } else if (a == bluy) { + listener->panelChanged(EvICMbluy, costr2); + } else if (a == preser) { + listener->panelChanged(EvICMpreser, costr2); } } @@ -702,13 +1231,236 @@ void ICMPanel::wpChanged() void ICMPanel::wtrcinChanged() { - if (wTRC->get_active_row_number() == 0) { - wGamma->set_sensitive(false); - wSlope->set_sensitive(false); + switch (ColorManagementParams::WorkingTrc(wTRC->get_active_row_number())) { + case ColorManagementParams::WorkingTrc::NONE: { + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + will->set_sensitive(false); + willulab->set_sensitive(false); + wprim->set_sensitive(false); + fbw->set_sensitive(false); + wprimlab->set_sensitive(false); + redFrame->hide(); + riaHBox->set_sensitive(false); + break; + } - } else { - wGamma->set_sensitive(true); - wSlope->set_sensitive(true); + case ColorManagementParams::WorkingTrc::CUSTOM: { + will->set_sensitive(false); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + willulab->set_sensitive(true); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + if ( + ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM + && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID + ) { + redBox->set_sensitive(false); + greBox->set_sensitive(false); + bluBox->set_sensitive(false); + } else { + redBox->set_sensitive(true); + greBox->set_sensitive(true); + bluBox->set_sensitive(true); + } + } + riaHBox->set_sensitive(true); + if (wGamma->getValue() <= 1.) { + wGamma->set_sensitive(true); + wSlope->set_sensitive(false); + } else { + wGamma->set_sensitive(true); + wSlope->set_sensitive(true); + } + break; + } + + case ColorManagementParams::WorkingTrc::BT709: { + wGamma->setValue(2.222); + wSlope->setValue(4.5); + will->set_sensitive(false); + willulab->set_sensitive(true); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + if ( + ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM + && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID + ) { + redBox->set_sensitive(false); + greBox->set_sensitive(false); + bluBox->set_sensitive(false); + } + } + riaHBox->set_sensitive(true); + break; + } + + case ColorManagementParams::WorkingTrc::SRGB: { + wGamma->setValue(2.4); + wSlope->setValue(12.92); + will->set_sensitive(false); + willulab->set_sensitive(true); + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + riaHBox->set_sensitive(true); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + if ( + ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM + && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID + ) { + redBox->set_sensitive(false); + greBox->set_sensitive(false); + bluBox->set_sensitive(false); + } else { + redBox->set_sensitive(true); + greBox->set_sensitive(true); + bluBox->set_sensitive(true); + } + } + break; + } + + case ColorManagementParams::WorkingTrc::GAMMA_2_2: { + wGamma->setValue(2.2); + wSlope->setValue(0.); + will->set_sensitive(false); + willulab->set_sensitive(true); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + riaHBox->set_sensitive(true); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + if ( + ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM + && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID + ) { + redBox->set_sensitive(false); + greBox->set_sensitive(false); + bluBox->set_sensitive(false); + } else { + redBox->set_sensitive(true); + greBox->set_sensitive(true); + bluBox->set_sensitive(true); + } + } + break; + } + + case ColorManagementParams::WorkingTrc::GAMMA_1_8: { + wGamma->setValue(1.8); + wSlope->setValue(0.); + will->set_sensitive(false); + willulab->set_sensitive(true); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + riaHBox->set_sensitive(true); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + if ( + ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM + && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID + ) { + redBox->set_sensitive(false); + greBox->set_sensitive(false); + bluBox->set_sensitive(false); + } else { + redBox->set_sensitive(true); + greBox->set_sensitive(true); + bluBox->set_sensitive(true); + } + } + break; + } + + case ColorManagementParams::WorkingTrc::LINEAR: { + wGamma->setValue(1.0); + wSlope->setValue(1.); + will->set_sensitive(false); + willulab->set_sensitive(true); + wprim->set_sensitive(true); + fbw->set_sensitive(true); + wprimlab->set_sensitive(true); + wGamma->set_sensitive(false); + wSlope->set_sensitive(false); + riaHBox->set_sensitive(true); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + redFrame->hide(); + } else { + redFrame->show(); + if ( + ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM + && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID + ) { + redBox->set_sensitive(false); + greBox->set_sensitive(false); + bluBox->set_sensitive(false); + } else { + redBox->set_sensitive(true); + greBox->set_sensitive(true); + bluBox->set_sensitive(true); + } + } + break; + } + } + wprimChanged(); + + switch (ColorManagementParams::Primaries(wprim->get_active_row_number())) { + case ColorManagementParams::Primaries::DEFAULT: + case ColorManagementParams::Primaries::SRGB: + case ColorManagementParams::Primaries::ADOBE_RGB: + case ColorManagementParams::Primaries::PRO_PHOTO: + case ColorManagementParams::Primaries::REC2020: + case ColorManagementParams::Primaries::ACES_P1: + case ColorManagementParams::Primaries::WIDE_GAMUT: + case ColorManagementParams::Primaries::ACES_P0: + case ColorManagementParams::Primaries::BRUCE_RGB: + case ColorManagementParams::Primaries::BETA_RGB: + case ColorManagementParams::Primaries::BEST_RGB: { + labgridcie->set_sensitive(false); + will->set_sensitive(false); + break; + } + + case ColorManagementParams::Primaries::CUSTOM: { + will->set_sensitive(true); + labgridcie->set_sensitive(false); + break; + } + + case ColorManagementParams::Primaries::CUSTOM_GRID: { + labgridcie->set_sensitive(true); + will->set_sensitive(false); + break; + } + } + + if (ColorManagementParams::WorkingTrc(wTRC->get_active_row_number()) == ColorManagementParams::WorkingTrc::NONE) { + redFrame->hide(); } if (listener) { @@ -716,6 +1468,284 @@ void ICMPanel::wtrcinChanged() } } +void ICMPanel::willChanged() +{ + switch (ColorManagementParams::Primaries(wprim->get_active_row_number())) { + case ColorManagementParams::Primaries::DEFAULT: + case ColorManagementParams::Primaries::SRGB: + case ColorManagementParams::Primaries::ADOBE_RGB: + case ColorManagementParams::Primaries::PRO_PHOTO: + case ColorManagementParams::Primaries::REC2020: + case ColorManagementParams::Primaries::ACES_P1: + case ColorManagementParams::Primaries::WIDE_GAMUT: + case ColorManagementParams::Primaries::ACES_P0: + case ColorManagementParams::Primaries::BRUCE_RGB: + case ColorManagementParams::Primaries::BETA_RGB: + case ColorManagementParams::Primaries::BEST_RGB: { + labgridcie->set_sensitive(false); + will->set_sensitive(false); + break; + } + + case ColorManagementParams::Primaries::CUSTOM: { + will->set_sensitive(true); + labgridcie->set_sensitive(false); + break; + } + + case ColorManagementParams::Primaries::CUSTOM_GRID: { + labgridcie->set_sensitive(true); + will->set_sensitive(false); + break; + } + } + + if (listener) { + listener->panelChanged(EvICMwillMethod, will->get_active_text()); + } +} + + + +void ICMPanel::wprimChanged() +{ + switch (ColorManagementParams::Primaries(wprim->get_active_row_number())) { + case ColorManagementParams::Primaries::DEFAULT: + case ColorManagementParams::Primaries::CUSTOM: + case ColorManagementParams::Primaries::CUSTOM_GRID: { + break; + } + + case ColorManagementParams::Primaries::SRGB: { + redx->setValue(0.64); + redy->setValue(0.33); + grex->setValue(0.30); + grey->setValue(0.60); + blux->setValue(0.15); + bluy->setValue(0.06); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65)); + break; + } + + case ColorManagementParams::Primaries::ADOBE_RGB: { + redx->setValue(0.64); + redy->setValue(0.33); + grex->setValue(0.21); + grey->setValue(0.71); + blux->setValue(0.15); + bluy->setValue(0.06); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65)); + break; + } + + case ColorManagementParams::Primaries::PRO_PHOTO: { + redx->setValue(0.7347); + redy->setValue(0.2653); + grex->setValue(0.1596); + grey->setValue(0.8404); + blux->setValue(0.0366); + bluy->setValue(0.0001); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50)); + break; + } + + case ColorManagementParams::Primaries::REC2020: { + redx->setValue(0.708); + redy->setValue(0.292); + grex->setValue(0.17); + grey->setValue(0.797); + blux->setValue(0.131); + bluy->setValue(0.046); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65)); + break; + } + + case ColorManagementParams::Primaries::ACES_P1: { + redx->setValue(0.713); + redy->setValue(0.293); + grex->setValue(0.165); + grey->setValue(0.830); + blux->setValue(0.128); + bluy->setValue(0.044); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D60)); + break; + } + + case ColorManagementParams::Primaries::WIDE_GAMUT: { + redx->setValue(0.735); + redy->setValue(0.265); + grex->setValue(0.115); + grey->setValue(0.826); + blux->setValue(0.1570); + bluy->setValue(0.018); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50)); + break; + } + + case ColorManagementParams::Primaries::ACES_P0: { + redx->setValue(0.7347); + redy->setValue(0.2653); + grex->setValue(0.); + grey->setValue(1.0); + blux->setValue(0.0001); + bluy->setValue(-0.077); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D60)); + break; + } + + case ColorManagementParams::Primaries::BRUCE_RGB: { + redx->setValue(0.64); + redy->setValue(0.33); + grex->setValue(0.28); + grey->setValue(0.65); + blux->setValue(0.15); + bluy->setValue(0.06); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65)); + break; + } + + case ColorManagementParams::Primaries::BETA_RGB: { + redx->setValue(0.6888); + redy->setValue(0.3112); + grex->setValue(0.1986); + grey->setValue(0.7551); + blux->setValue(0.1265); + bluy->setValue(0.0352); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50)); + break; + } + + case ColorManagementParams::Primaries::BEST_RGB: { + redx->setValue(0.7347); + redy->setValue(0.2653); + grex->setValue(0.2150); + grey->setValue(0.7750); + blux->setValue(0.130); + bluy->setValue(0.035); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50)); + break; + } + } + + + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) { + if (wProfNames->get_active_text() == "Rec2020") { + redx->setValue(0.708); + redy->setValue(0.292); + grex->setValue(0.17); + grey->setValue(0.797); + blux->setValue(0.131); + bluy->setValue(0.046); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65)); + } else if (wProfNames->get_active_text() == "sRGB") { + redx->setValue(0.64); + redy->setValue(0.33); + grex->setValue(0.30); + grey->setValue(0.60); + blux->setValue(0.15); + bluy->setValue(0.06); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65)); + } else if (wProfNames->get_active_text() == "Adobe RGB") { + redx->setValue(0.64); + redy->setValue(0.33); + grex->setValue(0.21); + grey->setValue(0.71); + blux->setValue(0.15); + bluy->setValue(0.06); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65)); + } else if (wProfNames->get_active_text() == "ProPhoto") { + redx->setValue(0.7347); + redy->setValue(0.2653); + grex->setValue(0.1596); + grey->setValue(0.8404); + blux->setValue(0.0366); + bluy->setValue(0.0001); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50)); + } else if (wProfNames->get_active_text() == "ACESp1") { + redx->setValue(0.713); + redy->setValue(0.293); + grex->setValue(0.165); + grey->setValue(0.830); + blux->setValue(0.128); + bluy->setValue(0.044); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D60)); + } else if (wProfNames->get_active_text() == "WideGamut") { + redx->setValue(0.735); + redy->setValue(0.265); + grex->setValue(0.115); + grey->setValue(0.826); + blux->setValue(0.1570); + bluy->setValue(0.018); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50)); + } else if (wProfNames->get_active_text() == "ACESp0") { + redx->setValue(0.7347); + redy->setValue(0.2653); + grex->setValue(0.); + grey->setValue(1.0); + blux->setValue(0.0001); + bluy->setValue(-0.077); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D60)); + } else if (wProfNames->get_active_text() == "BruceRGB") { + redx->setValue(0.64); + redy->setValue(0.33); + grex->setValue(0.28); + grey->setValue(0.65); + blux->setValue(0.15); + bluy->setValue(0.06); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65)); + } else if (wProfNames->get_active_text() == "Beta RGB") { + redx->setValue(0.6888); + redy->setValue(0.3112); + grex->setValue(0.1986); + grey->setValue(0.7551); + blux->setValue(0.1265); + bluy->setValue(0.0352); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50)); + } else if (wProfNames->get_active_text() == "BestRGB") { + redx->setValue(0.7347); + redy->setValue(0.2653); + grex->setValue(0.2150); + grey->setValue(0.7750); + blux->setValue(0.130); + bluy->setValue(0.035); + will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50)); + } + + redFrame->hide(); + } else { + redFrame->show(); + + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM) { + redBox->set_sensitive(false); + greBox->set_sensitive(false); + bluBox->set_sensitive(false); + labgridcie->set_sensitive(false); + will->set_sensitive(false); + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::CUSTOM_GRID) { + labgridcie->set_sensitive(true); + } + } else { + redBox->set_sensitive(true); + greBox->set_sensitive(true); + bluBox->set_sensitive(true); + labgridcie->set_sensitive(false); + will->set_sensitive(true); + } + + } + willChanged (); + + if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::CUSTOM_GRID) { + labgridcie->set_sensitive(true); + } else { + labgridcie->set_sensitive(false); + } + + if (listener) { + listener->panelChanged(EvICMwprimMethod, wprim->get_active_text()); + } +} + void ICMPanel::dcpIlluminantChanged() { if (listener) { @@ -897,6 +1927,39 @@ void ICMPanel::oiChanged(int n) } } +void ICMPanel::aiChanged(int n) +{ + + if (listener) { + Glib::ustring str; + + switch (n) { + case 0: + str = M("PREFERENCES_INTENT_PERCEPTUAL"); + break; + + case 1: + str = M("PREFERENCES_INTENT_RELATIVE"); + break; + + case 2: + str = M("PREFERENCES_INTENT_SATURATION"); + break; + + case 3: + str = M("PREFERENCES_INTENT_ABSOLUTE"); + break; + + case 4: + default: + str = M("GENERAL_UNCHANGED"); + break; + } + + listener->panelChanged(EvaIntent, str); + } +} + void ICMPanel::oBPCChanged() { if (multiImage) { @@ -923,6 +1986,32 @@ void ICMPanel::oBPCChanged() } } +void ICMPanel::fbwChanged() +{ + if (multiImage) { + if (fbw->get_inconsistent()) { + fbw->set_inconsistent(false); + fbwconn.block(true); + fbw->set_active(false); + fbwconn.block(false); + } else if (lastfbw) { + fbw->set_inconsistent(true); + } + + lastfbw = fbw->get_active(); + } + + if (listener) { + if (fbw->get_inconsistent()) { + listener->panelChanged(EvICMfbw, M("GENERAL_UNCHANGED")); + } else if (fbw->get_active()) { + listener->panelChanged(EvICMfbw, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(EvICMfbw, M("GENERAL_DISABLED")); + } + } +} + void ICMPanel::setRawMeta(bool raw, const rtengine::FramesData* pMeta) { @@ -948,6 +2037,8 @@ void ICMPanel::ipSelectionChanged() ipChanged(); } + + void ICMPanel::saveReferencePressed() { @@ -1022,10 +2113,21 @@ void ICMPanel::setBatchMode(bool batchMode) oProfNames->append(M("GENERAL_UNCHANGED")); oRendIntent->addEntry("template-24.png", M("GENERAL_UNCHANGED")); oRendIntent->show(); + aRendIntent->addEntry("template-24.png", M("GENERAL_UNCHANGED")); + aRendIntent->show(); wProfNames->append(M("GENERAL_UNCHANGED")); wTRC->append(M("GENERAL_UNCHANGED")); + will->append(M("GENERAL_UNCHANGED")); + wprim->append(M("GENERAL_UNCHANGED")); dcpIll->append(M("GENERAL_UNCHANGED")); wGamma->showEditedCB(); wSlope->showEditedCB(); + redx->showEditedCB(); + redy->showEditedCB(); + grex->showEditedCB(); + grey->showEditedCB(); + blux->showEditedCB(); + bluy->showEditedCB(); + preser->showEditedCB(); } diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index 81a011c59..fb3673188 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -36,24 +36,36 @@ public: virtual void saveInputICCReference(const Glib::ustring& fname, bool apply_wb) = 0; }; +class LabGrid; + class ICMPanel final : public ToolParamBlock, - public AdjusterListener, - public FoldableToolPanel + public FoldableToolPanel, + public rtengine::AutoprimListener, + public AdjusterListener { protected: Gtk::Frame* dcpFrame; Gtk::Frame* coipFrame; + Gtk::Frame* redFrame; Adjuster* wGamma; Adjuster* wSlope; + Adjuster* redx; + Adjuster* redy; + Adjuster* grex; + Adjuster* grey; + Adjuster* blux; + Adjuster* bluy; + Adjuster* preser; Gtk::Label* labmga; Gtk::Box* gabox; + Gtk::Label* blr; + Gtk::Label* blg; + Gtk::Label* blb; - - //bool freegamma; bool lastToneCurve; sigc::connection tcurveconn; bool lastApplyLookTable; @@ -64,6 +76,8 @@ protected: sigc::connection hsmconn; bool lastobpc; sigc::connection obpcconn; + bool lastfbw; + sigc::connection fbwconn; bool isBatchMode; private: @@ -79,9 +93,34 @@ private: rtengine::ProcEvent EvICMgamm; rtengine::ProcEvent EvICMslop; rtengine::ProcEvent EvICMtrcinMethod; + rtengine::ProcEvent EvICMwillMethod; + rtengine::ProcEvent EvICMwprimMethod; + rtengine::ProcEvent EvICMredx; + rtengine::ProcEvent EvICMredy; + rtengine::ProcEvent EvICMgrex; + rtengine::ProcEvent EvICMgrey; + rtengine::ProcEvent EvICMblux; + rtengine::ProcEvent EvICMbluy; + rtengine::ProcEvent EvaIntent; + rtengine::ProcEvent EvICMpreser; + rtengine::ProcEvent EvICMLabGridciexy; + rtengine::ProcEvent EvICMfbw; + LabGrid *labgridcie; + IdleRegister idle_register; + Gtk::Box* willuBox; + Gtk::Label* willulab; + Gtk::Box* wprimBox; + Gtk::Label* wprimlab; + Gtk::Label* cielab; + Gtk::Box* redBox; + Gtk::Box* greBox; + Gtk::Box* bluBox; + Gtk::Box* riaHBox; + Gtk::Box* preBox; Gtk::Box* iVBox; - Gtk::Box* wTRCHBox; + Gtk::Box* wTRCBox; + Gtk::CheckButton* fbw; Gtk::CheckButton* obpc; Gtk::RadioButton* inone; @@ -101,6 +140,12 @@ private: sigc::connection wprofnamesconn; MyComboBoxText* wTRC; sigc::connection wtrcconn; + MyComboBoxText* will; + sigc::connection willconn; + MyComboBoxText* wprim; + sigc::connection wprimconn; + std::unique_ptr aRendIntent; + sigc::connection arendintentconn; MyComboBoxText* oProfNames; sigc::connection oprofnamesconn; @@ -113,26 +158,43 @@ private: sigc::connection ipc; Glib::ustring oldip; ICMPanelListener* icmplistener; - + double dcpTemperatures[2]; Glib::ustring lastRefFilename; Glib::ustring camName; void updateDCP(int dcpIlluminant, Glib::ustring dcp_name); void updateRenderingIntent(const Glib::ustring &profile); + + float nextrx; + float nextry; + float nextbx; + float nextby; + float nextgx; + float nextgy; + float nextwx; + float nextwy; + public: ICMPanel(); + ~ICMPanel() override; void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; void setBatchMode(bool batchMode) override; void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void adjusterChanged(Adjuster* a, double newval) override; + void primChanged (float rx, float ry, float bx, float by, float gx, float gy) override; + void iprimChanged (float r_x, float r_y, float b_x, float b_y, float g_x, float g_y, float w_x, float w_y) override; void wpChanged(); void wtrcinChanged(); + void willChanged(); + void wprimChanged(); void opChanged(); void oiChanged(int n); + void aiChanged(int n); void oBPCChanged(); + void fbwChanged(); void ipChanged(); void ipSelectionChanged(); void dcpIlluminantChanged(); @@ -143,9 +205,13 @@ public: void setRawMeta(bool raw, const rtengine::FramesData* pMeta); void saveReferencePressed(); + void setListener(ToolPanelListener* tpl) override; + void setEditProvider(EditDataProvider *provider) override; void setICMPanelListener(ICMPanelListener* ipl) { icmplistener = ipl; } + }; + diff --git a/rtgui/labgrid.cc b/rtgui/labgrid.cc index d8a22b1d9..d0443d58d 100644 --- a/rtgui/labgrid.cc +++ b/rtgui/labgrid.cc @@ -4,6 +4,8 @@ * * Copyright (c) 2017 Alberto Griggio * + * Copyright (c) 2021 Jacques Desmis for CIE xy graph + * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -57,22 +59,34 @@ bool LabGridArea::notifyListener() { return int(v * 1000) / 1000.f; }; - listener->panelChanged(evt, Glib::ustring::compose(evtMsg, round(high_a), round(high_b), round(low_a), round(low_b))); + if (! ciexy_enabled){ + listener->panelChanged(evt, Glib::ustring::compose(evtMsg, round(high_a), round(high_b), round(low_a), round(low_b))); + } else { + float high_a1 = 0.55f * (high_a + 1.f) - 0.1f; + float high_b1 = 0.55f * (high_b + 1.f) - 0.1f; + float low_a1 = 0.55f * (low_a + 1.f) - 0.1f; + float low_b1 = 0.55f * (low_b + 1.f) - 0.1f; + float gre_x1 = 0.55f * (gre_x + 1.f) - 0.1f; + float gre_y1 = 0.55f * (gre_y + 1.f) - 0.1f; + listener->panelChanged(evt, Glib::ustring::compose(evtMsg, round(low_a1), round(low_b1), round(gre_x1), round(gre_y1), round(high_a1), round(high_b1))); + } } return false; } -LabGridArea::LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low): +LabGridArea::LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low, bool ciexy): Gtk::DrawingArea(), evt(evt), evtMsg(msg), litPoint(NONE), - low_a(0.f), high_a(0.f), low_b(0.f), high_b(0.f), - defaultLow_a(0.f), defaultHigh_a(0.f), defaultLow_b(0.f), defaultHigh_b(0.f), + low_a(0.f), high_a(0.f), low_b(0.f), high_b(0.f), gre_x(0.f), gre_y(0.f), whi_x(0.f), whi_y(0.f),//these variables are used as xy in Ciexy - no change labels + defaultLow_a(0.f), defaultHigh_a(0.f), defaultLow_b(0.f), defaultHigh_b(0.f), defaultgre_x(0.f), defaultgre_y(0.f), defaultwhi_x(0.f), defaultwhi_y(0.f), listener(nullptr), edited(false), isDragged(false), - low_enabled(enable_low) + low_enabled(enable_low), + ciexy_enabled(ciexy) + { set_can_focus(false); // prevent moving the grid while you're moving a point add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK); @@ -80,16 +94,21 @@ LabGridArea::LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool get_style_context()->add_class("drawingarea"); } -void LabGridArea::getParams(double &la, double &lb, double &ha, double &hb) const +void LabGridArea::getParams(double &la, double &lb, double &ha, double &hb, double &gx, double &gy, double &wx, double &wy) const { la = low_a; ha = high_a; lb = low_b; hb = high_b; + gx = gre_x; + gy = gre_y; + wx = whi_x; + wy = whi_y; + // printf("la=%f ha=%f lb=%f hb=%f gx=%f gy=%f\n", la, ha, lb, hb, gx, gy); } -void LabGridArea::setParams(double la, double lb, double ha, double hb, bool notify) +void LabGridArea::setParams(double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy, bool notify) { const double lo = -1.0; const double hi = 1.0; @@ -97,27 +116,37 @@ void LabGridArea::setParams(double la, double lb, double ha, double hb, bool not low_b = rtengine::LIM(lb, lo, hi); high_a = rtengine::LIM(ha, lo, hi); high_b = rtengine::LIM(hb, lo, hi); + gre_x = rtengine::LIM(gx, lo, hi); + gre_y = rtengine::LIM(gy, lo, hi); + whi_x = rtengine::LIM(wx, lo, hi); + whi_y = rtengine::LIM(wy, lo, hi); + queue_draw(); if (notify) { notifyListener(); } } -void LabGridArea::setDefault (double la, double lb, double ha, double hb) +void LabGridArea::setDefault (double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy) { defaultLow_a = la; defaultLow_b = lb; defaultHigh_a = ha; defaultHigh_b = hb; + defaultgre_x = gx; + defaultgre_y = gy; + defaultwhi_x = wx; + defaultwhi_y = wy; } void LabGridArea::reset(bool toInitial) { if (toInitial) { - setParams(defaultLow_a, defaultLow_b, defaultHigh_a, defaultHigh_b, true); + setParams(defaultLow_a, defaultLow_b, defaultHigh_a, defaultHigh_b, defaultgre_x, defaultgre_y, defaultwhi_x, defaultwhi_y, true); } else { - setParams(0., 0., 0., 0., true); + // printf("RESET \n"); + setParams(0., 0., 0., 0., 0., 0., 0., 0., true); } } @@ -166,6 +195,7 @@ bool LabGridArea::on_draw(const ::Cairo::RefPtr &crf) Gtk::Border padding = getPadding(style); // already scaled Cairo::RefPtr cr = getContext(); + if (isDirty()) { int width = allocation.get_width(); int height = allocation.get_height(); @@ -195,55 +225,208 @@ bool LabGridArea::on_draw(const ::Cairo::RefPtr &crf) // flip y: cr->translate(0, height); cr->scale(1., -1.); - const int cells = 8; - float step = 12000.f / float(cells/2); - double cellW = double(width) / double(cells); - double cellH = double(height) / double(cells); - double cellYMin = 0.; - double cellYMax = std::floor(cellH); - for (int j = 0; j < cells; j++) { - double cellXMin = 0.; - double cellXMax = std::floor(cellW); - for (int i = 0; i < cells; i++) { - float R, G, B; - float x, y, z; - int ii = i - cells/2; - int jj = j - cells/2; - float a = step * (ii + 0.5f); - float b = step * (jj + 0.5f); - Color::Lab2XYZ(25000.f, a, b, x, y, z); - Color::xyz2srgb(x, y, z, R, G, B); - cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f); - cr->rectangle( - cellXMin, - cellYMin, - cellXMax - cellXMin - (i == cells-1 ? 0. : double(s)), - cellYMax - cellYMin - (j == cells-1 ? 0. : double(s)) - ); - cellXMin = cellXMax; - cellXMax = std::floor(cellW * double(i+2) + 0.01); - cr->fill(); - } - cellYMin = cellYMax; - cellYMax = std::floor(cellH * double(j+2) + 0.01); - } + if (! ciexy_enabled) {//draw cells for Labgrid + int cells = 8; + float step = 12000.f / float(cells/2); + double cellW = double(width) / double(cells); + double cellH = double(height) / double(cells); + double cellYMin = 0.; + double cellYMax = std::floor(cellH); + for (int j = 0; j < cells; j++) { + double cellXMin = 0.; + double cellXMax = std::floor(cellW); + for (int i = 0; i < cells; i++) { + float R, G, B; + float x, y, z; + int ii = i - cells/2; + int jj = j - cells/2; + float a = step * (ii + 0.5f); + float b = step * (jj + 0.5f); + Color::Lab2XYZ(25000.f, a, b, x, y, z); + Color::xyz2srgb(x, y, z, R, G, B); + cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f); + cr->rectangle( + cellXMin, + cellYMin, + cellXMax - cellXMin - (i == cells-1 ? 0. : double(s)), + cellYMax - cellYMin - (j == cells-1 ? 0. : double(s)) + ); + cellXMin = cellXMax; + cellXMax = std::floor(cellW * double(i+2) + 0.01); + cr->fill(); + } + cellYMin = cellYMax; + cellYMax = std::floor(cellH * double(j+2) + 0.01); + } + } else {//cells for CIE xy + int cells = 600; + float step = 1.f / float(cells); + double cellW = double(width) / double(cells); + double cellH = double(height) / double(cells); + double cellYMin = 0.; + double cellYMax = std::floor(cellH); + //various approximations to simulate Ciexy curves graph + // this graph is not accurate...I replace curve by polygon or parabolic + float xa = 0.2653f / (0.7347f - 0.17f); + float xb = -0.17f * xa; + //linaer values + // float ax = (0.1f - 0.6f) / 0.08f; + // float bx = 0.6f; + // float ax0 = -0.1f / (0.17f - 0.08f); + // float bx0 = -0.17f* ax0; + float axs = (0.2653f - 0.65f) / (0.7347f - 0.35f); + float bxs = 0.65f - axs * 0.35f; + // float axss = (0.7f - 0.83f) / (0.3f - 0.1f); + // float bxss = 0.7f - 0.3f * axss; + //float bxsss = 0.65f; + //float axsss = (0.83f - bxsss) / 0.05f; + //float bx4s = 0.83f; + float ay = 0.4f; + float by = 0.4f; + for (int j = 0; j < cells; j++) { + double cellXMin = 0.; + double cellXMax = std::floor(cellW); + for (int i = 0; i < cells; i++) { + float R, G, B; + float XX, YY, ZZ; + float x = 1.1f * step * i - 0.1f;//Graph CIExy with -0.1 to 1 - must be enough + float y = 1.1f * step * j - 0.1;//Graph CIExy with -0.1 to 1 - must be enough + if(y > 0.5f) { + YY = 0.6f; + } else { + YY = ay * y + by; + } + XX = (x * YY) / y; + ZZ = ((1.f - x - y)* YY) / y; + float yr = xa * x + xb; + // float y0 = ax0 * x + bx0; + // float y1 = ax * x + bx; + float y2 = axs * x + bxs; + // float y3 = axss * x + bxss; + // float y4 = axsss * x + bxsss; + // float y5 = bx4s; + float y6 = 22.52f * x * x - 7.652f * x + 0.65f;//parabolic passing in x=0.17 y=0 - x=0.1 y =0.11 - x=0 y= 0.65 + float y3 = -1.266666f * x * x -0.170002f * x + 0.859686f;//other parabolic for green passing in x=0.35 y=0.65 - x=0.20 y=0.775 - x=0.1 y=0.83 + float y4 = -60.71428f * x * x + 6.821428f * x + 0.65f;//other parabolic x=0 y=0.65 - x=0.03 y=0.8 - x=0.07 y=0.83 + //small difference in the connection of the 2 last parabolic + + Color::xyz2srgb(XX, YY, ZZ, R, G, B); + //replace color by gray + if(y < yr && x > 0.17f) { + R = 0.7f; G = 0.7f; B = 0.7f; + } + /* + if(y < y0 && x <= 0.17f && x >= 0.08f) { + R = 0.7f; G = 0.7f; B = 0.7f; + } + if(y < y1 && x < 0.08f) { + R = 0.7f; G = 0.7f; B = 0.7f; + } + */ + if(y < y6 && y < 0.65f && x < 0.17f) { + R = 0.7f; G = 0.7f; B = 0.7f; + } + + if(y > y2 && x > 0.35f) {//0.35 + R = 0.7f; G = 0.7f; B = 0.7f; + } + if(y > y3 && x <= 0.35f && x > 0.06f) {//0.35 + R = 0.7f; G = 0.7f; B = 0.7f; + } + if(y > y4 && x <= 0.06f) { + R = 0.7f; G = 0.7f; B = 0.7f; + } + // if(y > y5 && x >= 0.07f && x <= 0.1f) { + // R = 0.7f; G = 0.7f; B = 0.7f; + // } + + cr->set_source_rgb(R , G , B); + + cr->rectangle( + cellXMin, + cellYMin, + cellXMax - cellXMin - (i == cells-1 ? 0. : 0.f * double(s)), + cellYMax - cellYMin - (j == cells-1 ? 0. : 0.f * double(s)) + ); + cellXMin = cellXMax; + cellXMax = std::floor(cellW * double(i+2) + 0.001); + cr->fill(); + } + cellYMin = cellYMax; + cellYMax = std::floor(cellH * double(j+2) + 0.001); + } + } // drawing the connection line cr->set_antialias(Cairo::ANTIALIAS_DEFAULT); - float loa, hia, lob, hib; + float loa, hia, lob, hib, grx, gry, whx, why; loa = .5 * (width + width * low_a); hia = .5 * (width + width * high_a); lob = .5 * (height + height * low_b); hib = .5 * (height + height * high_b); - cr->set_line_width(2. * double(s)); + grx = .5 * (width + width * gre_x); + gry = .5 * (height + height * gre_y); + whx = .5 * (width + width * whi_x); + why = .5 * (height + height * whi_y); + cr->set_line_width(1.5f * double(s)); cr->set_source_rgb(0.6, 0.6, 0.6); cr->move_to(loa, lob); cr->line_to(hia, hib); + if (ciexy_enabled) { + cr->move_to(loa, lob); + cr->line_to(grx, gry); + cr->move_to(grx, gry); + cr->line_to(hia, hib); + } cr->stroke(); + if (ciexy_enabled) { + //to convert from / to Ciexy <=> area + // pos_area = 1.81818 * (x + 0.1) - 1 + // x = 0.55 * (pos_area + 1) - 0.1 + cr->set_line_width(0.2f * double(s)); + cr->set_source_rgb(0.1, 0.1, 0.1); + //draw horiz and vertical lines + for(int i = 0; i < 22; i++) { + cr->move_to(0.04545 * i * width, 0.); + cr->line_to(0.04545 * i * width, height); + } + for(int i = 0; i < 22; i++) { + cr->move_to(0., 0.04545 * i * height ); + cr->line_to(width, 0.04545 * i * height); + } + + cr->stroke(); + //draw abciss and ordonate + cr->set_line_width(1.f * double(s)); + cr->set_source_rgb(0.4, 0., 0.); + cr->move_to(0.04545 * 2 * width, 0.); + cr->line_to(0.04545 * 2 * width, height); + cr->move_to(0., 0.04545 * 2 * height ); + cr->line_to(width, 0.04545 * 2 * height); + cr->stroke(); + + //draw 0 and 1 with circle and lines + cr->set_line_width(1.2f * double(s)); + cr->set_source_rgb(0.4, 0., 0.); + cr->arc(0.06 * width, 0.06 * height, 0.016 * width, 0, 2. * rtengine::RT_PI); + cr->stroke(); + cr->set_line_width(1.5f * double(s)); + cr->set_source_rgb(0.4, 0., 0.); + cr->move_to(0.985 * width, 0.08 * height); + cr->line_to(0.985 * width, 0.055 * height); + + cr->move_to(0.07 * width, 0.99 * height); + cr->line_to(0.07 * width, 0.965 * height); + + cr->stroke(); + + } + + // drawing points if (low_enabled) { - cr->set_source_rgb(0.1, 0.1, 0.1); + cr->set_source_rgb(0.1, 0.1, 0.1);//black for red in Ciexy if (litPoint == LOW) { cr->arc(loa, lob, 5 * s, 0, 2. * rtengine::RT_PI); } else { @@ -252,7 +435,23 @@ bool LabGridArea::on_draw(const ::Cairo::RefPtr &crf) cr->fill(); } - cr->set_source_rgb(0.9, 0.9, 0.9); + if (ciexy_enabled) { + cr->set_source_rgb(0.5, 0.5, 0.5);//gray for green + if (litPoint == GRE) { + cr->arc(grx, gry, 5 * s, 0, 2. * rtengine::RT_PI); + } else { + cr->arc(grx, gry, 3 * s, 0, 2. * rtengine::RT_PI); + } + cr->fill(); + } + + if (ciexy_enabled) {//White Point + cr->set_source_rgb(1., 1., 1.);//White + cr->arc(whx, why, 3 * s, 0, 2. * rtengine::RT_PI); + cr->fill(); + } + + cr->set_source_rgb(0.9, 0.9, 0.9);//white for blue en Ciexy if (litPoint == HIGH) { cr->arc(hia, hib, 5 * s, 0, 2. * rtengine::RT_PI); } else { @@ -269,10 +468,11 @@ bool LabGridArea::on_draw(const ::Cairo::RefPtr &crf) bool LabGridArea::on_button_press_event(GdkEventButton *event) { if (event->button == 1) { + if (!ciexy_enabled) { if (event->type == GDK_2BUTTON_PRESS) { switch (litPoint) { case NONE: - low_a = low_b = high_a = high_b = 0.f; + low_a = low_b = high_a = high_b = gre_x = gre_y = 0.f; break; case LOW: low_a = low_b = 0.f; @@ -280,6 +480,9 @@ bool LabGridArea::on_button_press_event(GdkEventButton *event) case HIGH: high_a = high_b = 0.f; break; + case GRE: + gre_x = gre_y = 0.f; + break; } edited = true; notifyListener(); @@ -287,6 +490,16 @@ bool LabGridArea::on_button_press_event(GdkEventButton *event) } else if (event->type == GDK_BUTTON_PRESS && litPoint != NONE) { isDragged = true; } + } else { + if (event->type == GDK_2BUTTON_PRESS) { + edited = true; + notifyListener(); + queue_draw(); + } else if (event->type == GDK_BUTTON_PRESS && litPoint != NONE) { + isDragged = true; + } + + } return false; } return true; @@ -328,6 +541,9 @@ bool LabGridArea::on_motion_notify_event(GdkEventMotion *event) } else if (litPoint == HIGH) { high_a = ma; high_b = mb; + } else if (litPoint == GRE) { + gre_x = ma; + gre_y = mb; } edited = true; grab_focus(); @@ -343,13 +559,18 @@ bool LabGridArea::on_motion_notify_event(GdkEventMotion *event) float lb = low_b; float ha = high_a; float hb = high_b; + float gx = gre_x; + float gy = gre_y; const float thrs = 0.05f; const float distlo = (la - ma) * (la - ma) + (lb - mb) * (lb - mb); const float disthi = (ha - ma) * (ha - ma) + (hb - mb) * (hb - mb); + const float distgxy = (gx - ma) * (gx - ma) + (gy - mb) * (gy - mb); if (low_enabled && distlo < thrs * thrs && distlo < disthi) { litPoint = LOW; } else if (disthi < thrs * thrs && disthi <= distlo) { litPoint = HIGH; + } else if (ciexy_enabled && distgxy < thrs * thrs && distgxy <= distlo) { + litPoint = GRE; } if ((oldLitPoint == NONE && litPoint != NONE) || (oldLitPoint != NONE && litPoint == NONE)) { queue_draw(); @@ -391,6 +612,10 @@ bool LabGridArea::lowEnabled() const return low_enabled; } +bool LabGridArea::ciexyEnabled() const +{ + return ciexy_enabled; +} void LabGridArea::setLowEnabled(bool yes) { @@ -400,17 +625,26 @@ void LabGridArea::setLowEnabled(bool yes) } } +void LabGridArea::setciexyEnabled(bool yes) +{ + if (ciexy_enabled != yes) { + ciexy_enabled = yes; + queue_draw(); + } +} //----------------------------------------------------------------------------- // LabGrid //----------------------------------------------------------------------------- -LabGrid::LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low): - grid(evt, msg, enable_low) +LabGrid::LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low, bool ciexy): + grid(evt, msg, enable_low, ciexy) { Gtk::Button *reset = Gtk::manage(new Gtk::Button()); reset->set_tooltip_markup(M("ADJUSTER_RESET_TO_DEFAULT")); - reset->add(*Gtk::manage(new RTImage("undo-small.png", "redo-small.png"))); + if(!ciexy) {//disabled for Cie xy + reset->add(*Gtk::manage(new RTImage("undo-small.png", "redo-small.png"))); + } reset->signal_button_release_event().connect(sigc::mem_fun(*this, &LabGrid::resetPressed)); setExpandAlignProperties(reset, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); diff --git a/rtgui/labgrid.h b/rtgui/labgrid.h index 78179210c..0ed4cdf98 100644 --- a/rtgui/labgrid.h +++ b/rtgui/labgrid.h @@ -48,17 +48,25 @@ private: rtengine::ProcEvent evt; Glib::ustring evtMsg; - enum State { NONE, HIGH, LOW }; + enum State { NONE, HIGH, LOW, GRE}; State litPoint; double low_a; double high_a; double low_b; double high_b; - + double gre_x; + double gre_y; + double whi_x; + double whi_y; + double defaultLow_a; double defaultHigh_a; double defaultLow_b; double defaultHigh_b; + double defaultgre_x; + double defaultgre_y; + double defaultwhi_x; + double defaultwhi_y; ToolPanelListener *listener; bool edited; @@ -67,16 +75,17 @@ private: static const int inset = 5; bool low_enabled; + bool ciexy_enabled; bool notifyListener(); void getLitPoint(); public: - LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low=true); + LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low=true, bool ciexy=false); - void getParams(double &la, double &lb, double &ha, double &hb) const; - void setParams(double la, double lb, double ha, double hb, bool notify); - void setDefault (double la, double lb, double ha, double hb); + void getParams(double &la, double &lb, double &ha, double &hb, double &gx, double &gy, double &wx, double &wy) const; + void setParams(double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy, bool notify); + void setDefault (double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy); void setEdited(bool yes); bool getEdited() const; void reset(bool toInitial); @@ -84,6 +93,8 @@ public: bool lowEnabled() const; void setLowEnabled(bool yes); + bool ciexyEnabled() const; + void setciexyEnabled(bool yes); bool on_draw(const ::Cairo::RefPtr &crf) override; void on_style_updated () override; @@ -103,16 +114,18 @@ private: bool resetPressed(GdkEventButton *event); public: - LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low=true); + LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low=true, bool ciexy=false); - void getParams(double &la, double &lb, double &ha, double &hb) const { return grid.getParams(la, lb, ha, hb); } - void setParams(double la, double lb, double ha, double hb, bool notify) { grid.setParams(la, lb, ha, hb, notify); } - void setDefault (double la, double lb, double ha, double hb) { grid.setDefault(la, lb, ha, hb); } + void getParams(double &la, double &lb, double &ha, double &hb, double &gx, double &gy, double &wx, double &wy) const { return grid.getParams(la, lb, ha, hb, gx, gy, wx, wy); } + void setParams(double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy, bool notify) { grid.setParams(la, lb, ha, hb, gx, gy, wx, wy, notify); } + void setDefault (double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy) { grid.setDefault(la, lb, ha, hb, gx, gy, wx, wy); } void setEdited(bool yes) { grid.setEdited(yes); } bool getEdited() const { return grid.getEdited(); } void reset(bool toInitial) { grid.reset(toInitial); } void setListener(ToolPanelListener *l) { grid.setListener(l); } bool lowEnabled() const { return grid.lowEnabled(); } void setLowEnabled(bool yes) { grid.setLowEnabled(yes); } + bool ciexyEnabled() const { return grid.ciexyEnabled(); } + void setciexyEnabled(bool yes) { grid.setciexyEnabled(yes); } }; diff --git a/rtgui/locallabtools.cc b/rtgui/locallabtools.cc index 444a4d5b2..371c1892b 100644 --- a/rtgui/locallabtools.cc +++ b/rtgui/locallabtools.cc @@ -422,7 +422,7 @@ LocallabColor::LocallabColor(): chroma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMA"), -100, 150, 1, 0))), curvactiv(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_CURV")))), gridFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LABGRID")))), - labgrid(Gtk::manage(new LabGrid(EvLocallabLabGridValue, M("TP_LOCALLAB_LABGRID_VALUES")))), + labgrid(Gtk::manage(new LabGrid(EvLocallabLabGridValue, M("TP_LOCALLAB_LABGRID_VALUES"), true, false))), gridMethod(Gtk::manage(new MyComboBoxText())), strengthgrid(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRGRID"), 0, 100, 1, 30))), sensi(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), @@ -1139,8 +1139,8 @@ void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const Param spot.labgridBLow / LocallabParams::LABGRIDL_CORR_MAX, spot.labgridAHigh / LocallabParams::LABGRIDL_CORR_MAX, spot.labgridBHigh / LocallabParams::LABGRIDL_CORR_MAX, - false); - + 0, 0, 0, 0, false); + // printf("labgridlow=%f \n", spot.labgridALow); if (spot.gridMethod == "one") { gridMethod->set_active(0); } else if (spot.gridMethod == "two") { @@ -1252,7 +1252,7 @@ void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const Param labgridmerg->setParams(0, 0, spot.labgridAHighmerg / LocallabParams::LABGRIDL_CORR_MAX, spot.labgridBHighmerg / LocallabParams::LABGRIDL_CORR_MAX, - false); + 0, 0, 0, 0, false); merlucol->setValue(spot.merlucol); enaColorMask->set_active(spot.enaColorMask); CCmaskshape->setCurve(spot.CCmaskcurve); @@ -1310,10 +1310,12 @@ void LocallabColor::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pe spot.contrast = contrast->getIntValue(); spot.chroma = chroma->getIntValue(); spot.curvactiv = curvactiv->get_active(); + double zerox = 0.; + double zeroy = 0.; labgrid->getParams(spot.labgridALow, spot.labgridBLow, spot.labgridAHigh, - spot.labgridBHigh); + spot.labgridBHigh, zerox, zeroy, zerox, zeroy); spot.labgridALow *= LocallabParams::LABGRIDL_CORR_MAX; spot.labgridAHigh *= LocallabParams::LABGRIDL_CORR_MAX; spot.labgridBLow *= LocallabParams::LABGRIDL_CORR_MAX; @@ -1427,10 +1429,12 @@ void LocallabColor::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pe spot.mercol = mercol->getValue(); spot.opacol = opacol->getValue(); spot.conthrcol = conthrcol->getValue(); + double zerox1 = 0.; + double zeroy1 = 0.; labgridmerg->getParams(spot.labgridALowmerg, spot.labgridBLowmerg, spot.labgridAHighmerg, - spot.labgridBHighmerg); + spot.labgridBHighmerg, zerox1, zeroy1, zerox1, zeroy1); spot.labgridALowmerg *= LocallabParams::LABGRIDL_CORR_MAX; spot.labgridAHighmerg *= LocallabParams::LABGRIDL_CORR_MAX; spot.labgridBLowmerg *= LocallabParams::LABGRIDL_CORR_MAX; @@ -1476,7 +1480,7 @@ void LocallabColor::setDefaults(const rtengine::procparams::ProcParams* defParam labgrid->setDefault(defSpot.labgridALow / LocallabParams::LABGRIDL_CORR_MAX, defSpot.labgridBLow / LocallabParams::LABGRIDL_CORR_MAX, defSpot.labgridAHigh / LocallabParams::LABGRIDL_CORR_MAX, - defSpot.labgridBHigh / LocallabParams::LABGRIDL_CORR_MAX); + defSpot.labgridBHigh / LocallabParams::LABGRIDL_CORR_MAX, 0, 0, 0, 0); strengthgrid->setDefault((double) defSpot.strengthgrid); sensi->setDefault((double)defSpot.sensi); structcol->setDefault((double)defSpot.structcol); @@ -1492,7 +1496,7 @@ void LocallabColor::setDefaults(const rtengine::procparams::ProcParams* defParam labgridmerg->setDefault(defSpot.labgridALowmerg / LocallabParams::LABGRIDL_CORR_MAX, defSpot.labgridBLowmerg / LocallabParams::LABGRIDL_CORR_MAX, defSpot.labgridAHighmerg / LocallabParams::LABGRIDL_CORR_MAX, - defSpot.labgridBHighmerg / LocallabParams::LABGRIDL_CORR_MAX); + defSpot.labgridBHighmerg / LocallabParams::LABGRIDL_CORR_MAX, 0, 0, 0, 0); merlucol->setDefault(defSpot.merlucol); strumaskcol->setDefault(defSpot.strumaskcol); contcol->setDefault(defSpot.contcol); @@ -1962,7 +1966,7 @@ void LocallabColor::convertParamToNormal() labgridmerg->setParams(0, 0, defSpot.labgridAHighmerg / LocallabParams::LABGRIDL_CORR_MAX, defSpot.labgridBHighmerg / LocallabParams::LABGRIDL_CORR_MAX, - false); + 0, 0, 0, 0, false); merlucol->setValue(defSpot.merlucol); strumaskcol->setValue(defSpot.strumaskcol); toolcol->set_active(defSpot.toolcol); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index d6808cf38..f6ad44605 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -439,7 +439,26 @@ void ParamsEdited::set(bool v) icm.outputBPC = v; icm.workingTRCGamma = v; icm.workingTRCSlope = v; + icm.redx = v; + icm.redy = v; + icm.grex = v; + icm.grey = v; + icm.blux = v; + icm.bluy = v; + icm.preser = v; + icm.fbw = v; + icm.labgridcieALow = v; + icm.labgridcieBLow = v; + icm.labgridcieAHigh = v; + icm.labgridcieBHigh = v; + icm.labgridcieGx = v; + icm.labgridcieGy = v; + icm.labgridcieWx = v; + icm.labgridcieWy = v; + icm.aRendIntent = v; icm.workingTRC = v; + icm.will = v; + icm.wprim = v; raw.bayersensor.method = v; raw.bayersensor.border = v; raw.bayersensor.imageNum = v; @@ -1709,7 +1728,26 @@ void ParamsEdited::initFrom(const std::vector& icm.outputBPC = icm.outputBPC && p.icm.outputBPC == other.icm.outputBPC ; icm.workingTRCGamma = icm.workingTRCGamma && p.icm.workingTRCGamma == other.icm.workingTRCGamma; icm.workingTRCSlope = icm.workingTRCSlope && p.icm.workingTRCSlope == other.icm.workingTRCSlope; + icm.redx = icm.redx && p.icm.redx == other.icm.redx; + icm.redy = icm.redy && p.icm.redy == other.icm.redy; + icm.grex = icm.grex && p.icm.grex == other.icm.grex; + icm.grey = icm.grey && p.icm.grey == other.icm.grey; + icm.blux = icm.blux && p.icm.blux == other.icm.blux; + icm.bluy = icm.bluy && p.icm.bluy == other.icm.bluy; + icm.labgridcieALow = icm.labgridcieALow && p.icm.labgridcieALow == other.icm.labgridcieALow; + icm.labgridcieBLow = icm.labgridcieBLow && p.icm.labgridcieBLow == other.icm.labgridcieBLow; + icm.labgridcieAHigh = icm.labgridcieAHigh && p.icm.labgridcieAHigh == other.icm.labgridcieAHigh; + icm.labgridcieBHigh = icm.labgridcieBHigh && p.icm.labgridcieBHigh == other.icm.labgridcieBHigh; + icm.labgridcieGx = icm.labgridcieGx && p.icm.labgridcieGx == other.icm.labgridcieGx; + icm.labgridcieGy = icm.labgridcieGy && p.icm.labgridcieGy == other.icm.labgridcieGy; + icm.labgridcieWx = icm.labgridcieWx && p.icm.labgridcieWx == other.icm.labgridcieWx; + icm.labgridcieWy = icm.labgridcieWy && p.icm.labgridcieWy == other.icm.labgridcieWy; + icm.preser = icm.preser && p.icm.preser == other.icm.preser; + icm.fbw = icm.fbw && p.icm.fbw == other.icm.fbw; + icm.aRendIntent = icm.aRendIntent && p.icm.aRendIntent == other.icm.aRendIntent; icm.workingTRC = icm.workingTRC && p.icm.workingTRC == other.icm.workingTRC; + icm.will = icm.will && p.icm.will == other.icm.will; + icm.wprim = icm.wprim && p.icm.wprim == other.icm.wprim; raw.bayersensor.method = raw.bayersensor.method && p.raw.bayersensor.method == other.raw.bayersensor.method; raw.bayersensor.border = raw.bayersensor.border && p.raw.bayersensor.border == other.raw.bayersensor.border; raw.bayersensor.imageNum = raw.bayersensor.imageNum && p.raw.bayersensor.imageNum == other.raw.bayersensor.imageNum; @@ -5722,10 +5760,86 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.icm.workingTRCSlope = mods.icm.workingTRCSlope; } + if (icm.redx) { + toEdit.icm.redx = mods.icm.redx; + } + + if (icm.redy) { + toEdit.icm.redy = mods.icm.redy; + } + + if (icm.grex) { + toEdit.icm.grex = mods.icm.grex; + } + + if (icm.grey) { + toEdit.icm.grey = mods.icm.grey; + } + + if (icm.blux) { + toEdit.icm.blux = mods.icm.blux; + } + + if (icm.bluy) { + toEdit.icm.bluy = mods.icm.bluy; + } + + if (icm.preser) { + toEdit.icm.preser = mods.icm.preser; + } + + if (icm.fbw) { + toEdit.icm.fbw = mods.icm.fbw; + } + + if (icm.labgridcieALow) { + toEdit.icm.labgridcieALow = mods.icm.labgridcieALow; + } + + if (icm.labgridcieBLow) { + toEdit.icm.labgridcieBLow = mods.icm.labgridcieBLow; + } + + if (icm.labgridcieAHigh) { + toEdit.icm.labgridcieAHigh = mods.icm.labgridcieAHigh; + } + + if (icm.labgridcieBHigh) { + toEdit.icm.labgridcieBHigh = mods.icm.labgridcieBHigh; + } + + if (icm.labgridcieGx) { + toEdit.icm.labgridcieGx = mods.icm.labgridcieGx; + } + + if (icm.labgridcieGy) { + toEdit.icm.labgridcieGy = mods.icm.labgridcieGy; + } + + if (icm.labgridcieWx) { + toEdit.icm.labgridcieWx = mods.icm.labgridcieWx; + } + + if (icm.labgridcieWy) { + toEdit.icm.labgridcieWy = mods.icm.labgridcieWy; + } + + if (icm.aRendIntent) { + toEdit.icm.aRendIntent = mods.icm.aRendIntent; + } + if (icm.workingTRC) { toEdit.icm.workingTRC = mods.icm.workingTRC; } + if (icm.will) { + toEdit.icm.will = mods.icm.will; + } + + if (icm.wprim) { + toEdit.icm.wprim = mods.icm.wprim; + } + if (raw.bayersensor.method) { toEdit.raw.bayersensor.method = mods.raw.bayersensor.method; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 7094f5492..09623ea1d 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -1099,7 +1099,25 @@ struct ColorManagementParamsEdited { bool workingTRC; bool workingTRCGamma; bool workingTRCSlope; - + bool will; + bool wprim; + bool redx; + bool redy; + bool grex; + bool grey; + bool blux; + bool bluy; + bool preser; + bool fbw; + bool labgridcieALow; + bool labgridcieBLow; + bool labgridcieAHigh; + bool labgridcieBHigh; + bool labgridcieGx; + bool labgridcieGy; + bool labgridcieWx; + bool labgridcieWy; + bool aRendIntent; bool outputProfile; bool outputIntent; bool outputBPC; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 920585aed..0866e970b 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -714,6 +714,7 @@ void ToolPanelCoordinator::initImage(rtengine::StagedImageProcessor* ipc_, bool ipc->setpdSharpenAutoRadiusListener (pdSharpening); ipc->setAutoWBListener(whitebalance); ipc->setAutoColorTonListener(colortoning); + ipc->setAutoprimListener(icm); ipc->setAutoChromaListener(dirpyrdenoise); ipc->setWaveletListener(wavelet); ipc->setRetinexListener(retinex); diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 448141497..12d133bc8 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -1749,7 +1749,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) strend->setValue(pp->wavelet.strend); detend->setValue(pp->wavelet.detend); thrend->setValue(pp->wavelet.thrend); - labgrid->setParams(pp->wavelet.labgridALow / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridBLow / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridAHigh / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridBHigh / WaveletParams::LABGRID_CORR_MAX, false); + labgrid->setParams(pp->wavelet.labgridALow / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridBLow / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridAHigh / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridBHigh / WaveletParams::LABGRID_CORR_MAX, 0, 0, 0, 0, false); sigm->setValue(pp->wavelet.sigm); levden->setValue(pp->wavelet.levden); @@ -2210,7 +2210,9 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pp->wavelet.ballum = ballum->getValue(); pp->wavelet.chromfi = chromfi->getValue(); pp->wavelet.chromco = chromco->getValue(); - labgrid->getParams(pp->wavelet.labgridALow, pp->wavelet.labgridBLow, pp->wavelet.labgridAHigh, pp->wavelet.labgridBHigh); + double zerox = 0.; + double zeroy = 0.; + labgrid->getParams(pp->wavelet.labgridALow, pp->wavelet.labgridBLow, pp->wavelet.labgridAHigh, pp->wavelet.labgridBHigh, zerox, zeroy, zerox, zeroy); pp->wavelet.labgridALow *= WaveletParams::LABGRID_CORR_MAX; pp->wavelet.labgridAHigh *= WaveletParams::LABGRID_CORR_MAX; pp->wavelet.labgridBLow *= WaveletParams::LABGRID_CORR_MAX; @@ -2670,7 +2672,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit balchrom->setDefault(defParams->wavelet.balchrom); chromfi->setDefault(defParams->wavelet.chromfi); chromco->setDefault(defParams->wavelet.chromco); - labgrid->setDefault(defParams->wavelet.labgridALow / WaveletParams::LABGRID_CORR_MAX, defParams->wavelet.labgridBLow / WaveletParams::LABGRID_CORR_MAX, defParams->wavelet.labgridAHigh / WaveletParams::LABGRID_CORR_MAX, defParams->wavelet.labgridBHigh / WaveletParams::LABGRID_CORR_MAX); + labgrid->setDefault(defParams->wavelet.labgridALow / WaveletParams::LABGRID_CORR_MAX, defParams->wavelet.labgridBLow / WaveletParams::LABGRID_CORR_MAX, defParams->wavelet.labgridAHigh / WaveletParams::LABGRID_CORR_MAX, defParams->wavelet.labgridBHigh / WaveletParams::LABGRID_CORR_MAX, 0, 0, 0, 0); greenlow->setDefault(defParams->wavelet.greenlow); bluelow->setDefault(defParams->wavelet.bluelow);