diff --git a/rtdata/languages/default b/rtdata/languages/default index 270973878..1c6814753 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -741,7 +741,6 @@ HISTORY_MSG_490;HDR TM - Amount HISTORY_MSG_491;White Balance HISTORY_MSG_492;RGB Curves HISTORY_MSG_493;L*a*b* Adjustments -HISTORY_MSG_494;Local - Bottom HISTORY_MSG_495;Local - Right HISTORY_MSG_496;Local - Center HISTORY_MSG_497;Local - Lightness/ @@ -842,7 +841,13 @@ HISTORY_MSG_592;Local - Warm Cool HISTORY_MSG_593;Local - Noise lum detail HISTORY_MSG_594;Local - Noise chro detail HISTORY_MSG_595;Local - Noise Scope -HISTORY_MSG_596;Local L*a*b* +HISTORY_MSG_597;Local L*a*b* +HISTORY_MSG_598;Local - Bottom +HISTORY_MSG_LOCALCONTRAST_ENABLED;Local Contrast +HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius +HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount +HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness +HISTORY_MSG_LOCALCONTRAST_LIGHTNESS;Local Contrast - Lightness HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -1024,6 +1029,7 @@ PARTIALPASTE_LENSGROUP;Lens Related Settings PARTIALPASTE_LOCALLAB;Local L*a*b* PARTIALPASTE_LOCGROUP;Local PARTIALPASTE_LENSPROFILE;Profiled lens correction +PARTIALPASTE_LOCALCONTRAST;Local contrast PARTIALPASTE_METAGROUP;Metadata PARTIALPASTE_PCVIGNETTE;Vignette filter PARTIALPASTE_PERSPECTIVE;Perspective @@ -1813,6 +1819,7 @@ TP_LENSPROFILE_LABEL;Profiled Lens Correction TP_LENSPROFILE_USECA;Chromatic aberration correction TP_LENSPROFILE_USEDIST;Distortion correction TP_LENSPROFILE_USEVIGN;Vignetting correction +<<<<<<< HEAD TP_LOCALLAB_ACTIV;Blur luminance only TP_LOCALLAB_ADJBLUR;Adjust and Blur TP_LOCALLAB_ARTIF;Reduce artifacts - Improve algoritm @@ -1923,6 +1930,14 @@ TP_LOCAL_WIDTH;Right TP_LOCAL_WIDTH_L;Left TP_LOCRETI_METHOD_TOOLTIP;Low = Reinforce low light.\nUniform = Equalize action.\nHigh = Reinforce high light.\n TP_NEUTRAL;Neutral +======= +TP_LOCALCONTRAST_LABEL;Local Contrast +TP_LOCALCONTRAST_RADIUS;Radius +TP_LOCALCONTRAST_AMOUNT;Amount +TP_LOCALCONTRAST_DARKNESS;Darkness level +TP_LOCALCONTRAST_LIGHTNESS;Lightness level +TP_NEUTRAL;Reset +>>>>>>> dev TP_NEUTRAL_TIP;Resets exposure sliders to neutral values.\nApplies to the same controls that Auto Levels applies to, regardless of whether you used Auto Levels or not. TP_PCVIGNETTE_FEATHER;Feather TP_PCVIGNETTE_FEATHER_TOOLTIP;Feathering:\n0 = corners only,\n50 = halfway to center,\n100 = to center. @@ -1972,7 +1987,7 @@ TP_RAW_DCBITERATIONS;Number of DCB iterations TP_RAW_DMETHOD;Method TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... -TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. TP_RAW_EAHD;EAHD TP_RAW_FALSECOLOR;False color suppression steps TP_RAW_FAST;Fast @@ -1981,7 +1996,7 @@ TP_RAW_HD_TOOLTIP;Lower values make hot/dead pixel detection more aggressive, bu TP_RAW_HPHD;HPHD TP_RAW_IGV;IGV TP_RAW_IMAGENUM;Sub-image -TP_RAW_IMAGENUM_TOOLTIP;Some raw files consist of several sub-images (Pentax Pixel Shift, Pentax 3-in-1 HDR, Canon Dual Pixel).\n\nWhen using any demosaicing method other than Pixel Shift, this selects which sub-image is used.\n\nWhen using the Pixel Shift demosaicing method on a Pixel Shift raw, all sub-images are used, and this selects which sub-image should be used for moving parts. +TP_RAW_IMAGENUM_TOOLTIP;Some raw files consist of several sub-images (Pentax/Sony Pixel Shift, Pentax 3-in-1 HDR, Canon Dual Pixel).\n\nWhen using any demosaicing method other than Pixel Shift, this selects which sub-image is used.\n\nWhen using the Pixel Shift demosaicing method on a Pixel Shift raw, all sub-images are used, and this selects which sub-image should be used for moving parts. TP_RAW_LABEL;Demosaicing TP_RAW_LMMSE;LMMSE TP_RAW_LMMSEITERATIONS;LMMSE enhancement steps @@ -2003,6 +2018,7 @@ TP_RAW_PIXELSHIFTHOLEFILL;Fill holes in motion mask TP_RAW_PIXELSHIFTHOLEFILL_TOOLTIP;Fill holes in motion mask TP_RAW_PIXELSHIFTLMMSE;Use LMMSE for moving parts TP_RAW_PIXELSHIFTLMMSE_TOOLTIP;Use LMMSE instead of AMaZE for areas of motion.\nUseful for high ISO images. +TP_RAW_PIXELSHIFTONEGREEN_TOOLTIP;Use one green instead of averaging two greens for regions without motion. TP_RAW_PIXELSHIFTMASKTHRESHOLD;3x3 new threshold TP_RAW_PIXELSHIFTMEDIAN;Use median for moving parts TP_RAW_PIXELSHIFTMEDIAN3;Exclude selected frame from median @@ -2021,6 +2037,7 @@ TP_RAW_PIXELSHIFTNONGREENCROSS2;Check green AMaZE TP_RAW_PIXELSHIFTNONGREENHORIZONTAL;Check red/blue horizontal TP_RAW_PIXELSHIFTNONGREENVERTICAL;Check red/blue vertical TP_RAW_PIXELSHIFTNREADISO;nRead +TP_RAW_PIXELSHIFTONEGREEN;Use one green instead of average TP_RAW_PIXELSHIFTPRNU;PRNU (%) TP_RAW_PIXELSHIFTREDBLUEWEIGHT;Red&Blue weight TP_RAW_PIXELSHIFTSHOWMOTION;Show motion mask diff --git a/rtdata/options/options.lin b/rtdata/options/options.lin index bbc1de057..4ff90246d 100644 --- a/rtdata/options/options.lin +++ b/rtdata/options/options.lin @@ -12,8 +12,8 @@ MultiUser=true [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;cr2;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions=3fr;arw;arq;cr2;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; +ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; [Output] PathTemplate=%p1/converted/%f diff --git a/rtdata/options/options.osx b/rtdata/options/options.osx index 25696cb85..9130ef9ad 100644 --- a/rtdata/options/options.osx +++ b/rtdata/options/options.osx @@ -12,8 +12,8 @@ MultiUser=true [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;cr2;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions=3fr;arw;arq;cr2;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; +ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; [Output] PathTemplate=%p1/converted/%f diff --git a/rtdata/options/options.win b/rtdata/options/options.win index 3f309fd16..33ab499be 100644 --- a/rtdata/options/options.win +++ b/rtdata/options/options.win @@ -14,8 +14,8 @@ UseSystemTheme=false [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;cr2;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions=3fr;arw;arq;cr2;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; +ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; [Output] PathTemplate=%p1/converted/%f diff --git a/rtdata/profiles/Pentax Pixel Shift/PS ISO High.pp3 b/rtdata/profiles/Pixel Shift/PS ISO High.pp3 similarity index 100% rename from rtdata/profiles/Pentax Pixel Shift/PS ISO High.pp3 rename to rtdata/profiles/Pixel Shift/PS ISO High.pp3 diff --git a/rtdata/profiles/Pentax Pixel Shift/PS ISO Low.pp3 b/rtdata/profiles/Pixel Shift/PS ISO Low.pp3 similarity index 100% rename from rtdata/profiles/Pentax Pixel Shift/PS ISO Low.pp3 rename to rtdata/profiles/Pixel Shift/PS ISO Low.pp3 diff --git a/rtdata/profiles/Pentax Pixel Shift/PS ISO Medium.pp3 b/rtdata/profiles/Pixel Shift/PS ISO Medium.pp3 similarity index 100% rename from rtdata/profiles/Pentax Pixel Shift/PS ISO Medium.pp3 rename to rtdata/profiles/Pixel Shift/PS ISO Medium.pp3 diff --git a/rtdata/profiles/Pentax Pixel Shift/PS No Motion.pp3 b/rtdata/profiles/Pixel Shift/PS No Motion.pp3 similarity index 100% rename from rtdata/profiles/Pentax Pixel Shift/PS No Motion.pp3 rename to rtdata/profiles/Pixel Shift/PS No Motion.pp3 diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 30880d7d8..6bc2881e6 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -116,6 +116,7 @@ set(RTENGINESOURCEFILES utils.cc rtlensfun.cc tmo_fattal02.cc + iplocalcontrast.cc ) if(LENSFUN_HAS_LOAD_DIRECTORY) diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 5a3a18fd1..610a22310 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -2285,6 +2285,13 @@ Camera constants: "ranges": { "black": 800, "white": 16300 } }, + { // Quality C, + "make_model": "Sony ILCE-7RM3", + "dcraw_matrix": [ 6640,-1847,-503,-5238,13010,2474,-993,1673,6527 ], // DNG_v10.1 D65 + "raw_crop": [ 0, 0, -36, 0 ], // full raw frame 8000x5320 - 36 rightmost columns are garbage + "ranges": { "black": 512, "white": 16300 } + }, + { // Quality C, No proper color data, beta samples, frame set to official jpeg, "make_model": [ "XIAOYI M1", "YI TECHNOLOGY M1" ], "dcraw_matrix": [ 7158,-1911,-606,-3603,10669,2530,-659,1236,5530 ], // XIAO YI DNG D65 diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 9ae313530..75891c589 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -2349,6 +2349,37 @@ void CLASS unpacked_load_raw() && (unsigned) (col-left_margin) < width) derror(); } + +// RT +void CLASS sony_arq_load_raw() +{ + static unsigned frame2pos[] = { 0, 1, 3, 2 }; + int row, col, bits=0; + ushort samples[4]; + unsigned frame = frame2pos[shot_select]; + + while (1 << ++bits < maximum); + for (row=0; row < ((frame < 2) ? 1 : raw_height); row++) { + for (col=0; col < ((row == 0) ? raw_width : 1); col++) { + RAW(row,col) = 0; + } + } + for (row=0; row < raw_height; row++) { + int r = row + (frame & 1); + for (col=0; col < raw_width; col++) { + int c = col + ((frame >> 1) & 1); + read_shorts(samples, 4); + if (r < raw_height && c < raw_width) { + RAW(r,c) = samples[(2 * (r & 1)) + (c & 1)]; + if ((RAW(r,c) >>= load_flags) >> bits + && (unsigned) (row-top_margin) < height + && (unsigned) (col-left_margin) < width) derror(); + } + } + } +} + + void CLASS sinar_4shot_load_raw() { ushort *pixel; @@ -6524,6 +6555,17 @@ void CLASS apply_tiff() if (!strncmp(make,"OLYMPUS",7) && tiff_ifd[raw].bytes*7 > raw_width*raw_height) load_raw = &CLASS olympus_load_raw; + // ------- RT ------- + if (!strncmp(make,"SONY",4) && + !strncmp(model,"ILCE-7RM3",9) && + tiff_samples == 4 && + tiff_ifd[raw].bytes == raw_width*raw_height*tiff_samples*2) { + load_raw = &CLASS sony_arq_load_raw; + colors = 3; + is_raw = 4; + filters = 0x94949494; + } + // ------------------ } break; case 6: case 7: case 99: diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h index 0a10f9732..5a2790801 100644 --- a/rtengine/dcraw.h +++ b/rtengine/dcraw.h @@ -409,6 +409,7 @@ sony_decrypt_t sony_decrypt; void sony_load_raw(); void sony_arw_load_raw(); void sony_arw2_load_raw(); +void sony_arq_load_raw(); // RT void smal_decode_segment (unsigned seg[2][2], int holes); void smal_v6_load_raw(); diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 47688fca6..f3516e5a8 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -473,7 +473,7 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* // ----------------------- Special file type detection (HDR, PixelShift) ------------------------ - uint16 bitspersample = 0, sampleformat = 0, photometric = 0, compression = 0; + uint16 bitspersample = 0, samplesperpixel = 0, sampleformat = 0, photometric = 0, compression = 0; rtexif::Tag* bps = frameRootDir->findTag("BitsPerSample"); rtexif::Tag* spp = frameRootDir->findTag("SamplesPerPixel"); rtexif::Tag* sf = frameRootDir->findTag("SampleFormat"); @@ -535,6 +535,7 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* } bitspersample = bps->toInt(); + samplesperpixel = spp->toInt(); photometric = pi->toInt(); if (photometric == PHOTOMETRIC_LOGLUV) { @@ -582,6 +583,26 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* sampleFormat = IIOSF_UNSIGNED_SHORT; } } + } else if (photometric == 34892 || photometric == 32892 /* Linear RAW (see DNG spec ; 32892 seem to be a flaw from Sony's ARQ files) */) { + if (sampleformat == SAMPLEFORMAT_IEEEFP) { + sampleFormat = IIOSF_FLOAT; + isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> sampleFormat = %d\n", sampleFormat); +#endif + } else if (sampleformat == SAMPLEFORMAT_INT || sampleformat == SAMPLEFORMAT_UINT) { + if (bitspersample == 8) { // shouldn't occur... + sampleFormat = IIOSF_UNSIGNED_CHAR; + } else if (bitspersample <= 16) { + sampleFormat = IIOSF_UNSIGNED_SHORT; + if (mnote && (!make.compare (0, 4, "SONY")) && bitspersample >= 12 && samplesperpixel == 4) { + isPixelShift = true; +#if PRINT_HDR_PS_DETECTION + printf("PixelShift detected ! -> \"Make\" = SONY, bitsPerPixel > 8, samplesPerPixel == 4\n"); +#endif + } + } + } } else if (photometric == PHOTOMETRIC_LOGLUV) { if (compression == COMPRESSION_SGILOG24) { sampleFormat = IIOSF_LOGLUV24; @@ -764,7 +785,7 @@ FrameData *FramesData::getFrameData (unsigned int frame) const bool FramesData::getPixelShift (unsigned int frame) const { - // So far only Pentax provide multi-frame HDR file. + // So far only Pentax and Sony provide multi-frame HDR file. // Only the first frame contains the HDR tag // If more brand have to be supported, this rule may need // to evolve diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index c35e46cdc..3917b618d 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -4577,7 +4577,8 @@ ProcParams* ImProcCoordinator::beginUpdateParams() void ImProcCoordinator::endUpdateParams(ProcEvent change) { - endUpdateParams(refreshmap[(int)change]); + int action = RefreshMapper::getInstance()->getAction(change); + endUpdateParams(action); } void ImProcCoordinator::endUpdateParams(int changeFlags) diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 4fb7a8099..995da9996 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -3438,6 +3438,9 @@ void ImProcFunctions::rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer int tW; int tH; + // zero out the buffers + memset(buffer, 0, 3 * sizeof (float) * TS * TS + 20 * 64 + 63); + // Allocating buffer for the PipetteBuffer float *editIFloatTmpR = nullptr, *editIFloatTmpG = nullptr, *editIFloatTmpB = nullptr, *editWhateverTmp = nullptr; @@ -4976,6 +4979,11 @@ void ImProcFunctions::rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer if (vCurveEnabled) { delete vCurve; } + + if (params->localContrast.enabled) { + // Alberto's local contrast + localContrast(lab); + } } /** diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 56acab9f2..334ead522 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -404,9 +404,11 @@ public: void BadpixelsLab(LabImage * src, LabImage * dst, double radius, int thresh, int mode, float skinprot, float chrom); void ToneMapFattal02(Imagefloat *rgb); - - Image8* lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm); - Image16* lab2rgb16(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, GammaValues *ga = nullptr); + //void localContrast(float *r, float *g, float *b, int width, int height); + void localContrast(LabImage *lab); + + Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm); + Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, GammaValues *ga = nullptr); // CieImage *ciec; 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); diff --git a/rtengine/iplocalcontrast.cc b/rtengine/iplocalcontrast.cc new file mode 100644 index 000000000..24739fb6b --- /dev/null +++ b/rtengine/iplocalcontrast.cc @@ -0,0 +1,70 @@ +/* -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Ported from G'MIC by Alberto Griggio + * + * The original implementation in G'MIC was authored by Arto Huotari, and was + * released under the CeCILL free software license (see + * http://www.cecill.info/licences/Licence_CeCILL_V2-en.html) + * + * 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 + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#ifdef _OPENMP +#include +#endif + +#include "improcfun.h" +#include "gauss.h" +#include "array2D.h" + +namespace rtengine { + +void ImProcFunctions::localContrast(LabImage *lab) +{ + if (!params->localContrast.enabled) { + return; + } + + const int width = lab->W; + const int height = lab->H; + const float a = params->localContrast.amount; + const float dark = params->localContrast.darkness; + const float light = params->localContrast.lightness; + array2D buf(width, height); + const float sigma = params->localContrast.radius / scale; + +#ifdef _OPENMP + #pragma omp parallel if(multiThread) +#endif + gaussianBlur(lab->L, buf, width, height, sigma); + +#ifdef _OPENMP + #pragma omp parallel for if(multiThread) +#endif + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + float bufval = (lab->L[y][x] - buf[y][x]) * a; + + if (dark != 1 || light != 1) { + bufval *= (bufval > 0.f) ? light : dark; + } + + lab->L[y][x] += bufval; + } + } +} + +} // namespace rtengine diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc index 256aaaf63..511e4c95d 100644 --- a/rtengine/pixelshift.cc +++ b/rtengine/pixelshift.cc @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////// // -// Algorithm for Pentax Pixel Shift raw files with motion detection +// Algorithm for Pentax/Sony Pixel Shift raw files with motion detection // // Copyright (C) 2016 - 2017 Ingo Weyrich // @@ -294,12 +294,11 @@ void calcFrameBrightnessFactor(unsigned int frame, uint32_t datalen, LUTsetProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::PIXELSHIFT))); plistener->setProgress(0.0); @@ -531,6 +566,9 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA } else if(model.find("K-1") != string::npos) { nRead = nReadK1[nReadIndex]; eperIsoModel = ePerIsoK1; + } else if(model.find("ILCE-7RM3") != string::npos) { + nRead = nReadILCE7RM3[nReadIndex]; + eperIsoModel = ePerIsoILCE7RM3; } else { // as long as we don't have values for Pentax KP, we use the values from K-70 nRead = nReadK70[nReadIndex]; eperIsoModel = ePerIsoK70; @@ -887,11 +925,25 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA const float blend = smoothFactor == 0.f ? 1.f : pow_F(std::max(psMask[i][j] - 1.f, 0.f), smoothFactor); #endif redDest[j + offsX] = intp(blend, redDest[j + offsX], psRed[i][j] ); - greenDest[j + offsX] = intp(blend, greenDest[j + offsX], ((*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset] + (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]) * 0.5f); + if(bayerParams.pixelShiftOneGreen) { + int greenFrame = (1 - offset != 0) ? 1 - offset : 3 - offset; + int greenJ = (1 - offset != 0) ? j : j + 1; + int greenI = (1 - offset != 0) ? i - offset + 1 : i + offset; + greenDest[j + offsX] = intp(blend, greenDest[j + offsX], (*rawDataFrames[greenFrame])[greenI][greenJ] * greenBrightness[greenFrame]); + } else { + greenDest[j + offsX] = intp(blend, greenDest[j + offsX], ((*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset] + (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]) * 0.5f); + } blueDest[j + offsX] = intp(blend, blueDest[j + offsX], psBlue[i][j]); } else { redDest[j + offsX] = psRed[i][j]; - greenDest[j + offsX] = ((*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset] + (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]) * 0.5f; + if(bayerParams.pixelShiftOneGreen) { + int greenFrame = (1 - offset != 0) ? 1 - offset : 3 - offset; + int greenJ = (1 - offset != 0) ? j : j + 1; + int greenI = (1 - offset != 0) ? i - offset + 1 : i + offset; + greenDest[j + offsX] = (*rawDataFrames[greenFrame])[greenI][greenJ] * greenBrightness[greenFrame]; + } else { + greenDest[j + offsX] = ((*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset] + (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]) * 0.5f; + } blueDest[j + offsX] = psBlue[i][j]; } } @@ -924,7 +976,14 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA for(; j < winw - 1; ++j) { // set red, green and blue values - green[i][j] = ((*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset] + (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]) * 0.5f; + if(bayerParams.pixelShiftOneGreen) { + int greenFrame = (1 - offset != 0) ? 1 - offset : 3 - offset; + int greenJ = (1 - offset != 0) ? j : j + 1; + int greenI = (1 - offset != 0) ? i - offset + 1 : i + offset; + green[i][j] = (*rawDataFrames[greenFrame])[greenI][greenJ] * greenBrightness[greenFrame]; + } else { + green[i][j] = ((*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset] + (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]) * 0.5f; + } nonGreenDest0[j] = (*rawDataFrames[(offset << 1) + offset])[i][j + offset] * ngbright[ng][(offset << 1) + offset]; nonGreenDest1[j] = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1] * ngbright[ng ^ 1][2 - offset]; offset ^= 1; // 0 => 1 or 1 => 0 diff --git a/rtengine/procevents.h b/rtengine/procevents.h index b219beecf..e8311025d 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -26,7 +26,7 @@ namespace rtengine // Aligned so the first entry starts on line 30 -enum ProcEvent { +enum ProcEventCode { EvPhotoLoaded = 0, EvProfileLoaded = 1, EvProfileChanged = 2, @@ -520,7 +520,7 @@ enum ProcEvent { EvWBEnabled = 490, EvRGBEnabled = 491, EvLEnabled = 492, - EvlocallablocY = 493, + EvPixelShiftOneGreen = 493, EvlocallablocX = 494, EvlocallabCenter = 495, EvlocallabDegree = 496, @@ -624,11 +624,32 @@ enum ProcEvent { Evlocallabsensiden = 594, Evlocallabhuerefblur = 595, EvlocallabEnabled = 596, - + EvlocallablocY = 597, NUMOFEVENTS }; + + +class ProcEvent { +public: + ProcEvent(): code_(0) {} + ProcEvent(ProcEventCode code): code_(code) {} + explicit ProcEvent(int code): code_(code) {} + operator int() { return code_; } + +private: + int code_; +}; + + +inline bool operator==(ProcEvent a, ProcEvent b) { return int(a) == int(b); } +inline bool operator==(ProcEvent a, ProcEventCode b) { return int(a) == int(b); } +inline bool operator==(ProcEventCode a, ProcEvent b) { return int(a) == int(b); } +inline bool operator!=(ProcEvent a, ProcEvent b) { return int(a) != int(b); } +inline bool operator!=(ProcEvent a, ProcEventCode b) { return int(a) != int(b); } +inline bool operator!=(ProcEventCode a, ProcEvent b) { return int(a) != int(b); } + } #endif diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 4a296f083..abe17d876 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -594,6 +594,34 @@ bool RGBCurvesParams::operator !=(const RGBCurvesParams& other) const return !(*this == other); } + +LocalContrastParams::LocalContrastParams(): + enabled(false), + radius(80), + amount(0.2), + darkness(1.0), + lightness(1.0) +{ +} + + +bool LocalContrastParams::operator==(const LocalContrastParams &other) const +{ + return + enabled == other.enabled + && radius == other.radius + && amount == other.amount + && darkness == other.darkness + && lightness == other.lightness; +} + + +bool LocalContrastParams::operator!=(const LocalContrastParams &other) const +{ + return !(*this == other); +} + + ColorToningParams::ColorToningParams() : enabled(false), autosat(true), @@ -2721,6 +2749,7 @@ RAWParams::BayerSensor::BayerSensor() : pixelShiftSmoothFactor(0.7), pixelShiftExp0(false), pixelShiftLmmse(false), + pixelShiftOneGreen(false), pixelShiftEqualBright(false), pixelShiftEqualBrightChannel(false), pixelShiftNonGreenCross(true), @@ -2770,6 +2799,7 @@ bool RAWParams::BayerSensor::operator ==(const BayerSensor& other) const && pixelShiftSmoothFactor == other.pixelShiftSmoothFactor && pixelShiftExp0 == other.pixelShiftExp0 && pixelShiftLmmse == other.pixelShiftLmmse + && pixelShiftOneGreen == other.pixelShiftOneGreen && pixelShiftEqualBright == other.pixelShiftEqualBright && pixelShiftEqualBrightChannel == other.pixelShiftEqualBrightChannel && pixelShiftNonGreenCross == other.pixelShiftNonGreenCross @@ -2808,6 +2838,7 @@ void RAWParams::BayerSensor::setPixelShiftDefaults() pixelShiftSmoothFactor = 0.7; pixelShiftExp0 = false; pixelShiftLmmse = false; + pixelShiftOneGreen = false; pixelShiftEqualBright = false; pixelShiftEqualBrightChannel = false; pixelShiftNonGreenCross = true; @@ -2956,6 +2987,8 @@ void ProcParams::setDefaults() rgbCurves = RGBCurvesParams(); + localContrast = LocalContrastParams(); + colorToning = ColorToningParams(); sharpenEdge = SharpenEdgeParams(); @@ -3125,6 +3158,14 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->retinex.transmissionCurve, "Retinex", "TransmissionCurve", retinex.transmissionCurve, keyFile); saveToKeyfile(!pedited || pedited->retinex.gaintransmissionCurve, "Retinex", "GainTransmissionCurve", retinex.gaintransmissionCurve, keyFile); +// Local contrast + saveToKeyfile(!pedited || pedited->localContrast.enabled, "Local Contrast", "Enabled", localContrast.enabled, keyFile); + saveToKeyfile(!pedited || pedited->localContrast.radius, "Local Contrast", "Radius", localContrast.radius, keyFile); + saveToKeyfile(!pedited || pedited->localContrast.amount, "Local Contrast", "Amount", localContrast.amount, keyFile); + saveToKeyfile(!pedited || pedited->localContrast.darkness, "Local Contrast", "Darkness", localContrast.darkness, keyFile); + saveToKeyfile(!pedited || pedited->localContrast.lightness, "Local Contrast", "Lightness", localContrast.lightness, keyFile); + + // Channel mixer saveToKeyfile(!pedited || pedited->chmixer.enabled, "Channel Mixer", "Enabled", chmixer.enabled, keyFile); @@ -3824,6 +3865,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftSmooth, "RAW Bayer", "pixelShiftSmoothFactor", raw.bayersensor.pixelShiftSmoothFactor, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftExp0, "RAW Bayer", "pixelShiftExp0", raw.bayersensor.pixelShiftExp0, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftLmmse, "RAW Bayer", "pixelShiftLmmse", raw.bayersensor.pixelShiftLmmse, keyFile); + saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftOneGreen, "RAW Bayer", "pixelShiftOneGreen", raw.bayersensor.pixelShiftOneGreen, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftEqualBright, "RAW Bayer", "pixelShiftEqualBright", raw.bayersensor.pixelShiftEqualBright, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftEqualBrightChannel, "RAW Bayer", "pixelShiftEqualBrightChannel", raw.bayersensor.pixelShiftEqualBrightChannel, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftNonGreenCross, "RAW Bayer", "pixelShiftNonGreenCross", raw.bayersensor.pixelShiftNonGreenCross, keyFile); @@ -4081,6 +4123,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Retinex", "GainTransmissionCurve", pedited, retinex.gaintransmissionCurve, pedited->retinex.gaintransmissionCurve); } + if (keyFile.has_group("Local Contrast")) { + assignFromKeyfile(keyFile, "Local Contrast", "Enabled", pedited, localContrast.enabled, pedited->localContrast.enabled); + assignFromKeyfile(keyFile, "Local Contrast", "Radius", pedited, localContrast.radius, pedited->localContrast.radius); + assignFromKeyfile(keyFile, "Local Contrast", "Amount", pedited, localContrast.amount, pedited->localContrast.amount); + assignFromKeyfile(keyFile, "Local Contrast", "Darkness", pedited, localContrast.darkness, pedited->localContrast.darkness); + assignFromKeyfile(keyFile, "Local Contrast", "Lightness", pedited, localContrast.lightness, pedited->localContrast.lightness); + } + if (keyFile.has_group ("Luminance Curve")) { if (ppVersion >= 329) { assignFromKeyfile(keyFile, "Luminance Curve", "Enabled", pedited, labCurve.enabled, pedited->labCurve.enabled); @@ -5269,6 +5319,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftSmoothFactor", pedited, raw.bayersensor.pixelShiftSmoothFactor, pedited->raw.bayersensor.pixelShiftSmooth); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftExp0", pedited, raw.bayersensor.pixelShiftExp0, pedited->raw.bayersensor.pixelShiftExp0); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftLmmse", pedited, raw.bayersensor.pixelShiftLmmse, pedited->raw.bayersensor.pixelShiftLmmse); + assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftOneGreen", pedited, raw.bayersensor.pixelShiftOneGreen, pedited->raw.bayersensor.pixelShiftOneGreen); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftEqualBright", pedited, raw.bayersensor.pixelShiftEqualBright, pedited->raw.bayersensor.pixelShiftEqualBright); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftEqualBrightChannel", pedited, raw.bayersensor.pixelShiftEqualBrightChannel, pedited->raw.bayersensor.pixelShiftEqualBrightChannel); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftNonGreenCross", pedited, raw.bayersensor.pixelShiftNonGreenCross, pedited->raw.bayersensor.pixelShiftNonGreenCross); @@ -5358,6 +5409,7 @@ bool ProcParams::operator ==(const ProcParams& other) const return toneCurve == other.toneCurve && retinex == other.retinex + && localContrast == other.localContrast && labCurve == other.labCurve && sharpenEdge == other.sharpenEdge && sharpenMicro == other.sharpenMicro diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 379da9692..1eab032a7 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -368,6 +368,24 @@ struct LCurveParams bool operator !=(const LCurveParams& other) const; }; + +/** + * Parameters for local contrast + */ +struct LocalContrastParams { + bool enabled; + int radius; + double amount; + double darkness; + double lightness; + + LocalContrastParams(); + + bool operator==(const LocalContrastParams &other) const; + bool operator!=(const LocalContrastParams &other) const; +}; + + /** * Parameters of the RGB curves */ @@ -1380,6 +1398,7 @@ struct RAWParams { double pixelShiftSmoothFactor; bool pixelShiftExp0; bool pixelShiftLmmse; + bool pixelShiftOneGreen; bool pixelShiftEqualBright; bool pixelShiftEqualBrightChannel; bool pixelShiftNonGreenCross; @@ -1476,6 +1495,7 @@ public: ToneCurveParams toneCurve; ///< Tone curve parameters LCurveParams labCurve; ///< CIELAB luminance curve parameters RetinexParams retinex; ///< Retinex parameters + LocalContrastParams localContrast; ////< Local contrast parameters RGBCurvesParams rgbCurves; ///< RGB curves parameters ColorToningParams colorToning; ///< Color Toning parameters SharpeningParams sharpening; ///< Sharpening parameters diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 33a1d9c53..8ef543f90 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2045,7 +2045,7 @@ void RawImageSource::demosaic (const RAWParams &raw) } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZE) ) { amaze_demosaic_RT (0, 0, W, H, rawData, red, green, blue); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::PIXELSHIFT) ) { - pixelshift(0, 0, W, H, raw.bayersensor, currFrame, ri->get_model(), raw.expos); + pixelshift(0, 0, W, H, raw.bayersensor, currFrame, ri->get_maker(), ri->get_model(), raw.expos); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCB) ) { dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::EAHD)) { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 4924b955a..d1496d4fd 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -269,7 +269,7 @@ protected: void xtransborder_interpolate (int border); void xtrans_interpolate (const int passes, const bool useCieLab); void fast_xtrans_interpolate (); - void pixelshift(int winx, int winy, int winw, int winh, const RAWParams::BayerSensor &bayerParams, unsigned int frame, const std::string &model, float rawWpCorrection); + void pixelshift(int winx, int winy, int winw, int winh, const RAWParams::BayerSensor &bayerParams, unsigned int frame, const std::string &make, const std::string &model, float rawWpCorrection); void hflip (Imagefloat* im); void vflip (Imagefloat* im); void getRawValues(int x, int y, int rotate, int &R, int &G, int &B); diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 9cb5d24b6..3038bf6b1 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -520,7 +520,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = { ALLNORAW, // EvWBEnabled RGBCURVE, // EvRGBEnabled LUMINANCECURVE, // EvLEnabled - LUMINANCECURVE, // EvlocallablocY + DEMOSAIC, // EvPixelShiftOneGreen LUMINANCECURVE, // EvlocallablocX LUMINANCECURVE, // EvlocallabCenter LUMINANCECURVE, // EvlocallabDegree @@ -623,6 +623,49 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // Evlocallabnoisechrodetail LUMINANCECURVE, // Evlocallabsensiden LUMINANCECURVE, // Evlocallabhuerefblur - LUMINANCECURVE // EvlocallabEnabled + LUMINANCECURVE, // EvlocallabEnabled + LUMINANCECURVE // EvlocallablocY }; + +namespace rtengine { + +RefreshMapper::RefreshMapper(): + next_event_(rtengine::NUMOFEVENTS) +{ + for (int event = 0; event < rtengine::NUMOFEVENTS; ++event) { + actions_[event] = refreshmap[event]; + } +} + + +ProcEvent RefreshMapper::newEvent() +{ + return ProcEvent(++next_event_); +} + + +void RefreshMapper::mapEvent(ProcEvent event, int action) +{ + actions_[event] = action; +} + + +int RefreshMapper::getAction(ProcEvent event) const +{ + auto it = actions_.find(event); + if (it == actions_.end()) { + return 0; + } else { + return it->second; + } +} + + +RefreshMapper *RefreshMapper::getInstance() +{ + static RefreshMapper instance; + return &instance; +} + +} // namespace rtengine diff --git a/rtengine/refreshmap.h b/rtengine/refreshmap.h index cea6b3c8e..09059470b 100644 --- a/rtengine/refreshmap.h +++ b/rtengine/refreshmap.h @@ -19,6 +19,9 @@ #ifndef __REFRESHMAP__ #define __REFRESHMAP__ +#include +#include "procevents.h" + // Use M_VOID if you wish to update the proc params without updating the preview at all ! #define M_VOID (1<<17) // Use M_MINUPDATE if you wish to update the preview without modifying the image (think about it like a "refreshPreview") @@ -74,4 +77,23 @@ #define OUTPUTPROFILE M_MONITOR extern int refreshmap[]; + +namespace rtengine { + +class RefreshMapper { +public: + static RefreshMapper *getInstance(); + ProcEvent newEvent(); + void mapEvent(ProcEvent event, int action); + int getAction(ProcEvent event) const; + +private: + RefreshMapper(); + + int next_event_; + std::unordered_map actions_; +}; + +} // namespace rtengine + #endif diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 8e6e62508..10e337913 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -120,7 +120,7 @@ public: /** @return the orientation of the image */ virtual std::string getOrientation (unsigned int frame = 0) const = 0; - /** @return true if the file is a PixelShift shot (Pentax bodies) */ + /** @return true if the file is a PixelShift shot (Pentax and Sony bodies) */ virtual bool getPixelShift (unsigned int frame = 0) const = 0; /** @return false: not an HDR file ; true: single or multi-frame HDR file (e.g. Pentax HDR raw file or 32 bit float DNG file or Log compressed) */ virtual bool getHDR (unsigned int frame = 0) const = 0; @@ -424,6 +424,7 @@ public: * The image update starts immediately in the background. If it is ready, the result is passed to a PreviewImageListener * and to a DetailedCropListener (if enabled). */ virtual void endUpdateParams (ProcEvent change) = 0; + void endUpdateParams(ProcEventCode change) { endUpdateParams(ProcEvent(change)); } virtual void endUpdateParams (int changeFlags) = 0; // Starts a minimal update virtual void startProcessing (int changeCode) = 0; diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 002ed4ee2..964310d2f 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -149,6 +149,8 @@ set(NONCLISOURCEFILES xtransrawexposure.cc zoompanel.cc fattaltonemap.cc + localcontrast.cc + eventmapper.cc ) include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 07cf47d18..509b00610 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -129,6 +129,10 @@ enum { ADDSET_EPD_REWEIGHTINGITERATES, ADDSET_FATTAL_ALPHA, ADDSET_FATTAL_BETA, + ADDSET_LOCALCONTRAST_RADIUS, + ADDSET_LOCALCONTRAST_AMOUNT, + ADDSET_LOCALCONTRAST_DARKNESS, + ADDSET_LOCALCONTRAST_LIGHTNESS, ADDSET_PARAM_NUM // THIS IS USED AS A DELIMITER!! }; diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 7ecd77f85..9cb9cccb5 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -195,6 +195,7 @@ void BatchToolPanelCoordinator::initSession () prsharpening->setAdjusterBehavior (options.baBehav[ADDSET_SHARP_RADIUS], options.baBehav[ADDSET_SHARP_AMOUNT], options.baBehav[ADDSET_SHARP_DAMPING], options.baBehav[ADDSET_SHARP_ITER], options.baBehav[ADDSET_SHARP_EDGETOL], options.baBehav[ADDSET_SHARP_HALOCTRL]); epd->setAdjusterBehavior (options.baBehav[ADDSET_EPD_STRENGTH], options.baBehav[ADDSET_EPD_GAMMA], options.baBehav[ADDSET_EPD_EDGESTOPPING], options.baBehav[ADDSET_EPD_SCALE], options.baBehav[ADDSET_EPD_REWEIGHTINGITERATES]); fattal->setAdjusterBehavior (options.baBehav[ADDSET_FATTAL_ALPHA], options.baBehav[ADDSET_FATTAL_BETA]); + localContrast->setAdjusterBehavior(options.baBehav[ADDSET_LOCALCONTRAST_RADIUS], options.baBehav[ADDSET_LOCALCONTRAST_AMOUNT], options.baBehav[ADDSET_LOCALCONTRAST_DARKNESS], options.baBehav[ADDSET_LOCALCONTRAST_LIGHTNESS]); sharpenEdge->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENEDGE_AMOUNT], options.baBehav[ADDSET_SHARPENEDGE_PASS]); sharpenMicro->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENMICRO_AMOUNT], options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY]); @@ -353,6 +354,9 @@ void BatchToolPanelCoordinator::initSession () if (options.baBehav[ADDSET_RAWFFCLIPCONTROL]) { pparams.raw.ff_clipControl = 0; } if (options.baBehav[ADDSET_PREPROCESS_GREENEQUIL]) { pparams.raw.bayersensor.greenthresh = 0; } if (options.baBehav[ADDSET_PREPROCESS_LINEDENOISE]) { pparams.raw.bayersensor.linenoise = 0; } + if (options.baBehav[ADDSET_LOCALCONTRAST_AMOUNT]) { pparams.localContrast.amount = 0; } + if (options.baBehav[ADDSET_LOCALCONTRAST_DARKNESS]) { pparams.localContrast.darkness = 0; } + if (options.baBehav[ADDSET_LOCALCONTRAST_LIGHTNESS]) { pparams.localContrast.lightness = 0; } // *INDENT-ON* } diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 9df7c106d..b294c9fee 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -225,6 +225,11 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA pixelShiftLmmse->set_tooltip_text (M("TP_RAW_PIXELSHIFTLMMSE_TOOLTIP")); pixelShiftOptions->pack_start(*pixelShiftLmmse); +// pixelShiftOneGreen = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTONEGREEN"), multiImage)); +// pixelShiftOneGreen->setCheckBoxListener (this); +// pixelShiftOneGreen->set_tooltip_text (M("TP_RAW_PIXELSHIFTONEGREEN_TOOLTIP")); +// pixelShiftOptions->pack_start(*pixelShiftOneGreen); + #ifdef PIXELSHIFTDEV pixelShiftMotion = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTMOTION"), 0, 100, 1, 70)); pixelShiftMotion->setAdjusterListener (this); @@ -376,6 +381,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params } pixelShiftSmooth->setValue (pp->raw.bayersensor.pixelShiftSmoothFactor); pixelShiftLmmse->setValue (pp->raw.bayersensor.pixelShiftLmmse); +// pixelShiftOneGreen->setValue (pp->raw.bayersensor.pixelShiftOneGreen); pixelShiftEqualBright->setValue (pp->raw.bayersensor.pixelShiftEqualBright); pixelShiftEqualBrightChannel->set_sensitive (pp->raw.bayersensor.pixelShiftEqualBright); pixelShiftEqualBrightChannel->setValue (pp->raw.bayersensor.pixelShiftEqualBrightChannel); @@ -427,6 +433,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params pixelShiftBlur->setEdited (pedited->raw.bayersensor.pixelShiftBlur); pixelShiftSmooth->setEditedState ( pedited->raw.bayersensor.pixelShiftSmooth ? Edited : UnEdited); pixelShiftLmmse->setEdited (pedited->raw.bayersensor.pixelShiftLmmse); +// pixelShiftOneGreen->setEdited (pedited->raw.bayersensor.pixelShiftOneGreen); pixelShiftEqualBright->setEdited (pedited->raw.bayersensor.pixelShiftEqualBright); pixelShiftEqualBrightChannel->setEdited (pedited->raw.bayersensor.pixelShiftEqualBrightChannel); pixelShiftNonGreenCross->setEdited (pedited->raw.bayersensor.pixelShiftNonGreenCross); @@ -531,6 +538,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pp->raw.bayersensor.pixelShiftBlur = pixelShiftBlur->getLastActive (); pp->raw.bayersensor.pixelShiftSmoothFactor = pixelShiftSmooth->getValue(); pp->raw.bayersensor.pixelShiftLmmse = pixelShiftLmmse->getLastActive (); +// pp->raw.bayersensor.pixelShiftOneGreen = pixelShiftOneGreen->getLastActive (); pp->raw.bayersensor.pixelShiftEqualBright = pixelShiftEqualBright->getLastActive (); pp->raw.bayersensor.pixelShiftEqualBrightChannel = pixelShiftEqualBrightChannel->getLastActive (); pp->raw.bayersensor.pixelShiftNonGreenCross = pixelShiftNonGreenCross->getLastActive (); @@ -583,6 +591,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pedited->raw.bayersensor.pixelShiftBlur = !pixelShiftBlur->get_inconsistent(); pedited->raw.bayersensor.pixelShiftSmooth = pixelShiftSmooth->getEditedState(); pedited->raw.bayersensor.pixelShiftLmmse = !pixelShiftLmmse->get_inconsistent(); +// pedited->raw.bayersensor.pixelShiftOneGreen = !pixelShiftOneGreen->get_inconsistent(); pedited->raw.bayersensor.pixelShiftEqualBright = !pixelShiftEqualBright->get_inconsistent(); pedited->raw.bayersensor.pixelShiftEqualBrightChannel = !pixelShiftEqualBrightChannel->get_inconsistent(); pedited->raw.bayersensor.pixelShiftNonGreenCross = !pixelShiftNonGreenCross->get_inconsistent(); @@ -849,6 +858,10 @@ void BayerProcess::checkBoxToggled (CheckBox* c, CheckValue newval) if (listener) { listener->panelChanged (EvPixelShiftLmmse, pixelShiftLmmse->getValueAsStr ()); } +// } else if (c == pixelShiftOneGreen) { +// if (listener) { +// listener->panelChanged (EvPixelShiftOneGreen, pixelShiftOneGreen->getValueAsStr ()); +// } } else if (c == pixelShiftEqualBright) { if (!batchMode) { pixelShiftEqualBrightChannel->set_sensitive(newval != CheckValue::off); diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index 6d9dd6062..e1a620474 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -49,6 +49,7 @@ protected: CheckBox* pixelShiftBlur; CheckBox* pixelShiftHoleFill; CheckBox* pixelShiftMedian; +// CheckBox* pixelShiftOneGreen; CheckBox* pixelShiftLmmse; CheckBox* pixelShiftEqualBright; CheckBox* pixelShiftEqualBrightChannel; diff --git a/rtgui/eventmapper.cc b/rtgui/eventmapper.cc new file mode 100644 index 000000000..de5258413 --- /dev/null +++ b/rtgui/eventmapper.cc @@ -0,0 +1,63 @@ +/* -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * 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 + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#include "eventmapper.h" + + +ProcEventMapper::ProcEventMapper() +{ + for (int event = 0; event < rtengine::NUMOFEVENTS; ++event) { + history_msgs_[event] = "HISTORY_MSG_" + std::to_string(event + 1); + } +} + + +ProcEventMapper *ProcEventMapper::getInstance() +{ + static ProcEventMapper instance; + return &instance; +} + + +rtengine::ProcEvent ProcEventMapper::newEvent(int action, const std::string &history_msg) +{ + rtengine::ProcEvent event = rtengine::RefreshMapper::getInstance()->newEvent(); + rtengine::RefreshMapper::getInstance()->mapEvent(event, action); + + if (history_msg.empty()) { + history_msgs_[event] = "HISTORY_MSG_" + std::to_string(event + 1); + } else { + history_msgs_[event] = history_msg; + } + + return event; +} + + +const std::string &ProcEventMapper::getHistoryMsg(rtengine::ProcEvent event) const +{ + static std::string empty; + auto it = history_msgs_.find(event); + if (it == history_msgs_.end()) { + return empty; + } else { + return it->second; + } +} diff --git a/rtgui/eventmapper.h b/rtgui/eventmapper.h new file mode 100644 index 000000000..87ccc1d9b --- /dev/null +++ b/rtgui/eventmapper.h @@ -0,0 +1,37 @@ +/* -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * 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 + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#pragma once + +#include +#include +#include "../rtengine/refreshmap.h" + + +class ProcEventMapper { +public: + static ProcEventMapper *getInstance(); + rtengine::ProcEvent newEvent(int action, const std::string &history_msg=""); + const std::string &getHistoryMsg(rtengine::ProcEvent event) const; + +private: + ProcEventMapper(); + + std::unordered_map history_msgs_; +}; diff --git a/rtgui/history.cc b/rtgui/history.cc index 95b1c9f4f..7a3efd2ef 100644 --- a/rtgui/history.cc +++ b/rtgui/history.cc @@ -20,6 +20,7 @@ #include "multilangmgr.h" #include "rtimage.h" #include "guiutils.h" +#include "eventmapper.h" using namespace rtengine; using namespace rtengine::procparams; @@ -237,7 +238,7 @@ void History::procParamsChanged (ProcParams* params, ProcEvent ev, Glib::ustring } // construct formatted list content - Glib::ustring text = M ("HISTORY_MSG_" + std::to_string (ev + 1)); + Glib::ustring text = M(ProcEventMapper::getInstance()->getHistoryMsg(ev)); Glib::RefPtr selection = hTreeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); diff --git a/rtgui/localcontrast.cc b/rtgui/localcontrast.cc new file mode 100644 index 000000000..727479c34 --- /dev/null +++ b/rtgui/localcontrast.cc @@ -0,0 +1,167 @@ +/** -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * 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 + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include "localcontrast.h" +#include "eventmapper.h" +#include +#include + +using namespace rtengine; +using namespace rtengine::procparams; + +LocalContrast::LocalContrast(): FoldableToolPanel(this, "localcontrast", M("TP_LOCALCONTRAST_LABEL"), false, true) +{ + auto m = ProcEventMapper::getInstance(); + EvLocalContrastEnabled = m->newEvent(RGBCURVE, "HISTORY_MSG_LOCALCONTRAST_ENABLED"); + EvLocalContrastRadius = m->newEvent(RGBCURVE, "HISTORY_MSG_LOCALCONTRAST_RADIUS"); + EvLocalContrastAmount = m->newEvent(RGBCURVE, "HISTORY_MSG_LOCALCONTRAST_AMOUNT"); + EvLocalContrastDarkness = m->newEvent(RGBCURVE, "HISTORY_MSG_LOCALCONTRAST_DARKNESS"); + EvLocalContrastLightness = m->newEvent(RGBCURVE, "HISTORY_MSG_LOCALCONTRAST_LIGHTNESS"); + + radius = Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_RADIUS"), 20., 200., 1., 80.)); + amount = Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_AMOUNT"), 0., 1., 0.01, 0.2)); + darkness = Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_DARKNESS"), 0., 3., 0.01, 1.)); + lightness = Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_LIGHTNESS"), 0., 3., 0.01, 1.)); + + radius->setAdjusterListener(this); + amount->setAdjusterListener(this); + darkness->setAdjusterListener(this); + lightness->setAdjusterListener(this); + + radius->show(); + amount->show(); + darkness->show(); + lightness->show(); + + pack_start(*radius); + pack_start(*amount); + pack_start(*darkness); + pack_start(*lightness); +} + + +void LocalContrast::read(const ProcParams *pp, const ParamsEdited *pedited) +{ + disableListener(); + + if (pedited) { + radius->setEditedState(pedited->localContrast.radius ? Edited : UnEdited); + amount->setEditedState(pedited->localContrast.amount ? Edited : UnEdited); + darkness->setEditedState(pedited->localContrast.darkness ? Edited : UnEdited); + lightness->setEditedState(pedited->localContrast.lightness ? Edited : UnEdited); + set_inconsistent(multiImage && !pedited->localContrast.enabled); + } + + setEnabled(pp->localContrast.enabled); + radius->setValue(pp->localContrast.radius); + amount->setValue(pp->localContrast.amount); + darkness->setValue(pp->localContrast.darkness); + lightness->setValue(pp->localContrast.lightness); + + enableListener(); +} + + +void LocalContrast::write(ProcParams *pp, ParamsEdited *pedited) +{ + pp->localContrast.radius = radius->getValue(); + pp->localContrast.amount = amount->getValue(); + pp->localContrast.darkness = darkness->getValue(); + pp->localContrast.lightness = lightness->getValue(); + pp->localContrast.enabled = getEnabled(); + + if (pedited) { + pedited->localContrast.radius = radius->getEditedState(); + pedited->localContrast.amount = amount->getEditedState(); + pedited->localContrast.darkness = darkness->getEditedState(); + pedited->localContrast.lightness = lightness->getEditedState(); + pedited->localContrast.enabled = !get_inconsistent(); + } +} + +void LocalContrast::setDefaults(const ProcParams *defParams, const ParamsEdited *pedited) +{ + radius->setDefault(defParams->localContrast.radius); + amount->setDefault(defParams->localContrast.amount); + darkness->setDefault(defParams->localContrast.darkness); + lightness->setDefault(defParams->localContrast.lightness); + + if (pedited) { + radius->setDefaultEditedState(pedited->localContrast.radius ? Edited : UnEdited); + amount->setDefaultEditedState(pedited->localContrast.amount ? Edited : UnEdited); + darkness->setDefaultEditedState(pedited->localContrast.darkness ? Edited : UnEdited); + lightness->setDefaultEditedState(pedited->localContrast.lightness ? Edited : UnEdited); + } else { + radius->setDefaultEditedState(Irrelevant); + amount->setDefaultEditedState(Irrelevant); + darkness->setDefaultEditedState(Irrelevant); + lightness->setDefaultEditedState(Irrelevant); + } +} + + +void LocalContrast::adjusterChanged(Adjuster* a, double newval) +{ + if (listener && getEnabled()) { + if (a == radius) { + listener->panelChanged(EvLocalContrastRadius, a->getTextValue()); + } else if (a == amount) { + listener->panelChanged(EvLocalContrastAmount, a->getTextValue()); + } else if (a == darkness) { + listener->panelChanged(EvLocalContrastDarkness, a->getTextValue()); + } else if (a == lightness) { + listener->panelChanged(EvLocalContrastLightness, a->getTextValue()); + } + } +} + + +void LocalContrast::enabledChanged () +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged(EvLocalContrastEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged(EvLocalContrastEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(EvLocalContrastEnabled, M("GENERAL_DISABLED")); + } + } +} + + +void LocalContrast::setBatchMode(bool batchMode) +{ + ToolPanel::setBatchMode(batchMode); + + radius->showEditedCB(); + amount->showEditedCB(); + darkness->showEditedCB(); + lightness->showEditedCB(); +} + + +void LocalContrast::setAdjusterBehavior(bool radiusAdd, bool amountAdd, bool darknessAdd, bool lightnessAdd) +{ + radius->setAddMode(radiusAdd); + amount->setAddMode(amountAdd); + darkness->setAddMode(darknessAdd); + lightness->setAddMode(lightnessAdd); +} + diff --git a/rtgui/localcontrast.h b/rtgui/localcontrast.h new file mode 100644 index 000000000..4f6f872af --- /dev/null +++ b/rtgui/localcontrast.h @@ -0,0 +1,53 @@ +/** -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * 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 + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#pragma once + +#include +#include "adjuster.h" +#include "toolpanel.h" + +class LocalContrast: public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ +private: + Adjuster *radius; + Adjuster *amount; + Adjuster *darkness; + Adjuster *lightness; + + rtengine::ProcEvent EvLocalContrastEnabled; + rtengine::ProcEvent EvLocalContrastRadius; + rtengine::ProcEvent EvLocalContrastAmount; + rtengine::ProcEvent EvLocalContrastDarkness; + rtengine::ProcEvent EvLocalContrastLightness; + +public: + + LocalContrast(); + + void read(const rtengine::procparams::ProcParams *pp, const ParamsEdited *pedited=nullptr); + void write(rtengine::procparams::ProcParams *pp, ParamsEdited *pedited=nullptr); + void setDefaults(const rtengine::procparams::ProcParams *defParams, const ParamsEdited *pedited=nullptr); + void setBatchMode(bool batchMode); + + void adjusterChanged(Adjuster *a, double newval); + void enabledChanged(); + void setAdjusterBehavior(bool radiusAdd, bool amountAdd, bool darknessAdd, bool lightnessAdd); +}; + diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index a0d56909e..f70f33aa3 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -98,6 +98,11 @@ void ParamsEdited::set(bool v) labCurve.avoidcolorshift = v; labCurve.rstprotection = v; labCurve.lcredsk = v; + localContrast.enabled = v; + localContrast.radius = v; + localContrast.amount = v; + localContrast.darkness = v; + localContrast.lightness = v; rgbCurves.enabled = v; rgbCurves.lumamode = v; rgbCurves.rcurve = v; @@ -528,6 +533,7 @@ void ParamsEdited::set(bool v) raw.bayersensor.pixelShiftSmooth = v; raw.bayersensor.pixelShiftExp0 = v; raw.bayersensor.pixelShiftLmmse = v; + raw.bayersensor.pixelShiftOneGreen = v; raw.bayersensor.pixelShiftEqualBright = v; raw.bayersensor.pixelShiftEqualBrightChannel = v; raw.bayersensor.pixelShiftNonGreenCross = v; @@ -756,6 +762,13 @@ void ParamsEdited::initFrom(const std::vector& labCurve.avoidcolorshift = labCurve.avoidcolorshift && p.labCurve.avoidcolorshift == other.labCurve.avoidcolorshift; labCurve.rstprotection = labCurve.rstprotection && p.labCurve.rstprotection == other.labCurve.rstprotection; labCurve.lcredsk = labCurve.lcredsk && p.labCurve.lcredsk == other.labCurve.lcredsk; + + localContrast.enabled = localContrast.enabled && p.localContrast.enabled == other.localContrast.enabled; + localContrast.radius = localContrast.radius && p.localContrast.radius == other.localContrast.radius; + localContrast.amount = localContrast.amount && p.localContrast.amount == other.localContrast.amount; + localContrast.darkness = localContrast.darkness && p.localContrast.darkness == other.localContrast.darkness; + localContrast.lightness = localContrast.lightness && p.localContrast.lightness == other.localContrast.lightness; + rgbCurves.enabled = rgbCurves.enabled && p.rgbCurves.enabled == other.rgbCurves.enabled; rgbCurves.lumamode = rgbCurves.lumamode && p.rgbCurves.lumamode == other.rgbCurves.lumamode; rgbCurves.rcurve = rgbCurves.rcurve && p.rgbCurves.rcurve == other.rgbCurves.rcurve; @@ -1187,6 +1200,7 @@ void ParamsEdited::initFrom(const std::vector& raw.bayersensor.pixelShiftSmooth = raw.bayersensor.pixelShiftSmooth && p.raw.bayersensor.pixelShiftSmoothFactor == other.raw.bayersensor.pixelShiftSmoothFactor; raw.bayersensor.pixelShiftExp0 = raw.bayersensor.pixelShiftExp0 && p.raw.bayersensor.pixelShiftExp0 == other.raw.bayersensor.pixelShiftExp0; raw.bayersensor.pixelShiftLmmse = raw.bayersensor.pixelShiftLmmse && p.raw.bayersensor.pixelShiftLmmse == other.raw.bayersensor.pixelShiftLmmse; + raw.bayersensor.pixelShiftOneGreen = raw.bayersensor.pixelShiftOneGreen && p.raw.bayersensor.pixelShiftOneGreen == other.raw.bayersensor.pixelShiftOneGreen; raw.bayersensor.pixelShiftEqualBright = raw.bayersensor.pixelShiftEqualBright && p.raw.bayersensor.pixelShiftEqualBright == other.raw.bayersensor.pixelShiftEqualBright; raw.bayersensor.pixelShiftEqualBrightChannel = raw.bayersensor.pixelShiftEqualBrightChannel && p.raw.bayersensor.pixelShiftEqualBrightChannel == other.raw.bayersensor.pixelShiftEqualBrightChannel; raw.bayersensor.pixelShiftNonGreenCross = raw.bayersensor.pixelShiftNonGreenCross && p.raw.bayersensor.pixelShiftNonGreenCross == other.raw.bayersensor.pixelShiftNonGreenCross; @@ -1595,6 +1609,22 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.labCurve.lcredsk = mods.labCurve.lcredsk; } + if (localContrast.enabled) { + toEdit.localContrast.enabled = mods.localContrast.enabled; + } + if (localContrast.radius) { + toEdit.localContrast.radius = mods.localContrast.radius; + } + if (localContrast.amount) { + toEdit.localContrast.amount = mods.localContrast.amount; + } + if (localContrast.darkness) { + toEdit.localContrast.darkness = mods.localContrast.darkness; + } + if (localContrast.lightness) { + toEdit.localContrast.lightness = mods.localContrast.lightness; + } + if (rgbCurves.enabled) { toEdit.rgbCurves.enabled = mods.rgbCurves.enabled; } @@ -3202,6 +3232,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.raw.bayersensor.pixelShiftLmmse = mods.raw.bayersensor.pixelShiftLmmse; } + if (raw.bayersensor.pixelShiftOneGreen) { + toEdit.raw.bayersensor.pixelShiftOneGreen = mods.raw.bayersensor.pixelShiftOneGreen; + } + if (raw.bayersensor.pixelShiftEqualBright) { toEdit.raw.bayersensor.pixelShiftEqualBright = mods.raw.bayersensor.pixelShiftEqualBright; } @@ -3734,7 +3768,7 @@ bool RAWParamsEdited::BayerSensor::isUnchanged() const return method && imageNum && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && greenEq && pixelShiftMotion && pixelShiftMotionCorrection && pixelShiftMotionCorrectionMethod && pixelShiftStddevFactorGreen && pixelShiftStddevFactorRed && pixelShiftStddevFactorBlue && pixelShiftEperIso && pixelShiftNreadIso && pixelShiftPrnu && pixelShiftSigma && pixelShiftSum && pixelShiftRedBlueWeight && pixelShiftShowMotion && pixelShiftShowMotionMaskOnly - && pixelShiftAutomatic && pixelShiftNonGreenHorizontal && pixelShiftNonGreenVertical && pixelShiftHoleFill && pixelShiftMedian && pixelShiftMedian3 && pixelShiftNonGreenCross && pixelShiftNonGreenCross2 && pixelShiftNonGreenAmaze && pixelShiftGreen && pixelShiftBlur && pixelShiftSmooth && pixelShiftExp0 && pixelShiftLmmse && pixelShiftEqualBright && pixelShiftEqualBrightChannel + && pixelShiftAutomatic && pixelShiftNonGreenHorizontal && pixelShiftNonGreenVertical && pixelShiftHoleFill && pixelShiftMedian && pixelShiftMedian3 && pixelShiftNonGreenCross && pixelShiftNonGreenCross2 && pixelShiftNonGreenAmaze && pixelShiftGreen && pixelShiftBlur && pixelShiftSmooth && pixelShiftExp0 && pixelShiftLmmse && pixelShiftOneGreen && pixelShiftEqualBright && pixelShiftEqualBrightChannel && linenoise && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index a47cfb3cb..246b67e91 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -118,6 +118,17 @@ public: bool clcurve; }; + +class LocalContrastParamsEdited { +public: + bool enabled; + bool radius; + bool amount; + bool darkness; + bool lightness; +}; + + class RGBCurvesParamsEdited { @@ -852,6 +863,7 @@ public: bool pixelShiftSmooth; bool pixelShiftExp0; bool pixelShiftLmmse; + bool pixelShiftOneGreen; bool pixelShiftEqualBright; bool pixelShiftEqualBrightChannel; bool pixelShiftNonGreenCross; @@ -908,6 +920,7 @@ public: GeneralParamsEdited general; ToneCurveParamsEdited toneCurve; LCurveParamsEdited labCurve; + LocalContrastParamsEdited localContrast; RGBCurvesParamsEdited rgbCurves; ColorToningEdited colorToning; RetinexParamsEdited retinex; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index 3ae11260d..e03fec91d 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -49,16 +49,17 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren loc ->set_name ("PartialPasteHeader"); // options in basic: - wb = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_WHITEBALANCE"))); - exposure = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_EXPOSURE"))); - sh = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_SHADOWSHIGHLIGHTS"))); - epd = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_EPD"))); - fattal = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_TM_FATTAL"))); - retinex = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_RETINEX"))); - pcvignette = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_PCVIGNETTE"))); - gradient = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_GRADIENT"))); - labcurve = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_LABCURVE"))); - colorappearance = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_COLORAPP"))); + wb = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_WHITEBALANCE"))); + exposure = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_EXPOSURE"))); + localcontrast = Gtk::manage(new Gtk::CheckButton(M("PARTIALPASTE_LOCALCONTRAST"))); + sh = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_SHADOWSHIGHLIGHTS"))); + epd = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_EPD"))); + fattal = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_TM_FATTAL"))); + retinex = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RETINEX"))); + pcvignette = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PCVIGNETTE"))); + gradient = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_GRADIENT"))); + labcurve = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_LABCURVE"))); + colorappearance = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_COLORAPP"))); // options in detail: sharpen = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_SHARPENING"))); @@ -146,6 +147,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren vboxes[0]->pack_start (*hseps[0], Gtk::PACK_SHRINK, 2); vboxes[0]->pack_start (*wb, Gtk::PACK_SHRINK, 2); vboxes[0]->pack_start (*exposure, Gtk::PACK_SHRINK, 2); + vboxes[0]->pack_start (*localcontrast, Gtk::PACK_SHRINK, 2); vboxes[0]->pack_start (*sh, Gtk::PACK_SHRINK, 2); vboxes[0]->pack_start (*epd, Gtk::PACK_SHRINK, 2); vboxes[0]->pack_start (*fattal, Gtk::PACK_SHRINK, 2); @@ -296,39 +298,41 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren // This can be improved // there is currently no binding of subsettings to CheckButton 'everything' for its inconsistent status - everythingConn = everything->signal_toggled().connect (sigc::mem_fun (*this, &PartialPasteDlg::everythingToggled)); - basicConn = basic->signal_toggled().connect (sigc::mem_fun (*this, &PartialPasteDlg::basicToggled)); - detailConn = detail->signal_toggled().connect (sigc::mem_fun (*this, &PartialPasteDlg::detailToggled)); - colorConn = color->signal_toggled().connect (sigc::mem_fun (*this, &PartialPasteDlg::colorToggled)); - lensConn = lens->signal_toggled().connect (sigc::mem_fun (*this, &PartialPasteDlg::lensToggled)); - compositionConn = composition->signal_toggled().connect (sigc::mem_fun (*this, &PartialPasteDlg::compositionToggled)); - metaConn = meta->signal_toggled().connect (sigc::mem_fun (*this, &PartialPasteDlg::metaToggled)); - rawConn = raw->signal_toggled().connect (sigc::mem_fun (*this, &PartialPasteDlg::rawToggled)); - wavConn = wav->signal_toggled().connect (sigc::mem_fun (*this, &PartialPasteDlg::wavToggled)); + everythingConn = everything->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::everythingToggled)); + basicConn = basic->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::basicToggled)); + detailConn = detail->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::detailToggled)); + colorConn = color->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::colorToggled)); + lensConn = lens->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::lensToggled)); + compositionConn = composition->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::compositionToggled)); + metaConn = meta->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::metaToggled)); + rawConn = raw->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::rawToggled)); + wavConn = wav->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::wavToggled)); // locConn = loc->signal_toggled().connect (sigc::mem_fun (*this, &PartialPasteDlg::locToggled)); - wbConn = wb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); - exposureConn = exposure->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); - shConn = sh->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); - epdConn = epd->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); - fattalConn = fattal->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); - retinexConn = retinex->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); - pcvignetteConn = pcvignette->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); - gradientConn = gradient->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); - labcurveConn = labcurve->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); - colorappearanceConn = colorappearance->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); + wbConn = wb->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + exposureConn = exposure->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + localcontrastConn = localcontrast->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + shConn = sh->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + epdConn = epd->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + fattalConn = fattal->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + retinexConn = retinex->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + pcvignetteConn = pcvignette->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + gradientConn = gradient->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + labcurveConn = labcurve->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + colorappearanceConn = colorappearance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); - sharpenConn = sharpen->signal_toggled().connect (sigc::bind (sigc::mem_fun (*detail, &Gtk::CheckButton::set_inconsistent), true)); - gradsharpenConn = sharpenedge->signal_toggled().connect (sigc::bind (sigc::mem_fun (*detail, &Gtk::CheckButton::set_inconsistent), true)); - microcontrastConn = sharpenmicro->signal_toggled().connect (sigc::bind (sigc::mem_fun (*detail, &Gtk::CheckButton::set_inconsistent), true)); - impdenConn = impden->signal_toggled().connect (sigc::bind (sigc::mem_fun (*detail, &Gtk::CheckButton::set_inconsistent), true)); - dirpyrdenConn = dirpyrden->signal_toggled().connect (sigc::bind (sigc::mem_fun (*detail, &Gtk::CheckButton::set_inconsistent), true)); - dirpyreqConn = dirpyreq->signal_toggled().connect (sigc::bind (sigc::mem_fun (*detail, &Gtk::CheckButton::set_inconsistent), true)); - defringeConn = defringe->signal_toggled().connect (sigc::bind (sigc::mem_fun (*detail, &Gtk::CheckButton::set_inconsistent), true)); - - waveletConn = wavelet->signal_toggled().connect (sigc::bind (sigc::mem_fun (*wav, &Gtk::CheckButton::set_inconsistent), true)); + sharpenConn = sharpen->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); + gradsharpenConn = sharpenedge->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); + microcontrastConn = sharpenmicro->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); + impdenConn = impden->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); + dirpyrdenConn = dirpyrden->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); + dirpyreqConn = dirpyreq->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); + defringeConn = defringe->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); // locallabConn = locallab->signal_toggled().connect (sigc::bind (sigc::mem_fun (*basic, &Gtk::CheckButton::set_inconsistent), true)); - icmConn = icm->signal_toggled().connect (sigc::bind (sigc::mem_fun (*color, &Gtk::CheckButton::set_inconsistent), true)); + + waveletConn = wavelet->signal_toggled().connect (sigc::bind (sigc::mem_fun(*wav, &Gtk::CheckButton::set_inconsistent), true)); + + icmConn = icm->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); //gamcsconn = gam->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); vibranceConn = vibrance->signal_toggled().connect (sigc::bind (sigc::mem_fun (*color, &Gtk::CheckButton::set_inconsistent), true)); chmixerConn = chmixer->signal_toggled().connect (sigc::bind (sigc::mem_fun (*color, &Gtk::CheckButton::set_inconsistent), true)); @@ -488,6 +492,7 @@ void PartialPasteDlg::basicToggled () ConnectionBlocker wbBlocker(wbConn); ConnectionBlocker exposureBlocker(exposureConn); + ConnectionBlocker localcontrastBlocker(localcontrastConn); ConnectionBlocker shBlocker(shConn); ConnectionBlocker epdBlocker(epdConn); ConnectionBlocker fattalBlocker(fattalConn); @@ -502,6 +507,7 @@ void PartialPasteDlg::basicToggled () wb->set_active (basic->get_active ()); exposure->set_active (basic->get_active ()); + localcontrast->set_active(basic->get_active()); sh->set_active (basic->get_active ()); epd->set_active (basic->get_active ()); fattal->set_active (basic->get_active ()); @@ -673,6 +679,10 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.toneCurve = falsePE.toneCurve; } + if (!localcontrast->get_active()) { + filterPE.localContrast = falsePE.localContrast; + } + if (!sh->get_active ()) { filterPE.sh = falsePE.sh; } diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index bb31ce4a4..45500237e 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -45,6 +45,7 @@ public: // options in basic: Gtk::CheckButton* wb; Gtk::CheckButton* exposure; + Gtk::CheckButton* localcontrast; Gtk::CheckButton* sh; Gtk::CheckButton* epd; Gtk::CheckButton* fattal; @@ -128,7 +129,7 @@ public: sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaConn, rawConn, wavConn, locConn; - sigc::connection wbConn, exposureConn, shConn, pcvignetteConn, gradientConn, labcurveConn, colorappearanceConn, locallabConn; + sigc::connection wbConn, exposureConn, localcontrastConn, shConn, pcvignetteConn, gradientConn, labcurveConn, colorappearanceConn, locallabConn; sigc::connection sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, defringeConn, epdConn, fattalConn, dirpyreqConn, waveletConn, retinexConn; sigc::connection vibranceConn, chmixerConn, hsveqConn, rgbcurvesConn, chmixerbwConn, colortoningConn, filmSimulationConn; sigc::connection distortionConn, cacorrConn, vignettingConn, lcpConn; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index fbcd1b683..b9869af7c 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -187,6 +187,14 @@ Gtk::Widget* Preferences::getBatchProcPanel () appendBehavList (mi, M ("TP_EXPOSURE_CONTRAST"), ADDSET_TC_CONTRAST, false); appendBehavList (mi, M ("TP_EXPOSURE_SATURATION"), ADDSET_TC_SATURATION, false); + mi = behModel->append(); + mi->set_value(behavColumns.label, M("TP_LOCALCONTRAST_LABEL")); + appendBehavList(mi, M("TP_LOCALCONTRAST_RADIUS"), ADDSET_LOCALCONTRAST_RADIUS, false); + appendBehavList(mi, M("TP_LOCALCONTRAST_AMOUNT"), ADDSET_LOCALCONTRAST_AMOUNT, false); + appendBehavList(mi, M("TP_LOCALCONTRAST_DARKNESS"), ADDSET_LOCALCONTRAST_DARKNESS, false); + appendBehavList(mi, M("TP_LOCALCONTRAST_LIGHTNESS"), ADDSET_LOCALCONTRAST_LIGHTNESS, false); + + mi = behModel->append (); mi->set_value (behavColumns.label, M ("TP_EPD_LABEL")); appendBehavList (mi, M ("TP_EPD_STRENGTH"), ADDSET_EPD_STRENGTH, false); diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 82327293f..c5bdce9ff 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -42,6 +42,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), hasChan coarse = Gtk::manage (new CoarsePanel ()); toneCurve = Gtk::manage (new ToneCurve ()); shadowshighlights = Gtk::manage (new ShadowsHighlights ()); + localContrast = Gtk::manage(new LocalContrast()); impulsedenoise = Gtk::manage (new ImpulseDenoise ()); defringe = Gtk::manage (new Defringe ()); dirpyrdenoise = Gtk::manage (new DirPyrDenoise ()); @@ -110,6 +111,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), hasChan addPanel (colorPanel, vibrance); addPanel (colorPanel, chmixer); addPanel (colorPanel, blackwhite); + addPanel (exposurePanel, localContrast); addPanel (exposurePanel, shadowshighlights); addPanel (detailsPanel, sharpening); addPanel (detailsPanel, sharpenEdge); @@ -328,7 +330,7 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: return; } - int changeFlags = refreshmap[ (int)event]; + int changeFlags = rtengine::RefreshMapper::getInstance()->getAction(event); ProcParams* params = ipc->beginUpdateParams (); @@ -340,7 +342,7 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: if (event == rtengine::EvCTHFlip || event == rtengine::EvCTVFlip) { if (fabs (params->rotate.degree) > 0.001) { params->rotate.degree *= -1; - changeFlags |= refreshmap[ (int)rtengine::EvROTDegree]; + changeFlags |= rtengine::RefreshMapper::getInstance()->getAction(rtengine::EvROTDegree); rotate->read (params); } } @@ -462,7 +464,7 @@ void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengi // start the IPC processing if (filterRawRefresh) { - ipc->endUpdateParams ( refreshmap[ (int)event] & ALLNORAW ); + ipc->endUpdateParams ( rtengine::RefreshMapper::getInstance()->getAction(event) & ALLNORAW ); } else { ipc->endUpdateParams (event); } diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 1f6f69760..44a93ac38 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -80,6 +80,7 @@ #include "filmsimulation.h" #include "prsharpening.h" #include "fattaltonemap.h" +#include "localcontrast.h" #include "guiutils.h" class ImageEditorCoordinator; @@ -122,6 +123,7 @@ protected: Crop* crop; ToneCurve* toneCurve; ShadowsHighlights* shadowshighlights; + LocalContrast *localContrast; Defringe* defringe; ImpulseDenoise* impulsedenoise; DirPyrDenoise* dirpyrdenoise;