diff --git a/.gitignore b/.gitignore index 7141ec92d..21ebf986a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,8 +13,8 @@ Makefile cmake_install.cmake install_manifest.txt -build -Build +build* +Build* Debug RelWithDebInfo MinSizeRel diff --git a/rtdata/images/Dark/actions/atom.png b/rtdata/images/Dark/actions/atom.png new file mode 100644 index 000000000..1e7ce3da0 Binary files /dev/null and b/rtdata/images/Dark/actions/atom.png differ diff --git a/rtdata/images/Dark/actions/equalizer-narrow.png b/rtdata/images/Dark/actions/equalizer-narrow.png new file mode 100644 index 000000000..dcf484ea7 Binary files /dev/null and b/rtdata/images/Dark/actions/equalizer-narrow.png differ diff --git a/rtdata/images/Dark/actions/equalizer-wide.png b/rtdata/images/Dark/actions/equalizer-wide.png new file mode 100644 index 000000000..50cfed8fa Binary files /dev/null and b/rtdata/images/Dark/actions/equalizer-wide.png differ diff --git a/rtdata/images/Light/actions/atom.png b/rtdata/images/Light/actions/atom.png new file mode 100644 index 000000000..55feaf8d7 Binary files /dev/null and b/rtdata/images/Light/actions/atom.png differ diff --git a/rtdata/images/Light/actions/equalizer-narrow.png b/rtdata/images/Light/actions/equalizer-narrow.png new file mode 100644 index 000000000..c9e2c5b26 Binary files /dev/null and b/rtdata/images/Light/actions/equalizer-narrow.png differ diff --git a/rtdata/images/Light/actions/equalizer-wide.png b/rtdata/images/Light/actions/equalizer-wide.png new file mode 100644 index 000000000..f5b0aca68 Binary files /dev/null and b/rtdata/images/Light/actions/equalizer-wide.png differ diff --git a/rtdata/languages/default b/rtdata/languages/default index 46783f2ce..c6b6c98a8 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -845,6 +845,7 @@ HISTORY_MSG_599;Local - Noise bilateral HISTORY_MSG_600;Local - Noise Equal. Black-White HISTORY_MSG_601;Local - Shape Rt-spot method HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +HISTORY_MSG_HISTMATCHING;Auto-matched Tone Curve HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness HISTORY_MSG_LOCALCONTRAST_ENABLED;Local Contrast @@ -936,6 +937,8 @@ MAIN_MSG_QOVERWRITE;Do you want to overwrite it? MAIN_MSG_SETPATHFIRST;You first have to set a target path in Preferences in order to use this function! MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. MAIN_MSG_WRITEFAILED;Failed to write\n"%1"\n\nMake sure that the folder exists and that you have write permission to it. +MAIN_TAB_ADVANCED;Advanced +MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w MAIN_TAB_COLOR;Color MAIN_TAB_COLOR_TOOLTIP;Shortcut: Alt-c MAIN_TAB_DETAIL;Detail @@ -956,8 +959,6 @@ MAIN_TAB_RAW;Raw MAIN_TAB_RAW_TOOLTIP;Shortcut: Alt-r MAIN_TAB_TRANSFORM;Transform MAIN_TAB_TRANSFORM_TOOLTIP;Shortcut: Alt-t -MAIN_TAB_WAVELET;Wavelet -MAIN_TAB_WAVELET_TOOLTIP;Shortcut: Alt-w MAIN_TOOLTIP_BACKCOLOR0;Background color of the preview: Theme-based\nShortcut: 9 MAIN_TOOLTIP_BACKCOLOR1;Background color of the preview: Black\nShortcut: 9 MAIN_TOOLTIP_BACKCOLOR2;Background color of the preview: White\nShortcut: 9 @@ -992,6 +993,7 @@ NAVIGATOR_XY_FULL;Width: %1, Height: %2 NAVIGATOR_XY_NA;x: --, y: -- OPTIONS_DEFIMG_MISSING;The default profile for non-raw photos could not be found or is not set.\n\nPlease check your profiles' directory, it may be missing or damaged.\n\nDefault internal values will be used. OPTIONS_DEFRAW_MISSING;The default profile for raw photos could not be found or is not set.\n\nPlease check your profiles' directory, it may be missing or damaged.\n\nDefault internal values will be used. +PARTIALPASTE_ADVANCEDGROUP;Advanced Settings PARTIALPASTE_BASICGROUP;Basic Settings PARTIALPASTE_CACORRECTION;Chromatic aberration correction PARTIALPASTE_CHANNELMIXER;Channel mixer @@ -1065,7 +1067,6 @@ PARTIALPASTE_SHARPENMICRO;Microcontrast PARTIALPASTE_TM_FATTAL;HDR Tone mapping PARTIALPASTE_VIBRANCE;Vibrance PARTIALPASTE_VIGNETTING;Vignetting correction -PARTIALPASTE_WAVELETGROUP;Wavelet Levels PARTIALPASTE_WHITEBALANCE;White balance PREFERENCES_ADD;Add PREFERENCES_APPLNEXTSTARTUP;restart required @@ -1689,6 +1690,8 @@ TP_EXPOSURE_CURVEEDITOR1;Tone curve 1 TP_EXPOSURE_CURVEEDITOR2;Tone curve 2 TP_EXPOSURE_CURVEEDITOR2_TOOLTIP;Please refer to the "Exposure > Tone Curves" RawPedia article to learn how to achieve the best results by using two tone curves. TP_EXPOSURE_EXPCOMP;Exposure compensation +TP_EXPOSURE_HISTMATCHING;Auto-matched Tone Curve +TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail. TP_EXPOSURE_LABEL;Exposure TP_EXPOSURE_SATURATION;Saturation TP_EXPOSURE_TCMODE_FILMLIKE;Film-like diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index f2023e88b..c12ade822 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -117,6 +117,7 @@ set(RTENGINESOURCEFILES rtlensfun.cc tmo_fattal02.cc iplocalcontrast.cc + histmatching.cc ) if(LENSFUN_HAS_LOAD_DIRECTORY) diff --git a/rtengine/histmatching.cc b/rtengine/histmatching.cc new file mode 100644 index 000000000..be618d4d7 --- /dev/null +++ b/rtengine/histmatching.cc @@ -0,0 +1,249 @@ +/* -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2018 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 "rawimagesource.h" +#include "rtthumbnail.h" +#include "curves.h" +#include "color.h" +#include "rt_math.h" +#include "iccstore.h" +#include "../rtgui/mydiagonalcurve.h" +#include "improcfun.h" +#define BENCHMARK +#include "StopWatch.h" +#include +#include + + +namespace rtengine { + +extern const Settings *settings; + +namespace { + +std::vector getCdf(const IImage8 &img) +{ + std::vector ret(256); + for (int y = 0; y < img.getHeight(); ++y) { + for (int x = 0; x < img.getWidth(); ++x) { + int lum = LIM(0, int(Color::rgbLuminance(float(img.r(y, x)), float(img.g(y, x)), float(img.b(y, x)))), 255); + ++ret[lum]; + } + } + + int sum = 0; + for (size_t i = 0; i < ret.size(); ++i) { + sum += ret[i]; + ret[i] = sum; + } + + return ret; +} + + +int findMatch(int val, const std::vector &cdf, int j) +{ + if (cdf[j] <= val) { + for (; j < int(cdf.size()); ++j) { + if (cdf[j] == val) { + return j; + } else if (cdf[j] > val) { + return (cdf[j] - val <= val - cdf[j-1] ? j : j-1); + } + } + return 255; + } else { + for (; j >= 0; --j) { + if (cdf[j] == val) { + return j; + } else if (cdf[j] < val) { + return (val - cdf[j] <= cdf[j+1] - val ? j : j+1); + } + } + return 0; + } +} + + +void mappingToCurve(const std::vector &mapping, std::vector &curve) +{ + curve.clear(); + + const int npoints = 8; + int idx = 1; + for (; idx < int(mapping.size()); ++idx) { + if (mapping[idx] >= idx) { + break; + } + } + int step = max(int(mapping.size())/npoints, 1); + + auto coord = [](int v) -> double { return double(v)/255.0; }; + auto doit = + [&](int start, int stop, int step, bool addstart) -> void + { + int prev = start; + if (addstart) { + curve.push_back(coord(start)); + curve.push_back(coord(mapping[start])); + } + for (int i = start; i < stop; ++i) { + int v = mapping[i]; + bool change = i > 0 && v != mapping[i-1]; + int diff = i - prev; + if (change && std::abs(diff - step) <= 1) { + curve.push_back(coord(i)); + curve.push_back(coord(v)); + prev = i; + } + } + }; + doit(0, idx, idx > step ? step : idx / 2, true); + doit(idx, int(mapping.size()), step, idx - step > step / 2); + if (curve.size() <= 2 || curve.back() < 0.99 || (1 - curve[curve.size()-2] > step / 512.0 && curve.back() < coord(mapping.back()))) { + curve.emplace_back(1.0); + curve.emplace_back(1.0); + } + if (curve.size() < 4) { + curve = { DCT_Linear }; // not enough points, fall back to linear + } else { + curve.insert(curve.begin(), DCT_Spline); + } +} + +} // namespace + + +void RawImageSource::getAutoMatchedToneCurve(std::vector &outCurve) +{ + BENCHFUN + + if (settings->verbose) { + std::cout << "performing histogram matching for " << getFileName() << " on the embedded thumbnail" << std::endl; + } + + if (!histMatchingCache.empty()) { + if (settings->verbose) { + std::cout << "tone curve found in cache" << std::endl; + outCurve = histMatchingCache; + return; + } + } + + outCurve = { DCT_Linear }; + + int fw, fh; + getFullSize(fw, fh, TR_NONE); + int skip = 10; + + if (settings->verbose) { + std::cout << "histogram matching: full raw image size is " << fw << "x" << fh << std::endl; + } + + ProcParams neutral; + + std::unique_ptr source; + { + RawMetaDataLocation rml; + eSensorType sensor_type; + int w, h; + std::unique_ptr thumb(Thumbnail::loadQuickFromRaw(getFileName(), rml, sensor_type, w, h, 1, false, true)); + if (!thumb) { + if (settings->verbose) { + std::cout << "histogram matching: no thumbnail found, generating a neutral curve" << std::endl; + } + histMatchingCache = outCurve; + return; + } + source.reset(thumb->quickProcessImage(neutral, fh / skip, TI_Nearest)); + + if (settings->verbose) { + std::cout << "histogram matching: extracted embedded thumbnail" << std::endl; + } + } + + std::unique_ptr target; + { + int tw = source->getWidth(), th = source->getHeight(); + float thumb_ratio = float(std::max(tw, th)) / float(std::min(tw, th)); + float target_ratio = float(std::max(fw, fh)) / float(std::min(fw, fh)); + int cx = 0, cy = 0; + if (std::abs(thumb_ratio - target_ratio) > 0.01) { + if (thumb_ratio > target_ratio) { + // crop the height + int ch = fh - (fw * float(th) / float(tw)); + cy += ch / 2; + fh -= ch; + } else { + // crop the width + int cw = fw - (fh * float(tw) / float(th)); + cx += cw / 2; + fw -= cw; + } + if (settings->verbose) { + std::cout << "histogram matching: cropping target to get an aspect ratio of " << std::fixed << std::setprecision(2) << thumb_ratio << ":1, new full size is " << fw << "x" << fh << std::endl; + } + } + PreviewProps pp(0, 0, fw, fh, skip); + ColorTemp currWB = getWB(); + std::unique_ptr image(new Imagefloat(int(fw / skip), int(fh / skip))); + getImage(currWB, TR_NONE, image.get(), pp, neutral.toneCurve, neutral.raw); + + // this could probably be made faster -- ideally we would need to just + // perform the transformation from camera space to the output space + // (taking gamma into account), but I couldn't find anything + // ready-made, so for now this will do. Remember the famous quote: + // "premature optimization is the root of all evil" :-) + convertColorSpace(image.get(), neutral.icm, currWB); + ImProcFunctions ipf(&neutral); + LabImage tmplab(image->getWidth(), image->getHeight()); + ipf.rgb2lab(*image, tmplab, neutral.icm.working); + image.reset(ipf.lab2rgbOut(&tmplab, 0, 0, tmplab.W, tmplab.H, neutral.icm)); + target.reset(image->to8()); + + if (settings->verbose) { + std::cout << "histogram matching: generated neutral rendering" << std::endl; + } + } + if (target->getWidth() != source->getWidth() || target->getHeight() != source->getHeight()) { + Image8 *tmp = new Image8(source->getWidth(), source->getHeight()); + target->resizeImgTo(source->getWidth(), source->getHeight(), TI_Nearest, tmp); + target.reset(tmp); + } + std::vector scdf = getCdf(*source); + std::vector tcdf = getCdf(*target); + + std::vector mapping; + int j = 0; + for (size_t i = 0; i < tcdf.size(); ++i) { + j = findMatch(tcdf[i], scdf, j); + mapping.push_back(j); + } + + mappingToCurve(mapping, outCurve); + + if (settings->verbose) { + std::cout << "histogram matching: generated curve with " << outCurve.size()/2 << " control points" << std::endl; + } + + histMatchingCache = outCurve; +} + +} // namespace rtengine diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index 891fb1600..81d0583ac 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -574,6 +574,7 @@ public: void setDefaultMonitorProfileName(const Glib::ustring &name) { + MyMutex::MyLock lock(mutex); defaultMonitorProfile = name; } diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 5a71bb532..675243b65 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -137,6 +137,13 @@ public: histGreenRaw.clear(); histBlueRaw.clear(); // only some sources will supply this } + + // for RAW files, compute a tone curve using histogram matching on the embedded thumbnail + virtual void getAutoMatchedToneCurve(std::vector &outCurve) + { + outCurve = { 0.0 }; + } + double getDirPyrDenoiseExpComp ( ) { return dirpyrdenoiseExpComp; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 6004a676a..09aa8ae41 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -596,6 +596,24 @@ void ImProcCoordinator::updatePreviewImage(int todo, Crop* cropCall) aeListener->autoExpChanged(params.toneCurve.expcomp, params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, params.toneCurve.hrenabled); } + if (params.toneCurve.histmatching) { + imgsrc->getAutoMatchedToneCurve(params.toneCurve.curve); + + if (params.toneCurve.autoexp) { + params.toneCurve.expcomp = 0.0; + } + + params.toneCurve.autoexp = false; + params.toneCurve.curveMode = ToneCurveParams::TcMode::FILMLIKE; + params.toneCurve.curve2 = { 0 }; + params.toneCurve.brightness = 0; + params.toneCurve.contrast = 0; + params.toneCurve.black = 0; + + if (aeListener) { + aeListener->autoMatchedToneCurveChanged(params.toneCurve.curveMode, params.toneCurve.curve); + } + } } progress("Exposure curve & CIELAB conversion...", 100 * readyphase / numofphases); diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 1162af84f..92cbda443 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -331,7 +331,8 @@ curveMode(ToneCurveParams::TcMode::STD), saturation(0), shcompr(50), hlcompr(0), - hlcomprthresh(33) + hlcomprthresh(33), + histmatching(false) { } @@ -353,7 +354,8 @@ bool ToneCurveParams::operator ==(const ToneCurveParams& other) const && saturation == other.saturation && shcompr == other.shcompr && hlcompr == other.hlcompr - && hlcomprthresh == other.hlcomprthresh; + && hlcomprthresh == other.hlcomprthresh + && histmatching == other.histmatching; } bool ToneCurveParams::operator !=(const ToneCurveParams& other) const @@ -3120,6 +3122,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->toneCurve.hlcompr, "Exposure", "HighlightCompr", toneCurve.hlcompr, keyFile); saveToKeyfile(!pedited || pedited->toneCurve.hlcomprthresh, "Exposure", "HighlightComprThreshold", toneCurve.hlcomprthresh, keyFile); saveToKeyfile(!pedited || pedited->toneCurve.shcompr, "Exposure", "ShadowCompr", toneCurve.shcompr, keyFile); + saveToKeyfile(!pedited || pedited->toneCurve.histmatching, "Exposure", "HistogramMatching", toneCurve.histmatching, keyFile); // Highlight recovery saveToKeyfile(!pedited || pedited->toneCurve.hrenabled, "HLRecovery", "Enabled", toneCurve.hrenabled, keyFile); @@ -4018,6 +4021,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Exposure", "Curve", pedited, toneCurve.curve, pedited->toneCurve.curve); assignFromKeyfile(keyFile, "Exposure", "Curve2", pedited, toneCurve.curve2, pedited->toneCurve.curve2); } + assignFromKeyfile(keyFile, "Exposure", "HistogramMatching", pedited, toneCurve.histmatching, pedited->toneCurve.histmatching); } if (keyFile.has_group("HLRecovery")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 041a1fe5b..c2e124dde 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -285,6 +285,7 @@ struct ToneCurveParams { int shcompr; int hlcompr; // Highlight Recovery's compression int hlcomprthresh; // Highlight Recovery's threshold + bool histmatching; // histogram matching ToneCurveParams(); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index beaefc9dd..76737e948 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -95,6 +95,7 @@ protected: float psGreenBrightness[4]; float psBlueBrightness[4]; + std::vector histMatchingCache; void hphd_vertical(float** hpmap, int col_from, int col_to); void hphd_horizontal(float** hpmap, int row_from, int row_to); @@ -185,6 +186,7 @@ public: } void getAutoExpHistogram(LUTu & histogram, int& histcompr); void getRAWHistogram(LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw); + void getAutoMatchedToneCurve(std::vector &outCurve); DCPProfile *getDCP(const ColorManagementParams &cmp, DCPProfile::ApplyState &as); void convertColorSpace(Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb); diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 7ee7e7dba..e7b9efe4e 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -295,6 +295,8 @@ public: * @param hlcomprthresh is the new threshold for hlcompr * @param hlrecons set to true if HighLight Reconstruction is enabled */ virtual void autoExpChanged (double brightness, int bright, int contrast, int black, int hlcompr, int hlcomprthresh, bool hlrecons) {} + + virtual void autoMatchedToneCurveChanged(procparams::ToneCurveParams::TcMode curveMode, const std::vector &curve) {} }; class AutoCamListener diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 348b91031..1edbc6e09 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -915,7 +915,7 @@ IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int } // Full thumbnail processing, second stage if complete profile exists -IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorType sensorType, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, double& myscale) +IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorType sensorType, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, double& myscale, bool forMonitor) { unsigned int imgNum = 0; if (isRaw) { @@ -1294,8 +1294,13 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT //ipf.colorCurve (labView, labView); // obtain final image - Image8* readyImg = new Image8 (fw, fh); - ipf.lab2monitorRgb (labView, readyImg); + Image8* readyImg = nullptr; + if (forMonitor) { + readyImg = new Image8 (fw, fh); + ipf.lab2monitorRgb (labView, readyImg); + } else { + readyImg = ipf.lab2rgb(labView, 0, 0, fw, fh, params.icm); + } delete labView; delete baseImg; diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index 2ee08de50..902f264fc 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -71,7 +71,7 @@ public: void init (); - IImage8* processImage (const procparams::ProcParams& pparams, eSensorType sensorType, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, double& scale); + IImage8* processImage (const procparams::ProcParams& pparams, eSensorType sensorType, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, double& scale, bool forMonitor=true); IImage8* quickProcessImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp); int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio); void getDimensions (int& w, int& h, double& scaleFac); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 6e1209d91..f7121a234 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -747,6 +747,21 @@ private: imgsrc->getAutoExpHistogram(aehist, aehistcompr); ipf.getAutoExp(aehist, aehistcompr, params.toneCurve.clip, expcomp, bright, contr, black, hlcompr, hlcomprthresh); } + if (params.toneCurve.histmatching) { + imgsrc->getAutoMatchedToneCurve(params.toneCurve.curve); + + if (params.toneCurve.autoexp) { + params.toneCurve.expcomp = 0.0; + } + + params.toneCurve.autoexp = false; + params.toneCurve.curveMode = ToneCurveParams::TcMode::FILMLIKE; + params.toneCurve.curve2 = { 0 }; + params.toneCurve.brightness = 0; + params.toneCurve.contrast = 0; + params.toneCurve.black = 0; + + } // at this stage, we can flush the raw data to free up quite an important amount of memory // commented out because it makes the application crash when batch processing... diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index c0be121a1..a61808bd9 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -49,6 +49,7 @@ void ParamsEdited::set(bool v) toneCurve.expcomp = v; toneCurve.hrenabled = v; toneCurve.method = v; + toneCurve.histmatching = v; retinex.cdcurve = v; retinex.mapcurve = v; retinex.cdHcurve = v; @@ -721,6 +722,7 @@ void ParamsEdited::initFrom(const std::vector& toneCurve.expcomp = toneCurve.expcomp && p.toneCurve.expcomp == other.toneCurve.expcomp; toneCurve.hrenabled = toneCurve.hrenabled && p.toneCurve.hrenabled == other.toneCurve.hrenabled; toneCurve.method = toneCurve.method && p.toneCurve.method == other.toneCurve.method; + toneCurve.histmatching = toneCurve.histmatching && p.toneCurve.histmatching == other.toneCurve.histmatching; retinex.cdcurve = retinex.cdcurve && p.retinex.cdcurve == other.retinex.cdcurve; retinex.mapcurve = retinex.mapcurve && p.retinex.mapcurve == other.retinex.mapcurve; retinex.cdHcurve = retinex.cdHcurve && p.retinex.cdHcurve == other.retinex.cdHcurve; @@ -1429,6 +1431,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.toneCurve.method = mods.toneCurve.method; } + if (toneCurve.histmatching) { + toEdit.toneCurve.histmatching = mods.toneCurve.histmatching; + } + if (retinex.enabled) { toEdit.retinex.enabled = mods.retinex.enabled; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 07f90a90e..f6f5d31e5 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -53,6 +53,7 @@ public: bool expcomp; bool hrenabled; bool method; + bool histmatching; }; class RetinexParamsEdited diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index e03fec91d..f8fbd0383 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -43,8 +43,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren meta ->set_name ("PartialPasteHeader"); raw = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_RAWGROUP"))); raw ->set_name ("PartialPasteHeader"); - wav = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_WAVELETGROUP"))); - wav ->set_name ("PartialPasteHeader"); + advanced = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_ADVANCEDGROUP"))); + advanced ->set_name("PartialPasteHeader"); loc = Gtk::manage (new Gtk::CheckButton (M ("PARTIALPASTE_LOCGROUP"))); loc ->set_name ("PartialPasteHeader"); @@ -151,12 +151,10 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren 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); - vboxes[0]->pack_start (*retinex, Gtk::PACK_SHRINK, 2); vboxes[0]->pack_start (*pcvignette, Gtk::PACK_SHRINK, 2); vboxes[0]->pack_start (*gradient, Gtk::PACK_SHRINK, 2); vboxes[0]->pack_start (*labcurve, Gtk::PACK_SHRINK, 2); // vboxes[0]->pack_start (*locallab, Gtk::PACK_SHRINK, 2); - vboxes[0]->pack_start (*colorappearance, Gtk::PACK_SHRINK, 2); //DETAIL vboxes[1]->pack_start (*detail, Gtk::PACK_SHRINK, 2); @@ -202,8 +200,10 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren vboxes[4]->pack_start (*commonTrans, Gtk::PACK_SHRINK, 2); //WAVELET - vboxes[5]->pack_start (*wav, Gtk::PACK_SHRINK, 2); + vboxes[5]->pack_start (*advanced, Gtk::PACK_SHRINK, 2); vboxes[5]->pack_start (*hseps[5], Gtk::PACK_SHRINK, 2); + vboxes[5]->pack_start (*retinex, Gtk::PACK_SHRINK, 2); + vboxes[5]->pack_start (*colorappearance, Gtk::PACK_SHRINK, 2); vboxes[5]->pack_start (*wavelet, Gtk::PACK_SHRINK, 2); //LOC @@ -306,7 +306,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren 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)); + advancedConn = advanced->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::advancedToggled)); // 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)); @@ -330,7 +330,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren 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)); - waveletConn = wavelet->signal_toggled().connect (sigc::bind (sigc::mem_fun(*wav, &Gtk::CheckButton::set_inconsistent), true)); + waveletConn = wavelet->signal_toggled().connect (sigc::bind (sigc::mem_fun(*advanced, &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)); @@ -401,7 +401,7 @@ void PartialPasteDlg::everythingToggled () ConnectionBlocker compositionBlocker(compositionConn); ConnectionBlocker metaBlocker(metaConn); ConnectionBlocker rawBlocker(rawConn); - ConnectionBlocker wavBlocker(wavConn); + ConnectionBlocker advancedBlocker(advancedConn); everything->set_inconsistent (false); @@ -414,7 +414,7 @@ void PartialPasteDlg::everythingToggled () composition->set_active (everything->get_active()); meta->set_active (everything->get_active()); raw->set_active (everything->get_active()); - wav->set_active (everything->get_active()); + advanced->set_active(everything->get_active()); loc->set_active (everything->get_active()); //toggle group children @@ -425,7 +425,7 @@ void PartialPasteDlg::everythingToggled () PartialPasteDlg::compositionToggled (); PartialPasteDlg::metaToggled (); PartialPasteDlg::rawToggled (); - PartialPasteDlg::wavToggled (); + PartialPasteDlg::advancedToggled (); // PartialPasteDlg::locToggled (); } @@ -498,9 +498,7 @@ void PartialPasteDlg::basicToggled () ConnectionBlocker fattalBlocker(fattalConn); ConnectionBlocker pcvignetteBlocker(pcvignetteConn); ConnectionBlocker gradientBlocker(gradientConn); - ConnectionBlocker retinexBlocker(retinexConn); ConnectionBlocker labcurveBlocker(labcurveConn); - ConnectionBlocker colorappearanceBlocker(colorappearanceConn); basic->set_inconsistent (false); @@ -513,9 +511,7 @@ void PartialPasteDlg::basicToggled () fattal->set_active (basic->get_active ()); pcvignette->set_active (basic->get_active ()); gradient->set_active (basic->get_active ()); - retinex->set_active (basic->get_active ()); labcurve->set_active (basic->get_active ()); - colorappearance->set_active (basic->get_active ()); /* locallab->set_active (basic->get_active ()); @@ -555,13 +551,17 @@ void PartialPasteDlg::detailToggled () dirpyreq->set_active (detail->get_active ()); } -void PartialPasteDlg::wavToggled () +void PartialPasteDlg::advancedToggled () { ConnectionBlocker waveletBlocker(waveletConn); + ConnectionBlocker retinexBlocker(retinexConn); + ConnectionBlocker colorappearanceBlocker(colorappearanceConn); - wav->set_inconsistent (false); - wavelet->set_active (wav->get_active ()); + advanced->set_inconsistent (false); + wavelet->set_active (advanced->get_active ()); + retinex->set_active (basic->get_active ()); + colorappearance->set_active (basic->get_active ()); } /* void PartialPasteDlg::locToggled () diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index 45500237e..7308e0784 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -39,7 +39,7 @@ public: Gtk::CheckButton* composition; Gtk::CheckButton* meta; Gtk::CheckButton* raw; - Gtk::CheckButton* wav; + Gtk::CheckButton* advanced; Gtk::CheckButton* loc; // options in basic: @@ -127,7 +127,7 @@ public: Gtk::CheckButton* ff_BlurType; Gtk::CheckButton* ff_ClipControl; - sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaConn, rawConn, wavConn, locConn; + sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaConn, rawConn, advancedConn, locConn; sigc::connection wbConn, exposureConn, localcontrastConn, shConn, pcvignetteConn, gradientConn, labcurveConn, colorappearanceConn, locallabConn; sigc::connection sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, defringeConn, epdConn, fattalConn, dirpyreqConn, waveletConn, retinexConn; @@ -151,7 +151,7 @@ public: void compositionToggled (); void metaToggled (); void rawToggled (); - void wavToggled (); + void advancedToggled (); void locToggled (); }; diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h index c6f2598b0..1eb54d68b 100644 --- a/rtgui/ppversion.h +++ b/rtgui/ppversion.h @@ -1,13 +1,15 @@ #pragma once // This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes -#define PPVERSION 329 +#define PPVERSION 330 #define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified /* Log of version changes + 330 2018-20-01 + Added 'Auto-matched Tone Curve' button, performing histogram matching 329 2017-12-09 - Added 'Enabled' flag for Channel Mixer, RGB Curves and HSV Equalizer + Added 'Enabled' flag for Channel Mixer, RGB Curves, HSV Equalizer and L*a*b* Adjustments 328 2017-11-22 Fix wrong type of ff_clipControl 327 2017-09-15 diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index a9dd35466..07822f857 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -22,12 +22,16 @@ #include #include "ppversion.h" #include "edit.h" +#include "eventmapper.h" using namespace rtengine; using namespace rtengine::procparams; ToneCurve::ToneCurve () : FoldableToolPanel(this, "tonecurve", M("TP_EXPOSURE_LABEL")) { + auto m = ProcEventMapper::getInstance(); + EvHistMatching = m->newEvent(AUTOEXP, "HISTORY_MSG_HISTMATCHING"); + EvHistMatchingBatch = m->newEvent(M_VOID, "HISTORY_MSG_HISTMATCHING"); CurveListener::setMulti(true); @@ -122,6 +126,11 @@ ToneCurve::ToneCurve () : FoldableToolPanel(this, "tonecurve", M("TP_EXPOSURE_LA //----------- Curve 1 ------------------------------ pack_start (*Gtk::manage (new Gtk::HSeparator())); + histmatching = Gtk::manage(new Gtk::ToggleButton(M("TP_EXPOSURE_HISTMATCHING"))); + histmatching->set_tooltip_markup(M("TP_EXPOSURE_HISTMATCHING_TOOLTIP")); + histmatchconn = histmatching->signal_toggled().connect(sigc::mem_fun(*this, &ToneCurve::histmatchingToggled)); + pack_start(*histmatching, true, true, 2); + toneCurveMode = Gtk::manage (new MyComboBoxText ()); toneCurveMode->append (M("TP_EXPOSURE_TCMODE_STANDARD")); toneCurveMode->append (M("TP_EXPOSURE_TCMODE_WEIGHTEDSTD")); @@ -226,6 +235,8 @@ void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) toneCurveMode->set_active(rtengine::toUnderlying(pp->toneCurve.curveMode)); toneCurveMode2->set_active(rtengine::toUnderlying(pp->toneCurve.curveMode2)); + histmatching->set_active(pp->toneCurve.histmatching); + if (pedited) { expcomp->setEditedState (pedited->toneCurve.expcomp ? Edited : UnEdited); black->setEditedState (pedited->toneCurve.black ? Edited : UnEdited); @@ -248,6 +259,8 @@ void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) if (!pedited->toneCurve.curveMode2) { toneCurveMode2->set_active(6); } + + histmatching->set_inconsistent(!pedited->toneCurve.histmatching); } enaconn.block (true); @@ -343,6 +356,8 @@ void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) pp->toneCurve.curveMode2 = ToneCurveParams::TcMode::PERCEPTUAL; } + pp->toneCurve.histmatching = histmatching->get_active(); + if (pedited) { pedited->toneCurve.expcomp = expcomp->getEditedState (); pedited->toneCurve.black = black->getEditedState (); @@ -360,6 +375,7 @@ void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) pedited->toneCurve.curveMode2 = toneCurveMode2->get_active_row_number() != 6; pedited->toneCurve.method = method->get_active_row_number() != 4; pedited->toneCurve.hrenabled = !hrenabled->get_inconsistent(); + pedited->toneCurve.histmatching = !histmatching->get_inconsistent(); } pp->toneCurve.hrenabled = hrenabled->get_active(); @@ -408,6 +424,8 @@ void ToneCurve::hrenabledChanged () autolevels->set_inconsistent (false); } + setHistmatching(false); + if (hrenabled->get_active ()) { listener->panelChanged (EvHREnabled, M("GENERAL_ENABLED")); } else { @@ -419,6 +437,7 @@ void ToneCurve::methodChanged () { if (listener) { + setHistmatching(false); if (hrenabled->get_active ()) { listener->panelChanged (EvHRMethod, method->get_active_text ()); } @@ -430,6 +449,7 @@ void ToneCurve::setRaw (bool raw) disableListener (); method->set_sensitive (raw); hrenabled->set_sensitive (raw); + histmatching->set_sensitive(raw); enableListener (); } @@ -471,6 +491,7 @@ void ToneCurve::curveChanged (CurveEditor* ce) { if (listener) { + setHistmatching(false); if (ce == shape) { listener->panelChanged (EvToneCurve1, M("HISTORY_CUSTOMCURVE")); } else if (ce == shape2) { @@ -483,6 +504,7 @@ void ToneCurve::curveMode1Changed () { //if (listener) listener->panelChanged (EvToneCurveMode, toneCurveMode->get_active_text()); if (listener) { + setHistmatching(false); Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::curveMode1Changed_)); } } @@ -500,6 +522,7 @@ void ToneCurve::curveMode2Changed () { //if (listener) listener->panelChanged (EvToneCurveMode, toneCurveMode->get_active_text()); if (listener) { + setHistmatching(false); Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::curveMode2Changed_)); } } @@ -544,6 +567,10 @@ void ToneCurve::adjusterChanged (Adjuster* a, double newval) return; } + if (a != expcomp && a != hlcompr && a != hlcomprthresh) { + setHistmatching(false); + } + Glib::ustring costr; if (a == expcomp) { @@ -580,6 +607,8 @@ void ToneCurve::neutral_pressed () // This method deselects auto levels and HL reconstruction auto // and sets neutral values to params in exposure panel + setHistmatching(false); + if (batchMode) { autolevels->set_inconsistent (false); autoconn.block (true); @@ -617,6 +646,7 @@ void ToneCurve::neutral_pressed () } void ToneCurve::autolevels_toggled () { + setHistmatching(false); if (batchMode) { if (autolevels->get_inconsistent()) { @@ -727,6 +757,7 @@ void ToneCurve::waitForAutoExp () toneCurveMode2->set_sensitive (false); hrenabled->set_sensitive(false); method->set_sensitive(false); + histmatching->set_sensitive(false); } void ToneCurve::autoExpChanged (double expcomp, int bright, int contr, int black, int hlcompr, int hlcomprthresh, bool hlrecons) @@ -766,6 +797,7 @@ void ToneCurve::enableAll () toneCurveMode2->set_sensitive (true); hrenabled->set_sensitive(true); method->set_sensitive(true); + histmatching->set_sensitive(true); } bool ToneCurve::autoExpComputed_ () @@ -858,3 +890,79 @@ void ToneCurve::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & his shape->updateBackgroundHistogram (histToneCurve); } + + +void ToneCurve::setHistmatching(bool enabled) +{ + if (histmatching->get_active()) { + histmatchconn.block(true); + histmatching->set_active(enabled); + histmatchconn.block(false); + histmatching->set_inconsistent(false); + } +} + + +void ToneCurve::histmatchingToggled() +{ + if (listener) { + if (!batchMode) { + if (histmatching->get_active()) { + listener->panelChanged(EvHistMatching, M("GENERAL_ENABLED")); + waitForAutoExp(); + } else { + listener->panelChanged(EvHistMatching, M("GENERAL_DISABLED")); + } + } else { + listener->panelChanged(EvHistMatchingBatch, histmatching->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } + } +} + + +void ToneCurve::autoMatchedToneCurveChanged(rtengine::procparams::ToneCurveParams::TcMode curveMode, const std::vector &curve) +{ + nextToneCurveMode = curveMode; + nextToneCurve = curve; + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->histmatchingComputed(); + + return FALSE; + }; + + idle_register.add(func, this); +} + + +bool ToneCurve::histmatchingComputed() +{ + GThreadLock lock; + disableListener(); + enableAll(); + brightness->setValue(0); + contrast->setValue(0); + black->setValue(0); + hlcompr->setValue(0); + + if (!black->getAddMode()) { + shcompr->set_sensitive(!((int)black->getValue() == 0)); + } + + if (autolevels->get_active() ) { + expcomp->setValue(0); + autoconn.block(true); + autolevels->set_active(false); + autoconn.block(false); + autolevels->set_inconsistent(false); + } + + toneCurveMode->set_active(rtengine::toUnderlying(nextToneCurveMode)); + shape->setCurve(nextToneCurve); + shape2->setCurve({ DCT_Linear }); + shape->openIfNonlinear(); + + enableListener(); + + return false; +} diff --git a/rtgui/tonecurve.h b/rtgui/tonecurve.h index 11ec64b96..e85fefa39 100644 --- a/rtgui/tonecurve.h +++ b/rtgui/tonecurve.h @@ -57,14 +57,19 @@ protected: Adjuster* saturation; MyComboBoxText* toneCurveMode; MyComboBoxText* toneCurveMode2; + Gtk::ToggleButton *histmatching; bool clipDirty, lastAuto; sigc::connection autoconn, neutralconn, tcmodeconn, tcmode2conn; + sigc::connection histmatchconn; CurveEditorGroup* curveEditorG; CurveEditorGroup* curveEditorG2; DiagonalCurveEditor* shape; DiagonalCurveEditor* shape2; + rtengine::ProcEvent EvHistMatching; + rtengine::ProcEvent EvHistMatchingBatch; + // used temporarily in eventing double nextExpcomp; int nextBrightness; @@ -73,6 +78,10 @@ protected: int nextHlcompr; int nextHlcomprthresh; bool nextHLRecons; + rtengine::procparams::ToneCurveParams::TcMode nextToneCurveMode; + std::vector nextToneCurve; + + void setHistmatching(bool enabled); public: ToneCurve (); @@ -107,6 +116,10 @@ public: bool isCurveExpanded (); void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histLRETI); + void histmatchingToggled(); + void autoMatchedToneCurveChanged(rtengine::procparams::ToneCurveParams::TcMode curveMode, const std::vector &curve); + bool histmatchingComputed(); + void setRaw (bool raw); void hrenabledChanged (); diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index b321bcc8d..10bdac2a4 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -36,7 +36,7 @@ ToolPanelCoordinator::ToolPanelCoordinator(bool batch) : ipc(nullptr), hasChange colorPanel = Gtk::manage(new ToolVBox()); transformPanel = Gtk::manage(new ToolVBox()); rawPanel = Gtk::manage(new ToolVBox()); - waveletPanel = Gtk::manage(new ToolVBox()); + advancedPanel = Gtk::manage (new ToolVBox ()); locallabPanel = Gtk::manage(new ToolVBox()); coarse = Gtk::manage(new CoarsePanel()); @@ -116,16 +116,16 @@ ToolPanelCoordinator::ToolPanelCoordinator(bool batch) : ipc(nullptr), hasChange addPanel(colorPanel, colortoning); addPanel(exposurePanel, epd); addPanel(exposurePanel, fattal); - addPanel(exposurePanel, retinex); + addPanel (advancedPanel, retinex); addPanel(exposurePanel, pcvignette); addPanel(exposurePanel, gradient); addPanel(exposurePanel, lcurve); - addPanel(exposurePanel, colorappearance); + addPanel (advancedPanel, colorappearance); addPanel(detailsPanel, impulsedenoise); addPanel(detailsPanel, dirpyrdenoise); addPanel(detailsPanel, defringe); addPanel(detailsPanel, dirpyrequalizer); - addPanel(waveletPanel, wavelet); + addPanel (advancedPanel, wavelet); addPanel(locallabPanel, locallab); addPanel(transformPanel, crop); addPanel(transformPanel, resize); @@ -166,7 +166,7 @@ ToolPanelCoordinator::ToolPanelCoordinator(bool batch) : ipc(nullptr), hasChange colorPanelSW = Gtk::manage(new MyScrolledWindow()); transformPanelSW = Gtk::manage(new MyScrolledWindow()); rawPanelSW = Gtk::manage(new MyScrolledWindow()); - waveletPanelSW = Gtk::manage(new MyScrolledWindow()); + advancedPanelSW = Gtk::manage (new MyScrolledWindow ()); locallabPanelSW = Gtk::manage(new MyScrolledWindow()); updateVScrollbars(options.hideTPVScrollbar); @@ -191,9 +191,9 @@ ToolPanelCoordinator::ToolPanelCoordinator(bool batch) : ipc(nullptr), hasChange colorPanel->pack_start(*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); colorPanel->pack_start(*vbPanelEnd[2], Gtk::PACK_SHRINK, 4); - waveletPanelSW->add(*waveletPanel); - waveletPanel->pack_start(*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); - waveletPanel->pack_start(*vbPanelEnd[5], Gtk::PACK_SHRINK, 0); + advancedPanelSW->add (*advancedPanel); + advancedPanel->pack_start (*Gtk::manage (new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); + advancedPanel->pack_start (*vbPanelEnd[5], Gtk::PACK_SHRINK, 0); locallabPanelSW->add(*locallabPanel); locallabPanel->pack_start(*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); @@ -213,7 +213,7 @@ ToolPanelCoordinator::ToolPanelCoordinator(bool batch) : ipc(nullptr), hasChange toiE = Gtk::manage(new TextOrIcon("exposure.png", M("MAIN_TAB_EXPOSURE"), M("MAIN_TAB_EXPOSURE_TOOLTIP"), type)); toiD = Gtk::manage(new TextOrIcon("detail.png", M("MAIN_TAB_DETAIL"), M("MAIN_TAB_DETAIL_TOOLTIP"), type)); toiC = Gtk::manage(new TextOrIcon("colour.png", M("MAIN_TAB_COLOR"), M("MAIN_TAB_COLOR_TOOLTIP"), type)); - toiW = Gtk::manage(new TextOrIcon("wavelet.png", M("MAIN_TAB_WAVELET"), M("MAIN_TAB_WAVELET_TOOLTIP"), type)); + toiW = Gtk::manage (new TextOrIcon ("atom.png", M ("MAIN_TAB_ADVANCED"), M ("MAIN_TAB_ADVANCED_TOOLTIP"), type)); toiL = Gtk::manage(new TextOrIcon("openhand.png", M("MAIN_TAB_LOCALLAB"), M("MAIN_TAB_LOCALLAB_TOOLTIP"), type)); toiT = Gtk::manage(new TextOrIcon("transform.png", M("MAIN_TAB_TRANSFORM"), M("MAIN_TAB_TRANSFORM_TOOLTIP"), type)); @@ -223,7 +223,7 @@ ToolPanelCoordinator::ToolPanelCoordinator(bool batch) : ipc(nullptr), hasChange toolPanelNotebook->append_page(*exposurePanelSW, *toiE); toolPanelNotebook->append_page(*detailsPanelSW, *toiD); toolPanelNotebook->append_page(*colorPanelSW, *toiC); - toolPanelNotebook->append_page(*waveletPanelSW, *toiW); + toolPanelNotebook->append_page (*advancedPanelSW, *toiW); toolPanelNotebook->append_page(*locallabPanelSW, *toiL); toolPanelNotebook->append_page(*transformPanelSW, *toiT); toolPanelNotebook->append_page(*rawPanelSW, *toiR); @@ -825,7 +825,7 @@ bool ToolPanelCoordinator::handleShortcutKey(GdkEventKey* event) return true; case GDK_KEY_w: - toolPanelNotebook->set_current_page(toolPanelNotebook->page_num(*waveletPanelSW)); + toolPanelNotebook->set_current_page (toolPanelNotebook->page_num (*advancedPanelSW)); return true; case GDK_KEY_o: @@ -850,7 +850,7 @@ void ToolPanelCoordinator::updateVScrollbars(bool hide) colorPanelSW->set_policy(Gtk::POLICY_AUTOMATIC, policy); transformPanelSW->set_policy(Gtk::POLICY_AUTOMATIC, policy); rawPanelSW->set_policy(Gtk::POLICY_AUTOMATIC, policy); - waveletPanelSW->set_policy(Gtk::POLICY_AUTOMATIC, policy); + advancedPanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy); locallabPanelSW->set_policy(Gtk::POLICY_AUTOMATIC, policy); for (auto currExp : expList) { diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 6aef40aed..c02fe29d0 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -162,7 +162,7 @@ protected: ToolVBox* colorPanel; ToolVBox* transformPanel; ToolVBox* rawPanel; - ToolVBox* waveletPanel; + ToolVBox* advancedPanel; //<<<<<<< HEAD ToolVBox* locallabPanel; // Gtk::Notebook* metadataPanel; @@ -189,7 +189,7 @@ protected: Gtk::ScrolledWindow* colorPanelSW; Gtk::ScrolledWindow* transformPanelSW; Gtk::ScrolledWindow* rawPanelSW; - Gtk::ScrolledWindow* waveletPanelSW; + Gtk::ScrolledWindow* advancedPanelSW; Gtk::ScrolledWindow* locallabPanelSW; std::vector expList; diff --git a/tools/source_icons/scalable/atom.file b/tools/source_icons/scalable/atom.file new file mode 100644 index 000000000..8c7faa135 --- /dev/null +++ b/tools/source_icons/scalable/atom.file @@ -0,0 +1 @@ +atom.png,w22,actions diff --git a/tools/source_icons/scalable/atom.svg b/tools/source_icons/scalable/atom.svg new file mode 100644 index 000000000..33eb0a7e5 --- /dev/null +++ b/tools/source_icons/scalable/atom.svg @@ -0,0 +1,121 @@ + + + + + Icons for the "Expert" tab in RawTherapee + + + + + + + + image/svg+xml + + Icons for the "Expert" tab in RawTherapee + + + Morgan Hardwood + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/source_icons/scalable/equalizer-narrow.file b/tools/source_icons/scalable/equalizer-narrow.file new file mode 100644 index 000000000..c922b3554 --- /dev/null +++ b/tools/source_icons/scalable/equalizer-narrow.file @@ -0,0 +1 @@ +equalizer-narrow.png,w22,actions diff --git a/tools/source_icons/scalable/equalizer-narrow.svg b/tools/source_icons/scalable/equalizer-narrow.svg new file mode 100644 index 000000000..b31128b36 --- /dev/null +++ b/tools/source_icons/scalable/equalizer-narrow.svg @@ -0,0 +1,201 @@ + + + + + Icons for the "Expert" tab in RawTherapee + + + + + + + + image/svg+xml + + Icons for the "Expert" tab in RawTherapee + + + Morgan Hardwood + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/source_icons/scalable/equalizer-wide.file b/tools/source_icons/scalable/equalizer-wide.file new file mode 100644 index 000000000..22ee0b4b9 --- /dev/null +++ b/tools/source_icons/scalable/equalizer-wide.file @@ -0,0 +1 @@ +equalizer-wide.png,w22,actions diff --git a/tools/source_icons/scalable/equalizer-wide.svg b/tools/source_icons/scalable/equalizer-wide.svg new file mode 100644 index 000000000..dcf184f56 --- /dev/null +++ b/tools/source_icons/scalable/equalizer-wide.svg @@ -0,0 +1,256 @@ + + + + + Icons for the "Expert" tab in RawTherapee + + + + + + + + image/svg+xml + + Icons for the "Expert" tab in RawTherapee + + + Morgan Hardwood + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +