From 0f894656a0a9c751efc5a6f45bcb1d7932e1c16f Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 21 Nov 2021 17:47:41 -0800 Subject: [PATCH 01/24] Add favorites customizer to preferences UI --- rtdata/languages/default | 5 + rtgui/CMakeLists.txt | 1 + rtgui/preferences.cc | 12 + rtgui/preferences.h | 4 + rtgui/toollocationpref.cc | 596 ++++++++++++++++++++++++++++++++++++++ rtgui/toollocationpref.h | 34 +++ rtgui/toolpanelcoord.cc | 250 ++++++++++++++++ rtgui/toolpanelcoord.h | 78 +++++ 8 files changed, 980 insertions(+) create mode 100644 rtgui/toollocationpref.cc create mode 100644 rtgui/toollocationpref.h diff --git a/rtdata/languages/default b/rtdata/languages/default index 747dfa863..525fa2d09 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1891,6 +1891,7 @@ PREFERENCES_STARTUPIMDIR;Image Directory at Startup PREFERENCES_TAB_BROWSER;File Browser PREFERENCES_TAB_COLORMGR;Color Management PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules +PREFERENCES_TAB_FAVORITES;Favorites PREFERENCES_TAB_GENERAL;General PREFERENCES_TAB_IMPROC;Image Processing PREFERENCES_TAB_PERFORMANCE;Performance @@ -1899,6 +1900,10 @@ PREFERENCES_THUMBNAIL_INSPECTOR_JPEG;Embedded JPEG preview PREFERENCES_THUMBNAIL_INSPECTOR_MODE;Image to show PREFERENCES_THUMBNAIL_INSPECTOR_RAW;Neutral raw rendering PREFERENCES_THUMBNAIL_INSPECTOR_RAW_IF_NO_JPEG_FULLSIZE;Embedded JPEG if fullsize, neutral raw otherwise +PREFERENCES_TOOLPANEL_AVAILABLETOOLS;Available Tools +PREFERENCES_TOOLPANEL_FAVORITE;Favorite +PREFERENCES_TOOLPANEL_FAVORITESPANEL;Favorites Panel +PREFERENCES_TOOLPANEL_TOOL;Tool PREFERENCES_TP_LABEL;Tool panel: PREFERENCES_TP_VSCROLLBAR;Hide vertical scrollbar PREFERENCES_USEBUNDLEDPROFILES;Use bundled profiles diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 7976bdc7a..cfb06ff0f 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -160,6 +160,7 @@ set(NONCLISOURCEFILES thumbnail.cc tonecurve.cc toolbar.cc + toollocationpref.cc toolpanel.cc toolpanelcoord.cc vibrance.cc diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index c6c2eb61b..556201732 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -29,6 +29,7 @@ #include #include "rtimage.h" #include "rtwindow.h" +#include "toollocationpref.h" #ifdef _OPENMP #include #endif @@ -65,6 +66,7 @@ Preferences::Preferences(RTWindow *rtwindow) , parent(rtwindow) , newFont(false) , newCPFont(false) + , toolLocationPreference(nullptr) { moptions.copyFrom(&options); @@ -102,6 +104,7 @@ Preferences::Preferences(RTWindow *rtwindow) nb->append_page(*getGeneralPanel(), M("PREFERENCES_TAB_GENERAL")); nb->append_page(*getImageProcessingPanel(), M("PREFERENCES_TAB_IMPROC")); + nb->append_page(*getFavoritesPanel(), M("PREFERENCES_TAB_FAVORITES")); nb->append_page(*getDynamicProfilePanel(), M("PREFERENCES_TAB_DYNAMICPROFILE")); nb->append_page(*getFileBrowserPanel(), M("PREFERENCES_TAB_BROWSER")); nb->append_page(*getColorManPanel(), M("PREFERENCES_TAB_COLORMGR")); @@ -492,6 +495,13 @@ void Preferences::behSetRadioToggled(const Glib::ustring& path) behAddSetRadioToggled(path, false); } +Gtk::Widget *Preferences::getFavoritesPanel() +{ + if (!toolLocationPreference) { + toolLocationPreference = Gtk::make_managed(moptions); + } + return toolLocationPreference; +} Gtk::Widget *Preferences::getDynamicProfilePanel() { @@ -1938,6 +1948,8 @@ void Preferences::storePreferences() moptions.cropGuides = Options::CropGuidesMode(cropGuidesCombo->get_active_row_number()); moptions.cropAutoFit = cropAutoFitCB->get_active(); + + toolLocationPreference->updateOptions(); } void Preferences::fillPreferences() diff --git a/rtgui/preferences.h b/rtgui/preferences.h index dfe1e008d..18d7a0581 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -28,6 +28,7 @@ class RTWindow; class Splash; +class ToolLocationPreference; class Preferences final : public Gtk::Dialog, @@ -244,6 +245,8 @@ class Preferences final : bool newFont; bool newCPFont; + ToolLocationPreference *toolLocationPreference; + void fillPreferences (); void storePreferences (); void parseDir (Glib::ustring dirname, std::vector& items, Glib::ustring ext); @@ -278,6 +281,7 @@ class Preferences final : Gtk::Widget *getGeneralPanel(); Gtk::Widget *getImageProcessingPanel(); + Gtk::Widget *getFavoritesPanel(); Gtk::Widget *getDynamicProfilePanel(); Gtk::Widget *getFileBrowserPanel(); Gtk::Widget *getColorManPanel(); diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc new file mode 100644 index 000000000..719a72a66 --- /dev/null +++ b/rtgui/toollocationpref.cc @@ -0,0 +1,596 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2021 Lawrence Lee + * + * 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 + +#include "guiutils.h" +#include "options.h" +#include "toollocationpref.h" +#include "toolpanelcoord.h" + +using Tool = ToolPanelCoordinator::Tool; + +std::string getToolName(Tool tool) +{ + switch (tool) { + case Tool::TONE_CURVE: + return "tonecurve"; + case Tool::SHADOWS_HIGHLIGHTS: + return "shadowshighlights"; + case Tool::IMPULSE_DENOISE: + return "impulsedenoise"; + case Tool::DEFRINGE_TOOL: + return "defringe"; + case Tool::SPOT: + return "spot"; + case Tool::DIR_PYR_DENOISE: + return "dirpyrdenoise"; + case Tool::EPD: + return "epd"; + case Tool::SHARPENING_TOOL: + return "sharpening"; + case Tool::LOCAL_CONTRAST: + return "localcontrast"; + case Tool::SHARPEN_EDGE: + return "sharpenedge"; + case Tool::SHARPEN_MICRO: + return "sharpenmicro"; + case Tool::L_CURVE: + return "labcurves"; + case Tool::RGB_CURVES: + return "rgbcurves"; + case Tool::COLOR_TONING: + return "colortoning"; + case Tool::LENS_GEOM: + return "lensgeom"; + case Tool::LENS_PROF: + return "lensprof"; + case Tool::DISTORTION: + return "distortion"; + case Tool::ROTATE: + return "rotate"; + case Tool::VIBRANCE: + return "vibrance"; + case Tool::COLOR_APPEARANCE: + return "colorappearance"; + case Tool::WHITE_BALANCE: + return "whitebalance"; + case Tool::VIGNETTING: + return "vignetting"; + case Tool::RETINEX_TOOL: + return "retinex"; + case Tool::GRADIENT: + return "gradient"; + case Tool::LOCALLAB: + return "locallab"; + case Tool::PC_VIGNETTE: + return "pcvignette"; + case Tool::PERSPECTIVE: + return "perspective"; + case Tool::CA_CORRECTION: + return "cacorrection"; + case Tool::CH_MIXER: + return "chmixer"; + case Tool::BLACK_WHITE: + return "blackwhite"; + case Tool::RESIZE_TOOL: + return "resize"; + case Tool::PR_SHARPENING: + return "prsharpening"; + case Tool::CROP_TOOL: + return "crop"; + case Tool::ICM: + return "icm"; + case Tool::WAVELET: + return "wavelet"; + case Tool::DIR_PYR_EQUALIZER: + return "dirpyrdenoise"; + case Tool::HSV_EQUALIZER: + return "hsvequalizer"; + case Tool::FILM_SIMULATION: + return "filmsimulation"; + case Tool::SOFT_LIGHT: + return "softlight"; + case Tool::DEHAZE: + return "dehaze"; + case Tool::SENSOR_BAYER: + return "sensorbayer"; + case Tool::SENSOR_XTRANS: + return "sensorxtrans"; + case Tool::BAYER_PROCESS: + return "bayerprocess"; + case Tool::XTRANS_PROCESS: + return "xtransprocess"; + case Tool::BAYER_PREPROCESS: + return "bayerpreprocess"; + case Tool::PREPROCESS: + return "preprocess"; + case Tool::DARKFRAME_TOOL: + return "darkframe"; + case Tool::FLATFIELD_TOOL: + return "flatfield"; + case Tool::RAW_CA_CORRECTION: + return "rawcacorrection"; + case Tool::RAW_EXPOSURE: + return "rawexposure"; + case Tool::PREPROCESS_WB: + return "preprocesswb"; + case Tool::BAYER_RAW_EXPOSURE: + return "bayerrawexposure"; + case Tool::XTRANS_RAW_EXPOSURE: + return "xtransrawexposure"; + case Tool::FATTAL: + return "fattal"; + case Tool::FILM_NEGATIVE: + return "filmnegative"; + case Tool::PD_SHARPENING: + return "capturesharpening"; + }; + return ""; +}; + +class FavoritesColumns : public Gtk::TreeModelColumnRecord +{ +public: + Gtk::TreeModelColumn toolName; + Gtk::TreeModelColumn tool; + + FavoritesColumns() + { + add(toolName); + add(tool); + } +}; + +class ToolListColumns : public Gtk::TreeModelColumnRecord +{ +public: + Gtk::TreeModelColumn toolName; + Gtk::TreeModelColumn tool; + Gtk::TreeModelColumn isFavorite; + Gtk::TreeModelColumn isEditable; + + ToolListColumns() + { + add(toolName); + add(tool); + add(isFavorite); + add(isEditable); + } +}; + +struct ToolLocationPreference::Impl { + static std::unordered_map toolNamesReverseMap; + + Options &options; + + // Tool list. + ToolListColumns toolListColumns; + Glib::RefPtr toolListModelPtr; + Gtk::CellRendererToggle toolListCellRendererFavorite; + Gtk::CellRendererText toolListCellRendererToolName; + Gtk::TreeViewColumn toolListViewColumnFavorite; + Gtk::TreeViewColumn toolListViewColumnToolName; + Gtk::TreeView *toolListViewPtr; + + // Favorites list. + FavoritesColumns favoritesColumns; + Glib::RefPtr favoritesModelPtr; + Gtk::CellRendererText favoritesCellRendererToolName; + Gtk::TreeViewColumn favoritesViewColumnToolName; + Gtk::TreeView *favoritesViewPtr; + + explicit Impl(Options &options); + + void addToolListRowGroup( + const std::vector &tools, + const Gtk::TreeIter &parentRowIter, + const std::unordered_set &favorites); + void favoriteToggled(const Glib::ustring &row_path); + Tool getToolFromName(const std::string &name) const; + void initFavoritesRows(const std::vector &favorites); + void initToolListRows(const std::vector &favorites); + std::vector toolNamesToTools( + const std::vector &tool_names) const; + void updateOptions(); +}; + +std::unordered_map + ToolLocationPreference::Impl::toolNamesReverseMap; + +Glib::ustring getToolPanelTitleKey(ToolPanelCoordinator::Panel panel) +{ + switch (panel) { + case ToolPanelCoordinator::Panel::FAVORITE: + return "MAIN_TAB_FAVORITES"; + case ToolPanelCoordinator::Panel::EXPOSURE: + return "MAIN_TAB_EXPOSURE"; + case ToolPanelCoordinator::Panel::DETAILS: + return "MAIN_TAB_DETAIL"; + case ToolPanelCoordinator::Panel::COLOR: + return "MAIN_TAB_COLOR"; + case ToolPanelCoordinator::Panel::ADVANCED: + return "MAIN_TAB_ADVANCED"; + case ToolPanelCoordinator::Panel::LOCALLAB: + return "MAIN_TAB_LOCALLAB"; + case ToolPanelCoordinator::Panel::TRANSFORM_PANEL: + return "MAIN_TAB_TRANSFORM"; + case ToolPanelCoordinator::Panel::RAW: + return "MAIN_TAB_RAW"; + } + return ""; +} + +Glib::ustring getToolTitleKey(Tool tool) +{ + using Tool = Tool; + switch (tool) { + case Tool::TONE_CURVE: + return "TP_EXPOSURE_LABEL"; + case Tool::SHADOWS_HIGHLIGHTS: + return "TP_SHADOWSHLIGHTS_LABEL"; + case Tool::IMPULSE_DENOISE: + return "TP_IMPULSEDENOISE_LABEL"; + case Tool::DEFRINGE_TOOL: + return "TP_DEFRINGE_LABEL"; + case Tool::SPOT: + return "TP_SPOT_LABEL"; + case Tool::DIR_PYR_DENOISE: + return "TP_DIRPYRDENOISE_LABEL"; + case Tool::EPD: + return "TP_EPD_LABEL"; + case Tool::SHARPENING_TOOL: + return "TP_SHARPENING_LABEL"; + case Tool::LOCAL_CONTRAST: + return "TP_LOCALCONTRAST_LABEL"; + case Tool::SHARPEN_EDGE: + return "TP_SHARPENEDGE_LABEL"; + case Tool::SHARPEN_MICRO: + return "TP_SHARPENMICRO_LABEL"; + case Tool::L_CURVE: + return "TP_LABCURVE_LABEL"; + case Tool::RGB_CURVES: + return "TP_RGBCURVES_LABEL"; + case Tool::COLOR_TONING: + return "TP_COLORTONING_LABEL"; + case Tool::LENS_GEOM: + return "TP_LENSGEOM_LABEL"; + case Tool::LENS_PROF: + return "TP_LENSPROFILE_LABEL"; + case Tool::DISTORTION: + return "TP_DISTORTION_LABEL"; + case Tool::ROTATE: + return "TP_ROTATE_LABEL"; + case Tool::VIBRANCE: + return "TP_VIBRANCE_LABEL"; + case Tool::COLOR_APPEARANCE: + return "TP_COLORAPP_LABEL"; + case Tool::WHITE_BALANCE: + return "TP_WBALANCE_LABEL"; + case Tool::VIGNETTING: + return "TP_VIGNETTING_LABEL"; + case Tool::RETINEX_TOOL: + return "TP_RETINEX_LABEL"; + case Tool::GRADIENT: + return "TP_GRADIENT_LABEL"; + case Tool::LOCALLAB: + return "TP_LOCALLAB_LABEL"; + case Tool::PC_VIGNETTE: + return "TP_PCVIGNETTE_LABEL"; + case Tool::PERSPECTIVE: + return "TP_PERSPECTIVE_LABEL"; + case Tool::CA_CORRECTION: + return "TP_CACORRECTION_LABEL"; + case Tool::CH_MIXER: + return "TP_CHMIXER_LABEL"; + case Tool::BLACK_WHITE: + return "TP_BWMIX_LABEL"; + case Tool::RESIZE_TOOL: + return "TP_RESIZE_LABEL"; + case Tool::PR_SHARPENING: + return "TP_PRSHARPENING_LABEL"; + case Tool::CROP_TOOL: + return "TP_CROP_LABEL"; + case Tool::ICM: + return "TP_ICM_LABEL"; + case Tool::WAVELET: + return "TP_WAVELET_LABEL"; + case Tool::DIR_PYR_EQUALIZER: + return "TP_DIRPYRDENOISE_LABEL"; + case Tool::HSV_EQUALIZER: + return "TP_HSVEQUALIZER_LABEL"; + case Tool::FILM_SIMULATION: + return "TP_FILMSIMULATION_LABEL"; + case Tool::SOFT_LIGHT: + return "TP_SOFTLIGHT_LABEL"; + case Tool::DEHAZE: + return "TP_DEHAZE_LABEL"; + case Tool::SENSOR_BAYER: + return "TP_RAW_SENSOR_BAYER_LABEL"; + case Tool::SENSOR_XTRANS: + return "TP_RAW_SENSOR_XTRANS_LABEL"; + case Tool::BAYER_PROCESS: + return "TP_RAW_LABEL"; + case Tool::XTRANS_PROCESS: + return "TP_RAW_LABEL"; + case Tool::BAYER_PREPROCESS: + return "TP_PREPROCESS_LABEL"; + case Tool::PREPROCESS: + return "TP_PREPROCESS_LABEL"; + case Tool::DARKFRAME_TOOL: + return "TP_DARKFRAME_LABEL"; + case Tool::FLATFIELD_TOOL: + return "TP_FLATFIELD_LABEL"; + case Tool::RAW_CA_CORRECTION: + return "TP_RAWCACORR_LABEL"; + case Tool::RAW_EXPOSURE: + return "TP_EXPOS_WHITEPOINT_LABEL"; + case Tool::PREPROCESS_WB: + return "TP_PREPROCWB_LABEL"; + case Tool::BAYER_RAW_EXPOSURE: + return "TP_EXPOS_BLACKPOINT_LABEL"; + case Tool::XTRANS_RAW_EXPOSURE: + return "TP_EXPOS_BLACKPOINT_LABEL"; + case Tool::FATTAL: + return "TP_TM_FATTAL_LABEL"; + case Tool::FILM_NEGATIVE: + return "TP_FILMNEGATIVE_LABEL"; + case Tool::PD_SHARPENING: + return "TP_PDSHARPENING_LABEL"; + }; + return ""; +} + +ToolLocationPreference::Impl::Impl(Options &options) : + options(options), + + toolListModelPtr(Gtk::TreeStore::create(toolListColumns)), + toolListViewColumnFavorite( + Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_FAVORITE"))), + toolListViewColumnToolName( + Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_TOOL"))), + toolListViewPtr(Gtk::make_managed()), + + favoritesModelPtr(Gtk::ListStore::create(favoritesColumns)), + favoritesViewColumnToolName( + Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_TOOL"))), + favoritesViewPtr(Gtk::make_managed()) +{ + const std::vector favorites = toolNamesToTools(options.favorites); + + // Tool list. + toolListViewPtr->set_model(toolListModelPtr); + toolListViewPtr->append_column(toolListViewColumnToolName); + toolListViewColumnToolName.pack_start(toolListCellRendererToolName); + toolListViewColumnToolName.set_expand(); + toolListViewColumnToolName.set_renderer( + toolListCellRendererToolName, toolListColumns.toolName); + toolListViewPtr->append_column(toolListViewColumnFavorite); + toolListViewColumnFavorite.pack_start(toolListCellRendererFavorite); + toolListViewColumnFavorite.set_expand(false); + toolListViewColumnFavorite.set_renderer( + toolListCellRendererFavorite, toolListColumns.isFavorite); + toolListViewColumnFavorite.add_attribute( + toolListCellRendererFavorite, "visible", toolListColumns.isEditable); + toolListCellRendererFavorite.signal_toggled().connect( + sigc::mem_fun(*this, &ToolLocationPreference::Impl::favoriteToggled)); + initToolListRows(favorites); + toolListViewPtr->expand_all(); + + // Favorites list. + favoritesViewPtr->set_model(favoritesModelPtr); + favoritesViewPtr->append_column(favoritesViewColumnToolName); + favoritesViewPtr->set_reorderable(true); + favoritesViewColumnToolName.pack_start(favoritesCellRendererToolName); + favoritesViewColumnToolName.set_renderer( + favoritesCellRendererToolName, favoritesColumns.toolName); + initFavoritesRows(favorites); +} + +void ToolLocationPreference::Impl::favoriteToggled(const Glib::ustring &row_path) +{ + auto row_iter = toolListModelPtr->get_iter(row_path); + const bool is_favorite = !row_iter->get_value(toolListColumns.isFavorite); + const Tool tool = row_iter->get_value(toolListColumns.tool); + + // Update favorite column in the tool list. + row_iter->set_value(toolListColumns.isFavorite, is_favorite); + + // Update the favorites list. + if (is_favorite) { + // Add to favorites list. + auto new_favorite_row_iter = favoritesModelPtr->append(); + new_favorite_row_iter->set_value( + favoritesColumns.toolName, + M(getToolTitleKey(tool))); + new_favorite_row_iter->set_value(favoritesColumns.tool, tool); + } else { + // Remove from favorites list. + const auto favorites_rows = favoritesModelPtr->children(); + auto row = favorites_rows.begin(); + while ( + row != favorites_rows.end() && + row->get_value(favoritesColumns.tool) != tool) { + row++; + } + if (row != favorites_rows.end()) { + favoritesModelPtr->erase(row); + } + } +} + +Tool ToolLocationPreference::Impl::getToolFromName(const std::string &name) const +{ + if (toolNamesReverseMap.empty()) { + // Create the name to tool mapping. + + const auto panels = ToolPanelCoordinator::getDefaultToolLayout(); + std::vector unprocessed_tool_trees; + + // Get the root tools from each panel. + for (const auto &panel_tools : panels) { + for (const auto &tool : panel_tools.second) { + unprocessed_tool_trees.push_back(&tool); + } + } + + // Process all the tools, including their children. + while (unprocessed_tool_trees.size() > 0) { + const ToolPanelCoordinator::ToolTree *tool_tree = + unprocessed_tool_trees.back(); + unprocessed_tool_trees.pop_back(); + toolNamesReverseMap[getToolName(tool_tree->id)] = tool_tree->id; + for (const auto &child_tree : tool_tree->children) { + unprocessed_tool_trees.push_back(&child_tree); + } + } + } + + return toolNamesReverseMap.at(name); +} + +void ToolLocationPreference::Impl::initFavoritesRows( + const std::vector &favorites) +{ + for (const auto tool : favorites) { + auto favorite_row_iter = favoritesModelPtr->append(); + favorite_row_iter->set_value( + favoritesColumns.toolName, + M(getToolTitleKey(tool))); + favorite_row_iter->set_value(favoritesColumns.tool, tool); + } +} + +void ToolLocationPreference::Impl::addToolListRowGroup( + const std::vector &tools, + const Gtk::TreeIter &parentRowIter, + const std::unordered_set &favorites) +{ + for (const ToolPanelCoordinator::ToolTree &tool : tools) { + auto tool_row_iter = toolListModelPtr->append(parentRowIter->children()); + tool_row_iter->set_value( + toolListColumns.toolName, + M(getToolTitleKey(tool.id))); + tool_row_iter->set_value(toolListColumns.tool, tool.id); + tool_row_iter->set_value( + toolListColumns.isFavorite, + favorites.count(tool.id) > 0); + tool_row_iter->set_value( + toolListColumns.isEditable, + ToolPanelCoordinator::isFavoritable(tool.id)); + addToolListRowGroup(tool.children, tool_row_iter, favorites); + } +}; + +void ToolLocationPreference::Impl::initToolListRows(const std::vector &favorites) +{ + const auto panel_tools = ToolPanelCoordinator::getDefaultToolLayout(); + std::unordered_set favorites_set; + + for (const auto &tool : favorites) { + favorites_set.insert(tool); + } + + for (const auto panel : { + ToolPanelCoordinator::Panel::EXPOSURE, + ToolPanelCoordinator::Panel::DETAILS, + ToolPanelCoordinator::Panel::COLOR, + ToolPanelCoordinator::Panel::ADVANCED, + ToolPanelCoordinator::Panel::LOCALLAB, + ToolPanelCoordinator::Panel::TRANSFORM_PANEL, + ToolPanelCoordinator::Panel::RAW, + }) { + auto tool_group_iter = toolListModelPtr->append(); + tool_group_iter->set_value( + toolListColumns.toolName, + M(getToolPanelTitleKey(panel))); + addToolListRowGroup(panel_tools.at(panel), tool_group_iter, favorites_set); + } +} + +std::vector ToolLocationPreference::Impl::toolNamesToTools( + const std::vector &tool_names) const +{ + std::vector tool_set; + + for (auto &&tool_name : tool_names) { + Tool tool; + try { + tool = getToolFromName(tool_name); + } catch (const std::exception &e) { + continue; + } + tool_set.push_back(tool); + } + + return tool_set; +} + +void ToolLocationPreference::Impl::updateOptions() +{ + const auto favorites_rows = favoritesModelPtr->children(); + options.favorites.resize(favorites_rows.size()); + for (unsigned i = 0; i < favorites_rows.size(); i++) { + const Tool tool = favorites_rows[i].get_value(favoritesColumns.tool); + options.favorites[i] = getToolName(tool); + } +} + +ToolLocationPreference::ToolLocationPreference(Options &options) : + impl(new Impl(options)) +{ + // Layout grid. + Gtk::Grid *layout_grid = Gtk::make_managed(); + layout_grid->set_column_spacing(4); + layout_grid->set_row_spacing(4); + add(*layout_grid); + + // Tool list. + Gtk::Frame *tool_list_frame = Gtk::make_managed( + M("PREFERENCES_TOOLPANEL_AVAILABLETOOLS")); + Gtk::ScrolledWindow *tool_list_scrolled_window = + Gtk::make_managed(); + tool_list_scrolled_window->property_hscrollbar_policy() = + Gtk::PolicyType::POLICY_NEVER; + layout_grid->attach_next_to(*tool_list_frame, Gtk::PositionType::POS_RIGHT); + tool_list_frame->add(*tool_list_scrolled_window); + tool_list_scrolled_window->add(*impl->toolListViewPtr); + impl->toolListViewPtr->set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_MINIMUM); + setExpandAlignProperties( + tool_list_frame, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL); + + // Favorites list. + Gtk::Frame *favorites_frame = Gtk::make_managed( + M("PREFERENCES_TOOLPANEL_FAVORITESPANEL")); + Gtk::ScrolledWindow *favorites_list_scrolled_window = + Gtk::make_managed(); + favorites_list_scrolled_window->property_hscrollbar_policy() = + Gtk::PolicyType::POLICY_NEVER; + layout_grid->attach_next_to(*favorites_frame, Gtk::PositionType::POS_RIGHT); + favorites_frame->add(*favorites_list_scrolled_window); + favorites_list_scrolled_window->add(*impl->favoritesViewPtr); + setExpandAlignProperties( + favorites_frame, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL); + + this->show_all(); +} + +void ToolLocationPreference::updateOptions() +{ + impl->updateOptions(); +} diff --git a/rtgui/toollocationpref.h b/rtgui/toollocationpref.h new file mode 100644 index 000000000..815df6839 --- /dev/null +++ b/rtgui/toollocationpref.h @@ -0,0 +1,34 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2021 Lawrence Lee + * + * 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 + +class Options; + +class ToolLocationPreference : public Gtk::Box +{ +private: + struct Impl; + std::unique_ptr impl; + +public: + explicit ToolLocationPreference(Options &options); + void updateOptions(); +}; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 00fcb208d..586d4755f 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -32,6 +32,241 @@ using namespace rtengine::procparams; +using Tool = ToolPanelCoordinator::Tool; +using ToolTree = struct ToolPanelCoordinator::ToolTree; + +const std::vector EXPOSURE_PANEL_TOOLS = { + { + .id = Tool::TONE_CURVE, + }, + { + .id = Tool::SHADOWS_HIGHLIGHTS, + }, + { + .id = Tool::EPD, + }, + { + .id = Tool::FATTAL, + }, + { + .id = Tool::PC_VIGNETTE, + }, + { + .id = Tool::GRADIENT, + }, + { + .id = Tool::L_CURVE, + }, +}; + +const std::vector DETAILS_PANEL_TOOLS = { + { + .id = Tool::SPOT, + }, + { + .id = Tool::SHARPENING_TOOL, + }, + { + .id = Tool::LOCAL_CONTRAST, + }, + { + .id = Tool::SHARPEN_EDGE, + }, + { + .id = Tool::SHARPEN_MICRO, + }, + { + .id = Tool::IMPULSE_DENOISE, + }, + { + .id = Tool::DIR_PYR_DENOISE, + }, + { + .id = Tool::DEFRINGE_TOOL, + }, + { + .id = Tool::DIR_PYR_EQUALIZER, + }, + { + .id = Tool::DEHAZE, + }, +}; + +const std::vector COLOR_PANEL_TOOLS = { + { + .id = Tool::WHITE_BALANCE, + }, + { + .id = Tool::VIBRANCE, + }, + { + .id = Tool::CH_MIXER, + }, + { + .id = Tool::BLACK_WHITE, + }, + { + .id = Tool::HSV_EQUALIZER, + }, + { + .id = Tool::FILM_SIMULATION, + }, + { + .id = Tool::FILM_NEGATIVE, + }, + { + .id = Tool::SOFT_LIGHT, + }, + { + .id = Tool::RGB_CURVES, + }, + { + .id = Tool::COLOR_TONING, + }, + { + .id = Tool::ICM, + }, +}; + +const std::vector ADVANCED_PANEL_TOOLS = { + { + .id = Tool::RETINEX_TOOL, + }, + { + .id = Tool::COLOR_APPEARANCE, + }, + { + .id = Tool::WAVELET, + }, +}; + +const std::vector LOCALLAB_PANEL_TOOLS = { + { + .id = Tool::LOCALLAB, + }, +}; + +const std::vector TRANSFORM_PANEL_TOOLS = { + { + .id = Tool::CROP_TOOL, + }, + { + .id = Tool::RESIZE_TOOL, + .children = { + { + .id = Tool::PR_SHARPENING, + }, + }, + }, + { + .id = Tool::LENS_GEOM, + .children = { + { + .id = Tool::ROTATE, + }, + { + .id = Tool::PERSPECTIVE, + }, + { + .id = Tool::LENS_PROF, + }, + { + .id = Tool::DISTORTION, + }, + { + .id = Tool::CA_CORRECTION, + }, + { + .id = Tool::VIGNETTING, + }, + }, + }, +}; + +const std::vector RAW_PANEL_TOOLS = { + { + .id = Tool::SENSOR_BAYER, + .children = { + { + { + .id = Tool::BAYER_PROCESS, + }, + { + .id = Tool::BAYER_RAW_EXPOSURE, + }, + { + .id = Tool::BAYER_PREPROCESS, + }, + { + .id = Tool::RAW_CA_CORRECTION, + }, + }, + }, + }, + { + .id = Tool::SENSOR_XTRANS, + .children = { + { + { + .id = Tool::XTRANS_PROCESS, + }, + { + .id = Tool::XTRANS_RAW_EXPOSURE, + }, + }, + }, + }, + { + .id = Tool::RAW_EXPOSURE, + }, + { + .id = Tool::PREPROCESS_WB, + }, + { + .id = Tool::PREPROCESS, + }, + { + .id = Tool::DARKFRAME_TOOL, + }, + { + .id = Tool::FLATFIELD_TOOL, + }, + { + .id = Tool::PD_SHARPENING, + }, +}; + +const std::unordered_map> PANEL_TOOLS = { + { + ToolPanelCoordinator::Panel::EXPOSURE, + EXPOSURE_PANEL_TOOLS + }, + { + ToolPanelCoordinator::Panel::DETAILS, + DETAILS_PANEL_TOOLS + }, + { + ToolPanelCoordinator::Panel::COLOR, + COLOR_PANEL_TOOLS + }, + { + ToolPanelCoordinator::Panel::ADVANCED, + ADVANCED_PANEL_TOOLS + }, + { + ToolPanelCoordinator::Panel::LOCALLAB, + LOCALLAB_PANEL_TOOLS + }, + { + ToolPanelCoordinator::Panel::TRANSFORM_PANEL, + TRANSFORM_PANEL_TOOLS + }, + { + ToolPanelCoordinator::Panel::RAW, + RAW_PANEL_TOOLS + }, +}; + ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favoritePanelSW(nullptr), hasChanged (false), editDataProvider (nullptr), photoLoadedOnce(false) { @@ -288,6 +523,21 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit prevPage = toolPanelNotebook->get_nth_page(0); } +const std::unordered_map> ToolPanelCoordinator::getDefaultToolLayout() +{ + return PANEL_TOOLS; +} + +bool ToolPanelCoordinator::isFavoritable(Tool tool) +{ + switch (tool) { + case Tool::PR_SHARPENING: + return false; + default: + return true; + } +} + void ToolPanelCoordinator::notebookPageChanged(Gtk::Widget* page, guint page_num) { // Locallab spot curves are set visible if at least one photo has been loaded (to avoid diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 13686d6e3..c4215ee2a 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -223,12 +223,90 @@ private: Gtk::Widget* prevPage; public: + enum class Panel { + FAVORITE, + EXPOSURE, + DETAILS, + COLOR, + ADVANCED, + LOCALLAB, + TRANSFORM_PANEL, + RAW, + }; + + enum class Tool { + TONE_CURVE, + SHADOWS_HIGHLIGHTS, + IMPULSE_DENOISE, + DEFRINGE_TOOL, + SPOT, + DIR_PYR_DENOISE, + EPD, + SHARPENING_TOOL, + LOCAL_CONTRAST, + SHARPEN_EDGE, + SHARPEN_MICRO, + L_CURVE, + RGB_CURVES, + COLOR_TONING, + LENS_GEOM, + LENS_PROF, + DISTORTION, + ROTATE, + VIBRANCE, + COLOR_APPEARANCE, + WHITE_BALANCE, + VIGNETTING, + RETINEX_TOOL, + GRADIENT, + LOCALLAB, + PC_VIGNETTE, + PERSPECTIVE, + CA_CORRECTION, + CH_MIXER, + BLACK_WHITE, + RESIZE_TOOL, + PR_SHARPENING, + CROP_TOOL, + ICM, + WAVELET, + DIR_PYR_EQUALIZER, + HSV_EQUALIZER, + FILM_SIMULATION, + SOFT_LIGHT, + DEHAZE, + SENSOR_BAYER, + SENSOR_XTRANS, + BAYER_PROCESS, + XTRANS_PROCESS, + BAYER_PREPROCESS, + PREPROCESS, + DARKFRAME_TOOL, + FLATFIELD_TOOL, + RAW_CA_CORRECTION, + RAW_EXPOSURE, + PREPROCESS_WB, + BAYER_RAW_EXPOSURE, + XTRANS_RAW_EXPOSURE, + FATTAL, + FILM_NEGATIVE, + PD_SHARPENING, + }; + + struct ToolTree { + Tool id; + std::vector children; + }; + CoarsePanel* coarse; Gtk::Notebook* toolPanelNotebook; ToolPanelCoordinator(bool batch = false); ~ToolPanelCoordinator () override; + static const std::unordered_map> getDefaultToolLayout(); + static bool isFavoritable(Tool tool); + bool getChangedState() { return hasChanged; From 23214ae5cd99905fef97e192561886b0210288bb Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Mon, 22 Nov 2021 21:38:14 -0800 Subject: [PATCH 02/24] Clean up code Fix compile warning, remove GTK functions not present in version 3.16, and make code more concise. --- rtgui/preferences.cc | 2 +- rtgui/toollocationpref.cc | 26 ++++++++++++-------------- rtgui/toolpanelcoord.cc | 2 +- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 556201732..de3553aee 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -498,7 +498,7 @@ void Preferences::behSetRadioToggled(const Glib::ustring& path) Gtk::Widget *Preferences::getFavoritesPanel() { if (!toolLocationPreference) { - toolLocationPreference = Gtk::make_managed(moptions); + toolLocationPreference = Gtk::manage(new ToolLocationPreference(moptions)); } return toolLocationPreference; } diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index 719a72a66..ccbc9310a 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -364,17 +364,16 @@ ToolLocationPreference::Impl::Impl(Options &options) : Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_FAVORITE"))), toolListViewColumnToolName( Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_TOOL"))), - toolListViewPtr(Gtk::make_managed()), + toolListViewPtr(Gtk::manage(new Gtk::TreeView(toolListModelPtr))), favoritesModelPtr(Gtk::ListStore::create(favoritesColumns)), favoritesViewColumnToolName( Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_TOOL"))), - favoritesViewPtr(Gtk::make_managed()) + favoritesViewPtr(Gtk::manage(new Gtk::TreeView(favoritesModelPtr))) { const std::vector favorites = toolNamesToTools(options.favorites); // Tool list. - toolListViewPtr->set_model(toolListModelPtr); toolListViewPtr->append_column(toolListViewColumnToolName); toolListViewColumnToolName.pack_start(toolListCellRendererToolName); toolListViewColumnToolName.set_expand(); @@ -386,14 +385,13 @@ ToolLocationPreference::Impl::Impl(Options &options) : toolListViewColumnFavorite.set_renderer( toolListCellRendererFavorite, toolListColumns.isFavorite); toolListViewColumnFavorite.add_attribute( - toolListCellRendererFavorite, "visible", toolListColumns.isEditable); + toolListCellRendererFavorite.property_visible(), toolListColumns.isEditable); toolListCellRendererFavorite.signal_toggled().connect( sigc::mem_fun(*this, &ToolLocationPreference::Impl::favoriteToggled)); initToolListRows(favorites); toolListViewPtr->expand_all(); // Favorites list. - favoritesViewPtr->set_model(favoritesModelPtr); favoritesViewPtr->append_column(favoritesViewColumnToolName); favoritesViewPtr->set_reorderable(true); favoritesViewColumnToolName.pack_start(favoritesCellRendererToolName); @@ -555,19 +553,19 @@ ToolLocationPreference::ToolLocationPreference(Options &options) : impl(new Impl(options)) { // Layout grid. - Gtk::Grid *layout_grid = Gtk::make_managed(); + Gtk::Grid *layout_grid = Gtk::manage(new Gtk::Grid()); layout_grid->set_column_spacing(4); layout_grid->set_row_spacing(4); add(*layout_grid); // Tool list. - Gtk::Frame *tool_list_frame = Gtk::make_managed( - M("PREFERENCES_TOOLPANEL_AVAILABLETOOLS")); + Gtk::Frame *tool_list_frame = Gtk::manage(new Gtk::Frame( + M("PREFERENCES_TOOLPANEL_AVAILABLETOOLS"))); Gtk::ScrolledWindow *tool_list_scrolled_window = - Gtk::make_managed(); + Gtk::manage(new Gtk::ScrolledWindow()); tool_list_scrolled_window->property_hscrollbar_policy() = Gtk::PolicyType::POLICY_NEVER; - layout_grid->attach_next_to(*tool_list_frame, Gtk::PositionType::POS_RIGHT); + layout_grid->attach_next_to(*tool_list_frame, Gtk::PositionType::POS_RIGHT, 1, 1); tool_list_frame->add(*tool_list_scrolled_window); tool_list_scrolled_window->add(*impl->toolListViewPtr); impl->toolListViewPtr->set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_MINIMUM); @@ -575,13 +573,13 @@ ToolLocationPreference::ToolLocationPreference(Options &options) : tool_list_frame, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL); // Favorites list. - Gtk::Frame *favorites_frame = Gtk::make_managed( - M("PREFERENCES_TOOLPANEL_FAVORITESPANEL")); + Gtk::Frame *favorites_frame = Gtk::manage(new Gtk::Frame( + M("PREFERENCES_TOOLPANEL_FAVORITESPANEL"))); Gtk::ScrolledWindow *favorites_list_scrolled_window = - Gtk::make_managed(); + Gtk::manage(new Gtk::ScrolledWindow()); favorites_list_scrolled_window->property_hscrollbar_policy() = Gtk::PolicyType::POLICY_NEVER; - layout_grid->attach_next_to(*favorites_frame, Gtk::PositionType::POS_RIGHT); + layout_grid->attach_next_to(*favorites_frame, Gtk::PositionType::POS_RIGHT, 1, 1); favorites_frame->add(*favorites_list_scrolled_window); favorites_list_scrolled_window->add(*impl->favoritesViewPtr); setExpandAlignProperties( diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 586d4755f..23b297d20 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -33,7 +33,7 @@ using namespace rtengine::procparams; using Tool = ToolPanelCoordinator::Tool; -using ToolTree = struct ToolPanelCoordinator::ToolTree; +using ToolTree = ToolPanelCoordinator::ToolTree; const std::vector EXPOSURE_PANEL_TOOLS = { { From ac19ea45076498c388526d2bc9b1b182487f3d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Wed, 24 Nov 2021 15:32:04 +0100 Subject: [PATCH 03/24] Fix `enum class` key in hashed containers --- rtgui/guiutils.h | 12 ++++++++++++ rtgui/toollocationpref.cc | 7 ++++--- rtgui/toolpanelcoord.cc | 10 +++++----- rtgui/toolpanelcoord.h | 4 +++- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index 126cf672b..21e775c36 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -20,6 +20,7 @@ #include #include +#include #include @@ -74,6 +75,17 @@ private: MyMutex mutex; }; +struct ScopedEnumHash { + template::value && !std::is_convertible::value, int>::type = 0> + size_t operator ()(T val) const noexcept + { + using type = typename std::underlying_type::type; + + return std::hash{}(static_cast(val)); + } +}; + + // TODO: The documentation says gdk_threads_enter and gdk_threads_leave should be replaced // by g_main_context_invoke(), g_idle_add() and related functions, but this will require more extensive changes. // We silence those warnings until then so that we notice the others. diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index ccbc9310a..c0bb6bea3 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -24,6 +24,7 @@ #include "toolpanelcoord.h" using Tool = ToolPanelCoordinator::Tool; +using Favorites = std::unordered_set; std::string getToolName(Tool tool) { @@ -200,7 +201,7 @@ struct ToolLocationPreference::Impl { void addToolListRowGroup( const std::vector &tools, const Gtk::TreeIter &parentRowIter, - const std::unordered_set &favorites); + const Favorites &favorites); void favoriteToggled(const Glib::ustring &row_path); Tool getToolFromName(const std::string &name) const; void initFavoritesRows(const std::vector &favorites); @@ -477,7 +478,7 @@ void ToolLocationPreference::Impl::initFavoritesRows( void ToolLocationPreference::Impl::addToolListRowGroup( const std::vector &tools, const Gtk::TreeIter &parentRowIter, - const std::unordered_set &favorites) + const Favorites &favorites) { for (const ToolPanelCoordinator::ToolTree &tool : tools) { auto tool_row_iter = toolListModelPtr->append(parentRowIter->children()); @@ -498,7 +499,7 @@ void ToolLocationPreference::Impl::addToolListRowGroup( void ToolLocationPreference::Impl::initToolListRows(const std::vector &favorites) { const auto panel_tools = ToolPanelCoordinator::getDefaultToolLayout(); - std::unordered_set favorites_set; + Favorites favorites_set; for (const auto &tool : favorites) { favorites_set.insert(tool); diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 23b297d20..fa2203958 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -236,7 +236,7 @@ const std::vector RAW_PANEL_TOOLS = { }, }; -const std::unordered_map> PANEL_TOOLS = { +const ToolPanelCoordinator::ToolLayout PANEL_TOOLS = { { ToolPanelCoordinator::Panel::EXPOSURE, EXPOSURE_PANEL_TOOLS @@ -378,7 +378,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit addfavoritePanel (detailsPanel, dehaze); addfavoritePanel (advancedPanel, wavelet); addfavoritePanel(locallabPanel, locallab); - + addfavoritePanel (transformPanel, crop); addfavoritePanel (transformPanel, resize); addPanel (resize->getPackBox(), prsharpening, 2); @@ -424,7 +424,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit transformPanelSW = Gtk::manage (new MyScrolledWindow ()); rawPanelSW = Gtk::manage (new MyScrolledWindow ()); advancedPanelSW = Gtk::manage (new MyScrolledWindow ()); - locallabPanelSW = Gtk::manage(new MyScrolledWindow()); + locallabPanelSW = Gtk::manage(new MyScrolledWindow()); // load panel endings for (int i = 0; i < 8; i++) { @@ -455,7 +455,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit locallabPanelSW->add(*locallabPanel); locallabPanel->pack_start(*vbPanelEnd[7], Gtk::PACK_SHRINK, 4); - + transformPanelSW->add (*transformPanel); transformPanel->pack_start (*vbPanelEnd[4], Gtk::PACK_SHRINK, 4); @@ -523,7 +523,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit prevPage = toolPanelNotebook->get_nth_page(0); } -const std::unordered_map> ToolPanelCoordinator::getDefaultToolLayout() +const ToolPanelCoordinator::ToolLayout& ToolPanelCoordinator::getDefaultToolLayout() { return PANEL_TOOLS; } diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index c4215ee2a..94e5a8717 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -298,13 +298,15 @@ public: std::vector children; }; + using ToolLayout = std::unordered_map, ScopedEnumHash>; + CoarsePanel* coarse; Gtk::Notebook* toolPanelNotebook; ToolPanelCoordinator(bool batch = false); ~ToolPanelCoordinator () override; - static const std::unordered_map> getDefaultToolLayout(); + static const ToolLayout& getDefaultToolLayout(); static bool isFavoritable(Tool tool); bool getChangedState() From c6a45ae765c842ab75aa9f936c35756ce1cc97de Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Thu, 25 Nov 2021 14:58:42 -0800 Subject: [PATCH 04/24] Move helper functions into anonymous namespace Move some functions in toollocationpref.cc. --- rtgui/toollocationpref.cc | 143 ++++++++++++++++++++------------------ 1 file changed, 74 insertions(+), 69 deletions(-) diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index c0bb6bea3..3e874627c 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -26,6 +26,9 @@ using Tool = ToolPanelCoordinator::Tool; using Favorites = std::unordered_set; +namespace +{ + std::string getToolName(Tool tool) { switch (tool) { @@ -145,75 +148,6 @@ std::string getToolName(Tool tool) return ""; }; -class FavoritesColumns : public Gtk::TreeModelColumnRecord -{ -public: - Gtk::TreeModelColumn toolName; - Gtk::TreeModelColumn tool; - - FavoritesColumns() - { - add(toolName); - add(tool); - } -}; - -class ToolListColumns : public Gtk::TreeModelColumnRecord -{ -public: - Gtk::TreeModelColumn toolName; - Gtk::TreeModelColumn tool; - Gtk::TreeModelColumn isFavorite; - Gtk::TreeModelColumn isEditable; - - ToolListColumns() - { - add(toolName); - add(tool); - add(isFavorite); - add(isEditable); - } -}; - -struct ToolLocationPreference::Impl { - static std::unordered_map toolNamesReverseMap; - - Options &options; - - // Tool list. - ToolListColumns toolListColumns; - Glib::RefPtr toolListModelPtr; - Gtk::CellRendererToggle toolListCellRendererFavorite; - Gtk::CellRendererText toolListCellRendererToolName; - Gtk::TreeViewColumn toolListViewColumnFavorite; - Gtk::TreeViewColumn toolListViewColumnToolName; - Gtk::TreeView *toolListViewPtr; - - // Favorites list. - FavoritesColumns favoritesColumns; - Glib::RefPtr favoritesModelPtr; - Gtk::CellRendererText favoritesCellRendererToolName; - Gtk::TreeViewColumn favoritesViewColumnToolName; - Gtk::TreeView *favoritesViewPtr; - - explicit Impl(Options &options); - - void addToolListRowGroup( - const std::vector &tools, - const Gtk::TreeIter &parentRowIter, - const Favorites &favorites); - void favoriteToggled(const Glib::ustring &row_path); - Tool getToolFromName(const std::string &name) const; - void initFavoritesRows(const std::vector &favorites); - void initToolListRows(const std::vector &favorites); - std::vector toolNamesToTools( - const std::vector &tool_names) const; - void updateOptions(); -}; - -std::unordered_map - ToolLocationPreference::Impl::toolNamesReverseMap; - Glib::ustring getToolPanelTitleKey(ToolPanelCoordinator::Panel panel) { switch (panel) { @@ -357,6 +291,77 @@ Glib::ustring getToolTitleKey(Tool tool) return ""; } +} + +class FavoritesColumns : public Gtk::TreeModelColumnRecord +{ +public: + Gtk::TreeModelColumn toolName; + Gtk::TreeModelColumn tool; + + FavoritesColumns() + { + add(toolName); + add(tool); + } +}; + +class ToolListColumns : public Gtk::TreeModelColumnRecord +{ +public: + Gtk::TreeModelColumn toolName; + Gtk::TreeModelColumn tool; + Gtk::TreeModelColumn isFavorite; + Gtk::TreeModelColumn isEditable; + + ToolListColumns() + { + add(toolName); + add(tool); + add(isFavorite); + add(isEditable); + } +}; + +struct ToolLocationPreference::Impl { + static std::unordered_map toolNamesReverseMap; + + Options &options; + + // Tool list. + ToolListColumns toolListColumns; + Glib::RefPtr toolListModelPtr; + Gtk::CellRendererToggle toolListCellRendererFavorite; + Gtk::CellRendererText toolListCellRendererToolName; + Gtk::TreeViewColumn toolListViewColumnFavorite; + Gtk::TreeViewColumn toolListViewColumnToolName; + Gtk::TreeView *toolListViewPtr; + + // Favorites list. + FavoritesColumns favoritesColumns; + Glib::RefPtr favoritesModelPtr; + Gtk::CellRendererText favoritesCellRendererToolName; + Gtk::TreeViewColumn favoritesViewColumnToolName; + Gtk::TreeView *favoritesViewPtr; + + explicit Impl(Options &options); + + void addToolListRowGroup( + const std::vector &tools, + const Gtk::TreeIter &parentRowIter, + const Favorites &favorites); + void favoriteToggled(const Glib::ustring &row_path); + Tool getToolFromName(const std::string &name) const; + void initFavoritesRows(const std::vector &favorites); + void initToolListRows(const std::vector &favorites); + std::vector toolNamesToTools( + const std::vector &tool_names) const; + void updateOptions(); +}; + +std::unordered_map + ToolLocationPreference::Impl::toolNamesReverseMap; + ToolLocationPreference::Impl::Impl(Options &options) : options(options), From fde15eaebb85a16f5c068ff46e54d8f9d5b48d6e Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Thu, 25 Nov 2021 15:35:02 -0800 Subject: [PATCH 05/24] Improve look of favorites preferences Set a fixed width for the lists, embed the preferences in a horizontally-scrollable window, and open the preferences window on the general tab. --- rtgui/preferences.cc | 8 +++++++- rtgui/preferences.h | 1 + rtgui/toollocationpref.cc | 9 ++------- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index de3553aee..39726c791 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -67,6 +67,7 @@ Preferences::Preferences(RTWindow *rtwindow) , newFont(false) , newCPFont(false) , toolLocationPreference(nullptr) + , swFavorites(nullptr) { moptions.copyFrom(&options); @@ -500,7 +501,12 @@ Gtk::Widget *Preferences::getFavoritesPanel() if (!toolLocationPreference) { toolLocationPreference = Gtk::manage(new ToolLocationPreference(moptions)); } - return toolLocationPreference; + if (!swFavorites) { + swFavorites = Gtk::manage(new Gtk::ScrolledWindow()); + swFavorites->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER); + swFavorites->add(*toolLocationPreference); + } + return swFavorites; } Gtk::Widget *Preferences::getDynamicProfilePanel() diff --git a/rtgui/preferences.h b/rtgui/preferences.h index 18d7a0581..33ca44eca 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -272,6 +272,7 @@ class Preferences final : Gtk::ScrolledWindow *swGeneral; Gtk::ScrolledWindow *swImageProcessing; + Gtk::ScrolledWindow *swFavorites; Gtk::ScrolledWindow *swDynamicProfile; Gtk::ScrolledWindow *swFileBrowser; Gtk::ScrolledWindow *swColorMan; diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index 3e874627c..d0a8cdf34 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -569,12 +569,10 @@ ToolLocationPreference::ToolLocationPreference(Options &options) : M("PREFERENCES_TOOLPANEL_AVAILABLETOOLS"))); Gtk::ScrolledWindow *tool_list_scrolled_window = Gtk::manage(new Gtk::ScrolledWindow()); - tool_list_scrolled_window->property_hscrollbar_policy() = - Gtk::PolicyType::POLICY_NEVER; + tool_list_scrolled_window->set_min_content_width(550); layout_grid->attach_next_to(*tool_list_frame, Gtk::PositionType::POS_RIGHT, 1, 1); tool_list_frame->add(*tool_list_scrolled_window); tool_list_scrolled_window->add(*impl->toolListViewPtr); - impl->toolListViewPtr->set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_MINIMUM); setExpandAlignProperties( tool_list_frame, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL); @@ -583,15 +581,12 @@ ToolLocationPreference::ToolLocationPreference(Options &options) : M("PREFERENCES_TOOLPANEL_FAVORITESPANEL"))); Gtk::ScrolledWindow *favorites_list_scrolled_window = Gtk::manage(new Gtk::ScrolledWindow()); - favorites_list_scrolled_window->property_hscrollbar_policy() = - Gtk::PolicyType::POLICY_NEVER; + favorites_list_scrolled_window->set_min_content_width(400); layout_grid->attach_next_to(*favorites_frame, Gtk::PositionType::POS_RIGHT, 1, 1); favorites_frame->add(*favorites_list_scrolled_window); favorites_list_scrolled_window->add(*impl->favoritesViewPtr); setExpandAlignProperties( favorites_frame, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL); - - this->show_all(); } void ToolLocationPreference::updateOptions() From 4fe39a82a5e024777e7b6d314158b1dbb8182ed1 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Fri, 26 Nov 2021 15:46:24 -0800 Subject: [PATCH 06/24] Add buttons for reordering favorites --- rtgui/toollocationpref.cc | 194 +++++++++++++++++++++++++++++++++++++- 1 file changed, 191 insertions(+), 3 deletions(-) diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index d0a8cdf34..2330759a4 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -20,6 +20,7 @@ #include "guiutils.h" #include "options.h" +#include "rtimage.h" #include "toollocationpref.h" #include "toolpanelcoord.h" @@ -291,7 +292,28 @@ Glib::ustring getToolTitleKey(Tool tool) return ""; } -} +class ListEditButtons : public Gtk::Box +{ +private: + Gtk::TreeView &list; + Glib::RefPtr listStore; + Gtk::Button buttonUp; + Gtk::Button buttonDown; + Gtk::Button buttonRemove; + + sigc::signal> signalRowsPreErase; + + void onButtonDownPressed(); + void onButtonRemovePressed(); + void onButtonUpPressed(); + void onListSelectionChanged(); + void updateButtonSensitivity(); + +public: + explicit ListEditButtons(Gtk::TreeView &list, Glib::RefPtr listStore); + + sigc::signal> getSignalRowsPreErase(); +}; class FavoritesColumns : public Gtk::TreeModelColumnRecord { @@ -323,6 +345,148 @@ public: } }; +ListEditButtons::ListEditButtons(Gtk::TreeView &list, Glib::RefPtr listStore) : + Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL), + list(list), + listStore(listStore) +{ + assert(list.get_model() == listStore); + + // Set button images. + RTImage *image_button_up = Gtk::manage(new RTImage("arrow-up-small.png")); + RTImage *image_button_down = Gtk::manage(new RTImage("arrow-down-small.png")); + RTImage *image_button_remove = Gtk::manage(new RTImage("remove-small.png")); + buttonUp.set_image(*image_button_up); + buttonDown.set_image(*image_button_down); + buttonRemove.set_image(*image_button_remove); + + // Connect signals for changing button sensitivity. + const auto on_list_sel_changed_fun = sigc::mem_fun( + *this, &ListEditButtons::onListSelectionChanged); + const auto on_row_deleted_fun = sigc::hide(on_list_sel_changed_fun); + const auto on_row_inserted_fun = sigc::hide(on_row_deleted_fun); + list.get_selection()->signal_changed().connect(on_list_sel_changed_fun); + listStore->signal_row_deleted().connect(on_row_deleted_fun); + listStore->signal_row_inserted().connect(on_row_inserted_fun); + + // Connect signals for buttons. + buttonUp.signal_pressed().connect(sigc::mem_fun( + *this, &ListEditButtons::onButtonUpPressed)); + buttonDown.signal_pressed().connect(sigc::mem_fun( + *this, &ListEditButtons::onButtonDownPressed)); + buttonRemove.signal_pressed().connect(sigc::mem_fun( + *this, &ListEditButtons::onButtonRemovePressed)); + + updateButtonSensitivity(); + + add(buttonUp); + add(buttonDown); + add(buttonRemove); +} + +void ListEditButtons::onButtonDownPressed() +{ + const auto list_children = listStore->children(); + const std::vector selected = + list.get_selection()->get_selected_rows(); + + if (selected.size() != 1) { // Only one can be selected. + return; + } + + auto selected_row_iter = listStore->get_iter(selected[0]); + auto next_row_iter = selected_row_iter; + next_row_iter++; + + if (next_row_iter == list_children.end()) { // Can't be last row. + return; + } + + listStore->iter_swap(selected_row_iter, next_row_iter); + updateButtonSensitivity(); +} + +void ListEditButtons::onButtonRemovePressed() +{ + const std::vector selected_paths = + list.get_selection()->get_selected_rows(); + std::vector selected; + + // Get row references, which are valid until the row is removed. + for (const auto & row_path : selected_paths) { + selected.push_back(Gtk::TreeModel::RowReference(listStore, row_path)); + } + + signalRowsPreErase.emit(selected_paths); + + for (const auto & row_ref : selected) { + const auto row_path = row_ref.get_path(); + if (row_path) { + listStore->erase(listStore->get_iter(row_path)); + } + } + + updateButtonSensitivity(); +} + +void ListEditButtons::onButtonUpPressed() +{ + const auto list_children = listStore->children(); + const std::vector selected = + list.get_selection()->get_selected_rows(); + + if (selected.size() != 1) { // Only one can be selected. + return; + } + + auto selected_row_iter = listStore->get_iter(selected[0]); + + if (selected_row_iter == list_children.begin()) { // Can't be first row. + return; + } + + auto prev_row_iter = selected_row_iter; + prev_row_iter--; + listStore->iter_swap(selected_row_iter, prev_row_iter); + updateButtonSensitivity(); +} + +void ListEditButtons::onListSelectionChanged() +{ + updateButtonSensitivity(); +} + +void ListEditButtons::updateButtonSensitivity() +{ + assert(list.get_model() == listStore); + + const std::vector selected = + list.get_selection()->get_selected_rows(); + + // Update sensitivity of the move up/down buttons. + if (selected.size() != 1) { + // Items can only be moved if one row is selected. + buttonDown.set_sensitive(false); + buttonUp.set_sensitive(false); + } else { + auto selected_row_iter = list.get_model()->get_iter(selected[0]); + const auto list_children = listStore->children(); + buttonUp.set_sensitive(!selected_row_iter->equal(list_children.begin())); + buttonDown.set_sensitive(!(++selected_row_iter)->equal(list_children.end())); + } + + // Update sensitivity of the remove button. + buttonRemove.set_sensitive(selected.size() > 0); +} + +sigc::signal> +ListEditButtons::getSignalRowsPreErase() +{ + return signalRowsPreErase; +} + +} + struct ToolLocationPreference::Impl { static std::unordered_map toolNamesReverseMap; @@ -336,6 +500,7 @@ struct ToolLocationPreference::Impl { Gtk::TreeViewColumn toolListViewColumnFavorite; Gtk::TreeViewColumn toolListViewColumnToolName; Gtk::TreeView *toolListViewPtr; + std::unordered_map toolListToolToRowIterMap; // Favorites list. FavoritesColumns favoritesColumns; @@ -343,6 +508,7 @@ struct ToolLocationPreference::Impl { Gtk::CellRendererText favoritesCellRendererToolName; Gtk::TreeViewColumn favoritesViewColumnToolName; Gtk::TreeView *favoritesViewPtr; + ListEditButtons favoritesListEditButtons; explicit Impl(Options &options); @@ -354,6 +520,7 @@ struct ToolLocationPreference::Impl { Tool getToolFromName(const std::string &name) const; void initFavoritesRows(const std::vector &favorites); void initToolListRows(const std::vector &favorites); + void onFavoritesRowsPreRemove(const std::vector paths); std::vector toolNamesToTools( const std::vector &tool_names) const; void updateOptions(); @@ -375,7 +542,8 @@ ToolLocationPreference::Impl::Impl(Options &options) : favoritesModelPtr(Gtk::ListStore::create(favoritesColumns)), favoritesViewColumnToolName( Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_TOOL"))), - favoritesViewPtr(Gtk::manage(new Gtk::TreeView(favoritesModelPtr))) + favoritesViewPtr(Gtk::manage(new Gtk::TreeView(favoritesModelPtr))), + favoritesListEditButtons(*favoritesViewPtr, favoritesModelPtr) { const std::vector favorites = toolNamesToTools(options.favorites); @@ -403,6 +571,10 @@ ToolLocationPreference::Impl::Impl(Options &options) : favoritesViewColumnToolName.pack_start(favoritesCellRendererToolName); favoritesViewColumnToolName.set_renderer( favoritesCellRendererToolName, favoritesColumns.toolName); + favoritesListEditButtons.getSignalRowsPreErase().connect(sigc::mem_fun( + *this, &ToolLocationPreference::Impl::onFavoritesRowsPreRemove)); + favoritesViewPtr->get_selection()->set_mode( + Gtk::SelectionMode::SELECTION_MULTIPLE); initFavoritesRows(favorites); } @@ -497,6 +669,7 @@ void ToolLocationPreference::Impl::addToolListRowGroup( tool_row_iter->set_value( toolListColumns.isEditable, ToolPanelCoordinator::isFavoritable(tool.id)); + toolListToolToRowIterMap[tool.id] = tool_row_iter; addToolListRowGroup(tool.children, tool_row_iter, favorites); } }; @@ -527,6 +700,18 @@ void ToolLocationPreference::Impl::initToolListRows(const std::vector &fav } } +void ToolLocationPreference::Impl::onFavoritesRowsPreRemove( + const std::vector paths) +{ + // Unset the favorite column in the tools list for tools about to be removed + // from the favorites list. + for (const auto &path : paths) { + const auto &row_iter = toolListToolToRowIterMap.at( + favoritesModelPtr->get_iter(path)->get_value(favoritesColumns.tool)); + row_iter->set_value(toolListColumns.isFavorite, false); + } +} + std::vector ToolLocationPreference::Impl::toolNamesToTools( const std::vector &tool_names) const { @@ -579,11 +764,14 @@ ToolLocationPreference::ToolLocationPreference(Options &options) : // Favorites list. Gtk::Frame *favorites_frame = Gtk::manage(new Gtk::Frame( M("PREFERENCES_TOOLPANEL_FAVORITESPANEL"))); + Gtk::Box *favorites_box = Gtk::manage(new Gtk::Box()); Gtk::ScrolledWindow *favorites_list_scrolled_window = Gtk::manage(new Gtk::ScrolledWindow()); favorites_list_scrolled_window->set_min_content_width(400); layout_grid->attach_next_to(*favorites_frame, Gtk::PositionType::POS_RIGHT, 1, 1); - favorites_frame->add(*favorites_list_scrolled_window); + favorites_box->pack_start(*favorites_list_scrolled_window, false, false); + favorites_box->pack_start(impl->favoritesListEditButtons, false, false); + favorites_frame->add(*favorites_box); favorites_list_scrolled_window->add(*impl->favoritesViewPtr); setExpandAlignProperties( favorites_frame, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL); From 16a9e3932fb8379537bb1d435631faf0d4334bb2 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Fri, 26 Nov 2021 16:39:50 -0800 Subject: [PATCH 07/24] Fix compilation error Add hasher to unordered_map with an enum class key. --- rtgui/toollocationpref.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index 2330759a4..0dda56806 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -500,7 +500,8 @@ struct ToolLocationPreference::Impl { Gtk::TreeViewColumn toolListViewColumnFavorite; Gtk::TreeViewColumn toolListViewColumnToolName; Gtk::TreeView *toolListViewPtr; - std::unordered_map toolListToolToRowIterMap; + std::unordered_map + toolListToolToRowIterMap; // Favorites list. FavoritesColumns favoritesColumns; From 9a67dd726e4c85d3a468466b62de3fa37b42f5ee Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Fri, 26 Nov 2021 21:01:37 -0800 Subject: [PATCH 08/24] Comment code for tool location preferences --- rtgui/toollocationpref.cc | 106 ++++++++++++++++++++++++++++++++++++++ rtgui/toollocationpref.h | 11 ++++ 2 files changed, 117 insertions(+) diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index 0dda56806..32cd73e97 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -30,6 +30,12 @@ using Favorites = std::unordered_set; namespace { +/** + * Gets the tool name for the tool's ToolPanel as a string. + * + * @param tool The name as a raw string, or an empty string if the tool is + * unknown. + */ std::string getToolName(Tool tool) { switch (tool) { @@ -149,6 +155,9 @@ std::string getToolName(Tool tool) return ""; }; +/** + * Returns the language key for the panel's title. + */ Glib::ustring getToolPanelTitleKey(ToolPanelCoordinator::Panel panel) { switch (panel) { @@ -172,6 +181,9 @@ Glib::ustring getToolPanelTitleKey(ToolPanelCoordinator::Panel panel) return ""; } +/** + * Returns the language key for the tool's title. + */ Glib::ustring getToolTitleKey(Tool tool) { using Tool = Tool; @@ -292,6 +304,13 @@ Glib::ustring getToolTitleKey(Tool tool) return ""; } +/** + * A widget with buttons (packed vertically) for modifying a list store with a + * tree view. + * + * Includes buttons for moving single rows up or down and a button for removing + * selected rows. + */ class ListEditButtons : public Gtk::Box { private: @@ -310,15 +329,34 @@ private: void updateButtonSensitivity(); public: + /** + * Constructs an edit buttons widget for modifying the provided list store. + * + * @param list The tree view for which selections are made in. The tree + * view's model MUST be the list store. + * @param listStore The list store that the widget will modify. + */ explicit ListEditButtons(Gtk::TreeView &list, Glib::RefPtr listStore); + /** + * Returns the signal that gets emitted right before this widget removes + * rows from its list store. + * + * The signal contains a vector of tree model paths of the rows that will be + * erased. + */ sigc::signal> getSignalRowsPreErase(); }; +/** + * Model columns for the favorites list. + */ class FavoritesColumns : public Gtk::TreeModelColumnRecord { public: + /** The tool's display name. */ Gtk::TreeModelColumn toolName; + /** The tool. */ Gtk::TreeModelColumn tool; FavoritesColumns() @@ -328,12 +366,19 @@ public: } }; +/** + * Model columns for the available tools list. + */ class ToolListColumns : public Gtk::TreeModelColumnRecord { public: + /** The tool's display name. */ Gtk::TreeModelColumn toolName; + /** The tool. */ Gtk::TreeModelColumn tool; + /** Is the tool added to favorites. */ Gtk::TreeModelColumn isFavorite; + /** Can the tool be added to favorites. */ Gtk::TreeModelColumn isEditable; ToolListColumns() @@ -394,6 +439,7 @@ void ListEditButtons::onButtonDownPressed() return; } + // Get the selected row and next row. auto selected_row_iter = listStore->get_iter(selected[0]); auto next_row_iter = selected_row_iter; next_row_iter++; @@ -402,6 +448,7 @@ void ListEditButtons::onButtonDownPressed() return; } + // Move the selected row down and update the buttons. listStore->iter_swap(selected_row_iter, next_row_iter); updateButtonSensitivity(); } @@ -419,6 +466,7 @@ void ListEditButtons::onButtonRemovePressed() signalRowsPreErase.emit(selected_paths); + // Remove the selected rows. for (const auto & row_ref : selected) { const auto row_path = row_ref.get_path(); if (row_path) { @@ -445,6 +493,7 @@ void ListEditButtons::onButtonUpPressed() return; } + // Swap selected row with the previous row. auto prev_row_iter = selected_row_iter; prev_row_iter--; listStore->iter_swap(selected_row_iter, prev_row_iter); @@ -469,6 +518,8 @@ void ListEditButtons::updateButtonSensitivity() buttonDown.set_sensitive(false); buttonUp.set_sensitive(false); } else { + // Up button cannot be used on the first row. Down button cannot be used + // on the last row. auto selected_row_iter = list.get_model()->get_iter(selected[0]); const auto list_children = listStore->children(); buttonUp.set_sensitive(!selected_row_iter->equal(list_children.begin())); @@ -511,19 +562,68 @@ struct ToolLocationPreference::Impl { Gtk::TreeView *favoritesViewPtr; ListEditButtons favoritesListEditButtons; + /** + * Constructs an implementation that gets values from and updates the + * provided options object. + */ explicit Impl(Options &options); + /** + * Adds the tools in the tool tree as a child in the provided row. + * + * @param tools The tool tree. + * @param parentRowIter An iterator to the row under which to add the tools. + * @param favorites The tools which are currently marked as favorites. + */ void addToolListRowGroup( const std::vector &tools, const Gtk::TreeIter &parentRowIter, const Favorites &favorites); + /** + * Toggles the tool list favorite column and updates the favorites list. + * + * @param row_path Path to the tool list model row. + */ void favoriteToggled(const Glib::ustring &row_path); + /** + * Gets the tool with the provided tool name. + * + * @param name The tool name as a raw string. + * @return The tool. + */ Tool getToolFromName(const std::string &name) const; + /** + * Initializes the favorites list. + * + * @param favorites Tools that are currently marked as favorites. + */ void initFavoritesRows(const std::vector &favorites); + /** + * Initializes the available tools list. + * + * @param favorites Tools that are currently marked as favorites. + */ void initToolListRows(const std::vector &favorites); + /** + * Updates the favorites column of the available tools list when tools are + * about to be removed from the favorites list. + * + * @param paths Paths in the favorites list pointing to the rows that are + * about to be removed. + */ void onFavoritesRowsPreRemove(const std::vector paths); + /** + * Converts tool names to their corresponding tools. + * + * @param tool_names The tool names that need to be converted. + * @return The tools. + */ std::vector toolNamesToTools( const std::vector &tool_names) const; + /** + * Updates the options object associated with this object with the current + * favorites preferences. + */ void updateOptions(); }; @@ -533,6 +633,7 @@ std::unordered_map ToolLocationPreference::Impl::Impl(Options &options) : options(options), + // Tool list. toolListModelPtr(Gtk::TreeStore::create(toolListColumns)), toolListViewColumnFavorite( Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_FAVORITE"))), @@ -540,6 +641,7 @@ ToolLocationPreference::Impl::Impl(Options &options) : Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_TOOL"))), toolListViewPtr(Gtk::manage(new Gtk::TreeView(toolListModelPtr))), + // Favorites list. favoritesModelPtr(Gtk::ListStore::create(favoritesColumns)), favoritesViewColumnToolName( Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_TOOL"))), @@ -644,6 +746,7 @@ Tool ToolLocationPreference::Impl::getToolFromName(const std::string &name) cons void ToolLocationPreference::Impl::initFavoritesRows( const std::vector &favorites) { + // Add the favorites to the favorites list store. for (const auto tool : favorites) { auto favorite_row_iter = favoritesModelPtr->append(); favorite_row_iter->set_value( @@ -658,6 +761,7 @@ void ToolLocationPreference::Impl::addToolListRowGroup( const Gtk::TreeIter &parentRowIter, const Favorites &favorites) { + // Recursively add the tool and its children to the tool list tree store. for (const ToolPanelCoordinator::ToolTree &tool : tools) { auto tool_row_iter = toolListModelPtr->append(parentRowIter->children()); tool_row_iter->set_value( @@ -680,10 +784,12 @@ void ToolLocationPreference::Impl::initToolListRows(const std::vector &fav const auto panel_tools = ToolPanelCoordinator::getDefaultToolLayout(); Favorites favorites_set; + // Convert the favorites vector into a set for fast lookup. for (const auto &tool : favorites) { favorites_set.insert(tool); } + // Add each panel and their children to the tool list. for (const auto panel : { ToolPanelCoordinator::Panel::EXPOSURE, ToolPanelCoordinator::Panel::DETAILS, diff --git a/rtgui/toollocationpref.h b/rtgui/toollocationpref.h index 815df6839..c7bee8695 100644 --- a/rtgui/toollocationpref.h +++ b/rtgui/toollocationpref.h @@ -22,6 +22,9 @@ class Options; +/** + * Widget for configuring the location of tools in the tool panel tabs. + */ class ToolLocationPreference : public Gtk::Box { private: @@ -29,6 +32,14 @@ private: std::unique_ptr impl; public: + /** + * Constructs a tool location preference widget that gets values from and + * updates the provided options object. + */ explicit ToolLocationPreference(Options &options); + /** + * Updates the options object associated with this object with the current + * favorites preferences. + */ void updateOptions(); }; From 8bd7712cce1dba8cd6cf0d876008a35646141942 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Fri, 26 Nov 2021 21:34:19 -0800 Subject: [PATCH 09/24] Add error handling to tool location preferences --- rtgui/toollocationpref.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index 32cd73e97..a6c7bf6b4 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -16,6 +16,7 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include #include #include "guiutils.h" @@ -152,6 +153,7 @@ std::string getToolName(Tool tool) case Tool::PD_SHARPENING: return "capturesharpening"; }; + assert(false); return ""; }; @@ -178,6 +180,7 @@ Glib::ustring getToolPanelTitleKey(ToolPanelCoordinator::Panel panel) case ToolPanelCoordinator::Panel::RAW: return "MAIN_TAB_RAW"; } + assert(false); return ""; } @@ -301,6 +304,7 @@ Glib::ustring getToolTitleKey(Tool tool) case Tool::PD_SHARPENING: return "TP_PDSHARPENING_LABEL"; }; + assert(false); return ""; } @@ -471,6 +475,8 @@ void ListEditButtons::onButtonRemovePressed() const auto row_path = row_ref.get_path(); if (row_path) { listStore->erase(listStore->get_iter(row_path)); + } else if (rtengine::settings->verbose) { + std::cout << "Unable to remove row because it does not exist anymore." << std::endl; } } @@ -829,6 +835,10 @@ std::vector ToolLocationPreference::Impl::toolNamesToTools( try { tool = getToolFromName(tool_name); } catch (const std::exception &e) { + if (rtengine::settings->verbose) { + std::cerr << "Unrecognized tool name \"" << tool_name << "\"." << std::endl; + } + assert(false); continue; } tool_set.push_back(tool); From 778b26d5bd26cce1f5bb8f6815f426ccd316cbed Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 5 Dec 2021 17:09:23 -0800 Subject: [PATCH 10/24] Make tool locations dynamic Update tool locations after changing favorite tools preferences. --- rtdata/themes/RawTherapee-GTK3-20_.css | 2 +- rtgui/editorpanel.cc | 7 + rtgui/editorpanel.h | 1 + rtgui/preferences.cc | 3 + rtgui/rtwindow.cc | 8 + rtgui/rtwindow.h | 1 + rtgui/toollocationpref.cc | 167 +------ rtgui/toolpanel.cc | 9 +- rtgui/toolpanel.h | 11 + rtgui/toolpanelcoord.cc | 608 ++++++++++++++++++++----- rtgui/toolpanelcoord.h | 43 +- 11 files changed, 586 insertions(+), 274 deletions(-) diff --git a/rtdata/themes/RawTherapee-GTK3-20_.css b/rtdata/themes/RawTherapee-GTK3-20_.css index 57c6db148..c576e0ddf 100644 --- a/rtdata/themes/RawTherapee-GTK3-20_.css +++ b/rtdata/themes/RawTherapee-GTK3-20_.css @@ -758,7 +758,7 @@ button.radio#histButton:hover { #MyExpander:first-child { border-top: none; } -#MyExpander:nth-last-child(2), +#MyExpander:nth-last-child(1), #MyExpander #MyExpander:nth-last-child(1) { border-bottom: 0.0833333333333333em solid rgba(0,0,0,0.3); } diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 78a07ddd6..888fc9518 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -2486,6 +2486,13 @@ void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition) } +void EditorPanel::updateToolPanelToolLocations( + const std::vector &favorites) +{ + if (tpc) { + tpc->updateToolLocations(favorites); + } +} void EditorPanel::defaultMonitorProfileChanged (const Glib::ustring &profile_name, bool auto_monitor_profile) { diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 7675face5..0ffe44ace 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -185,6 +185,7 @@ public: void updateProfiles (const Glib::ustring &printerProfile, rtengine::RenderingIntent printerIntent, bool printerBPC); void updateTPVScrollbar (bool hide); void updateHistogramPosition (int oldPosition, int newPosition); + void updateToolPanelToolLocations(const std::vector &favorites); void defaultMonitorProfileChanged (const Glib::ustring &profile_name, bool auto_monitor_profile); diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 39726c791..e67d16015 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -2572,6 +2572,9 @@ void Preferences::workflowUpdate() parent->updateProfiles (moptions.rtSettings.printerProfile, rtengine::RenderingIntent(moptions.rtSettings.printerIntent), moptions.rtSettings.printerBPC); } + if (moptions.favorites != options.favorites) { + parent->updateToolPanelToolLocations(moptions.favorites); + } } void Preferences::addExtPressed() diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index 1b90d631b..15715a2fd 100755 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -1110,6 +1110,14 @@ void RTWindow::updateHistogramPosition (int oldPosition, int newPosition) } } +void RTWindow::updateToolPanelToolLocations( + const std::vector &favorites) +{ + if (epanel) { + epanel->updateToolPanelToolLocations(favorites); + } +} + bool RTWindow::splashClosed (GdkEventAny* event) { delete splash; diff --git a/rtgui/rtwindow.h b/rtgui/rtwindow.h index 0c1cd2572..d35755185 100755 --- a/rtgui/rtwindow.h +++ b/rtgui/rtwindow.h @@ -124,6 +124,7 @@ public: void updateFBQueryTB (bool singleRow); void updateFBToolBarVisibility (bool showFilmStripToolBar); void updateShowtooltipVisibility (bool showtooltip); + void updateToolPanelToolLocations(const std::vector &favorites); bool getIsFullscreen() { return is_fullscreen; diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index a6c7bf6b4..561be4601 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -31,132 +31,6 @@ using Favorites = std::unordered_set; namespace { -/** - * Gets the tool name for the tool's ToolPanel as a string. - * - * @param tool The name as a raw string, or an empty string if the tool is - * unknown. - */ -std::string getToolName(Tool tool) -{ - switch (tool) { - case Tool::TONE_CURVE: - return "tonecurve"; - case Tool::SHADOWS_HIGHLIGHTS: - return "shadowshighlights"; - case Tool::IMPULSE_DENOISE: - return "impulsedenoise"; - case Tool::DEFRINGE_TOOL: - return "defringe"; - case Tool::SPOT: - return "spot"; - case Tool::DIR_PYR_DENOISE: - return "dirpyrdenoise"; - case Tool::EPD: - return "epd"; - case Tool::SHARPENING_TOOL: - return "sharpening"; - case Tool::LOCAL_CONTRAST: - return "localcontrast"; - case Tool::SHARPEN_EDGE: - return "sharpenedge"; - case Tool::SHARPEN_MICRO: - return "sharpenmicro"; - case Tool::L_CURVE: - return "labcurves"; - case Tool::RGB_CURVES: - return "rgbcurves"; - case Tool::COLOR_TONING: - return "colortoning"; - case Tool::LENS_GEOM: - return "lensgeom"; - case Tool::LENS_PROF: - return "lensprof"; - case Tool::DISTORTION: - return "distortion"; - case Tool::ROTATE: - return "rotate"; - case Tool::VIBRANCE: - return "vibrance"; - case Tool::COLOR_APPEARANCE: - return "colorappearance"; - case Tool::WHITE_BALANCE: - return "whitebalance"; - case Tool::VIGNETTING: - return "vignetting"; - case Tool::RETINEX_TOOL: - return "retinex"; - case Tool::GRADIENT: - return "gradient"; - case Tool::LOCALLAB: - return "locallab"; - case Tool::PC_VIGNETTE: - return "pcvignette"; - case Tool::PERSPECTIVE: - return "perspective"; - case Tool::CA_CORRECTION: - return "cacorrection"; - case Tool::CH_MIXER: - return "chmixer"; - case Tool::BLACK_WHITE: - return "blackwhite"; - case Tool::RESIZE_TOOL: - return "resize"; - case Tool::PR_SHARPENING: - return "prsharpening"; - case Tool::CROP_TOOL: - return "crop"; - case Tool::ICM: - return "icm"; - case Tool::WAVELET: - return "wavelet"; - case Tool::DIR_PYR_EQUALIZER: - return "dirpyrdenoise"; - case Tool::HSV_EQUALIZER: - return "hsvequalizer"; - case Tool::FILM_SIMULATION: - return "filmsimulation"; - case Tool::SOFT_LIGHT: - return "softlight"; - case Tool::DEHAZE: - return "dehaze"; - case Tool::SENSOR_BAYER: - return "sensorbayer"; - case Tool::SENSOR_XTRANS: - return "sensorxtrans"; - case Tool::BAYER_PROCESS: - return "bayerprocess"; - case Tool::XTRANS_PROCESS: - return "xtransprocess"; - case Tool::BAYER_PREPROCESS: - return "bayerpreprocess"; - case Tool::PREPROCESS: - return "preprocess"; - case Tool::DARKFRAME_TOOL: - return "darkframe"; - case Tool::FLATFIELD_TOOL: - return "flatfield"; - case Tool::RAW_CA_CORRECTION: - return "rawcacorrection"; - case Tool::RAW_EXPOSURE: - return "rawexposure"; - case Tool::PREPROCESS_WB: - return "preprocesswb"; - case Tool::BAYER_RAW_EXPOSURE: - return "bayerrawexposure"; - case Tool::XTRANS_RAW_EXPOSURE: - return "xtransrawexposure"; - case Tool::FATTAL: - return "fattal"; - case Tool::FILM_NEGATIVE: - return "filmnegative"; - case Tool::PD_SHARPENING: - return "capturesharpening"; - }; - assert(false); - return ""; -}; - /** * Returns the language key for the panel's title. */ @@ -591,13 +465,6 @@ struct ToolLocationPreference::Impl { * @param row_path Path to the tool list model row. */ void favoriteToggled(const Glib::ustring &row_path); - /** - * Gets the tool with the provided tool name. - * - * @param name The tool name as a raw string. - * @return The tool. - */ - Tool getToolFromName(const std::string &name) const; /** * Initializes the favorites list. * @@ -719,36 +586,6 @@ void ToolLocationPreference::Impl::favoriteToggled(const Glib::ustring &row_path } } -Tool ToolLocationPreference::Impl::getToolFromName(const std::string &name) const -{ - if (toolNamesReverseMap.empty()) { - // Create the name to tool mapping. - - const auto panels = ToolPanelCoordinator::getDefaultToolLayout(); - std::vector unprocessed_tool_trees; - - // Get the root tools from each panel. - for (const auto &panel_tools : panels) { - for (const auto &tool : panel_tools.second) { - unprocessed_tool_trees.push_back(&tool); - } - } - - // Process all the tools, including their children. - while (unprocessed_tool_trees.size() > 0) { - const ToolPanelCoordinator::ToolTree *tool_tree = - unprocessed_tool_trees.back(); - unprocessed_tool_trees.pop_back(); - toolNamesReverseMap[getToolName(tool_tree->id)] = tool_tree->id; - for (const auto &child_tree : tool_tree->children) { - unprocessed_tool_trees.push_back(&child_tree); - } - } - } - - return toolNamesReverseMap.at(name); -} - void ToolLocationPreference::Impl::initFavoritesRows( const std::vector &favorites) { @@ -833,7 +670,7 @@ std::vector ToolLocationPreference::Impl::toolNamesToTools( for (auto &&tool_name : tool_names) { Tool tool; try { - tool = getToolFromName(tool_name); + tool = ToolPanelCoordinator::getToolFromName(tool_name); } catch (const std::exception &e) { if (rtengine::settings->verbose) { std::cerr << "Unrecognized tool name \"" << tool_name << "\"." << std::endl; @@ -853,7 +690,7 @@ void ToolLocationPreference::Impl::updateOptions() options.favorites.resize(favorites_rows.size()); for (unsigned i = 0; i < favorites_rows.size(); i++) { const Tool tool = favorites_rows[i].get_value(favoritesColumns.tool); - options.favorites[i] = getToolName(tool); + options.favorites[i] = ToolPanelCoordinator::getToolName(tool); } } diff --git a/rtgui/toolpanel.cc b/rtgui/toolpanel.cc index cfc53639b..bf191133d 100644 --- a/rtgui/toolpanel.cc +++ b/rtgui/toolpanel.cc @@ -73,7 +73,14 @@ FoldableToolPanel::FoldableToolPanel(Gtk::Box* content, Glib::ustring toolName, exp->signal_button_release_event().connect_notify( sigc::mem_fun(this, &FoldableToolPanel::foldThemAll) ); enaConn = signal_enabled_toggled().connect( sigc::mem_fun(*this, &FoldableToolPanel::enabled_toggled) ); - exp->add (*content); + Gtk::Box *expanderContents = Gtk::manage( + new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); + subToolsContainer = Gtk::manage( + new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); + expanderContents->pack_start(*content, false, false, 0); + expanderContents->pack_start(*subToolsContainer, false, false, 0); + + exp->add(*expanderContents, false); exp->show (); } diff --git a/rtgui/toolpanel.h b/rtgui/toolpanel.h index 8fdb4540d..ce14dc64f 100644 --- a/rtgui/toolpanel.h +++ b/rtgui/toolpanel.h @@ -98,6 +98,10 @@ public: { return nullptr; } + virtual Gtk::Box *getSubToolsContainer() const + { + return nullptr; + } virtual void setExpanded (bool expanded) {} virtual bool getExpanded () { @@ -164,6 +168,7 @@ class FoldableToolPanel : protected: Gtk::Box* parentContainer; MyExpander* exp; + Gtk::Box *subToolsContainer; bool lastEnabled; sigc::connection enaConn; void foldThemAll (GdkEventButton* event); @@ -177,6 +182,12 @@ public: { return exp; } + + Gtk::Box *getSubToolsContainer() const final + { + return subToolsContainer; + } + void setExpanded (bool expanded) final { if (exp) { diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index fa2203958..1b81fb014 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -267,6 +267,8 @@ const ToolPanelCoordinator::ToolLayout PANEL_TOOLS = { }, }; +std::unordered_map ToolPanelCoordinator::toolNamesReverseMap; + ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favoritePanelSW(nullptr), hasChanged (false), editDataProvider (nullptr), photoLoadedOnce(false) { @@ -345,71 +347,33 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit // Valeurs par dfaut: // Best -> low ISO // Medium -> High ISO - favorites.resize(options.favorites.size(), nullptr); - addfavoritePanel (colorPanel, whitebalance); - addfavoritePanel (exposurePanel, toneCurve); - addfavoritePanel (colorPanel, vibrance); - addfavoritePanel (colorPanel, chmixer); - addfavoritePanel (colorPanel, blackwhite); - addfavoritePanel (exposurePanel, shadowshighlights); - addfavoritePanel (detailsPanel, spot); - addfavoritePanel (detailsPanel, sharpening); - addfavoritePanel (detailsPanel, localContrast); - addfavoritePanel (detailsPanel, sharpenEdge); - addfavoritePanel (detailsPanel, sharpenMicro); - addfavoritePanel (colorPanel, hsvequalizer); - addfavoritePanel (colorPanel, filmSimulation); - addfavoritePanel (colorPanel, filmNegative); - addfavoritePanel (colorPanel, softlight); - addfavoritePanel (colorPanel, rgbcurves); - addfavoritePanel (colorPanel, colortoning); - addfavoritePanel (exposurePanel, epd); - addfavoritePanel (exposurePanel, fattal); - addfavoritePanel (advancedPanel, retinex); - addfavoritePanel (exposurePanel, pcvignette); - addfavoritePanel (exposurePanel, gradient); - addfavoritePanel (exposurePanel, lcurve); - addfavoritePanel (advancedPanel, colorappearance); - addfavoritePanel (detailsPanel, impulsedenoise); - addfavoritePanel (detailsPanel, dirpyrdenoise); - addfavoritePanel (detailsPanel, defringe); - addfavoritePanel (detailsPanel, dirpyrequalizer); - addfavoritePanel (detailsPanel, dehaze); - addfavoritePanel (advancedPanel, wavelet); - addfavoritePanel(locallabPanel, locallab); + for (const auto &panel_tool_layout : getDefaultToolLayout()) { + const auto &panel_tools = panel_tool_layout.second; + std::vector unprocessed_tools; - addfavoritePanel (transformPanel, crop); - addfavoritePanel (transformPanel, resize); - addPanel (resize->getPackBox(), prsharpening, 2); - addfavoritePanel (transformPanel, lensgeom); - addfavoritePanel (lensgeom->getPackBox(), rotate, 2); - addfavoritePanel (lensgeom->getPackBox(), perspective, 2); - addfavoritePanel (lensgeom->getPackBox(), lensProf, 2); - addfavoritePanel (lensgeom->getPackBox(), distortion, 2); - addfavoritePanel (lensgeom->getPackBox(), cacorrection, 2); - addfavoritePanel (lensgeom->getPackBox(), vignetting, 2); - addfavoritePanel (colorPanel, icm); - addfavoritePanel (rawPanel, sensorbayer); - addfavoritePanel (sensorbayer->getPackBox(), bayerprocess, 2); - addfavoritePanel (sensorbayer->getPackBox(), bayerrawexposure, 2); - addfavoritePanel (sensorbayer->getPackBox(), bayerpreprocess, 2); - addfavoritePanel (sensorbayer->getPackBox(), rawcacorrection, 2); - addfavoritePanel (rawPanel, sensorxtrans); - addfavoritePanel (sensorxtrans->getPackBox(), xtransprocess, 2); - addfavoritePanel (sensorxtrans->getPackBox(), xtransrawexposure, 2); - addfavoritePanel (rawPanel, rawexposure); - addfavoritePanel (rawPanel, preprocessWB); - addfavoritePanel (rawPanel, preprocess); - addfavoritePanel (rawPanel, darkframe); - addfavoritePanel (rawPanel, flatfield); - addfavoritePanel (rawPanel, pdSharpening); + // Start with the root tools for every panel. + for (const auto &tool_tree : panel_tools) { + unprocessed_tools.push_back(&tool_tree); + } - int favoriteCount = 0; - for(auto it = favorites.begin(); it != favorites.end(); ++it) { - if (*it) { - addPanel(favoritePanel, *it); - ++favoriteCount; + // Process each tool. + while (!unprocessed_tools.empty()) { + // Pop from stack of unprocessed. + const ToolTree *cur_tool = unprocessed_tools.back(); + unprocessed_tools.pop_back(); + // Add tool to list of expanders and tool panels. + FoldableToolPanel *tool_panel = getFoldableToolPanel(*cur_tool); + expList.push_back(tool_panel->getExpander()); + toolPanels.push_back(tool_panel); + expanderToToolPanelMap[tool_panel->getExpander()] = tool_panel; + toolToDefaultToolTreeMap[cur_tool->id] = cur_tool; + // Show all now, since they won't be attached to a parent. + tool_panel->getExpander()->show_all(); + // Add children to unprocessed. + for (const auto &child_tool : cur_tool->children) { + unprocessed_tools.push_back(&child_tool); + } } } @@ -418,6 +382,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit toolPanelNotebook = new Gtk::Notebook(); toolPanelNotebook->set_name("ToolPanelNotebook"); + favoritePanelSW.reset(new MyScrolledWindow()); exposurePanelSW = Gtk::manage (new MyScrolledWindow ()); detailsPanelSW = Gtk::manage (new MyScrolledWindow ()); colorPanelSW = Gtk::manage (new MyScrolledWindow ()); @@ -434,35 +399,58 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit vbPanelEnd[i]->pack_start(*imgPanelEnd[i], Gtk::PACK_SHRINK); vbPanelEnd[i]->show_all(); } - if(favoriteCount > 0) { - favoritePanelSW = Gtk::manage(new MyScrolledWindow()); - favoritePanelSW->add(*favoritePanel); - favoritePanel->pack_start(*vbPanelEnd[0], Gtk::PACK_SHRINK, 4); - } updateVScrollbars(options.hideTPVScrollbar); - exposurePanelSW->add (*exposurePanel); - exposurePanel->pack_start (*vbPanelEnd[1], Gtk::PACK_SHRINK, 4); + Gtk::Box *favoritePanelContainer = + Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); + Gtk::Box *exposurePanelContainer = + Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); + Gtk::Box *detailsPanelContainer = + Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); + Gtk::Box *colorPanelContainer = + Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); + Gtk::Box *advancedPanelContainer = + Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); + Gtk::Box *locallabPanelContainer = + Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); + Gtk::Box *transformPanelContainer = + Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); + Gtk::Box *rawPanelContainer = + Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); - detailsPanelSW->add (*detailsPanel); - detailsPanel->pack_start (*vbPanelEnd[2], Gtk::PACK_SHRINK, 4); + favoritePanelSW->add(*favoritePanelContainer); + favoritePanelContainer->pack_start(*favoritePanel, Gtk::PACK_SHRINK, 0); + favoritePanelContainer->pack_start(*vbPanelEnd[0], Gtk::PACK_SHRINK, 4); - colorPanelSW->add (*colorPanel); - colorPanel->pack_start (*vbPanelEnd[3], Gtk::PACK_SHRINK, 4); + exposurePanelSW->add (*exposurePanelContainer); + exposurePanelContainer->pack_start(*exposurePanel, Gtk::PACK_SHRINK, 0); + exposurePanelContainer->pack_start (*vbPanelEnd[1], Gtk::PACK_SHRINK, 4); - advancedPanelSW->add (*advancedPanel); - advancedPanel->pack_start (*vbPanelEnd[6], Gtk::PACK_SHRINK, 0); + detailsPanelSW->add (*detailsPanelContainer); + detailsPanelContainer->pack_start(*detailsPanel, Gtk::PACK_SHRINK, 0); + detailsPanelContainer->pack_start (*vbPanelEnd[2], Gtk::PACK_SHRINK, 4); - locallabPanelSW->add(*locallabPanel); - locallabPanel->pack_start(*vbPanelEnd[7], Gtk::PACK_SHRINK, 4); + colorPanelSW->add (*colorPanelContainer); + colorPanelContainer->pack_start(*colorPanel, Gtk::PACK_SHRINK, 0); + colorPanelContainer->pack_start (*vbPanelEnd[3], Gtk::PACK_SHRINK, 4); - transformPanelSW->add (*transformPanel); - transformPanel->pack_start (*vbPanelEnd[4], Gtk::PACK_SHRINK, 4); + advancedPanelSW->add (*advancedPanelContainer); + advancedPanelContainer->pack_start(*advancedPanel, Gtk::PACK_SHRINK, 0); + advancedPanelContainer->pack_start (*vbPanelEnd[6], Gtk::PACK_SHRINK, 0); - rawPanelSW->add (*rawPanel); - rawPanel->pack_start (*vbPanelEnd[5], Gtk::PACK_SHRINK, 0); + locallabPanelSW->add(*locallabPanelContainer); + locallabPanelContainer->pack_start(*locallabPanel, Gtk::PACK_SHRINK, 0); + locallabPanelContainer->pack_start(*vbPanelEnd[7], Gtk::PACK_SHRINK, 4); - toiF = Gtk::manage (new TextOrIcon ("star.png", M ("MAIN_TAB_FAVORITES"), M ("MAIN_TAB_FAVORITES_TOOLTIP"))); + transformPanelSW->add (*transformPanelContainer); + transformPanelContainer->pack_start(*transformPanel, Gtk::PACK_SHRINK, 0); + transformPanelContainer->pack_start (*vbPanelEnd[4], Gtk::PACK_SHRINK, 4); + + rawPanelSW->add (*rawPanelContainer); + rawPanelContainer->pack_start(*rawPanel, Gtk::PACK_SHRINK, 0); + rawPanelContainer->pack_start (*vbPanelEnd[5], Gtk::PACK_SHRINK, 0); + + toiF.reset(new TextOrIcon ("star.png", M ("MAIN_TAB_FAVORITES"), M ("MAIN_TAB_FAVORITES_TOOLTIP"))); toiE = Gtk::manage (new TextOrIcon ("exposure.png", M ("MAIN_TAB_EXPOSURE"), M ("MAIN_TAB_EXPOSURE_TOOLTIP"))); toiD = Gtk::manage (new TextOrIcon ("detail.png", M ("MAIN_TAB_DETAIL"), M ("MAIN_TAB_DETAIL_TOOLTIP"))); toiC = Gtk::manage (new TextOrIcon ("color-circles.png", M ("MAIN_TAB_COLOR"), M ("MAIN_TAB_COLOR_TOOLTIP"))); @@ -472,9 +460,6 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit toiT = Gtk::manage (new TextOrIcon ("transform.png", M ("MAIN_TAB_TRANSFORM"), M ("MAIN_TAB_TRANSFORM_TOOLTIP"))); toiR = Gtk::manage (new TextOrIcon ("bayer.png", M ("MAIN_TAB_RAW"), M ("MAIN_TAB_RAW_TOOLTIP"))); toiM = Gtk::manage (new TextOrIcon ("metadata.png", M ("MAIN_TAB_METADATA"), M ("MAIN_TAB_METADATA_TOOLTIP"))); - if (favoritePanelSW) { - toolPanelNotebook->append_page (*favoritePanelSW, *toiF); - } toolPanelNotebook->append_page (*exposurePanelSW, *toiE); toolPanelNotebook->append_page (*detailsPanelSW, *toiD); toolPanelNotebook->append_page (*colorPanelSW, *toiC); @@ -491,6 +476,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit toolPanelNotebook->set_scrollable(); toolPanelNotebook->show_all(); + updateToolLocations(options.favorites); notebookconn = toolPanelNotebook->signal_switch_page().connect( sigc::mem_fun(*this, &ToolPanelCoordinator::notebookPageChanged)); @@ -528,6 +514,156 @@ const ToolPanelCoordinator::ToolLayout& ToolPanelCoordinator::getDefaultToolLayo return PANEL_TOOLS; } +Tool ToolPanelCoordinator::getToolFromName(const std::string &name) +{ + if (toolNamesReverseMap.empty()) { + // Create the name to tool mapping. + + const auto panels = ToolPanelCoordinator::getDefaultToolLayout(); + std::vector unprocessed_tool_trees; + + // Get the root tools from each panel. + for (const auto &panel_tools : panels) { + for (const auto &tool : panel_tools.second) { + unprocessed_tool_trees.push_back(&tool); + } + } + + // Process all the tools, including their children. + while (unprocessed_tool_trees.size() > 0) { + const ToolPanelCoordinator::ToolTree *tool_tree = + unprocessed_tool_trees.back(); + unprocessed_tool_trees.pop_back(); + toolNamesReverseMap[getToolName(tool_tree->id)] = tool_tree->id; + for (const auto &child_tree : tool_tree->children) { + unprocessed_tool_trees.push_back(&child_tree); + } + } + } + + return toolNamesReverseMap.at(name); +} + +std::string ToolPanelCoordinator::getToolName(Tool tool) +{ + switch (tool) { + case Tool::TONE_CURVE: + return "tonecurve"; + case Tool::SHADOWS_HIGHLIGHTS: + return "shadowshighlights"; + case Tool::IMPULSE_DENOISE: + return "impulsedenoise"; + case Tool::DEFRINGE_TOOL: + return "defringe"; + case Tool::SPOT: + return "spot"; + case Tool::DIR_PYR_DENOISE: + return "dirpyrdenoise"; + case Tool::EPD: + return "epd"; + case Tool::SHARPENING_TOOL: + return "sharpening"; + case Tool::LOCAL_CONTRAST: + return "localcontrast"; + case Tool::SHARPEN_EDGE: + return "sharpenedge"; + case Tool::SHARPEN_MICRO: + return "sharpenmicro"; + case Tool::L_CURVE: + return "labcurves"; + case Tool::RGB_CURVES: + return "rgbcurves"; + case Tool::COLOR_TONING: + return "colortoning"; + case Tool::LENS_GEOM: + return "lensgeom"; + case Tool::LENS_PROF: + return "lensprof"; + case Tool::DISTORTION: + return "distortion"; + case Tool::ROTATE: + return "rotate"; + case Tool::VIBRANCE: + return "vibrance"; + case Tool::COLOR_APPEARANCE: + return "colorappearance"; + case Tool::WHITE_BALANCE: + return "whitebalance"; + case Tool::VIGNETTING: + return "vignetting"; + case Tool::RETINEX_TOOL: + return "retinex"; + case Tool::GRADIENT: + return "gradient"; + case Tool::LOCALLAB: + return "locallab"; + case Tool::PC_VIGNETTE: + return "pcvignette"; + case Tool::PERSPECTIVE: + return "perspective"; + case Tool::CA_CORRECTION: + return "cacorrection"; + case Tool::CH_MIXER: + return "chmixer"; + case Tool::BLACK_WHITE: + return "blackwhite"; + case Tool::RESIZE_TOOL: + return "resize"; + case Tool::PR_SHARPENING: + return "prsharpening"; + case Tool::CROP_TOOL: + return "crop"; + case Tool::ICM: + return "icm"; + case Tool::WAVELET: + return "wavelet"; + case Tool::DIR_PYR_EQUALIZER: + return "dirpyrdenoise"; + case Tool::HSV_EQUALIZER: + return "hsvequalizer"; + case Tool::FILM_SIMULATION: + return "filmsimulation"; + case Tool::SOFT_LIGHT: + return "softlight"; + case Tool::DEHAZE: + return "dehaze"; + case Tool::SENSOR_BAYER: + return "sensorbayer"; + case Tool::SENSOR_XTRANS: + return "sensorxtrans"; + case Tool::BAYER_PROCESS: + return "bayerprocess"; + case Tool::XTRANS_PROCESS: + return "xtransprocess"; + case Tool::BAYER_PREPROCESS: + return "bayerpreprocess"; + case Tool::PREPROCESS: + return "preprocess"; + case Tool::DARKFRAME_TOOL: + return "darkframe"; + case Tool::FLATFIELD_TOOL: + return "flatfield"; + case Tool::RAW_CA_CORRECTION: + return "rawcacorrection"; + case Tool::RAW_EXPOSURE: + return "rawexposure"; + case Tool::PREPROCESS_WB: + return "preprocesswb"; + case Tool::BAYER_RAW_EXPOSURE: + return "bayerrawexposure"; + case Tool::XTRANS_RAW_EXPOSURE: + return "xtransrawexposure"; + case Tool::FATTAL: + return "fattal"; + case Tool::FILM_NEGATIVE: + return "filmnegative"; + case Tool::PD_SHARPENING: + return "capturesharpening"; + }; + assert(false); + return ""; +}; + bool ToolPanelCoordinator::isFavoritable(Tool tool) { switch (tool) { @@ -540,6 +676,8 @@ bool ToolPanelCoordinator::isFavoritable(Tool tool) void ToolPanelCoordinator::notebookPageChanged(Gtk::Widget* page, guint page_num) { + updatePanelTools(page, options.favorites); + // Locallab spot curves are set visible if at least one photo has been loaded (to avoid // segfault) and locallab panel is active if (photoLoadedOnce) { @@ -557,26 +695,140 @@ void ToolPanelCoordinator::notebookPageChanged(Gtk::Widget* page, guint page_num } } +void ToolPanelCoordinator::updateFavoritesPanel( + const std::vector &favoritesNames) +{ + std::unordered_set favorites_set; + std::vector> favorites_tool_tree; + + for (const auto &tool_name : favoritesNames) { + Tool tool = getToolFromName(tool_name.raw()); + favorites_set.insert(tool); + favorites_tool_tree.push_back( + std::ref(*(toolToDefaultToolTreeMap.at(tool)))); + } + + updateToolPanel(favoritePanel, favorites_tool_tree, 1, favorites_set); +} + +void ToolPanelCoordinator::updatePanelTools( + Gtk::Widget *page, const std::vector &favorites) +{ + if (page == favoritePanelSW.get()) { + updateFavoritesPanel(favorites); + return; + } + + ToolVBox *panel = nullptr; + const std::vector *default_panel_tools = nullptr; + if (page == exposurePanelSW) { + panel = exposurePanel; + default_panel_tools = &EXPOSURE_PANEL_TOOLS; + } else if (page == detailsPanelSW) { + panel = detailsPanel; + default_panel_tools = &DETAILS_PANEL_TOOLS; + } else if (page == colorPanelSW) { + panel = colorPanel; + default_panel_tools = &COLOR_PANEL_TOOLS; + } else if (page == transformPanelSW) { + panel = transformPanel; + default_panel_tools = &TRANSFORM_PANEL_TOOLS; + } else if (page == rawPanelSW) { + panel = rawPanel; + default_panel_tools = &RAW_PANEL_TOOLS; + } else if (page == advancedPanelSW) { + panel = advancedPanel; + default_panel_tools = &ADVANCED_PANEL_TOOLS; + } else if (page == locallabPanelSW) { + panel = locallabPanel; + default_panel_tools = &LOCALLAB_PANEL_TOOLS; + } else { + return; + } + assert(panel && default_panel_tools); + + std::unordered_set favoriteTools; + for (const auto &tool_name : favorites) { + favoriteTools.insert(getToolFromName(tool_name.raw())); + } + + updateToolPanel(panel, *default_panel_tools, 1, favoriteTools); +} + +template +typename std::enable_if::value, void>::type +ToolPanelCoordinator::updateToolPanel( + Gtk::Box *panelBox, + const std::vector &children, + int level, + std::unordered_set favorites) +{ + const bool is_favorite_panel = panelBox == favoritePanel; + const std::vector old_tool_panels = panelBox->get_children(); + auto old_widgets_iter = old_tool_panels.begin(); + auto new_tool_trees_iter = children.begin(); + + // Indicates if this tool should not be added. Favorite tools are skipped + // unless the parent panel box is the favorites panel. + const auto should_skip_tool = + [is_favorite_panel, &favorites](const ToolTree &tool_tree) { + return !is_favorite_panel && favorites.count(tool_tree.id); + }; + + // Keep tools that are already correct. + while ( + old_widgets_iter != old_tool_panels.end() && + new_tool_trees_iter != children.end()) { + if (should_skip_tool(*new_tool_trees_iter)) { + ++new_tool_trees_iter; + continue; + } + if (*old_widgets_iter != + getFoldableToolPanel(*new_tool_trees_iter)->getExpander()) { + break; + } + ++old_widgets_iter; + } + + // Remove incorrect tools. + for (auto iter = old_tool_panels.end(); iter != old_widgets_iter;) { + --iter; + FoldableToolPanel *old_tool_panel = expanderToToolPanelMap.at(*iter); + assert(*iter == old_tool_panel->getExpander()); + panelBox->remove(**iter); + old_tool_panel->setParent(nullptr); + } + + // Add correct tools. + for (; new_tool_trees_iter != children.end(); new_tool_trees_iter++) { + if (should_skip_tool(*new_tool_trees_iter)) { + continue; + } + FoldableToolPanel *tool_panel = + getFoldableToolPanel(*new_tool_trees_iter); + if (tool_panel->getParent()) { + tool_panel->getParent()->remove(*tool_panel->getExpander()); + } + addPanel(panelBox, tool_panel, level); + } + + // Update the child tools. + for (const ToolTree &tool_tree : children) { + const FoldableToolPanel *tool_panel = getFoldableToolPanel(tool_tree); + updateToolPanel( + tool_panel->getSubToolsContainer(), + tool_tree.children, + level + 1, + favorites); + } +} + void ToolPanelCoordinator::addPanel(Gtk::Box* where, FoldableToolPanel* panel, int level) { panel->setParent(where); panel->setLevel(level); - - expList.push_back(panel->getExpander()); where->pack_start(*panel->getExpander(), false, false); - toolPanels.push_back(panel); -} -void ToolPanelCoordinator::addfavoritePanel (Gtk::Box* where, FoldableToolPanel* panel, int level) -{ - auto name = panel->getToolName(); - auto it = std::find(options.favorites.begin(), options.favorites.end(), name); - if (it != options.favorites.end()) { - int index = std::distance(options.favorites.begin(), it); - favorites[index] = panel; - } else { - addPanel(where, panel, level); - } } ToolPanelCoordinator::~ToolPanelCoordinator () @@ -1366,6 +1618,30 @@ void ToolPanelCoordinator::foldAllButOne(Gtk::Box* parent, FoldableToolPanel* op } } +void ToolPanelCoordinator::updateToolLocations(const std::vector &favorites) +{ + const int fav_page_num = toolPanelNotebook->page_num(*favoritePanelSW); + + // Add or remove favorites tab if necessary. + if (favorites.empty() && fav_page_num != -1) { + toolPanelNotebook->remove_page(fav_page_num); + } else if (!favorites.empty() && fav_page_num == -1) { + toolPanelNotebook->prepend_page(*favoritePanelSW, *toiF); + } + + // Update favorite tool panels list. + favoritesToolPanels.clear(); + for (const auto &favorite_name : favorites) { + favoritesToolPanels.push_back( + getFoldableToolPanel(getToolFromName(favorite_name))); + } + + int cur_page_num = toolPanelNotebook->get_current_page(); + Gtk::Widget *const cur_page = toolPanelNotebook->get_nth_page(cur_page_num); + + updatePanelTools(cur_page, favorites); +} + bool ToolPanelCoordinator::handleShortcutKey(GdkEventKey* event) { @@ -1376,7 +1652,7 @@ bool ToolPanelCoordinator::handleShortcutKey(GdkEventKey* event) if (alt) { switch (event->keyval) { case GDK_KEY_u: - if (favoritePanelSW) { + if (toolPanelNotebook->page_num(*favoritePanelSW) >= 0) { toolPanelNotebook->set_current_page (toolPanelNotebook->page_num (*favoritePanelSW)); } return true; @@ -1422,9 +1698,7 @@ void ToolPanelCoordinator::updateVScrollbars(bool hide) { GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected Gtk::PolicyType policy = hide ? Gtk::POLICY_NEVER : Gtk::POLICY_AUTOMATIC; - if (favoritePanelSW) { - favoritePanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy); - } + favoritePanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy); exposurePanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy); detailsPanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy); colorPanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy); @@ -1456,7 +1730,7 @@ void ToolPanelCoordinator::toolSelected(ToolMode tool) notebookconn.block(true); // "signal_switch_page" event is blocked to avoid unsubscribing Locallab (allows a correct behavior when switching to another tool using toolbar) auto checkFavorite = [this](FoldableToolPanel* tool) { - for (auto fav : favorites) { + for (auto fav : favoritesToolPanels) { if (fav == tool) { return true; } @@ -1512,6 +1786,8 @@ void ToolPanelCoordinator::toolSelected(ToolMode tool) break; } + updateToolLocations(options.favorites); + notebookconn.block(false); } @@ -1541,3 +1817,127 @@ bool ToolPanelCoordinator::getFilmNegativeSpot(rtengine::Coord spot, int spotSiz { return ipc && ipc->getFilmNegativeSpot(spot.x, spot.y, spotSize, refInput, refOutput); } + +FoldableToolPanel *ToolPanelCoordinator::getFoldableToolPanel(Tool tool) const +{ + switch (tool) { + case Tool::TONE_CURVE: + return toneCurve; + case Tool::SHADOWS_HIGHLIGHTS: + return shadowshighlights; + case Tool::IMPULSE_DENOISE: + return impulsedenoise; + case Tool::DEFRINGE_TOOL: + return defringe; + case Tool::SPOT: + return spot; + case Tool::DIR_PYR_DENOISE: + return dirpyrdenoise; + case Tool::EPD: + return epd; + case Tool::SHARPENING_TOOL: + return sharpening; + case Tool::LOCAL_CONTRAST: + return localContrast; + case Tool::SHARPEN_EDGE: + return sharpenEdge; + case Tool::SHARPEN_MICRO: + return sharpenMicro; + case Tool::L_CURVE: + return lcurve; + case Tool::RGB_CURVES: + return rgbcurves; + case Tool::COLOR_TONING: + return colortoning; + case Tool::LENS_GEOM: + return lensgeom; + case Tool::LENS_PROF: + return lensProf; + case Tool::DISTORTION: + return distortion; + case Tool::ROTATE: + return rotate; + case Tool::VIBRANCE: + return vibrance; + case Tool::COLOR_APPEARANCE: + return colorappearance; + case Tool::WHITE_BALANCE: + return whitebalance; + case Tool::VIGNETTING: + return vignetting; + case Tool::RETINEX_TOOL: + return retinex; + case Tool::GRADIENT: + return gradient; + case Tool::LOCALLAB: + return locallab; + case Tool::PC_VIGNETTE: + return pcvignette; + case Tool::PERSPECTIVE: + return perspective; + case Tool::CA_CORRECTION: + return cacorrection; + case Tool::CH_MIXER: + return chmixer; + case Tool::BLACK_WHITE: + return blackwhite; + case Tool::RESIZE_TOOL: + return resize; + case Tool::PR_SHARPENING: + return prsharpening; + case Tool::CROP_TOOL: + return crop; + case Tool::ICM: + return icm; + case Tool::WAVELET: + return wavelet; + case Tool::DIR_PYR_EQUALIZER: + return dirpyrequalizer; + case Tool::HSV_EQUALIZER: + return hsvequalizer; + case Tool::FILM_SIMULATION: + return filmSimulation; + case Tool::SOFT_LIGHT: + return softlight; + case Tool::DEHAZE: + return dehaze; + case Tool::SENSOR_BAYER: + return sensorbayer; + case Tool::SENSOR_XTRANS: + return sensorxtrans; + case Tool::BAYER_PROCESS: + return bayerprocess; + case Tool::XTRANS_PROCESS: + return xtransprocess; + case Tool::BAYER_PREPROCESS: + return bayerpreprocess; + case Tool::PREPROCESS: + return preprocess; + case Tool::DARKFRAME_TOOL: + return darkframe; + case Tool::FLATFIELD_TOOL: + return flatfield; + case Tool::RAW_CA_CORRECTION: + return rawcacorrection; + case Tool::RAW_EXPOSURE: + return rawexposure; + case Tool::PREPROCESS_WB: + return preprocessWB; + case Tool::BAYER_RAW_EXPOSURE: + return bayerrawexposure; + case Tool::XTRANS_RAW_EXPOSURE: + return xtransrawexposure; + case Tool::FATTAL: + return fattal; + case Tool::FILM_NEGATIVE: + return filmNegative; + case Tool::PD_SHARPENING: + return pdSharpening; + }; + return nullptr; +} + +FoldableToolPanel *ToolPanelCoordinator::getFoldableToolPanel(const ToolTree &toolTree) const +{ + return getFoldableToolPanel(toolTree.id); +} diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 94e5a8717..3182d3e16 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -18,6 +18,7 @@ */ #pragma once +#include #include #include @@ -169,11 +170,13 @@ protected: FilmNegative* filmNegative; PdSharpening* pdSharpening; std::vector paramcListeners; + std::unordered_map + expanderToToolPanelMap; rtengine::StagedImageProcessor* ipc; std::vector toolPanels; - std::vector favorites; + std::vector favoritesToolPanels; ToolVBox* favoritePanel; ToolVBox* exposurePanel; ToolVBox* detailsPanel; @@ -184,7 +187,7 @@ protected: ToolVBox* locallabPanel; ToolBar* toolBar; - TextOrIcon* toiF; + std::unique_ptr toiF; TextOrIcon* toiE; TextOrIcon* toiD; TextOrIcon* toiC; @@ -197,7 +200,7 @@ protected: Gtk::Image* imgPanelEnd[8]; Gtk::Box* vbPanelEnd[8]; - Gtk::ScrolledWindow* favoritePanelSW; + std::unique_ptr favoritePanelSW; Gtk::ScrolledWindow* exposurePanelSW; Gtk::ScrolledWindow* detailsPanelSW; Gtk::ScrolledWindow* colorPanelSW; @@ -215,6 +218,8 @@ protected: void updateVScrollbars(bool hide); void addfavoritePanel (Gtk::Box* where, FoldableToolPanel* panel, int level = 1); void notebookPageChanged(Gtk::Widget* page, guint page_num); + void updatePanelTools( + Gtk::Widget *page, const std::vector &favorites); private: EditDataProvider *editDataProvider; @@ -307,6 +312,20 @@ public: ~ToolPanelCoordinator () override; static const ToolLayout& getDefaultToolLayout(); + /** + * Gets the tool with the provided tool name. + * + * @param name The tool name as a raw string. + * @return The tool. + */ + static Tool getToolFromName(const std::string &name); + /** + * Gets the tool name for the tool's ToolPanel as a string. + * + * @param tool The name as a raw string, or an empty string if the tool is + * unknown. + */ + static std::string getToolName(Tool tool); static bool isFavoritable(Tool tool); bool getChangedState() @@ -326,6 +345,7 @@ public: const LUTu& histLRETI ); void foldAllButOne(Gtk::Box* parent, FoldableToolPanel* openedSection); + void updateToolLocations(const std::vector &favorites); // multiple listeners can be added that are notified on changes (typical: profile panel and the history) void addPParamsChangeListener(PParamsChangeListener* pp) @@ -433,6 +453,23 @@ public: void setEditProvider(EditDataProvider *provider); +protected: + static std::unordered_map toolNamesReverseMap; + + std::unordered_map + toolToDefaultToolTreeMap; + + FoldableToolPanel *getFoldableToolPanel(Tool tool) const; + FoldableToolPanel *getFoldableToolPanel(const ToolTree &tool) const; + void updateFavoritesPanel(const std::vector &favorites); + template + typename std::enable_if::value, void>::type + updateToolPanel( + Gtk::Box *panelBox, + const std::vector &children, + int level, + std::unordered_set favorites); + private: IdleRegister idle_register; }; From acda4da22633983b9c72b1fdb046f3aecb87cdd8 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 5 Dec 2021 18:07:10 -0800 Subject: [PATCH 11/24] Fix favorites panel not being added Favorites panel would not show after adding tools to the favorites panel if the program started with no favorites. --- rtgui/toolpanelcoord.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 1b81fb014..985fb5461 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -421,6 +421,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit favoritePanelSW->add(*favoritePanelContainer); favoritePanelContainer->pack_start(*favoritePanel, Gtk::PACK_SHRINK, 0); favoritePanelContainer->pack_start(*vbPanelEnd[0], Gtk::PACK_SHRINK, 4); + favoritePanelSW->show_all(); exposurePanelSW->add (*exposurePanelContainer); exposurePanelContainer->pack_start(*exposurePanel, Gtk::PACK_SHRINK, 0); @@ -460,6 +461,10 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit toiT = Gtk::manage (new TextOrIcon ("transform.png", M ("MAIN_TAB_TRANSFORM"), M ("MAIN_TAB_TRANSFORM_TOOLTIP"))); toiR = Gtk::manage (new TextOrIcon ("bayer.png", M ("MAIN_TAB_RAW"), M ("MAIN_TAB_RAW_TOOLTIP"))); toiM = Gtk::manage (new TextOrIcon ("metadata.png", M ("MAIN_TAB_METADATA"), M ("MAIN_TAB_METADATA_TOOLTIP"))); + toiF->show_all(); + if (options.favorites.size()) { + toolPanelNotebook->append_page(*favoritePanelSW, *toiF); + } toolPanelNotebook->append_page (*exposurePanelSW, *toiE); toolPanelNotebook->append_page (*detailsPanelSW, *toiD); toolPanelNotebook->append_page (*colorPanelSW, *toiC); From f8a1deb371737971d61e494a23b5d37708517564 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Thu, 9 Dec 2021 21:27:39 -0800 Subject: [PATCH 12/24] Add option to clone favorite tools If cloning is enabled, favorite tools will appear in the favorites panel and in the original location. --- rtdata/languages/default | 1 + rtgui/editorpanel.cc | 4 ++-- rtgui/editorpanel.h | 3 ++- rtgui/options.cc | 6 ++++++ rtgui/options.h | 1 + rtgui/preferences.cc | 6 ++++-- rtgui/rtwindow.cc | 4 ++-- rtgui/rtwindow.h | 3 ++- rtgui/toollocationpref.cc | 16 ++++++++++++++++ rtgui/toolpanelcoord.cc | 39 ++++++++++++++++++++++++--------------- rtgui/toolpanelcoord.h | 13 +++++++++---- 11 files changed, 69 insertions(+), 27 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 525fa2d09..bd65781a8 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1901,6 +1901,7 @@ PREFERENCES_THUMBNAIL_INSPECTOR_MODE;Image to show PREFERENCES_THUMBNAIL_INSPECTOR_RAW;Neutral raw rendering PREFERENCES_THUMBNAIL_INSPECTOR_RAW_IF_NO_JPEG_FULLSIZE;Embedded JPEG if fullsize, neutral raw otherwise PREFERENCES_TOOLPANEL_AVAILABLETOOLS;Available Tools +PREFERENCES_TOOLPANEL_CLONE_FAVORITES;Keep favorite tools in original locations PREFERENCES_TOOLPANEL_FAVORITE;Favorite PREFERENCES_TOOLPANEL_FAVORITESPANEL;Favorites Panel PREFERENCES_TOOLPANEL_TOOL;Tool diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 888fc9518..64fa50a6a 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -2487,10 +2487,10 @@ void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition) } void EditorPanel::updateToolPanelToolLocations( - const std::vector &favorites) + const std::vector &favorites, bool cloneFavoriteTools) { if (tpc) { - tpc->updateToolLocations(favorites); + tpc->updateToolLocations(favorites, cloneFavoriteTools); } } diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 0ffe44ace..bb0ecbc89 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -185,7 +185,8 @@ public: void updateProfiles (const Glib::ustring &printerProfile, rtengine::RenderingIntent printerIntent, bool printerBPC); void updateTPVScrollbar (bool hide); void updateHistogramPosition (int oldPosition, int newPosition); - void updateToolPanelToolLocations(const std::vector &favorites); + void updateToolPanelToolLocations( + const std::vector &favorites, bool cloneFavoriteTools); void defaultMonitorProfileChanged (const Glib::ustring &profile_name, bool auto_monitor_profile); diff --git a/rtgui/options.cc b/rtgui/options.cc index 70b0fa010..b5463949a 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -424,6 +424,7 @@ void Options::setDefaults() //crvOpen.clear (); parseExtensions.clear(); favorites.clear(); + cloneFavoriteTools = true; parseExtensionsEnabled.clear(); parsedExtensions.clear(); parsedExtensionsSet.clear(); @@ -1220,6 +1221,10 @@ void Options::readFromFile(Glib::ustring fname) favorites = keyFile.get_string_list("GUI", "Favorites"); } + if (keyFile.has_key("GUI", "FavoritesCloneTools")) { + cloneFavoriteTools = keyFile.get_boolean("GUI", "FavoritesCloneTools"); + } + if (keyFile.has_key("GUI", "WindowWidth")) { windowWidth = keyFile.get_integer("GUI", "WindowWidth"); } @@ -2261,6 +2266,7 @@ void Options::saveToFile(Glib::ustring fname) Glib::ArrayHandle ahfavorites = favorites; keyFile.set_string_list("GUI", "Favorites", ahfavorites); + keyFile.set_boolean("GUI", "FavoritesCloneTools", cloneFavoriteTools); keyFile.set_integer("GUI", "WindowWidth", windowWidth); keyFile.set_integer("GUI", "WindowHeight", windowHeight); keyFile.set_integer("GUI", "WindowX", windowX); diff --git a/rtgui/options.h b/rtgui/options.h index bc5e41c91..6f21d1d76 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -428,6 +428,7 @@ public: bool fastexport_use_fast_pipeline; std::vector favorites; + bool cloneFavoriteTools; // Dialog settings Glib::ustring lastIccDir; Glib::ustring lastDarkframeDir; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index e67d16015..493f84f5a 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -2572,8 +2572,10 @@ void Preferences::workflowUpdate() parent->updateProfiles (moptions.rtSettings.printerProfile, rtengine::RenderingIntent(moptions.rtSettings.printerIntent), moptions.rtSettings.printerBPC); } - if (moptions.favorites != options.favorites) { - parent->updateToolPanelToolLocations(moptions.favorites); + if (moptions.cloneFavoriteTools != options.cloneFavoriteTools || + moptions.favorites != options.favorites) { + parent->updateToolPanelToolLocations( + moptions.favorites, moptions.cloneFavoriteTools); } } diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index 15715a2fd..f3eb658e5 100755 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -1111,10 +1111,10 @@ void RTWindow::updateHistogramPosition (int oldPosition, int newPosition) } void RTWindow::updateToolPanelToolLocations( - const std::vector &favorites) + const std::vector &favorites, bool cloneFavoriteTools) { if (epanel) { - epanel->updateToolPanelToolLocations(favorites); + epanel->updateToolPanelToolLocations(favorites, cloneFavoriteTools); } } diff --git a/rtgui/rtwindow.h b/rtgui/rtwindow.h index d35755185..0ef5abb1f 100755 --- a/rtgui/rtwindow.h +++ b/rtgui/rtwindow.h @@ -124,7 +124,8 @@ public: void updateFBQueryTB (bool singleRow); void updateFBToolBarVisibility (bool showFilmStripToolBar); void updateShowtooltipVisibility (bool showtooltip); - void updateToolPanelToolLocations(const std::vector &favorites); + void updateToolPanelToolLocations( + const std::vector &favorites, bool cloneFavoriteTools); bool getIsFullscreen() { return is_fullscreen; diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index 561be4601..849ff29b6 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -423,6 +423,9 @@ struct ToolLocationPreference::Impl { Options &options; + // General options. + Gtk::CheckButton *cloneFavoriteToolsToggleWidget; + // Tool list. ToolListColumns toolListColumns; Glib::RefPtr toolListModelPtr; @@ -506,6 +509,10 @@ std::unordered_map ToolLocationPreference::Impl::Impl(Options &options) : options(options), + // General options. + cloneFavoriteToolsToggleWidget(Gtk::manage( + new Gtk::CheckButton(M("PREFERENCES_TOOLPANEL_CLONE_FAVORITES")))), + // Tool list. toolListModelPtr(Gtk::TreeStore::create(toolListColumns)), toolListViewColumnFavorite( @@ -523,6 +530,9 @@ ToolLocationPreference::Impl::Impl(Options &options) : { const std::vector favorites = toolNamesToTools(options.favorites); + // General options. + cloneFavoriteToolsToggleWidget->set_active(options.cloneFavoriteTools); + // Tool list. toolListViewPtr->append_column(toolListViewColumnToolName); toolListViewColumnToolName.pack_start(toolListCellRendererToolName); @@ -686,6 +696,8 @@ std::vector ToolLocationPreference::Impl::toolNamesToTools( void ToolLocationPreference::Impl::updateOptions() { + options.cloneFavoriteTools = cloneFavoriteToolsToggleWidget->get_active(); + const auto favorites_rows = favoritesModelPtr->children(); options.favorites.resize(favorites_rows.size()); for (unsigned i = 0; i < favorites_rows.size(); i++) { @@ -729,6 +741,10 @@ ToolLocationPreference::ToolLocationPreference(Options &options) : favorites_list_scrolled_window->add(*impl->favoritesViewPtr); setExpandAlignProperties( favorites_frame, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL); + + // General options. + layout_grid->attach_next_to( + *impl->cloneFavoriteToolsToggleWidget, Gtk::PositionType::POS_BOTTOM, 2, 1); } void ToolLocationPreference::updateOptions() diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 985fb5461..4991e68d8 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -481,7 +481,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit toolPanelNotebook->set_scrollable(); toolPanelNotebook->show_all(); - updateToolLocations(options.favorites); + updateToolLocations(options.favorites, options.cloneFavoriteTools); notebookconn = toolPanelNotebook->signal_switch_page().connect( sigc::mem_fun(*this, &ToolPanelCoordinator::notebookPageChanged)); @@ -681,7 +681,7 @@ bool ToolPanelCoordinator::isFavoritable(Tool tool) void ToolPanelCoordinator::notebookPageChanged(Gtk::Widget* page, guint page_num) { - updatePanelTools(page, options.favorites); + updatePanelTools(page, options.favorites, options.cloneFavoriteTools); // Locallab spot curves are set visible if at least one photo has been loaded (to avoid // segfault) and locallab panel is active @@ -701,7 +701,8 @@ void ToolPanelCoordinator::notebookPageChanged(Gtk::Widget* page, guint page_num } void ToolPanelCoordinator::updateFavoritesPanel( - const std::vector &favoritesNames) + const std::vector &favoritesNames, + bool cloneFavoriteTools) { std::unordered_set favorites_set; std::vector> favorites_tool_tree; @@ -713,14 +714,17 @@ void ToolPanelCoordinator::updateFavoritesPanel( std::ref(*(toolToDefaultToolTreeMap.at(tool)))); } - updateToolPanel(favoritePanel, favorites_tool_tree, 1, favorites_set); + updateToolPanel( + favoritePanel, favorites_tool_tree, 1, favorites_set, cloneFavoriteTools); } void ToolPanelCoordinator::updatePanelTools( - Gtk::Widget *page, const std::vector &favorites) + Gtk::Widget *page, + const std::vector &favorites, + bool cloneFavoriteTools) { if (page == favoritePanelSW.get()) { - updateFavoritesPanel(favorites); + updateFavoritesPanel(favorites, cloneFavoriteTools); return; } @@ -757,7 +761,7 @@ void ToolPanelCoordinator::updatePanelTools( favoriteTools.insert(getToolFromName(tool_name.raw())); } - updateToolPanel(panel, *default_panel_tools, 1, favoriteTools); + updateToolPanel(panel, *default_panel_tools, 1, favoriteTools, cloneFavoriteTools); } template @@ -766,18 +770,21 @@ ToolPanelCoordinator::updateToolPanel( Gtk::Box *panelBox, const std::vector &children, int level, - std::unordered_set favorites) + std::unordered_set favorites, + bool cloneFavoriteTools) { const bool is_favorite_panel = panelBox == favoritePanel; + const bool skip_favorites = !cloneFavoriteTools && !is_favorite_panel; const std::vector old_tool_panels = panelBox->get_children(); auto old_widgets_iter = old_tool_panels.begin(); auto new_tool_trees_iter = children.begin(); // Indicates if this tool should not be added. Favorite tools are skipped - // unless the parent panel box is the favorites panel. + // if they are sub-tools within the favorites panel, or if tool cloning is + // off and they are not within the favorites panel. const auto should_skip_tool = - [is_favorite_panel, &favorites](const ToolTree &tool_tree) { - return !is_favorite_panel && favorites.count(tool_tree.id); + [skip_favorites, &favorites](const ToolTree &tool_tree) { + return skip_favorites && favorites.count(tool_tree.id); }; // Keep tools that are already correct. @@ -824,7 +831,8 @@ ToolPanelCoordinator::updateToolPanel( tool_panel->getSubToolsContainer(), tool_tree.children, level + 1, - favorites); + favorites, + cloneFavoriteTools && !is_favorite_panel); } } @@ -1623,7 +1631,8 @@ void ToolPanelCoordinator::foldAllButOne(Gtk::Box* parent, FoldableToolPanel* op } } -void ToolPanelCoordinator::updateToolLocations(const std::vector &favorites) +void ToolPanelCoordinator::updateToolLocations( + const std::vector &favorites, bool cloneFavoriteTools) { const int fav_page_num = toolPanelNotebook->page_num(*favoritePanelSW); @@ -1644,7 +1653,7 @@ void ToolPanelCoordinator::updateToolLocations(const std::vector int cur_page_num = toolPanelNotebook->get_current_page(); Gtk::Widget *const cur_page = toolPanelNotebook->get_nth_page(cur_page_num); - updatePanelTools(cur_page, favorites); + updatePanelTools(cur_page, favorites, cloneFavoriteTools); } bool ToolPanelCoordinator::handleShortcutKey(GdkEventKey* event) @@ -1791,7 +1800,7 @@ void ToolPanelCoordinator::toolSelected(ToolMode tool) break; } - updateToolLocations(options.favorites); + updateToolLocations(options.favorites, options.cloneFavoriteTools); notebookconn.block(false); } diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 3182d3e16..8c0f6beaf 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -219,7 +219,9 @@ protected: void addfavoritePanel (Gtk::Box* where, FoldableToolPanel* panel, int level = 1); void notebookPageChanged(Gtk::Widget* page, guint page_num); void updatePanelTools( - Gtk::Widget *page, const std::vector &favorites); + Gtk::Widget *page, + const std::vector &favorites, + bool cloneFavoriteTools); private: EditDataProvider *editDataProvider; @@ -345,7 +347,8 @@ public: const LUTu& histLRETI ); void foldAllButOne(Gtk::Box* parent, FoldableToolPanel* openedSection); - void updateToolLocations(const std::vector &favorites); + void updateToolLocations( + const std::vector &favorites, bool cloneFavoriteTools); // multiple listeners can be added that are notified on changes (typical: profile panel and the history) void addPParamsChangeListener(PParamsChangeListener* pp) @@ -461,14 +464,16 @@ protected: FoldableToolPanel *getFoldableToolPanel(Tool tool) const; FoldableToolPanel *getFoldableToolPanel(const ToolTree &tool) const; - void updateFavoritesPanel(const std::vector &favorites); + void updateFavoritesPanel( + const std::vector &favorites, bool cloneFavoriteTools); template typename std::enable_if::value, void>::type updateToolPanel( Gtk::Box *panelBox, const std::vector &children, int level, - std::unordered_set favorites); + std::unordered_set favorites, + bool cloneFavoriteTools); private: IdleRegister idle_register; From 80944d6c9b83f242a0d7f113ab08e073d6a7e03f Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Fri, 10 Dec 2021 22:24:18 -0800 Subject: [PATCH 13/24] Change look of favorites preferences Set column widths based on DPI and font size in pseudo-HiDPI mode. Move favorites buttons to left side of list. --- rtgui/toollocationpref.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index 849ff29b6..d4021f03b 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -22,6 +22,7 @@ #include "guiutils.h" #include "options.h" #include "rtimage.h" +#include "rtscalable.h" #include "toollocationpref.h" #include "toolpanelcoord.h" @@ -720,7 +721,8 @@ ToolLocationPreference::ToolLocationPreference(Options &options) : M("PREFERENCES_TOOLPANEL_AVAILABLETOOLS"))); Gtk::ScrolledWindow *tool_list_scrolled_window = Gtk::manage(new Gtk::ScrolledWindow()); - tool_list_scrolled_window->set_min_content_width(550); + tool_list_scrolled_window->set_min_content_width( + 400 * (RTScalable::getTweakedDPI() / RTScalable::baseDPI)); layout_grid->attach_next_to(*tool_list_frame, Gtk::PositionType::POS_RIGHT, 1, 1); tool_list_frame->add(*tool_list_scrolled_window); tool_list_scrolled_window->add(*impl->toolListViewPtr); @@ -733,10 +735,11 @@ ToolLocationPreference::ToolLocationPreference(Options &options) : Gtk::Box *favorites_box = Gtk::manage(new Gtk::Box()); Gtk::ScrolledWindow *favorites_list_scrolled_window = Gtk::manage(new Gtk::ScrolledWindow()); - favorites_list_scrolled_window->set_min_content_width(400); + favorites_list_scrolled_window->set_min_content_width( + 300 * (RTScalable::getTweakedDPI() / RTScalable::baseDPI)); layout_grid->attach_next_to(*favorites_frame, Gtk::PositionType::POS_RIGHT, 1, 1); - favorites_box->pack_start(*favorites_list_scrolled_window, false, false); favorites_box->pack_start(impl->favoritesListEditButtons, false, false); + favorites_box->pack_start(*favorites_list_scrolled_window, false, false); favorites_frame->add(*favorites_box); favorites_list_scrolled_window->add(*impl->favoritesViewPtr); setExpandAlignProperties( From 546c99d276b3855c293d2d4638b91a2c500af3bb Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sat, 11 Dec 2021 15:35:52 -0800 Subject: [PATCH 14/24] Clean up favorites preferences code --- rtgui/toollocationpref.cc | 54 +++++++++++++++++---------------- rtgui/toolpanelcoord.cc | 64 ++++++++++++++++++++++++++++++++------- rtgui/toolpanelcoord.h | 7 +++-- 3 files changed, 85 insertions(+), 40 deletions(-) diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index d4021f03b..f489c4f63 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -199,7 +199,7 @@ private: Gtk::Button buttonDown; Gtk::Button buttonRemove; - sigc::signal> signalRowsPreErase; + sigc::signal &> signalRowsPreErase; void onButtonDownPressed(); void onButtonRemovePressed(); @@ -224,7 +224,7 @@ public: * The signal contains a vector of tree model paths of the rows that will be * erased. */ - sigc::signal> getSignalRowsPreErase(); + sigc::signal &> getSignalRowsPreErase() const; }; /** @@ -319,7 +319,7 @@ void ListEditButtons::onButtonDownPressed() } // Get the selected row and next row. - auto selected_row_iter = listStore->get_iter(selected[0]); + const auto selected_row_iter = listStore->get_iter(selected[0]); auto next_row_iter = selected_row_iter; next_row_iter++; @@ -336,17 +336,21 @@ void ListEditButtons::onButtonRemovePressed() { const std::vector selected_paths = list.get_selection()->get_selected_rows(); - std::vector selected; + std::vector selected(selected_paths.size()); // Get row references, which are valid until the row is removed. - for (const auto & row_path : selected_paths) { - selected.push_back(Gtk::TreeModel::RowReference(listStore, row_path)); - } + std::transform( + selected_paths.begin(), + selected_paths.end(), + selected.begin(), + [this](const Gtk::TreeModel::Path &row_path) { + return Gtk::TreeModel::RowReference(listStore, row_path); + }); signalRowsPreErase.emit(selected_paths); // Remove the selected rows. - for (const auto & row_ref : selected) { + for (const auto &row_ref : selected) { const auto row_path = row_ref.get_path(); if (row_path) { listStore->erase(listStore->get_iter(row_path)); @@ -368,7 +372,7 @@ void ListEditButtons::onButtonUpPressed() return; } - auto selected_row_iter = listStore->get_iter(selected[0]); + const auto selected_row_iter = listStore->get_iter(selected[0]); if (selected_row_iter == list_children.begin()) { // Can't be first row. return; @@ -411,8 +415,8 @@ void ListEditButtons::updateButtonSensitivity() buttonRemove.set_sensitive(selected.size() > 0); } -sigc::signal> -ListEditButtons::getSignalRowsPreErase() +sigc::signal &> +ListEditButtons::getSignalRowsPreErase() const { return signalRowsPreErase; } @@ -420,8 +424,6 @@ ListEditButtons::getSignalRowsPreErase() } struct ToolLocationPreference::Impl { - static std::unordered_map toolNamesReverseMap; - Options &options; // General options. @@ -488,7 +490,7 @@ struct ToolLocationPreference::Impl { * @param paths Paths in the favorites list pointing to the rows that are * about to be removed. */ - void onFavoritesRowsPreRemove(const std::vector paths); + void onFavoritesRowsPreRemove(const std::vector &paths); /** * Converts tool names to their corresponding tools. * @@ -504,9 +506,6 @@ struct ToolLocationPreference::Impl { void updateOptions(); }; -std::unordered_map - ToolLocationPreference::Impl::toolNamesReverseMap; - ToolLocationPreference::Impl::Impl(Options &options) : options(options), @@ -577,7 +576,7 @@ void ToolLocationPreference::Impl::favoriteToggled(const Glib::ustring &row_path // Update the favorites list. if (is_favorite) { // Add to favorites list. - auto new_favorite_row_iter = favoritesModelPtr->append(); + const auto new_favorite_row_iter = favoritesModelPtr->append(); new_favorite_row_iter->set_value( favoritesColumns.toolName, M(getToolTitleKey(tool))); @@ -602,7 +601,7 @@ void ToolLocationPreference::Impl::initFavoritesRows( { // Add the favorites to the favorites list store. for (const auto tool : favorites) { - auto favorite_row_iter = favoritesModelPtr->append(); + const auto favorite_row_iter = favoritesModelPtr->append(); favorite_row_iter->set_value( favoritesColumns.toolName, M(getToolTitleKey(tool))); @@ -617,7 +616,8 @@ void ToolLocationPreference::Impl::addToolListRowGroup( { // Recursively add the tool and its children to the tool list tree store. for (const ToolPanelCoordinator::ToolTree &tool : tools) { - auto tool_row_iter = toolListModelPtr->append(parentRowIter->children()); + const auto tool_row_iter = + toolListModelPtr->append(parentRowIter->children()); tool_row_iter->set_value( toolListColumns.toolName, M(getToolTitleKey(tool.id))); @@ -653,7 +653,7 @@ void ToolLocationPreference::Impl::initToolListRows(const std::vector &fav ToolPanelCoordinator::Panel::TRANSFORM_PANEL, ToolPanelCoordinator::Panel::RAW, }) { - auto tool_group_iter = toolListModelPtr->append(); + const auto tool_group_iter = toolListModelPtr->append(); tool_group_iter->set_value( toolListColumns.toolName, M(getToolPanelTitleKey(panel))); @@ -662,7 +662,7 @@ void ToolLocationPreference::Impl::initToolListRows(const std::vector &fav } void ToolLocationPreference::Impl::onFavoritesRowsPreRemove( - const std::vector paths) + const std::vector &paths) { // Unset the favorite column in the tools list for tools about to be removed // from the favorites list. @@ -678,13 +678,15 @@ std::vector ToolLocationPreference::Impl::toolNamesToTools( { std::vector tool_set; - for (auto &&tool_name : tool_names) { + for (const auto &tool_name : tool_names) { Tool tool; try { tool = ToolPanelCoordinator::getToolFromName(tool_name); - } catch (const std::exception &e) { + } catch (const std::out_of_range &e) { if (rtengine::settings->verbose) { - std::cerr << "Unrecognized tool name \"" << tool_name << "\"." << std::endl; + std::cerr + << "Unrecognized tool name \"" << tool_name << "\"." + << std::endl; } assert(false); continue; @@ -701,7 +703,7 @@ void ToolLocationPreference::Impl::updateOptions() const auto favorites_rows = favoritesModelPtr->children(); options.favorites.resize(favorites_rows.size()); - for (unsigned i = 0; i < favorites_rows.size(); i++) { + for (Gtk::TreeNodeChildren::size_type i = 0; i < favorites_rows.size(); i++) { const Tool tool = favorites_rows[i].get_value(favoritesColumns.tool); options.favorites[i] = ToolPanelCoordinator::getToolName(tool); } diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 4991e68d8..f89c76b8d 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -16,6 +16,8 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include + #include "multilangmgr.h" #include "toolpanelcoord.h" #include "metadatapanel.h" @@ -350,12 +352,14 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit for (const auto &panel_tool_layout : getDefaultToolLayout()) { const auto &panel_tools = panel_tool_layout.second; - std::vector unprocessed_tools; + std::vector unprocessed_tools(panel_tools.size()); // Start with the root tools for every panel. - for (const auto &tool_tree : panel_tools) { - unprocessed_tools.push_back(&tool_tree); - } + std::transform( + panel_tools.begin(), + panel_tools.end(), + unprocessed_tools.begin(), + [](const ToolTree &tool_tree) { return &tool_tree; }); // Process each tool. while (!unprocessed_tools.empty()) { @@ -363,7 +367,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit const ToolTree *cur_tool = unprocessed_tools.back(); unprocessed_tools.pop_back(); // Add tool to list of expanders and tool panels. - FoldableToolPanel *tool_panel = getFoldableToolPanel(*cur_tool); + FoldableToolPanel *const tool_panel = getFoldableToolPanel(*cur_tool); expList.push_back(tool_panel->getExpander()); toolPanels.push_back(tool_panel); expanderToToolPanelMap[tool_panel->getExpander()] = tool_panel; @@ -514,7 +518,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit prevPage = toolPanelNotebook->get_nth_page(0); } -const ToolPanelCoordinator::ToolLayout& ToolPanelCoordinator::getDefaultToolLayout() +const ToolPanelCoordinator::ToolLayout &ToolPanelCoordinator::getDefaultToolLayout() { return PANEL_TOOLS; } @@ -708,10 +712,22 @@ void ToolPanelCoordinator::updateFavoritesPanel( std::vector> favorites_tool_tree; for (const auto &tool_name : favoritesNames) { - Tool tool = getToolFromName(tool_name.raw()); + Tool tool; + try { + tool = getToolFromName(tool_name.raw()); + } catch (const std::out_of_range &e) { + if (rtengine::settings->verbose) { + std::cerr + << "Unrecognized favorite tool \"" << tool_name << "\"" + << std::endl; + } + continue; + } + if (isFavoritable(tool)) { favorites_set.insert(tool); favorites_tool_tree.push_back( std::ref(*(toolToDefaultToolTreeMap.at(tool)))); + } } updateToolPanel( @@ -758,7 +774,20 @@ void ToolPanelCoordinator::updatePanelTools( std::unordered_set favoriteTools; for (const auto &tool_name : favorites) { - favoriteTools.insert(getToolFromName(tool_name.raw())); + Tool tool; + try { + tool = getToolFromName(tool_name.raw()); + } catch (const std::out_of_range &e) { + if (rtengine::settings->verbose) { + std::cerr + << "Unrecognized favorite tool \"" << tool_name << "\"" + << std::endl; + } + continue; + } + if (isFavoritable(tool)) { + favoriteTools.insert(tool); + } } updateToolPanel(panel, *default_panel_tools, 1, favoriteTools, cloneFavoriteTools); @@ -770,7 +799,7 @@ ToolPanelCoordinator::updateToolPanel( Gtk::Box *panelBox, const std::vector &children, int level, - std::unordered_set favorites, + const std::unordered_set &favorites, bool cloneFavoriteTools) { const bool is_favorite_panel = panelBox == favoritePanel; @@ -1646,8 +1675,20 @@ void ToolPanelCoordinator::updateToolLocations( // Update favorite tool panels list. favoritesToolPanels.clear(); for (const auto &favorite_name : favorites) { - favoritesToolPanels.push_back( - getFoldableToolPanel(getToolFromName(favorite_name))); + Tool tool; + try { + tool = getToolFromName(favorite_name.raw()); + } catch (const std::out_of_range &e) { + if (rtengine::settings->verbose) { + std::cerr + << "Unrecognized favorite tool \"" << favorite_name << "\"" + << std::endl; + } + continue; + } + if (isFavoritable(tool)) { + favoritesToolPanels.push_back(getFoldableToolPanel(tool)); + } } int cur_page_num = toolPanelNotebook->get_current_page(); @@ -1948,6 +1989,7 @@ FoldableToolPanel *ToolPanelCoordinator::getFoldableToolPanel(Tool tool) const case Tool::PD_SHARPENING: return pdSharpening; }; + assert(false); return nullptr; } diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 8c0f6beaf..cd354738e 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -305,7 +305,7 @@ public: std::vector children; }; - using ToolLayout = std::unordered_map, ScopedEnumHash>; + using ToolLayout = std::unordered_map &, ScopedEnumHash>; CoarsePanel* coarse; Gtk::Notebook* toolPanelNotebook; @@ -313,12 +313,13 @@ public: ToolPanelCoordinator(bool batch = false); ~ToolPanelCoordinator () override; - static const ToolLayout& getDefaultToolLayout(); + static const ToolLayout &getDefaultToolLayout(); /** * Gets the tool with the provided tool name. * * @param name The tool name as a raw string. * @return The tool. + * @throws std::out_of_range If the name is not recognized. */ static Tool getToolFromName(const std::string &name); /** @@ -472,7 +473,7 @@ protected: Gtk::Box *panelBox, const std::vector &children, int level, - std::unordered_set favorites, + const std::unordered_set &favorites, bool cloneFavoriteTools); private: From 40678f67b021de85db7c5d742fc7be2195912576 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sat, 11 Dec 2021 21:21:54 -0800 Subject: [PATCH 15/24] Refactor tool name code --- rtgui/bayerpreprocess.cc | 4 +- rtgui/bayerpreprocess.h | 1 + rtgui/bayerprocess.cc | 3 +- rtgui/bayerprocess.h | 1 + rtgui/bayerrawexposure.cc | 4 +- rtgui/bayerrawexposure.h | 2 + rtgui/blackwhite.cc | 3 +- rtgui/blackwhite.h | 1 + rtgui/cacorrection.cc | 4 +- rtgui/cacorrection.h | 1 + rtgui/chmixer.cc | 4 +- rtgui/chmixer.h | 1 + rtgui/colorappearance.cc | 4 +- rtgui/colorappearance.h | 2 + rtgui/colortoning.cc | 3 +- rtgui/colortoning.h | 2 + rtgui/crop.cc | 4 +- rtgui/crop.h | 2 + rtgui/darkframe.cc | 4 +- rtgui/darkframe.h | 1 + rtgui/defringe.cc | 4 +- rtgui/defringe.h | 1 + rtgui/dehaze.cc | 4 +- rtgui/dehaze.h | 1 + rtgui/dirpyrdenoise.cc | 4 +- rtgui/dirpyrdenoise.h | 2 + rtgui/dirpyrequalizer.cc | 4 +- rtgui/dirpyrequalizer.h | 1 + rtgui/distortion.cc | 4 +- rtgui/distortion.h | 1 + rtgui/epd.cc | 4 +- rtgui/epd.h | 1 + rtgui/fattaltonemap.cc | 4 +- rtgui/fattaltonemap.h | 1 + rtgui/filmnegative.cc | 4 +- rtgui/filmnegative.h | 2 + rtgui/filmsimulation.cc | 4 +- rtgui/filmsimulation.h | 2 + rtgui/flatfield.cc | 4 +- rtgui/flatfield.h | 1 + rtgui/gradient.cc | 4 +- rtgui/gradient.h | 1 + rtgui/hsvequalizer.cc | 4 +- rtgui/hsvequalizer.h | 1 + rtgui/icmpanel.cc | 4 +- rtgui/icmpanel.h | 2 + rtgui/impulsedenoise.cc | 4 +- rtgui/impulsedenoise.h | 1 + rtgui/labcurve.cc | 4 +- rtgui/labcurve.h | 1 + rtgui/lensgeom.cc | 4 +- rtgui/lensgeom.h | 1 + rtgui/lensprofile.cc | 4 +- rtgui/lensprofile.h | 2 + rtgui/localcontrast.cc | 4 +- rtgui/localcontrast.h | 1 + rtgui/locallab.cc | 4 +- rtgui/locallab.h | 2 + rtgui/pcvignette.cc | 4 +- rtgui/pcvignette.h | 1 + rtgui/pdsharpening.cc | 4 +- rtgui/pdsharpening.h | 1 + rtgui/perspective.cc | 4 +- rtgui/perspective.h | 1 + rtgui/preprocess.cc | 4 +- rtgui/preprocess.h | 1 + rtgui/preprocesswb.cc | 4 +- rtgui/preprocesswb.h | 1 + rtgui/prsharpening.cc | 4 +- rtgui/prsharpening.h | 1 + rtgui/rawcacorrection.cc | 4 +- rtgui/rawcacorrection.h | 1 + rtgui/rawexposure.cc | 4 +- rtgui/rawexposure.h | 1 + rtgui/resize.cc | 4 +- rtgui/resize.h | 2 + rtgui/retinex.cc | 4 +- rtgui/retinex.h | 2 + rtgui/rgbcurves.cc | 4 +- rtgui/rgbcurves.h | 1 + rtgui/rotate.cc | 4 +- rtgui/rotate.h | 1 + rtgui/sensorbayer.cc | 4 +- rtgui/sensorbayer.h | 1 + rtgui/sensorxtrans.cc | 4 +- rtgui/sensorxtrans.h | 1 + rtgui/shadowshighlights.cc | 4 +- rtgui/shadowshighlights.h | 1 + rtgui/sharpenedge.cc | 3 +- rtgui/sharpenedge.h | 1 + rtgui/sharpening.cc | 4 +- rtgui/sharpening.h | 1 + rtgui/sharpenmicro.cc | 3 +- rtgui/sharpenmicro.h | 1 + rtgui/softlight.cc | 4 +- rtgui/softlight.h | 1 + rtgui/spot.cc | 4 +- rtgui/spot.h | 1 + rtgui/tonecurve.cc | 4 +- rtgui/tonecurve.h | 2 + rtgui/toollocationpref.cc | 2 +- rtgui/toolpanelcoord.cc | 112 ++++++++++++++++++------------------- rtgui/vibrance.cc | 4 +- rtgui/vibrance.h | 1 + rtgui/vignetting.cc | 4 +- rtgui/vignetting.h | 1 + rtgui/wavelet.cc | 4 +- rtgui/wavelet.h | 2 + rtgui/whitebalance.cc | 4 +- rtgui/whitebalance.h | 1 + rtgui/xtransprocess.cc | 4 +- rtgui/xtransprocess.h | 1 + rtgui/xtransrawexposure.cc | 4 +- rtgui/xtransrawexposure.h | 1 + 114 files changed, 290 insertions(+), 113 deletions(-) diff --git a/rtgui/bayerpreprocess.cc b/rtgui/bayerpreprocess.cc index 793496b5f..e8b965736 100644 --- a/rtgui/bayerpreprocess.cc +++ b/rtgui/bayerpreprocess.cc @@ -28,7 +28,9 @@ using namespace rtengine; using namespace rtengine::procparams; -BayerPreProcess::BayerPreProcess() : FoldableToolPanel(this, "bayerpreprocess", M("TP_PREPROCESS_LABEL"), options.prevdemo != PD_Sidecar) +const Glib::ustring BayerPreProcess::TOOL_NAME = "bayerpreprocess"; + +BayerPreProcess::BayerPreProcess() : FoldableToolPanel(this, TOOL_NAME, M("TP_PREPROCESS_LABEL"), options.prevdemo != PD_Sidecar) { auto m = ProcEventMapper::getInstance(); EvLineDenoiseDirection = m->newEvent(DARKFRAME, "HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION"); diff --git a/rtgui/bayerpreprocess.h b/rtgui/bayerpreprocess.h index 16b469626..8b5f8d981 100644 --- a/rtgui/bayerpreprocess.h +++ b/rtgui/bayerpreprocess.h @@ -37,6 +37,7 @@ protected: rtengine::ProcEvent EvPDAFLinesFilter; public: + static const Glib::ustring TOOL_NAME; BayerPreProcess (); diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 4d1657a47..e7e038e52 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -28,9 +28,10 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring BayerProcess::TOOL_NAME = "bayerprocess"; BayerProcess::BayerProcess () : - FoldableToolPanel(this, "bayerprocess", M("TP_RAW_LABEL"), options.prevdemo != PD_Sidecar), + FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_LABEL"), options.prevdemo != PD_Sidecar), oldMethod(-1) { diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index b9c63e9b2..00a5c8aac 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -76,6 +76,7 @@ protected: rtengine::ProcEvent EvDemosaicPixelshiftDemosaicMethod; rtengine::ProcEvent EvPixelshiftAverage; public: + static const Glib::ustring TOOL_NAME; BayerProcess (); ~BayerProcess () override; diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc index 157abc2cf..834384a91 100644 --- a/rtgui/bayerrawexposure.cc +++ b/rtgui/bayerrawexposure.cc @@ -26,7 +26,9 @@ using namespace rtengine; using namespace rtengine::procparams; -BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, "bayerrawexposure", M("TP_EXPOS_BLACKPOINT_LABEL"), options.prevdemo != PD_Sidecar) +const Glib::ustring BayerRAWExposure::TOOL_NAME = "bayerrawexposure"; + +BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOS_BLACKPOINT_LABEL"), options.prevdemo != PD_Sidecar) { PexBlack1 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_1"), -2048, 2048, 1.0, 0)); //black level PexBlack1->setAdjusterListener (this); diff --git a/rtgui/bayerrawexposure.h b/rtgui/bayerrawexposure.h index eb18aa0e3..53c5817f8 100644 --- a/rtgui/bayerrawexposure.h +++ b/rtgui/bayerrawexposure.h @@ -31,6 +31,8 @@ class BayerRAWExposure final : public FoldableToolPanel { public: + static const Glib::ustring TOOL_NAME; + BayerRAWExposure (); void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc index e713f1450..c92e68896 100644 --- a/rtgui/blackwhite.cc +++ b/rtgui/blackwhite.cc @@ -34,8 +34,9 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring BlackWhite::TOOL_NAME = "blackwhite"; -BlackWhite::BlackWhite (): FoldableToolPanel(this, "blackwhite", M("TP_BWMIX_LABEL"), false, true) +BlackWhite::BlackWhite (): FoldableToolPanel(this, TOOL_NAME, M("TP_BWMIX_LABEL"), false, true) { CurveListener::setMulti(true); diff --git a/rtgui/blackwhite.h b/rtgui/blackwhite.h index 505d842db..fe41ccda0 100644 --- a/rtgui/blackwhite.h +++ b/rtgui/blackwhite.h @@ -40,6 +40,7 @@ class BlackWhite final : public ColorProvider { public: + static const Glib::ustring TOOL_NAME; BlackWhite (); ~BlackWhite () override; diff --git a/rtgui/cacorrection.cc b/rtgui/cacorrection.cc index 971c0a284..52ed782df 100644 --- a/rtgui/cacorrection.cc +++ b/rtgui/cacorrection.cc @@ -27,7 +27,9 @@ using namespace rtengine; using namespace rtengine::procparams; -CACorrection::CACorrection () : FoldableToolPanel(this, "cacorrection", M("TP_CACORRECTION_LABEL")) +const Glib::ustring CACorrection::TOOL_NAME = "cacorrection"; + +CACorrection::CACorrection () : FoldableToolPanel(this, TOOL_NAME, M("TP_CACORRECTION_LABEL")) { Gtk::Image* icaredL = Gtk::manage (new RTImage ("circle-red-cyan-small.png")); diff --git a/rtgui/cacorrection.h b/rtgui/cacorrection.h index 12d6396eb..7afccb4de 100644 --- a/rtgui/cacorrection.h +++ b/rtgui/cacorrection.h @@ -34,6 +34,7 @@ protected: Adjuster* blue; public: + static const Glib::ustring TOOL_NAME; CACorrection (); diff --git a/rtgui/chmixer.cc b/rtgui/chmixer.cc index 619d7be3e..e54ddfc5d 100644 --- a/rtgui/chmixer.cc +++ b/rtgui/chmixer.cc @@ -25,7 +25,9 @@ using namespace rtengine; using namespace rtengine::procparams; -ChMixer::ChMixer (): FoldableToolPanel(this, "chmixer", M("TP_CHMIXER_LABEL"), false, true) +const Glib::ustring ChMixer::TOOL_NAME = "chmixer"; + +ChMixer::ChMixer (): FoldableToolPanel(this, TOOL_NAME, M("TP_CHMIXER_LABEL"), false, true) { imgIcon[0] = Gtk::manage (new RTImage ("circle-red-small.png")); diff --git a/rtgui/chmixer.h b/rtgui/chmixer.h index d80b89cf7..831449c30 100644 --- a/rtgui/chmixer.h +++ b/rtgui/chmixer.h @@ -36,6 +36,7 @@ protected: Gtk::Image *imgIcon[9]; public: + static const Glib::ustring TOOL_NAME; ChMixer (); diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc index f579da6e6..6a3346f18 100644 --- a/rtgui/colorappearance.cc +++ b/rtgui/colorappearance.cc @@ -44,6 +44,8 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring ColorAppearance::TOOL_NAME = "colorappearance"; + static double wbSlider2Temp (double sval) { @@ -212,7 +214,7 @@ static double wbTemp2Slider (double temp) } -ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance", M ("TP_COLORAPP_LABEL"), false, true) +ColorAppearance::ColorAppearance () : FoldableToolPanel (this, TOOL_NAME, M ("TP_COLORAPP_LABEL"), false, true) { CurveListener::setMulti (true); std::vector milestones; diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h index ce1971e85..caa481c34 100644 --- a/rtgui/colorappearance.h +++ b/rtgui/colorappearance.h @@ -39,6 +39,8 @@ class ColorAppearance final : public ColorProvider { public: + static const Glib::ustring TOOL_NAME; + ColorAppearance (); ~ColorAppearance () override; diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 0140c5b62..5e97084c9 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -14,6 +14,7 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring ColorToning::TOOL_NAME = "colortoning"; namespace { @@ -33,7 +34,7 @@ inline float round_ab(float v) } // namespace -ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLORTONING_LABEL"), false, true) +ColorToning::ColorToning () : FoldableToolPanel(this, TOOL_NAME, M("TP_COLORTONING_LABEL"), false, true) { nextbw = 0; CurveListener::setMulti(true); diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h index be3a83c2d..e763a069c 100644 --- a/rtgui/colortoning.h +++ b/rtgui/colortoning.h @@ -30,6 +30,8 @@ class ColorToning final : public AdjusterListener { public: + static const Glib::ustring TOOL_NAME; + ColorToning (); ~ColorToning() override; void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; diff --git a/rtgui/crop.cc b/rtgui/crop.cc index 853cec255..21a32b653 100644 --- a/rtgui/crop.cc +++ b/rtgui/crop.cc @@ -29,6 +29,8 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring Crop::TOOL_NAME = "crop"; + namespace { @@ -124,7 +126,7 @@ private: }; Crop::Crop(): - FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true), + FoldableToolPanel(this, TOOL_NAME, M("TP_CROP_LABEL"), false, true), crop_ratios(new CropRatios), opt(0), wDirty(true), diff --git a/rtgui/crop.h b/rtgui/crop.h index c6636b917..83eb6bbbb 100644 --- a/rtgui/crop.h +++ b/rtgui/crop.h @@ -41,6 +41,8 @@ class Crop final : public rtengine::SizeListener { public: + static const Glib::ustring TOOL_NAME; + Crop(); ~Crop() override; diff --git a/rtgui/darkframe.cc b/rtgui/darkframe.cc index b6b1201a7..9cb45ae98 100644 --- a/rtgui/darkframe.cc +++ b/rtgui/darkframe.cc @@ -30,7 +30,9 @@ using namespace rtengine; using namespace rtengine::procparams; -DarkFrame::DarkFrame () : FoldableToolPanel(this, "darkframe", M("TP_DARKFRAME_LABEL")), dfChanged(false), lastDFauto(false), dfp(nullptr), israw(true) +const Glib::ustring DarkFrame::TOOL_NAME = "darkframe"; + +DarkFrame::DarkFrame () : FoldableToolPanel(this, TOOL_NAME, M("TP_DARKFRAME_LABEL")), dfChanged(false), lastDFauto(false), dfp(nullptr), israw(true) { hbdf = Gtk::manage(new Gtk::Box()); hbdf->set_spacing(4); diff --git a/rtgui/darkframe.h b/rtgui/darkframe.h index 58e8b4842..fea8299a4 100644 --- a/rtgui/darkframe.h +++ b/rtgui/darkframe.h @@ -62,6 +62,7 @@ protected: bool israw; public: + static const Glib::ustring TOOL_NAME; DarkFrame (); diff --git a/rtgui/defringe.cc b/rtgui/defringe.cc index 7aae8377a..72388ac8c 100644 --- a/rtgui/defringe.cc +++ b/rtgui/defringe.cc @@ -30,7 +30,9 @@ using namespace rtengine; using namespace rtengine::procparams; -Defringe::Defringe () : FoldableToolPanel(this, "defringe", M("TP_DEFRINGE_LABEL"), true, true) +const Glib::ustring Defringe::TOOL_NAME = "defringe"; + +Defringe::Defringe () : FoldableToolPanel(this, TOOL_NAME, M("TP_DEFRINGE_LABEL"), true, true) { std::vector bottomMilestones; diff --git a/rtgui/defringe.h b/rtgui/defringe.h index ebf1eecd8..d939ff926 100644 --- a/rtgui/defringe.h +++ b/rtgui/defringe.h @@ -46,6 +46,7 @@ protected: bool edges; public: + static const Glib::ustring TOOL_NAME; Defringe (); ~Defringe () override; diff --git a/rtgui/dehaze.cc b/rtgui/dehaze.cc index 76d309afc..b77b76945 100644 --- a/rtgui/dehaze.cc +++ b/rtgui/dehaze.cc @@ -29,7 +29,9 @@ using namespace rtengine; using namespace rtengine::procparams; -Dehaze::Dehaze(): FoldableToolPanel(this, "dehaze", M("TP_DEHAZE_LABEL"), false, true) +const Glib::ustring Dehaze::TOOL_NAME = "dehaze"; + +Dehaze::Dehaze(): FoldableToolPanel(this, TOOL_NAME, M("TP_DEHAZE_LABEL"), false, true) { auto m = ProcEventMapper::getInstance(); EvDehazeEnabled = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_ENABLED"); diff --git a/rtgui/dehaze.h b/rtgui/dehaze.h index 155efa522..1da50d7dd 100644 --- a/rtgui/dehaze.h +++ b/rtgui/dehaze.h @@ -39,6 +39,7 @@ private: rtengine::ProcEvent EvDehazeSaturation; public: + static const Glib::ustring TOOL_NAME; Dehaze(); diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc index 3bf7c21f4..f2b780eba 100644 --- a/rtgui/dirpyrdenoise.cc +++ b/rtgui/dirpyrdenoise.cc @@ -33,7 +33,9 @@ using namespace rtengine; using namespace rtengine::procparams; -DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP_DIRPYRDENOISE_LABEL"), true, true), lastmedian(false) +const Glib::ustring DirPyrDenoise::TOOL_NAME = "dirpyrdenoise"; + +DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, TOOL_NAME, M("TP_DIRPYRDENOISE_LABEL"), true, true), lastmedian(false) { std::vector milestones; CurveListener::setMulti(true); diff --git a/rtgui/dirpyrdenoise.h b/rtgui/dirpyrdenoise.h index 71c9b1894..dadd96988 100644 --- a/rtgui/dirpyrdenoise.h +++ b/rtgui/dirpyrdenoise.h @@ -40,6 +40,8 @@ class DirPyrDenoise final : public ColorProvider { public: + static const Glib::ustring TOOL_NAME; + DirPyrDenoise (); ~DirPyrDenoise () override; diff --git a/rtgui/dirpyrequalizer.cc b/rtgui/dirpyrequalizer.cc index 9393d7c42..46966ea45 100644 --- a/rtgui/dirpyrequalizer.cc +++ b/rtgui/dirpyrequalizer.cc @@ -24,7 +24,9 @@ using namespace rtengine; using namespace rtengine::procparams; -DirPyrEqualizer::DirPyrEqualizer () : FoldableToolPanel(this, "dirpyrequalizer", M("TP_DIRPYREQUALIZER_LABEL"), true, true) +const Glib::ustring DirPyrEqualizer::TOOL_NAME = "dirpyrequalizer"; + +DirPyrEqualizer::DirPyrEqualizer () : FoldableToolPanel(this, TOOL_NAME, M("TP_DIRPYREQUALIZER_LABEL"), true, true) { std::vector milestones; diff --git a/rtgui/dirpyrequalizer.h b/rtgui/dirpyrequalizer.h index bb03e1a53..39b201b9b 100644 --- a/rtgui/dirpyrequalizer.h +++ b/rtgui/dirpyrequalizer.h @@ -56,6 +56,7 @@ protected: bool lastgamutlab; public: + static const Glib::ustring TOOL_NAME; DirPyrEqualizer (); ~DirPyrEqualizer () override; diff --git a/rtgui/distortion.cc b/rtgui/distortion.cc index 165ccee06..84566ab80 100644 --- a/rtgui/distortion.cc +++ b/rtgui/distortion.cc @@ -27,7 +27,9 @@ using namespace rtengine; using namespace rtengine::procparams; -Distortion::Distortion (): FoldableToolPanel(this, "distortion", M("TP_DISTORTION_LABEL")) +const Glib::ustring Distortion::TOOL_NAME = "distortion"; + +Distortion::Distortion (): FoldableToolPanel(this, TOOL_NAME, M("TP_DISTORTION_LABEL")) { rlistener = nullptr; diff --git a/rtgui/distortion.h b/rtgui/distortion.h index 7ef33d73a..98044bacf 100644 --- a/rtgui/distortion.h +++ b/rtgui/distortion.h @@ -37,6 +37,7 @@ protected: LensGeomListener * rlistener; public: + static const Glib::ustring TOOL_NAME; Distortion (); diff --git a/rtgui/epd.cc b/rtgui/epd.cc index d032cf28d..073c5ecdd 100644 --- a/rtgui/epd.cc +++ b/rtgui/epd.cc @@ -26,7 +26,9 @@ using namespace rtengine; using namespace rtengine::procparams; -EdgePreservingDecompositionUI::EdgePreservingDecompositionUI () : FoldableToolPanel(this, "epd", M("TP_EPD_LABEL"), true, true) +const Glib::ustring EdgePreservingDecompositionUI::TOOL_NAME = "epd"; + +EdgePreservingDecompositionUI::EdgePreservingDecompositionUI () : FoldableToolPanel(this, TOOL_NAME, M("TP_EPD_LABEL"), true, true) { strength = Gtk::manage(new Adjuster (M("TP_EPD_STRENGTH"), -1.0, 2.0, 0.01, 0.5)); diff --git a/rtgui/epd.h b/rtgui/epd.h index 6a5160623..1d866d690 100644 --- a/rtgui/epd.h +++ b/rtgui/epd.h @@ -36,6 +36,7 @@ protected: Adjuster *reweightingIterates; public: + static const Glib::ustring TOOL_NAME; EdgePreservingDecompositionUI(); diff --git a/rtgui/fattaltonemap.cc b/rtgui/fattaltonemap.cc index 89a1e9e30..d4ed90612 100644 --- a/rtgui/fattaltonemap.cc +++ b/rtgui/fattaltonemap.cc @@ -31,7 +31,9 @@ using namespace rtengine; using namespace rtengine::procparams; -FattalToneMapping::FattalToneMapping(): FoldableToolPanel(this, "fattal", M("TP_TM_FATTAL_LABEL"), true, true) +const Glib::ustring FattalToneMapping::TOOL_NAME = "fattal"; + +FattalToneMapping::FattalToneMapping(): FoldableToolPanel(this, TOOL_NAME, M("TP_TM_FATTAL_LABEL"), true, true) { auto m = ProcEventMapper::getInstance(); EvTMFattalAnchor = m->newEvent(HDR, "HISTORY_MSG_TM_FATTAL_ANCHOR"); diff --git a/rtgui/fattaltonemap.h b/rtgui/fattaltonemap.h index 3d36ec7d2..f5c19f15c 100644 --- a/rtgui/fattaltonemap.h +++ b/rtgui/fattaltonemap.h @@ -33,6 +33,7 @@ protected: rtengine::ProcEvent EvTMFattalAnchor; public: + static const Glib::ustring TOOL_NAME; FattalToneMapping(); diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 068575a96..292fa98ae 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -28,6 +28,8 @@ #include "../rtengine/procparams.h" #include "../rtengine/color.h" +const Glib::ustring FilmNegative::TOOL_NAME = "filmnegative"; + namespace { @@ -184,7 +186,7 @@ void rgb2temp(const RGB &refOut, double &outLev, double &temp, double &green) } FilmNegative::FilmNegative() : - FoldableToolPanel(this, "filmnegative", M("TP_FILMNEGATIVE_LABEL"), false, true), + FoldableToolPanel(this, TOOL_NAME, M("TP_FILMNEGATIVE_LABEL"), false, true), EditSubscriber(ET_OBJECTS), NEUTRAL_TEMP(rtengine::ColorTemp(1., 1., 1., 1.)), evFilmNegativeExponents(ProcEventMapper::getInstance()->newEvent(ALLNORAW, "HISTORY_MSG_FILMNEGATIVE_VALUES")), diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h index 21a7dce5c..722625fa2 100644 --- a/rtgui/filmnegative.h +++ b/rtgui/filmnegative.h @@ -52,6 +52,8 @@ class FilmNegative final : public rtengine::FilmNegListener { public: + static const Glib::ustring TOOL_NAME; + FilmNegative(); ~FilmNegative() override; diff --git a/rtgui/filmsimulation.cc b/rtgui/filmsimulation.cc index 6b40bb586..55a8e0ffe 100644 --- a/rtgui/filmsimulation.cc +++ b/rtgui/filmsimulation.cc @@ -12,6 +12,8 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring FilmSimulation::TOOL_NAME = "filmsimulation"; + namespace { @@ -61,7 +63,7 @@ bool notifySlowParseDir (const std::chrono::system_clock::time_point& startedAt) } FilmSimulation::FilmSimulation() - : FoldableToolPanel( this, "filmsimulation", M("TP_FILMSIMULATION_LABEL"), false, true ) + : FoldableToolPanel( this, TOOL_NAME, M("TP_FILMSIMULATION_LABEL"), false, true ) { m_clutComboBox = Gtk::manage( new ClutComboBox(options.clutsDir) ); int foundClutsCount = m_clutComboBox->foundClutsCount(); diff --git a/rtgui/filmsimulation.h b/rtgui/filmsimulation.h index cfe7016bb..ed30b866e 100644 --- a/rtgui/filmsimulation.h +++ b/rtgui/filmsimulation.h @@ -56,6 +56,8 @@ private: class FilmSimulation : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { public: + static const Glib::ustring TOOL_NAME; + FilmSimulation(); void adjusterChanged(Adjuster* a, double newval) override; diff --git a/rtgui/flatfield.cc b/rtgui/flatfield.cc index 71fa0aab6..7e4086c07 100644 --- a/rtgui/flatfield.cc +++ b/rtgui/flatfield.cc @@ -30,7 +30,9 @@ using namespace rtengine; using namespace rtengine::procparams; -FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_LABEL")) +const Glib::ustring FlatField::TOOL_NAME = "flatfield"; + +FlatField::FlatField () : FoldableToolPanel(this, TOOL_NAME, M("TP_FLATFIELD_LABEL")) { hbff = Gtk::manage(new Gtk::Box()); flatFieldFile = Gtk::manage(new MyFileChooserButton(M("TP_FLATFIELD_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); diff --git a/rtgui/flatfield.h b/rtgui/flatfield.h index 0d6f167e1..9b20b3e6f 100644 --- a/rtgui/flatfield.h +++ b/rtgui/flatfield.h @@ -67,6 +67,7 @@ protected: IdleRegister idle_register; public: + static const Glib::ustring TOOL_NAME; FlatField (); ~FlatField () override; diff --git a/rtgui/gradient.cc b/rtgui/gradient.cc index 1274da9ab..26be51975 100644 --- a/rtgui/gradient.cc +++ b/rtgui/gradient.cc @@ -25,7 +25,9 @@ enum GeometryIndex { } -Gradient::Gradient () : FoldableToolPanel(this, "gradient", M("TP_GRADIENT_LABEL"), false, true), EditSubscriber(ET_OBJECTS), lastObject(-1), draggedPointOldAngle(-1000.) +const Glib::ustring Gradient::TOOL_NAME = "gradient"; + +Gradient::Gradient () : FoldableToolPanel(this, TOOL_NAME, M("TP_GRADIENT_LABEL"), false, true), EditSubscriber(ET_OBJECTS), lastObject(-1), draggedPointOldAngle(-1000.) { editHBox = Gtk::manage (new Gtk::Box()); diff --git a/rtgui/gradient.h b/rtgui/gradient.h index dc0371932..d7754007c 100644 --- a/rtgui/gradient.h +++ b/rtgui/gradient.h @@ -38,6 +38,7 @@ protected: void releaseEdit(); public: + static const Glib::ustring TOOL_NAME; Gradient (); ~Gradient () override; diff --git a/rtgui/hsvequalizer.cc b/rtgui/hsvequalizer.cc index 817ba1f4d..ddb1d2fb5 100644 --- a/rtgui/hsvequalizer.cc +++ b/rtgui/hsvequalizer.cc @@ -28,9 +28,11 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring HSVEqualizer::TOOL_NAME = "hsvequalizer"; + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -HSVEqualizer::HSVEqualizer () : FoldableToolPanel(this, "hsvequalizer", M("TP_HSVEQUALIZER_LABEL"), false, true) +HSVEqualizer::HSVEqualizer () : FoldableToolPanel(this, TOOL_NAME, M("TP_HSVEQUALIZER_LABEL"), false, true) { std::vector bottomMilestones; diff --git a/rtgui/hsvequalizer.h b/rtgui/hsvequalizer.h index 77c1ee1b0..1f80cd9e4 100644 --- a/rtgui/hsvequalizer.h +++ b/rtgui/hsvequalizer.h @@ -44,6 +44,7 @@ protected: FlatCurveEditor* vshape; public: + static const Glib::ustring TOOL_NAME; HSVEqualizer (); ~HSVEqualizer () override; diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index 45d0f6622..254882736 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -35,7 +35,9 @@ using namespace rtengine; using namespace rtengine::procparams; -ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunchanged(nullptr), icmplistener(nullptr) +const Glib::ustring ICMPanel::TOOL_NAME = "icm"; + +ICMPanel::ICMPanel() : FoldableToolPanel(this, TOOL_NAME, M("TP_ICM_LABEL")), iunchanged(nullptr), icmplistener(nullptr) { auto m = ProcEventMapper::getInstance(); EvICMprimariMethod = m->newEvent(GAMMA, "HISTORY_MSG_ICM_OUTPUT_PRIMARIES"); diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index 063da28d1..422b674ff 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -177,6 +177,8 @@ private: float nextwy; public: + static const Glib::ustring TOOL_NAME; + ICMPanel(); ~ICMPanel() override; diff --git a/rtgui/impulsedenoise.cc b/rtgui/impulsedenoise.cc index cc2e10899..1df662aad 100644 --- a/rtgui/impulsedenoise.cc +++ b/rtgui/impulsedenoise.cc @@ -28,7 +28,9 @@ using namespace rtengine; using namespace rtengine::procparams; -ImpulseDenoise::ImpulseDenoise () : FoldableToolPanel(this, "impulsedenoise", M("TP_IMPULSEDENOISE_LABEL"), true, true) +const Glib::ustring ImpulseDenoise::TOOL_NAME = "impulsedenoise"; + +ImpulseDenoise::ImpulseDenoise () : FoldableToolPanel(this, TOOL_NAME, M("TP_IMPULSEDENOISE_LABEL"), true, true) { thresh = Gtk::manage (new Adjuster (M("TP_IMPULSEDENOISE_THRESH"), 0, 100, 1, 50)); diff --git a/rtgui/impulsedenoise.h b/rtgui/impulsedenoise.h index b8acafcfc..c4c297927 100644 --- a/rtgui/impulsedenoise.h +++ b/rtgui/impulsedenoise.h @@ -34,6 +34,7 @@ protected: //Adjuster* edge; public: + static const Glib::ustring TOOL_NAME; ImpulseDenoise (); diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index dca1dfd45..1d49cd6ff 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -32,7 +32,9 @@ using namespace rtengine; using namespace rtengine::procparams; -LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL"), false, true) +const Glib::ustring LCurve::TOOL_NAME = "labcurves"; + +LCurve::LCurve () : FoldableToolPanel(this, TOOL_NAME, M("TP_LABCURVE_LABEL"), false, true) { brightness = Gtk::manage (new Adjuster (M("TP_LABCURVE_BRIGHTNESS"), -100., 100., 1., 0.)); contrast = Gtk::manage (new Adjuster (M("TP_LABCURVE_CONTRAST"), -100., 100., 1., 0.)); diff --git a/rtgui/labcurve.h b/rtgui/labcurve.h index dfb79ae7a..b9039baca 100644 --- a/rtgui/labcurve.h +++ b/rtgui/labcurve.h @@ -69,6 +69,7 @@ protected: //%%%%%%%%%%%%%%%% public: + static const Glib::ustring TOOL_NAME; LCurve (); ~LCurve () override; diff --git a/rtgui/lensgeom.cc b/rtgui/lensgeom.cc index 8bdbf6dd4..6b9d70fb0 100644 --- a/rtgui/lensgeom.cc +++ b/rtgui/lensgeom.cc @@ -27,7 +27,9 @@ using namespace rtengine; using namespace rtengine::procparams; -LensGeometry::LensGeometry () : FoldableToolPanel(this, "lensgeom", M("TP_LENSGEOM_LABEL")), rlistener(nullptr), lastFill(false) +const Glib::ustring LensGeometry::TOOL_NAME = "lensgeom"; + +LensGeometry::LensGeometry () : FoldableToolPanel(this, TOOL_NAME, M("TP_LENSGEOM_LABEL")), rlistener(nullptr), lastFill(false) { auto m = ProcEventMapper::getInstance(); diff --git a/rtgui/lensgeom.h b/rtgui/lensgeom.h index 73c28b006..e8f85faac 100644 --- a/rtgui/lensgeom.h +++ b/rtgui/lensgeom.h @@ -39,6 +39,7 @@ protected: rtengine::ProcEvent EvTransMethod; public: + static const Glib::ustring TOOL_NAME; LensGeometry (); ~LensGeometry () override; diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 73fb0399b..65c962b7b 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -36,8 +36,10 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring LensProfilePanel::TOOL_NAME = "lensprof"; + LensProfilePanel::LensProfilePanel() : - FoldableToolPanel(this, "lensprof", M("TP_LENSPROFILE_LABEL")), + FoldableToolPanel(this, TOOL_NAME, M("TP_LENSPROFILE_LABEL")), lcModeChanged(false), lcpFileChanged(false), useDistChanged(false), diff --git a/rtgui/lensprofile.h b/rtgui/lensprofile.h index 7b5b7343c..42746f41e 100644 --- a/rtgui/lensprofile.h +++ b/rtgui/lensprofile.h @@ -28,6 +28,8 @@ class LensProfilePanel final : public FoldableToolPanel { public: + static const Glib::ustring TOOL_NAME; + LensProfilePanel(); void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; diff --git a/rtgui/localcontrast.cc b/rtgui/localcontrast.cc index 6b668a1eb..a56f9cb15 100644 --- a/rtgui/localcontrast.cc +++ b/rtgui/localcontrast.cc @@ -29,7 +29,9 @@ using namespace rtengine; using namespace rtengine::procparams; -LocalContrast::LocalContrast(): FoldableToolPanel(this, "localcontrast", M("TP_LOCALCONTRAST_LABEL"), false, true) +const Glib::ustring LocalContrast::TOOL_NAME = "localcontrast"; + +LocalContrast::LocalContrast(): FoldableToolPanel(this, TOOL_NAME, M("TP_LOCALCONTRAST_LABEL"), false, true) { auto m = ProcEventMapper::getInstance(); /* EvLocalContrastEnabled = m->newEvent(RGBCURVE, "HISTORY_MSG_LOCALCONTRAST_ENABLED"); diff --git a/rtgui/localcontrast.h b/rtgui/localcontrast.h index d1d25fb3d..fa769c35e 100644 --- a/rtgui/localcontrast.h +++ b/rtgui/localcontrast.h @@ -38,6 +38,7 @@ private: rtengine::ProcEvent EvLocalContrastLightness; public: + static const Glib::ustring TOOL_NAME; LocalContrast(); diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index 880125085..db9fc6e1a 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -29,6 +29,8 @@ using namespace procparams; extern Options options; +const Glib::ustring Locallab::TOOL_NAME = "locallab"; + /* ==== LocallabToolList ==== */ LocallabToolList::LocallabToolList(): // Tool list GUI elements @@ -142,7 +144,7 @@ void LocallabToolList::toolRowSelected() /* ==== Locallab ==== */ Locallab::Locallab(): - FoldableToolPanel(this, "locallab", M("TP_LOCALLAB_LABEL"), false, true), + FoldableToolPanel(this, TOOL_NAME, M("TP_LOCALLAB_LABEL"), false, true), // Spot control panel widget expsettings(Gtk::manage(new ControlSpotPanel())), diff --git a/rtgui/locallab.h b/rtgui/locallab.h index d86d8c5c1..c615d49ae 100644 --- a/rtgui/locallab.h +++ b/rtgui/locallab.h @@ -131,6 +131,8 @@ private: Glib::ustring spotName; public: + static const Glib::ustring TOOL_NAME; + Locallab(); // FoldableToolPanel management functions diff --git a/rtgui/pcvignette.cc b/rtgui/pcvignette.cc index 9c141d618..1ed7446b1 100644 --- a/rtgui/pcvignette.cc +++ b/rtgui/pcvignette.cc @@ -8,7 +8,9 @@ using namespace rtengine; using namespace rtengine::procparams; -PCVignette::PCVignette () : FoldableToolPanel(this, "pcvignette", M("TP_PCVIGNETTE_LABEL"), false, true) +const Glib::ustring PCVignette::TOOL_NAME = "pcvignette"; + +PCVignette::PCVignette () : FoldableToolPanel(this, TOOL_NAME, M("TP_PCVIGNETTE_LABEL"), false, true) { strength = Gtk::manage (new Adjuster (M("TP_PCVIGNETTE_STRENGTH"), -6, 6, 0.01, 0)); strength->set_tooltip_text (M("TP_PCVIGNETTE_STRENGTH_TOOLTIP")); diff --git a/rtgui/pcvignette.h b/rtgui/pcvignette.h index 87915703f..825654630 100644 --- a/rtgui/pcvignette.h +++ b/rtgui/pcvignette.h @@ -20,6 +20,7 @@ protected: Adjuster* roundness; public: + static const Glib::ustring TOOL_NAME; PCVignette (); diff --git a/rtgui/pdsharpening.cc b/rtgui/pdsharpening.cc index 45d5b545c..57133048c 100644 --- a/rtgui/pdsharpening.cc +++ b/rtgui/pdsharpening.cc @@ -31,8 +31,10 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring PdSharpening::TOOL_NAME = "capturesharpening"; + PdSharpening::PdSharpening() : - FoldableToolPanel(this, "capturesharpening", M("TP_PDSHARPENING_LABEL"), false, true), + FoldableToolPanel(this, TOOL_NAME, M("TP_PDSHARPENING_LABEL"), false, true), lastAutoContrast(true), lastAutoRadius(true) { diff --git a/rtgui/pdsharpening.h b/rtgui/pdsharpening.h index eb0576ceb..c4902e4b6 100644 --- a/rtgui/pdsharpening.h +++ b/rtgui/pdsharpening.h @@ -50,6 +50,7 @@ protected: IdleRegister idle_register; public: + static const Glib::ustring TOOL_NAME; PdSharpening (); ~PdSharpening () override; diff --git a/rtgui/perspective.cc b/rtgui/perspective.cc index d06243524..be151e9bc 100644 --- a/rtgui/perspective.cc +++ b/rtgui/perspective.cc @@ -27,6 +27,8 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring PerspCorrection::TOOL_NAME = "perspective"; + namespace { @@ -84,7 +86,7 @@ std::vector valuesToControlLines( } -PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M("TP_PERSPECTIVE_LABEL")) +PerspCorrection::PerspCorrection () : FoldableToolPanel(this, TOOL_NAME, M("TP_PERSPECTIVE_LABEL")) { auto mapper = ProcEventMapper::getInstance(); diff --git a/rtgui/perspective.h b/rtgui/perspective.h index 404b02010..6ca2381e3 100644 --- a/rtgui/perspective.h +++ b/rtgui/perspective.h @@ -104,6 +104,7 @@ public: static constexpr std::size_t MIN_HORIZ_LINES = 2; /** Minimum number of vertical lines for vertical/full correction. */ static constexpr std::size_t MIN_VERT_LINES = 2; + static const Glib::ustring TOOL_NAME; PerspCorrection (); diff --git a/rtgui/preprocess.cc b/rtgui/preprocess.cc index b9326e3ad..4d7df213c 100644 --- a/rtgui/preprocess.cc +++ b/rtgui/preprocess.cc @@ -28,7 +28,9 @@ using namespace rtengine; using namespace rtengine::procparams; -PreProcess::PreProcess () : FoldableToolPanel(this, "preprocess", M("TP_PREPROCESS_LABEL"), options.prevdemo != PD_Sidecar) +const Glib::ustring PreProcess::TOOL_NAME = "preprocess"; + +PreProcess::PreProcess () : FoldableToolPanel(this, TOOL_NAME, M("TP_PREPROCESS_LABEL"), options.prevdemo != PD_Sidecar) { Gtk::Box* hotdeadPixel = Gtk::manage( new Gtk::Box () ); diff --git a/rtgui/preprocess.h b/rtgui/preprocess.h index d10ff5223..047413bdb 100644 --- a/rtgui/preprocess.h +++ b/rtgui/preprocess.h @@ -38,6 +38,7 @@ protected: sigc::connection dpixelconn; Adjuster* hdThreshold; public: + static const Glib::ustring TOOL_NAME; PreProcess (); diff --git a/rtgui/preprocesswb.cc b/rtgui/preprocesswb.cc index dddd7fdc2..9251f9440 100644 --- a/rtgui/preprocesswb.cc +++ b/rtgui/preprocesswb.cc @@ -29,8 +29,10 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring PreprocessWB::TOOL_NAME = "preprocesswb"; + PreprocessWB::PreprocessWB() : - FoldableToolPanel(this, "preprocesswb", M("TP_PREPROCWB_LABEL")), + FoldableToolPanel(this, TOOL_NAME, M("TP_PREPROCWB_LABEL")), evPreprocessWBMode(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_PREPROCWB_MODE")), mode(Gtk::manage(new MyComboBoxText())) { diff --git a/rtgui/preprocesswb.h b/rtgui/preprocesswb.h index 343d2e9e9..08e1dc468 100644 --- a/rtgui/preprocesswb.h +++ b/rtgui/preprocesswb.h @@ -34,6 +34,7 @@ private: MyComboBoxText* mode; public: + static const Glib::ustring TOOL_NAME; PreprocessWB(); diff --git a/rtgui/prsharpening.cc b/rtgui/prsharpening.cc index c79fff1a1..d3c936fa2 100644 --- a/rtgui/prsharpening.cc +++ b/rtgui/prsharpening.cc @@ -23,7 +23,9 @@ using namespace rtengine; using namespace rtengine::procparams; -PrSharpening::PrSharpening () : FoldableToolPanel(this, "prsharpening", M("TP_PRSHARPENING_LABEL"), false, true) +const Glib::ustring PrSharpening::TOOL_NAME = "prsharpening"; + +PrSharpening::PrSharpening () : FoldableToolPanel(this, TOOL_NAME, M("TP_PRSHARPENING_LABEL"), false, true) { auto m = ProcEventMapper::getInstance(); diff --git a/rtgui/prsharpening.h b/rtgui/prsharpening.h index 4128bc4c5..ea22234f8 100644 --- a/rtgui/prsharpening.h +++ b/rtgui/prsharpening.h @@ -59,6 +59,7 @@ protected: sigc::connection hcConn; rtengine::ProcEvent EvPrShrContrast; public: + static const Glib::ustring TOOL_NAME; PrSharpening (); ~PrSharpening () override; diff --git a/rtgui/rawcacorrection.cc b/rtgui/rawcacorrection.cc index 58c7995f9..473ca2ed3 100644 --- a/rtgui/rawcacorrection.cc +++ b/rtgui/rawcacorrection.cc @@ -28,7 +28,9 @@ using namespace rtengine; using namespace rtengine::procparams; -RAWCACorr::RAWCACorr () : FoldableToolPanel(this, "rawcacorrection", M("TP_RAWCACORR_LABEL")) +const Glib::ustring RAWCACorr::TOOL_NAME = "rawcacorrection"; + +RAWCACorr::RAWCACorr () : FoldableToolPanel(this, TOOL_NAME, M("TP_RAWCACORR_LABEL")) { auto m = ProcEventMapper::getInstance(); EvPreProcessCAAutoiterations = m->newEvent(DARKFRAME, "HISTORY_MSG_RAWCACORR_AUTOIT"); diff --git a/rtgui/rawcacorrection.h b/rtgui/rawcacorrection.h index 3c95602a7..88b65528e 100644 --- a/rtgui/rawcacorrection.h +++ b/rtgui/rawcacorrection.h @@ -43,6 +43,7 @@ protected: rtengine::ProcEvent EvPreProcessCAColourshiftHistory; public: + static const Glib::ustring TOOL_NAME; RAWCACorr (); diff --git a/rtgui/rawexposure.cc b/rtgui/rawexposure.cc index 7b5ecabc9..778283b75 100644 --- a/rtgui/rawexposure.cc +++ b/rtgui/rawexposure.cc @@ -28,7 +28,9 @@ using namespace rtengine; using namespace rtengine::procparams; -RAWExposure::RAWExposure () : FoldableToolPanel(this, "rawexposure", M("TP_EXPOS_WHITEPOINT_LABEL")) +const Glib::ustring RAWExposure::TOOL_NAME = "rawexposure"; + +RAWExposure::RAWExposure () : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOS_WHITEPOINT_LABEL")) { PexPos = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_LINEAR"), 0.1, 16.0, 0.01, 1)); PexPos->setAdjusterListener (this); diff --git a/rtgui/rawexposure.h b/rtgui/rawexposure.h index 33c897113..ca839d230 100644 --- a/rtgui/rawexposure.h +++ b/rtgui/rawexposure.h @@ -33,6 +33,7 @@ protected: Adjuster* PexPos; public: + static const Glib::ustring TOOL_NAME; RAWExposure (); diff --git a/rtgui/resize.cc b/rtgui/resize.cc index 0bbb65845..258ccf791 100644 --- a/rtgui/resize.cc +++ b/rtgui/resize.cc @@ -29,7 +29,9 @@ using namespace rtengine; using namespace rtengine::procparams; -Resize::Resize () : FoldableToolPanel(this, "resize", M("TP_RESIZE_LABEL"), false, true), maxw(100000), maxh(100000) +const Glib::ustring Resize::TOOL_NAME = "resize"; + +Resize::Resize () : FoldableToolPanel(this, TOOL_NAME, M("TP_RESIZE_LABEL"), false, true), maxw(100000), maxh(100000) { auto m = ProcEventMapper::getInstance(); EvResizeAllowUpscaling = m->newEvent(RESIZE, "HISTORY_MSG_RESIZE_ALLOWUPSCALING"); diff --git a/rtgui/resize.h b/rtgui/resize.h index d13bf8aa4..71fefb503 100644 --- a/rtgui/resize.h +++ b/rtgui/resize.h @@ -32,6 +32,8 @@ class Resize final : public rtengine::SizeListener { public: + static const Glib::ustring TOOL_NAME; + Resize (); ~Resize () override; diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index a9d7cc376..3aac6f203 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -14,7 +14,9 @@ using namespace rtengine; using namespace rtengine::procparams; -Retinex::Retinex () : FoldableToolPanel (this, "retinex", M ("TP_RETINEX_LABEL"), false, true), lastmedianmap (false) +const Glib::ustring Retinex::TOOL_NAME = "retinex"; + +Retinex::Retinex () : FoldableToolPanel (this, TOOL_NAME, M ("TP_RETINEX_LABEL"), false, true), lastmedianmap (false) { CurveListener::setMulti (true); std::vector milestones; diff --git a/rtgui/retinex.h b/rtgui/retinex.h index bf480c9cc..bdcbcc466 100644 --- a/rtgui/retinex.h +++ b/rtgui/retinex.h @@ -109,6 +109,8 @@ protected: sigc::connection medianmapConn; public: + static const Glib::ustring TOOL_NAME; + Retinex(); ~Retinex() override; diff --git a/rtgui/rgbcurves.cc b/rtgui/rgbcurves.cc index 5e7616e70..0dd6805fe 100644 --- a/rtgui/rgbcurves.cc +++ b/rtgui/rgbcurves.cc @@ -27,7 +27,9 @@ using namespace rtengine; using namespace rtengine::procparams; -RGBCurves::RGBCurves () : FoldableToolPanel(this, "rgbcurves", M("TP_RGBCURVES_LABEL"), false, true), lastLumamode(false) +const Glib::ustring RGBCurves::TOOL_NAME = "rgbcurves"; + +RGBCurves::RGBCurves () : FoldableToolPanel(this, TOOL_NAME, M("TP_RGBCURVES_LABEL"), false, true), lastLumamode(false) { lumamode = Gtk::manage (new Gtk::CheckButton (M("TP_RGBCURVES_LUMAMODE"))); diff --git a/rtgui/rgbcurves.h b/rtgui/rgbcurves.h index edc80eb41..d7e3c3853 100644 --- a/rtgui/rgbcurves.h +++ b/rtgui/rgbcurves.h @@ -45,6 +45,7 @@ protected: sigc::connection lumamodeConn; public: + static const Glib::ustring TOOL_NAME; RGBCurves (); ~RGBCurves () override; diff --git a/rtgui/rotate.cc b/rtgui/rotate.cc index 06c53cd4e..944c54e6d 100644 --- a/rtgui/rotate.cc +++ b/rtgui/rotate.cc @@ -29,7 +29,9 @@ using namespace rtengine; using namespace rtengine::procparams; -Rotate::Rotate () : FoldableToolPanel(this, "rotate", M("TP_ROTATE_LABEL")) +const Glib::ustring Rotate::TOOL_NAME = "rotate"; + +Rotate::Rotate () : FoldableToolPanel(this, TOOL_NAME, M("TP_ROTATE_LABEL")) { rlistener = nullptr; diff --git a/rtgui/rotate.h b/rtgui/rotate.h index 41e10eb4d..26db33ffd 100644 --- a/rtgui/rotate.h +++ b/rtgui/rotate.h @@ -36,6 +36,7 @@ protected: LensGeomListener* rlistener; public: + static const Glib::ustring TOOL_NAME; Rotate (); diff --git a/rtgui/sensorbayer.cc b/rtgui/sensorbayer.cc index 39ed5cb91..002cdf1de 100644 --- a/rtgui/sensorbayer.cc +++ b/rtgui/sensorbayer.cc @@ -20,7 +20,9 @@ #include "guiutils.h" #include "rtimage.h" -SensorBayer::SensorBayer () : FoldableToolPanel(this, "sensorbayer", M("TP_RAW_SENSOR_BAYER_LABEL")) +const Glib::ustring SensorBayer::TOOL_NAME = "sensorbayer"; + +SensorBayer::SensorBayer () : FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_SENSOR_BAYER_LABEL")) { packBox = Gtk::manage (new ToolParamBlock ()); diff --git a/rtgui/sensorbayer.h b/rtgui/sensorbayer.h index 2401bf760..0e65b8b38 100644 --- a/rtgui/sensorbayer.h +++ b/rtgui/sensorbayer.h @@ -31,6 +31,7 @@ protected: ToolParamBlock* packBox; public: + static const Glib::ustring TOOL_NAME; SensorBayer (); diff --git a/rtgui/sensorxtrans.cc b/rtgui/sensorxtrans.cc index f13e6607f..c4a5bf76d 100644 --- a/rtgui/sensorxtrans.cc +++ b/rtgui/sensorxtrans.cc @@ -20,7 +20,9 @@ #include "guiutils.h" #include "rtimage.h" -SensorXTrans::SensorXTrans () : FoldableToolPanel(this, "sensorxtrans", M("TP_RAW_SENSOR_XTRANS_LABEL")) +const Glib::ustring SensorXTrans::TOOL_NAME = "sensorxtrans"; + +SensorXTrans::SensorXTrans () : FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_SENSOR_XTRANS_LABEL")) { packBox = Gtk::manage (new ToolParamBlock ()); diff --git a/rtgui/sensorxtrans.h b/rtgui/sensorxtrans.h index eee014f6c..12c851db3 100644 --- a/rtgui/sensorxtrans.h +++ b/rtgui/sensorxtrans.h @@ -31,6 +31,7 @@ protected: ToolParamBlock* packBox; public: + static const Glib::ustring TOOL_NAME; SensorXTrans (); diff --git a/rtgui/shadowshighlights.cc b/rtgui/shadowshighlights.cc index a168527d6..3c821d863 100644 --- a/rtgui/shadowshighlights.cc +++ b/rtgui/shadowshighlights.cc @@ -25,7 +25,9 @@ using namespace rtengine; using namespace rtengine::procparams; -ShadowsHighlights::ShadowsHighlights () : FoldableToolPanel(this, "shadowshighlights", M("TP_SHADOWSHLIGHTS_LABEL"), false, true) +const Glib::ustring ShadowsHighlights::TOOL_NAME = "shadowshighlights"; + +ShadowsHighlights::ShadowsHighlights () : FoldableToolPanel(this, TOOL_NAME, M("TP_SHADOWSHLIGHTS_LABEL"), false, true) { auto m = ProcEventMapper::getInstance(); EvSHColorspace = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_SH_COLORSPACE"); diff --git a/rtgui/shadowshighlights.h b/rtgui/shadowshighlights.h index 7bb0bb01c..fd8b30a6a 100644 --- a/rtgui/shadowshighlights.h +++ b/rtgui/shadowshighlights.h @@ -40,6 +40,7 @@ protected: rtengine::ProcEvent EvSHColorspace; public: + static const Glib::ustring TOOL_NAME; ShadowsHighlights (); diff --git a/rtgui/sharpenedge.cc b/rtgui/sharpenedge.cc index e00d919c3..247a8a5d7 100644 --- a/rtgui/sharpenedge.cc +++ b/rtgui/sharpenedge.cc @@ -28,8 +28,9 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring SharpenEdge::TOOL_NAME = "sharpenedge"; -SharpenEdge::SharpenEdge () : FoldableToolPanel(this, "sharpenedge", M("TP_SHARPENEDGE_LABEL"), true, true) +SharpenEdge::SharpenEdge () : FoldableToolPanel(this, TOOL_NAME, M("TP_SHARPENEDGE_LABEL"), true, true) { passes = Gtk::manage(new Adjuster (M("TP_SHARPENEDGE_PASSES"), 1, 4, 1, 2)); diff --git a/rtgui/sharpenedge.h b/rtgui/sharpenedge.h index a813d86e1..bfb48b408 100644 --- a/rtgui/sharpenedge.h +++ b/rtgui/sharpenedge.h @@ -44,6 +44,7 @@ protected: bool lastchanthree; public: + static const Glib::ustring TOOL_NAME; SharpenEdge (); diff --git a/rtgui/sharpening.cc b/rtgui/sharpening.cc index 687358349..ba39ac97c 100644 --- a/rtgui/sharpening.cc +++ b/rtgui/sharpening.cc @@ -23,7 +23,9 @@ using namespace rtengine; using namespace rtengine::procparams; -Sharpening::Sharpening () : FoldableToolPanel(this, "sharpening", M("TP_SHARPENING_LABEL"), true, true) +const Glib::ustring Sharpening::TOOL_NAME = "sharpening"; + +Sharpening::Sharpening () : FoldableToolPanel(this, TOOL_NAME, M("TP_SHARPENING_LABEL"), true, true) { auto m = ProcEventMapper::getInstance(); EvSharpenContrast = m->newEvent(SHARPENING, "HISTORY_MSG_SHARPENING_CONTRAST"); diff --git a/rtgui/sharpening.h b/rtgui/sharpening.h index aa65b3662..e30db3dd2 100644 --- a/rtgui/sharpening.h +++ b/rtgui/sharpening.h @@ -62,6 +62,7 @@ protected: rtengine::ProcEvent EvSharpenContrast; rtengine::ProcEvent EvSharpenBlur; public: + static const Glib::ustring TOOL_NAME; Sharpening (); ~Sharpening () override; diff --git a/rtgui/sharpenmicro.cc b/rtgui/sharpenmicro.cc index 78228d27c..527d146d7 100644 --- a/rtgui/sharpenmicro.cc +++ b/rtgui/sharpenmicro.cc @@ -29,8 +29,9 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring SharpenMicro::TOOL_NAME = "sharpenmicro"; -SharpenMicro::SharpenMicro () : FoldableToolPanel(this, "sharpenmicro", M("TP_SHARPENMICRO_LABEL"), true, true) +SharpenMicro::SharpenMicro () : FoldableToolPanel(this, TOOL_NAME, M("TP_SHARPENMICRO_LABEL"), true, true) { auto m = ProcEventMapper::getInstance(); diff --git a/rtgui/sharpenmicro.h b/rtgui/sharpenmicro.h index 23224dd60..876117e68 100644 --- a/rtgui/sharpenmicro.h +++ b/rtgui/sharpenmicro.h @@ -47,6 +47,7 @@ protected: bool lastmatrix; public: + static const Glib::ustring TOOL_NAME; SharpenMicro (); diff --git a/rtgui/softlight.cc b/rtgui/softlight.cc index 84461f169..3a7f84985 100644 --- a/rtgui/softlight.cc +++ b/rtgui/softlight.cc @@ -29,7 +29,9 @@ using namespace rtengine; using namespace rtengine::procparams; -SoftLight::SoftLight(): FoldableToolPanel(this, "softlight", M("TP_SOFTLIGHT_LABEL"), false, true) +const Glib::ustring SoftLight::TOOL_NAME = "softlight"; + +SoftLight::SoftLight(): FoldableToolPanel(this, TOOL_NAME, M("TP_SOFTLIGHT_LABEL"), false, true) { auto m = ProcEventMapper::getInstance(); EvSoftLightEnabled = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_SOFTLIGHT_ENABLED"); diff --git a/rtgui/softlight.h b/rtgui/softlight.h index 710da4e34..3b9ff5399 100644 --- a/rtgui/softlight.h +++ b/rtgui/softlight.h @@ -32,6 +32,7 @@ private: rtengine::ProcEvent EvSoftLightStrength; public: + static const Glib::ustring TOOL_NAME; SoftLight(); diff --git a/rtgui/spot.cc b/rtgui/spot.cc index 6e9143dbe..ffc380534 100644 --- a/rtgui/spot.cc +++ b/rtgui/spot.cc @@ -52,8 +52,10 @@ enum GeometryIndex { } +const Glib::ustring Spot::TOOL_NAME = "spot"; + Spot::Spot() : - FoldableToolPanel(this, "spot", M ("TP_SPOT_LABEL"), true, true), + FoldableToolPanel(this, TOOL_NAME, M ("TP_SPOT_LABEL"), true, true), EditSubscriber(ET_OBJECTS), draggedSide(DraggedSide::NONE), lastObject(-1), diff --git a/rtgui/spot.h b/rtgui/spot.h index 85cefa4c2..6320e068e 100644 --- a/rtgui/spot.h +++ b/rtgui/spot.h @@ -97,6 +97,7 @@ protected: Geometry* getVisibleGeometryFromMO (int MOID); public: + static const Glib::ustring TOOL_NAME; Spot (); ~Spot (); diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index 8a33575ca..677f73683 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -33,7 +33,9 @@ using namespace rtengine; using namespace rtengine::procparams; -ToneCurve::ToneCurve() : FoldableToolPanel(this, "tonecurve", M("TP_EXPOSURE_LABEL")) +const Glib::ustring ToneCurve::TOOL_NAME = "tonecurve"; + +ToneCurve::ToneCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOSURE_LABEL")) { auto m = ProcEventMapper::getInstance(); EvHistMatching = m->newEvent(AUTOEXP, "HISTORY_MSG_HISTMATCHING"); diff --git a/rtgui/tonecurve.h b/rtgui/tonecurve.h index 6dd77951d..7ba2178ac 100644 --- a/rtgui/tonecurve.h +++ b/rtgui/tonecurve.h @@ -97,6 +97,8 @@ protected: void setHistmatching(bool enabled); public: + static const Glib::ustring TOOL_NAME; + ToneCurve (); ~ToneCurve () override; diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index f489c4f63..cf2386257 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -137,7 +137,7 @@ Glib::ustring getToolTitleKey(Tool tool) case Tool::WAVELET: return "TP_WAVELET_LABEL"; case Tool::DIR_PYR_EQUALIZER: - return "TP_DIRPYRDENOISE_LABEL"; + return "TP_DIRPYREQUALIZER_LABEL"; case Tool::HSV_EQUALIZER: return "TP_HSVEQUALIZER_LABEL"; case Tool::FILM_SIMULATION: diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index f89c76b8d..7d98d0dc1 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -557,117 +557,117 @@ std::string ToolPanelCoordinator::getToolName(Tool tool) { switch (tool) { case Tool::TONE_CURVE: - return "tonecurve"; + return ToneCurve::TOOL_NAME; case Tool::SHADOWS_HIGHLIGHTS: - return "shadowshighlights"; + return ShadowsHighlights::TOOL_NAME; case Tool::IMPULSE_DENOISE: - return "impulsedenoise"; + return ImpulseDenoise::TOOL_NAME; case Tool::DEFRINGE_TOOL: - return "defringe"; + return Defringe::TOOL_NAME; case Tool::SPOT: - return "spot"; + return Spot::TOOL_NAME; case Tool::DIR_PYR_DENOISE: - return "dirpyrdenoise"; + return DirPyrDenoise::TOOL_NAME; case Tool::EPD: - return "epd"; + return EdgePreservingDecompositionUI::TOOL_NAME; case Tool::SHARPENING_TOOL: - return "sharpening"; + return Sharpening::TOOL_NAME; case Tool::LOCAL_CONTRAST: - return "localcontrast"; + return LocalContrast::TOOL_NAME; case Tool::SHARPEN_EDGE: - return "sharpenedge"; + return SharpenEdge::TOOL_NAME; case Tool::SHARPEN_MICRO: - return "sharpenmicro"; + return SharpenMicro::TOOL_NAME; case Tool::L_CURVE: - return "labcurves"; + return LCurve::TOOL_NAME; case Tool::RGB_CURVES: - return "rgbcurves"; + return RGBCurves::TOOL_NAME; case Tool::COLOR_TONING: - return "colortoning"; + return ColorToning::TOOL_NAME; case Tool::LENS_GEOM: - return "lensgeom"; + return LensGeometry::TOOL_NAME; case Tool::LENS_PROF: - return "lensprof"; + return LensProfilePanel::TOOL_NAME; case Tool::DISTORTION: - return "distortion"; + return Distortion::TOOL_NAME; case Tool::ROTATE: - return "rotate"; + return Rotate::TOOL_NAME; case Tool::VIBRANCE: - return "vibrance"; + return Vibrance::TOOL_NAME; case Tool::COLOR_APPEARANCE: - return "colorappearance"; + return ColorAppearance::TOOL_NAME; case Tool::WHITE_BALANCE: - return "whitebalance"; + return WhiteBalance::TOOL_NAME; case Tool::VIGNETTING: - return "vignetting"; + return Vignetting::TOOL_NAME; case Tool::RETINEX_TOOL: - return "retinex"; + return Retinex::TOOL_NAME; case Tool::GRADIENT: - return "gradient"; + return Gradient::TOOL_NAME; case Tool::LOCALLAB: - return "locallab"; + return Locallab::TOOL_NAME; case Tool::PC_VIGNETTE: - return "pcvignette"; + return PCVignette::TOOL_NAME; case Tool::PERSPECTIVE: - return "perspective"; + return PerspCorrection::TOOL_NAME; case Tool::CA_CORRECTION: - return "cacorrection"; + return CACorrection::TOOL_NAME; case Tool::CH_MIXER: - return "chmixer"; + return ChMixer::TOOL_NAME; case Tool::BLACK_WHITE: - return "blackwhite"; + return BlackWhite::TOOL_NAME; case Tool::RESIZE_TOOL: - return "resize"; + return Resize::TOOL_NAME; case Tool::PR_SHARPENING: - return "prsharpening"; + return PrSharpening::TOOL_NAME; case Tool::CROP_TOOL: - return "crop"; + return Crop::TOOL_NAME; case Tool::ICM: - return "icm"; + return ICMPanel::TOOL_NAME; case Tool::WAVELET: - return "wavelet"; + return Wavelet::TOOL_NAME; case Tool::DIR_PYR_EQUALIZER: - return "dirpyrdenoise"; + return DirPyrEqualizer::TOOL_NAME; case Tool::HSV_EQUALIZER: - return "hsvequalizer"; + return HSVEqualizer::TOOL_NAME; case Tool::FILM_SIMULATION: - return "filmsimulation"; + return FilmSimulation::TOOL_NAME; case Tool::SOFT_LIGHT: - return "softlight"; + return SoftLight::TOOL_NAME; case Tool::DEHAZE: - return "dehaze"; + return Dehaze::TOOL_NAME; case Tool::SENSOR_BAYER: - return "sensorbayer"; + return SensorBayer::TOOL_NAME; case Tool::SENSOR_XTRANS: - return "sensorxtrans"; + return SensorXTrans::TOOL_NAME; case Tool::BAYER_PROCESS: - return "bayerprocess"; + return BayerProcess::TOOL_NAME; case Tool::XTRANS_PROCESS: - return "xtransprocess"; + return XTransProcess::TOOL_NAME; case Tool::BAYER_PREPROCESS: - return "bayerpreprocess"; + return BayerPreProcess::TOOL_NAME; case Tool::PREPROCESS: - return "preprocess"; + return PreProcess::TOOL_NAME; case Tool::DARKFRAME_TOOL: - return "darkframe"; + return DarkFrame::TOOL_NAME; case Tool::FLATFIELD_TOOL: - return "flatfield"; + return FlatField::TOOL_NAME; case Tool::RAW_CA_CORRECTION: - return "rawcacorrection"; + return RAWCACorr::TOOL_NAME; case Tool::RAW_EXPOSURE: - return "rawexposure"; + return RAWExposure::TOOL_NAME; case Tool::PREPROCESS_WB: - return "preprocesswb"; + return PreprocessWB::TOOL_NAME; case Tool::BAYER_RAW_EXPOSURE: - return "bayerrawexposure"; + return BayerRAWExposure::TOOL_NAME; case Tool::XTRANS_RAW_EXPOSURE: - return "xtransrawexposure"; + return XTransRAWExposure::TOOL_NAME; case Tool::FATTAL: - return "fattal"; + return FattalToneMapping::TOOL_NAME; case Tool::FILM_NEGATIVE: - return "filmnegative"; + return FilmNegative::TOOL_NAME; case Tool::PD_SHARPENING: - return "capturesharpening"; + return PdSharpening::TOOL_NAME; }; assert(false); return ""; diff --git a/rtgui/vibrance.cc b/rtgui/vibrance.cc index 4a9fab3d3..f2eb8fc4e 100644 --- a/rtgui/vibrance.cc +++ b/rtgui/vibrance.cc @@ -27,7 +27,9 @@ using namespace rtengine; using namespace rtengine::procparams; -Vibrance::Vibrance () : FoldableToolPanel(this, "vibrance", M("TP_VIBRANCE_LABEL"), false, true) +const Glib::ustring Vibrance::TOOL_NAME = "vibrance"; + +Vibrance::Vibrance () : FoldableToolPanel(this, TOOL_NAME, M("TP_VIBRANCE_LABEL"), false, true) { std::vector milestones; diff --git a/rtgui/vibrance.h b/rtgui/vibrance.h index 12acc7948..ee3d029ee 100644 --- a/rtgui/vibrance.h +++ b/rtgui/vibrance.h @@ -57,6 +57,7 @@ protected: sigc::connection pastsattogconn; public: + static const Glib::ustring TOOL_NAME; Vibrance (); ~Vibrance () override; diff --git a/rtgui/vignetting.cc b/rtgui/vignetting.cc index 04a350b99..c2652de42 100644 --- a/rtgui/vignetting.cc +++ b/rtgui/vignetting.cc @@ -23,7 +23,9 @@ using namespace rtengine; using namespace rtengine::procparams; -Vignetting::Vignetting () : FoldableToolPanel(this, "vignetting", M("TP_VIGNETTING_LABEL")) +const Glib::ustring Vignetting::TOOL_NAME = "vignetting"; + +Vignetting::Vignetting () : FoldableToolPanel(this, TOOL_NAME, M("TP_VIGNETTING_LABEL")) { amount = Gtk::manage (new Adjuster (M("TP_VIGNETTING_AMOUNT"), -100, 100, 1, 0)); diff --git a/rtgui/vignetting.h b/rtgui/vignetting.h index be7765094..bcb7f9d19 100644 --- a/rtgui/vignetting.h +++ b/rtgui/vignetting.h @@ -37,6 +37,7 @@ protected: Adjuster* centerY; public: + static const Glib::ustring TOOL_NAME; Vignetting (); diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index f14dd8c8c..e9ee19335 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -34,6 +34,8 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring Wavelet::TOOL_NAME = "wavelet"; + namespace { @@ -62,7 +64,7 @@ std::vector makeWholeHueRange() } Wavelet::Wavelet() : - FoldableToolPanel(this, "wavelet", M("TP_WAVELET_LABEL"), true, true), + FoldableToolPanel(this, TOOL_NAME, M("TP_WAVELET_LABEL"), true, true), curveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CONTEDIT"))), curveEditorC(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CONTRASTEDIT"))), CCWcurveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CCURVE"))), diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index bdbf7bbc3..eee9af91c 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -45,6 +45,8 @@ class Wavelet final : public FoldableToolPanel { public: + static const Glib::ustring TOOL_NAME; + Wavelet(); ~Wavelet() override; bool wavComputed_(); diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc index fbcf40faf..f6a26e335 100644 --- a/rtgui/whitebalance.cc +++ b/rtgui/whitebalance.cc @@ -34,6 +34,8 @@ using namespace rtengine; using namespace rtengine::procparams; +const Glib::ustring WhiteBalance::TOOL_NAME = "whitebalance"; + Glib::RefPtr WhiteBalance::wbPixbufs[toUnderlying(WBEntry::Type::CUSTOM) + 1]; void WhiteBalance::init () @@ -142,7 +144,7 @@ static double wbTemp2Slider(double temp) return sval; } -WhiteBalance::WhiteBalance () : FoldableToolPanel(this, "whitebalance", M("TP_WBALANCE_LABEL"), true, true), wbp(nullptr), wblistener(nullptr) +WhiteBalance::WhiteBalance () : FoldableToolPanel(this, TOOL_NAME, M("TP_WBALANCE_LABEL"), true, true), wbp(nullptr), wblistener(nullptr) { Gtk::Grid* methodgrid = Gtk::manage(new Gtk::Grid()); diff --git a/rtgui/whitebalance.h b/rtgui/whitebalance.h index 1ed99a2aa..f172590c8 100644 --- a/rtgui/whitebalance.h +++ b/rtgui/whitebalance.h @@ -98,6 +98,7 @@ protected: std::pair findWBEntry (const Glib::ustring& label, enum WB_LabelType lblType = WBLT_GUI); public: + static const Glib::ustring TOOL_NAME; WhiteBalance (); ~WhiteBalance () override; diff --git a/rtgui/xtransprocess.cc b/rtgui/xtransprocess.cc index 89fd0f8a4..d6850da63 100644 --- a/rtgui/xtransprocess.cc +++ b/rtgui/xtransprocess.cc @@ -27,7 +27,9 @@ using namespace rtengine; using namespace rtengine::procparams; -XTransProcess::XTransProcess () : FoldableToolPanel(this, "xtransprocess", M("TP_RAW_LABEL"), options.prevdemo != PD_Sidecar) +const Glib::ustring XTransProcess::TOOL_NAME = "xtransprocess"; + +XTransProcess::XTransProcess () : FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_LABEL"), options.prevdemo != PD_Sidecar) { auto m = ProcEventMapper::getInstance(); EvDemosaicBorder = m->newEvent(DEMOSAIC, "HISTORY_MSG_RAW_BORDER"); diff --git a/rtgui/xtransprocess.h b/rtgui/xtransprocess.h index 4725f4a6d..6639a3796 100644 --- a/rtgui/xtransprocess.h +++ b/rtgui/xtransprocess.h @@ -52,6 +52,7 @@ protected: rtengine::ProcEvent EvDemosaicContrast; public: + static const Glib::ustring TOOL_NAME; XTransProcess (); ~XTransProcess () override; diff --git a/rtgui/xtransrawexposure.cc b/rtgui/xtransrawexposure.cc index e1b56b9f0..2e26b8f63 100644 --- a/rtgui/xtransrawexposure.cc +++ b/rtgui/xtransrawexposure.cc @@ -27,7 +27,9 @@ using namespace rtengine; using namespace rtengine::procparams; -XTransRAWExposure::XTransRAWExposure () : FoldableToolPanel(this, "xtransrawexposure", M("TP_EXPOS_BLACKPOINT_LABEL")) +const Glib::ustring XTransRAWExposure::TOOL_NAME = "xtransrawexposure"; + +XTransRAWExposure::XTransRAWExposure () : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOS_BLACKPOINT_LABEL")) { PexBlackRed = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_RED"), -2048, 2048, 1.0, 0)); //black level PexBlackRed->setAdjusterListener (this); diff --git a/rtgui/xtransrawexposure.h b/rtgui/xtransrawexposure.h index a8daf6972..c332bc510 100644 --- a/rtgui/xtransrawexposure.h +++ b/rtgui/xtransrawexposure.h @@ -37,6 +37,7 @@ protected: private: // Gtk::CheckButton* PextwoGreen; public: + static const Glib::ustring TOOL_NAME; XTransRAWExposure (); From 697af1fcb3d2c4d742fa03a60c7902d888853b10 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 12 Dec 2021 16:27:43 -0800 Subject: [PATCH 16/24] Fix tool location updater optimization --- rtgui/toolpanelcoord.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 7d98d0dc1..df28ca21f 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -828,6 +828,7 @@ ToolPanelCoordinator::updateToolPanel( getFoldableToolPanel(*new_tool_trees_iter)->getExpander()) { break; } + ++new_tool_trees_iter; ++old_widgets_iter; } From 901f4e4f6340b84b5c68d43dfb37028e1818bc25 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 12 Dec 2021 17:09:01 -0800 Subject: [PATCH 17/24] Fix memory leak --- rtgui/toolpanelcoord.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index df28ca21f..592c4c97e 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -884,6 +884,17 @@ ToolPanelCoordinator::~ToolPanelCoordinator () // which is responsible of segfault if listener isn't deactivated before notebookconn.block(true); + // Foldable tool panels manage (Gtk::manage) their expanders. Each expander + // will only be automatically deleted if attached to a parent and the parent + // is deleted. This is a hack in lieu of a potentially tedious refactoring + // of FoldableToolPanel. + std::unique_ptr hidden_tool_panel_parent(new Gtk::Box()); + for (const auto expander : expList) { + if (!expander->get_parent()) { + hidden_tool_panel_parent->add(*expander); + } + } + delete toolPanelNotebook; delete toolBar; } From d29b451aa643022f54ffebf14fadfe7a514c03e7 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 12 Dec 2021 17:09:53 -0800 Subject: [PATCH 18/24] Hide local adjustments from batch process favorite --- rtgui/toolpanelcoord.cc | 7 ++++--- rtgui/toolpanelcoord.h | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 592c4c97e..360aca7a0 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -271,7 +271,7 @@ const ToolPanelCoordinator::ToolLayout PANEL_TOOLS = { std::unordered_map ToolPanelCoordinator::toolNamesReverseMap; -ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favoritePanelSW(nullptr), hasChanged (false), editDataProvider (nullptr), photoLoadedOnce(false) +ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favoritePanelSW(nullptr), hasChanged (false), batch(batch), editDataProvider (nullptr), photoLoadedOnce(false) { favoritePanel = Gtk::manage (new ToolVBox ()); @@ -812,8 +812,9 @@ ToolPanelCoordinator::updateToolPanel( // if they are sub-tools within the favorites panel, or if tool cloning is // off and they are not within the favorites panel. const auto should_skip_tool = - [skip_favorites, &favorites](const ToolTree &tool_tree) { - return skip_favorites && favorites.count(tool_tree.id); + [this, skip_favorites, &favorites](const ToolTree &tool_tree) { + return (skip_favorites && favorites.count(tool_tree.id)) || + (batch && tool_tree.id == Tool::LOCALLAB); }; // Keep tools that are already correct. diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index cd354738e..fda89ef37 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -212,6 +212,7 @@ protected: std::vector expList; bool hasChanged; + bool batch; void addPanel(Gtk::Box* where, FoldableToolPanel* panel, int level = 1); void foldThemAll(GdkEventButton* event); From 012103b4e2d8aa0dba38dc5ccdd4ea668e20198c Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 12 Dec 2021 17:50:12 -0800 Subject: [PATCH 19/24] Fix update of tool locations after changing pref Only the editor panel in single editor mode was being updated. This commit makes them update in multiple editor mode and also updates the batch editor. --- rtgui/editwindow.cc | 8 ++++++++ rtgui/editwindow.h | 2 ++ rtgui/filepanel.cc | 8 ++++++++ rtgui/filepanel.h | 2 ++ rtgui/rtwindow.cc | 13 +++++++++++++ 5 files changed, 33 insertions(+) diff --git a/rtgui/editwindow.cc b/rtgui/editwindow.cc index d0e53d730..4ba1b369a 100644 --- a/rtgui/editwindow.cc +++ b/rtgui/editwindow.cc @@ -485,3 +485,11 @@ void EditWindow::set_title_decorated(Glib::ustring fname) set_title("RawTherapee " + M("EDITWINDOW_TITLE") + subtitle); } + +void EditWindow::updateToolPanelToolLocations( + const std::vector &favorites, bool cloneFavoriteTools) +{ + for (const auto& panel : epanels) { + panel.second->updateToolPanelToolLocations(favorites, cloneFavoriteTools); + } +} diff --git a/rtgui/editwindow.h b/rtgui/editwindow.h index b8eeaee82..b9304c5af 100644 --- a/rtgui/editwindow.h +++ b/rtgui/editwindow.h @@ -64,6 +64,8 @@ public: bool selectEditorPanel(const std::string &name); bool closeOpenEditors(); bool isProcessing(); + void updateToolPanelToolLocations( + const std::vector &favorites, bool cloneFavoriteTools); void toFront(); bool keyPressed (GdkEventKey* event); diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index 682dd1746..63ebd5632 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -436,3 +436,11 @@ void FilePanel::updateTPVScrollbar (bool hide) { tpc->updateTPVScrollbar (hide); } + +void FilePanel::updateToolPanelToolLocations( + const std::vector &favorites, bool cloneFavoriteTools) +{ + if (tpc) { + tpc->updateToolLocations(favorites, cloneFavoriteTools); + } +} diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h index ba5dfa7c9..4a006f002 100644 --- a/rtgui/filepanel.h +++ b/rtgui/filepanel.h @@ -83,6 +83,8 @@ public: bool handleShortcutKey (GdkEventKey* event); bool handleShortcutKeyRelease(GdkEventKey *event); void updateTPVScrollbar (bool hide); + void updateToolPanelToolLocations( + const std::vector &favorites, bool cloneFavoriteTools); private: void on_NB_switch_page(Gtk::Widget* page, guint page_num); diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index f3eb658e5..8dfb18b12 100755 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -1113,9 +1113,22 @@ void RTWindow::updateHistogramPosition (int oldPosition, int newPosition) void RTWindow::updateToolPanelToolLocations( const std::vector &favorites, bool cloneFavoriteTools) { + if (fpanel) { + fpanel->updateToolPanelToolLocations(favorites, cloneFavoriteTools); + } + if (epanel) { epanel->updateToolPanelToolLocations(favorites, cloneFavoriteTools); } + + for (const auto &panel : epanels) { + panel.second->updateToolPanelToolLocations(favorites, cloneFavoriteTools); + } + + if (options.multiDisplayMode > 0) { + EditWindow::getInstance(this) + ->updateToolPanelToolLocations(favorites, cloneFavoriteTools); + } } bool RTWindow::splashClosed (GdkEventAny* event) From a7010d25cd88ce15b558d3c20fb61868798e555d Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 19 Dec 2021 14:51:47 -0800 Subject: [PATCH 20/24] Fix theme margins Fix spacing that was changed due to the restructuring of foldable tool panels. --- .../themes/RawTherapee - Legacy-GTK3-20_.css | 31 ++++++++++++++--- rtdata/themes/RawTherapee-GTK3-20_.css | 27 +++++++++++++++ rtdata/themes/TooWaBlue-GTK3-20_.css | 3 ++ rtgui/lensgeom.cc | 3 -- rtgui/lensgeom.h | 6 ---- rtgui/resize.cc | 10 +++--- rtgui/resize.h | 6 ---- rtgui/sensorbayer.cc | 3 -- rtgui/sensorbayer.h | 8 ----- rtgui/sensorxtrans.cc | 3 -- rtgui/sensorxtrans.h | 8 ----- rtgui/toolpanel.cc | 6 ++-- rtgui/toolpanel.h | 6 ++-- rtgui/toolpanelcoord.cc | 33 ++++++++++--------- 14 files changed, 85 insertions(+), 68 deletions(-) diff --git a/rtdata/themes/RawTherapee - Legacy-GTK3-20_.css b/rtdata/themes/RawTherapee - Legacy-GTK3-20_.css index dd7be3bfd..07a0bd65d 100644 --- a/rtdata/themes/RawTherapee - Legacy-GTK3-20_.css +++ b/rtdata/themes/RawTherapee - Legacy-GTK3-20_.css @@ -760,6 +760,23 @@ button.radio#histButton:hover { margin-right: 0.25em; } +/* ExpanderContents is just a logical container. Don't add additional spacing. */ +#ExpanderBox > .ExpanderContents > * { + margin: 0; + min-height: 0; + padding: 0; +} + +/* For sub-tools containers that go below another widget, add some margin + * between them if the container has children. */ +#MyExpander .SubToolsContainer:not(:first-child) > :first-child { + margin-top: 0.1666666666666666em; +} + +#MyExpander .SubToolsContainer { + min-height: 0; +} + /* Tool background */ #ExpanderBox > box, #ExpanderBox > grid { background-color: #363636; @@ -808,9 +825,11 @@ button.radio#histButton:hover { } #LocallabToolPanel > box > checkbutton, #LocallabToolPanel > box > box, #LocallabToolPanel > grid > checkbutton, #LocallabToolPanel > box > grid, #LocallabToolPanel > grid > grid, #LocallabToolPanel frame > box > grid, #LocallabToolPanel frame > grid > grid, #LocallabToolPanel frame > grid > box, -#ExpanderBox > box > checkbutton, #ExpanderBox > box > box, #ExpanderBox > grid > checkbutton, #ExpanderBox > box > grid, #ExpanderBox > grid > grid, #ExpanderBox frame > box > grid, #ExpanderBox frame > grid > grid, #ExpanderBox frame > grid > box, -#ExpanderBox2 > box > checkbutton, #ExpanderBox2 > box > box, #ExpanderBox2 > grid > checkbutton, #ExpanderBox2 > box > grid, #ExpanderBox2 > grid > grid, #ExpanderBox2 frame > box > grid, #ExpanderBox2 frame > grid > grid, #ExpanderBox2 frame > grid > box, -#ExpanderBox3 > box > checkbutton, #ExpanderBox3 > box > box, #ExpanderBox3 > grid > checkbutton, #ExpanderBox3 > box > grid, #ExpanderBox3 > grid > grid, #ExpanderBox3 frame > box > grid, #ExpanderBox3 frame > grid > grid, #ExpanderBox3 frame > grid > box { +#ExpanderBox > .ExpanderContents > box:not(.SubToolsContainer) > checkbutton, #ExpanderBox > .ExpanderContents > box:not(.SubToolsContainer) > box, #ExpanderBox > .ExpanderContents > grid > checkbutton, #ExpanderBox > .ExpanderContents > box:not(.SubToolsContainer) > grid, #ExpanderBox > .ExpanderContents > grid > grid, #ExpanderBox frame > box > grid, #ExpanderBox frame > grid > grid, #ExpanderBox frame > grid > box, +#ExpanderBox2 > .ExpanderContents > box:not(.SubToolsContainer) > checkbutton, #ExpanderBox2 > .ExpanderContents > box:not(.SubToolsContainer) > box, #ExpanderBox2 > .ExpanderContents > grid > checkbutton, #ExpanderBox2 > .ExpanderContents > box:not(.SubToolsContainer) > grid, #ExpanderBox2 > .ExpanderContents > grid > grid, #ExpanderBox2 frame > box > grid, #ExpanderBox2 frame > grid > grid, #ExpanderBox2 frame > grid > box, +#ExpanderBox2 > box:not(.ExpanderContents) > checkbutton, #ExpanderBox2 > box:not(.ExpanderContents) > box, #ExpanderBox2 > grid > checkbutton, #ExpanderBox2 > box:not(.ExpanderContents) > grid, #ExpanderBox2 > grid > grid, #ExpanderBox2 frame > box > grid, #ExpanderBox2 frame > grid > grid, #ExpanderBox2 frame > grid > box, +#ExpanderBox3 > .ExpanderContents > box:not(.SubToolsContainer) > checkbutton, #ExpanderBox3 > .ExpanderContents > box:not(.SubToolsContainer) > box, #ExpanderBox3 > .ExpanderContents > grid > checkbutton, #ExpanderBox3 > .ExpanderContents > box:not(.SubToolsContainer) > grid, #ExpanderBox3 > .ExpanderContents > grid > grid, #ExpanderBox3 frame > box > grid, #ExpanderBox3 frame > grid > grid, #ExpanderBox3 frame > grid > box, +#ExpanderBox3 > box:not(.ExpanderContents) > checkbutton, #ExpanderBox3 > box:not(.ExpanderContents) > box, #ExpanderBox3 > grid > checkbutton, #ExpanderBox3 > box:not(.ExpanderContents) > grid, #ExpanderBox3 > grid > grid, #ExpanderBox3 frame > box > grid, #ExpanderBox3 frame > grid > grid, #ExpanderBox3 frame > grid > box { margin-top: 0.1666666666666666em; } @@ -1099,6 +1118,10 @@ dialog frame > label:not(.dummy) { min-width: 25em; } +#ToolPanelNotebook .PanelEnding { + margin-top: 4px; +} + #ToolPanelNotebook header { background-color: #383838; border-color: #262626; @@ -1395,4 +1418,4 @@ progressbar progress { .grid-spacing > * { margin: 0.1666666666666666em; -} \ No newline at end of file +} diff --git a/rtdata/themes/RawTherapee-GTK3-20_.css b/rtdata/themes/RawTherapee-GTK3-20_.css index c576e0ddf..2e314510a 100644 --- a/rtdata/themes/RawTherapee-GTK3-20_.css +++ b/rtdata/themes/RawTherapee-GTK3-20_.css @@ -766,6 +766,29 @@ button.radio#histButton:hover { border-bottom: none; } +/* ExpanderContents is just a logical container. Don't add additional spacing. */ +#ExpanderBox > .ExpanderContents > * { + margin: 0; + min-height: 0; + padding: 0; +} + +/* For sub-tools containers that go below another widget, add some margin + * between them if the container has children. */ +#MyExpander .SubToolsContainer:not(:first-child) > :first-child { + margin-top: 0.3333333333333333em; +} + +#MyExpander .SubToolsContainer { + min-height: 0; +} + +.SubToolsContainer > #MyExpander, +.ToolParamBlock > #MyExpander, +.ExpanderContents, +#MyExpander .ToolParamBlock { + margin: 0; +} /* Tool background */ #ExpanderBox > box, @@ -1046,6 +1069,10 @@ dialog frame > label:not(.dummy) { padding: 0; } +#ToolPanelNotebook .PanelEnding { + margin-top: 4px; +} + #ToolPanelNotebook header tabs { padding: 0.0833333333333333em; background-color: #2A2A2A; diff --git a/rtdata/themes/TooWaBlue-GTK3-20_.css b/rtdata/themes/TooWaBlue-GTK3-20_.css index 4e7e192ad..2e9c6ccde 100644 --- a/rtdata/themes/TooWaBlue-GTK3-20_.css +++ b/rtdata/themes/TooWaBlue-GTK3-20_.css @@ -963,6 +963,9 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #ToolPanelNotebook { background-color: @bg-dark-grey; } +#ToolPanelNotebook .PanelEnding { + margin-top: 4px; +} #ToolPanelNotebook > header { border-bottom: 0.083333333333333333em solid @view-grid-border; margin-left: 0.083333333333333333em; diff --git a/rtgui/lensgeom.cc b/rtgui/lensgeom.cc index 6b9d70fb0..e8febf8e2 100644 --- a/rtgui/lensgeom.cc +++ b/rtgui/lensgeom.cc @@ -52,9 +52,6 @@ LensGeometry::LensGeometry () : FoldableToolPanel(this, TOOL_NAME, M("TP_LENSGEO autoCrop->get_style_context()->add_class("independent"); pack_start (*autoCrop, Gtk::PACK_SHRINK, 2); - packBox = Gtk::manage (new ToolParamBlock ()); - pack_start (*packBox); - method->connect(method->signal_changed().connect(sigc::mem_fun(*this, &LensGeometry::methodChanged))); autoCrop->signal_pressed().connect(sigc::mem_fun(*this, &LensGeometry::autoCropPressed)); fillConn = fill->signal_toggled().connect(sigc::mem_fun(*this, &LensGeometry::fillPressed)); diff --git a/rtgui/lensgeom.h b/rtgui/lensgeom.h index e8f85faac..fa260e177 100644 --- a/rtgui/lensgeom.h +++ b/rtgui/lensgeom.h @@ -35,7 +35,6 @@ protected: Gtk::CheckButton* fill; bool lastFill; sigc::connection fillConn; - ToolParamBlock* packBox; rtengine::ProcEvent EvTransMethod; public: @@ -44,11 +43,6 @@ public: LensGeometry (); ~LensGeometry () override; - Gtk::Box* getPackBox () - { - return packBox; - } - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; void setBatchMode (bool batchMode) override; diff --git a/rtgui/resize.cc b/rtgui/resize.cc index 258ccf791..de9f6b4d1 100644 --- a/rtgui/resize.cc +++ b/rtgui/resize.cc @@ -172,10 +172,8 @@ Resize::Resize () : FoldableToolPanel(this, TOOL_NAME, M("TP_RESIZE_LABEL"), fal method->signal_changed().connect ( sigc::mem_fun(*this, &Resize::methodChanged) ); sconn = spec->signal_changed().connect ( sigc::mem_fun(*this, &Resize::specChanged) ); - packBox = Gtk::manage (new ToolParamBlock ()); - pack_end (*packBox); - packBox->hide(); - packBox->set_tooltip_markup (M("TP_PRSHARPENING_TOOLTIP")); + getSubToolsContainer()->hide(); + getSubToolsContainer()->set_tooltip_markup (M("TP_PRSHARPENING_TOOLTIP")); show_all(); } @@ -398,9 +396,9 @@ void Resize::methodChanged () // Post-resize Sharpening assumes the image is in Lab space, and currently Lanczos is the only method which uses that space, and Lanczos is on row 0. if (method->get_active_row_number() == 0) { - packBox->set_sensitive(true); + getSubToolsContainer()->set_sensitive(true); } else { - packBox->set_sensitive(false); + getSubToolsContainer()->set_sensitive(false); } } diff --git a/rtgui/resize.h b/rtgui/resize.h index 71fefb503..674bbb34f 100644 --- a/rtgui/resize.h +++ b/rtgui/resize.h @@ -37,11 +37,6 @@ public: Resize (); ~Resize () override; - Gtk::Box* getPackBox () - { - return packBox; - } - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; @@ -89,7 +84,6 @@ private: int cropw, croph; sigc::connection sconn, aconn, wconn, hconn, leconn, seconn; bool wDirty, hDirty, leDirty, seDirty; - ToolParamBlock* packBox; IdleRegister idle_register; static constexpr int MAX_SCALE = 16; // 16 to match the main preview max scale of 1600% diff --git a/rtgui/sensorbayer.cc b/rtgui/sensorbayer.cc index 002cdf1de..70537f666 100644 --- a/rtgui/sensorbayer.cc +++ b/rtgui/sensorbayer.cc @@ -25,8 +25,5 @@ const Glib::ustring SensorBayer::TOOL_NAME = "sensorbayer"; SensorBayer::SensorBayer () : FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_SENSOR_BAYER_LABEL")) { - packBox = Gtk::manage (new ToolParamBlock ()); - pack_start (*packBox); - show_all (); } diff --git a/rtgui/sensorbayer.h b/rtgui/sensorbayer.h index 0e65b8b38..d3d867ace 100644 --- a/rtgui/sensorbayer.h +++ b/rtgui/sensorbayer.h @@ -27,16 +27,8 @@ class SensorBayer final : public FoldableToolPanel { -protected: - ToolParamBlock* packBox; - public: static const Glib::ustring TOOL_NAME; SensorBayer (); - - Gtk::Box* getPackBox () - { - return packBox; - } }; diff --git a/rtgui/sensorxtrans.cc b/rtgui/sensorxtrans.cc index c4a5bf76d..45e5d57e4 100644 --- a/rtgui/sensorxtrans.cc +++ b/rtgui/sensorxtrans.cc @@ -25,8 +25,5 @@ const Glib::ustring SensorXTrans::TOOL_NAME = "sensorxtrans"; SensorXTrans::SensorXTrans () : FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_SENSOR_XTRANS_LABEL")) { - packBox = Gtk::manage (new ToolParamBlock ()); - pack_start (*packBox); - show_all (); } diff --git a/rtgui/sensorxtrans.h b/rtgui/sensorxtrans.h index 12c851db3..2e5c10483 100644 --- a/rtgui/sensorxtrans.h +++ b/rtgui/sensorxtrans.h @@ -27,16 +27,8 @@ class SensorXTrans final: public FoldableToolPanel { -protected: - ToolParamBlock* packBox; - public: static const Glib::ustring TOOL_NAME; SensorXTrans (); - - Gtk::Box* getPackBox () - { - return packBox; - } }; diff --git a/rtgui/toolpanel.cc b/rtgui/toolpanel.cc index bf191133d..6db30bb14 100644 --- a/rtgui/toolpanel.cc +++ b/rtgui/toolpanel.cc @@ -38,6 +38,7 @@ ToolVBox::ToolVBox() { ToolParamBlock::ToolParamBlock() { set_orientation(Gtk::ORIENTATION_VERTICAL); + get_style_context()->add_class("ToolParamBlock"); //GTK318 #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 20 set_spacing(2); // Vertical space between parameters in a single tool @@ -75,8 +76,9 @@ FoldableToolPanel::FoldableToolPanel(Gtk::Box* content, Glib::ustring toolName, Gtk::Box *expanderContents = Gtk::manage( new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); - subToolsContainer = Gtk::manage( - new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); + subToolsContainer = Gtk::manage(new ToolParamBlock()); + subToolsContainer->get_style_context()->add_class("SubToolsContainer"); + expanderContents->get_style_context()->add_class("ExpanderContents"); expanderContents->pack_start(*content, false, false, 0); expanderContents->pack_start(*subToolsContainer, false, false, 0); diff --git a/rtgui/toolpanel.h b/rtgui/toolpanel.h index ce14dc64f..5ec59c9c2 100644 --- a/rtgui/toolpanel.h +++ b/rtgui/toolpanel.h @@ -98,7 +98,7 @@ public: { return nullptr; } - virtual Gtk::Box *getSubToolsContainer() const + virtual ToolParamBlock *getSubToolsContainer() const { return nullptr; } @@ -168,7 +168,7 @@ class FoldableToolPanel : protected: Gtk::Box* parentContainer; MyExpander* exp; - Gtk::Box *subToolsContainer; + ToolParamBlock *subToolsContainer; bool lastEnabled; sigc::connection enaConn; void foldThemAll (GdkEventButton* event); @@ -183,7 +183,7 @@ public: return exp; } - Gtk::Box *getSubToolsContainer() const final + ToolParamBlock *getSubToolsContainer() const final { return subToolsContainer; } diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 360aca7a0..cd04583c9 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -400,6 +400,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit vbPanelEnd[i] = Gtk::manage (new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); imgPanelEnd[i] = Gtk::manage (new RTImage ("ornament1.png")); imgPanelEnd[i]->show(); + vbPanelEnd[i]->get_style_context()->add_class("PanelEnding"); vbPanelEnd[i]->pack_start(*imgPanelEnd[i], Gtk::PACK_SHRINK); vbPanelEnd[i]->show_all(); } @@ -423,37 +424,37 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL)); favoritePanelSW->add(*favoritePanelContainer); - favoritePanelContainer->pack_start(*favoritePanel, Gtk::PACK_SHRINK, 0); - favoritePanelContainer->pack_start(*vbPanelEnd[0], Gtk::PACK_SHRINK, 4); + favoritePanelContainer->pack_start(*favoritePanel, Gtk::PACK_SHRINK); + favoritePanelContainer->pack_start(*vbPanelEnd[0], Gtk::PACK_SHRINK); favoritePanelSW->show_all(); exposurePanelSW->add (*exposurePanelContainer); - exposurePanelContainer->pack_start(*exposurePanel, Gtk::PACK_SHRINK, 0); - exposurePanelContainer->pack_start (*vbPanelEnd[1], Gtk::PACK_SHRINK, 4); + exposurePanelContainer->pack_start(*exposurePanel, Gtk::PACK_SHRINK); + exposurePanelContainer->pack_start (*vbPanelEnd[1], Gtk::PACK_SHRINK); detailsPanelSW->add (*detailsPanelContainer); - detailsPanelContainer->pack_start(*detailsPanel, Gtk::PACK_SHRINK, 0); - detailsPanelContainer->pack_start (*vbPanelEnd[2], Gtk::PACK_SHRINK, 4); + detailsPanelContainer->pack_start(*detailsPanel, Gtk::PACK_SHRINK); + detailsPanelContainer->pack_start (*vbPanelEnd[2], Gtk::PACK_SHRINK); colorPanelSW->add (*colorPanelContainer); - colorPanelContainer->pack_start(*colorPanel, Gtk::PACK_SHRINK, 0); - colorPanelContainer->pack_start (*vbPanelEnd[3], Gtk::PACK_SHRINK, 4); + colorPanelContainer->pack_start(*colorPanel, Gtk::PACK_SHRINK); + colorPanelContainer->pack_start (*vbPanelEnd[3], Gtk::PACK_SHRINK); advancedPanelSW->add (*advancedPanelContainer); - advancedPanelContainer->pack_start(*advancedPanel, Gtk::PACK_SHRINK, 0); - advancedPanelContainer->pack_start (*vbPanelEnd[6], Gtk::PACK_SHRINK, 0); + advancedPanelContainer->pack_start(*advancedPanel, Gtk::PACK_SHRINK); + advancedPanelContainer->pack_start (*vbPanelEnd[6], Gtk::PACK_SHRINK); locallabPanelSW->add(*locallabPanelContainer); - locallabPanelContainer->pack_start(*locallabPanel, Gtk::PACK_SHRINK, 0); - locallabPanelContainer->pack_start(*vbPanelEnd[7], Gtk::PACK_SHRINK, 4); + locallabPanelContainer->pack_start(*locallabPanel, Gtk::PACK_SHRINK); + locallabPanelContainer->pack_start(*vbPanelEnd[7], Gtk::PACK_SHRINK); transformPanelSW->add (*transformPanelContainer); - transformPanelContainer->pack_start(*transformPanel, Gtk::PACK_SHRINK, 0); - transformPanelContainer->pack_start (*vbPanelEnd[4], Gtk::PACK_SHRINK, 4); + transformPanelContainer->pack_start(*transformPanel, Gtk::PACK_SHRINK); + transformPanelContainer->pack_start (*vbPanelEnd[4], Gtk::PACK_SHRINK); rawPanelSW->add (*rawPanelContainer); - rawPanelContainer->pack_start(*rawPanel, Gtk::PACK_SHRINK, 0); - rawPanelContainer->pack_start (*vbPanelEnd[5], Gtk::PACK_SHRINK, 0); + rawPanelContainer->pack_start(*rawPanel, Gtk::PACK_SHRINK); + rawPanelContainer->pack_start (*vbPanelEnd[5], Gtk::PACK_SHRINK); toiF.reset(new TextOrIcon ("star.png", M ("MAIN_TAB_FAVORITES"), M ("MAIN_TAB_FAVORITES_TOOLTIP"))); toiE = Gtk::manage (new TextOrIcon ("exposure.png", M ("MAIN_TAB_EXPOSURE"), M ("MAIN_TAB_EXPOSURE_TOOLTIP"))); From 6a0067d7387365fc094ed66a698b46b771e84c34 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Fri, 24 Dec 2021 16:03:58 -0800 Subject: [PATCH 21/24] Disable favorite tool cloning by default Also add tooltip stating that tool cloning may cause a delay while switching between tabs. --- rtdata/languages/default | 1 + rtgui/options.cc | 2 +- rtgui/toollocationpref.cc | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index bd65781a8..d409c4393 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1902,6 +1902,7 @@ PREFERENCES_THUMBNAIL_INSPECTOR_RAW;Neutral raw rendering PREFERENCES_THUMBNAIL_INSPECTOR_RAW_IF_NO_JPEG_FULLSIZE;Embedded JPEG if fullsize, neutral raw otherwise PREFERENCES_TOOLPANEL_AVAILABLETOOLS;Available Tools PREFERENCES_TOOLPANEL_CLONE_FAVORITES;Keep favorite tools in original locations +PREFERENCES_TOOLPANEL_CLONE_FAVORITES_TOOLTIP;If set, favorite tools will appear in both the favorites tab and their original tabs.\n\nNote: Enabling this option may result in a slight delay when switching tabs. PREFERENCES_TOOLPANEL_FAVORITE;Favorite PREFERENCES_TOOLPANEL_FAVORITESPANEL;Favorites Panel PREFERENCES_TOOLPANEL_TOOL;Tool diff --git a/rtgui/options.cc b/rtgui/options.cc index b5463949a..f597d3a1c 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -424,7 +424,7 @@ void Options::setDefaults() //crvOpen.clear (); parseExtensions.clear(); favorites.clear(); - cloneFavoriteTools = true; + cloneFavoriteTools = false; parseExtensionsEnabled.clear(); parsedExtensions.clear(); parsedExtensionsSet.clear(); diff --git a/rtgui/toollocationpref.cc b/rtgui/toollocationpref.cc index cf2386257..cf25dbc34 100644 --- a/rtgui/toollocationpref.cc +++ b/rtgui/toollocationpref.cc @@ -532,6 +532,8 @@ ToolLocationPreference::Impl::Impl(Options &options) : // General options. cloneFavoriteToolsToggleWidget->set_active(options.cloneFavoriteTools); + cloneFavoriteToolsToggleWidget->set_tooltip_text( + M("PREFERENCES_TOOLPANEL_CLONE_FAVORITES_TOOLTIP")); // Tool list. toolListViewPtr->append_column(toolListViewColumnToolName); From a3adbce04b91f2cbb892d810df92805b216db4d2 Mon Sep 17 00:00:00 2001 From: "U-PCSPECIALIST01\\jdesm" Date: Mon, 6 Feb 2023 19:00:14 +0100 Subject: [PATCH 22/24] Support for Nikon Z9 --- rtengine/camconst.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 7a143e850..07f08d9a6 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -1973,6 +1973,11 @@ Camera constants: "dcraw_matrix" : [13705, -6004, -1401, -5464, 13568, 2062, -940, 1706, 7618] // DNG }, + { // Quality C + "make_model" : "NIKON Z 9", + "dcraw_matrix" : [13389, -6049, -1441, -4544, 12757, 1969, 229, 498, 7390] //DNG + }, + { // Quality C, only color matrix and PDAF lines info "make_model" : "Nikon Z 6", "dcraw_matrix" : [8210, -2534, -683, -5355, 13338, 2212, -1143, 1928, 6464], // DNG v13.2 From e5d46032ffbe8b21946019203260ab1aefe9c483 Mon Sep 17 00:00:00 2001 From: Desmis Date: Thu, 9 Feb 2023 07:14:20 +0100 Subject: [PATCH 23/24] Add "Inpaint opposed" to Highlight reconstruction and improved Itcwb (#6635) * Essai HL * Try Inpaint opposed * Code improvment * Add file * Improvment to process inpaint opposed and color propagation * Clean code * Change Blend to Coloropp in Profile pp3 * Enable BENCHFUN hilite_recon * Clean rtengine cmakelist * Comment unused code * Neutralise unused code * Change bad Exposure in Pop2Lab.pp3 * Try to fix bug when Inpaint Opposed is used and White balance disabled * Changes to refreshmap * Change to improccoordinator M_RETINEX * Clean unused commented code * Force Inpaint-opposed in rawimagesouce if wb change * Suppressed message in console * Change events and limits to 1 the number of calls to inpaint-opposed * Comment code * Add gain theshold to inpaint opposed * fixed typo in procparams.cc * Change in option.cc itcwb_sort to true * Change itcw sorted in options and rawimagesource.cc * Change sampling read datas Itcwb * Allow or not purple in WB itcwb * Added option icwb.nopurple to bypass settings * Added code comment Itcwb * optimize Itcwb between green and student * Formated code used by Itcwb with Astylert.bat * Change color_match - thanks to Lawrence37 * Remove wrong text --- rtdata/languages/default | 3 + .../Auto-Matched Curve - ISO High.pp3 | 2 +- .../profiles/Auto-Matched Curve - ISO Low.pp3 | 2 +- .../Auto-Matched Curve - ISO Medium.pp3 | 2 +- .../Film Negative - Black and White.pp3 | 2 +- rtdata/profiles/Film Negative.pp3 | 2 +- rtdata/profiles/Pop/Pop 1.pp3 | 2 +- rtdata/profiles/Pop/Pop 2 Lab.pp3 | 2 +- rtdata/profiles/Pop/Pop 3 Skin.pp3 | 2 +- rtdata/profiles/Pop/Pop 4 Black-and-White.pp3 | 2 +- .../Standard Film Curve - ISO High.pp3 | 2 +- .../Standard Film Curve - ISO Low.pp3 | 2 +- .../Standard Film Curve - ISO Medium.pp3 | 2 +- rtengine/clutstore.cc | 2 +- rtengine/colortemp.cc | 91 +- rtengine/colortemp.h | 14 +- rtengine/dcrop.cc | 12 +- rtengine/filmnegativeproc.cc | 2 +- rtengine/hilite_recon.cc | 373 ++++++- rtengine/iimage.h | 2 +- rtengine/imagesource.h | 9 +- rtengine/improccoordinator.cc | 29 +- rtengine/iplocallab.cc | 2 +- rtengine/linalgebra.h | 275 ++++++ rtengine/perspectivecorrection.cc | 2 +- rtengine/previewimage.cc | 2 +- rtengine/procparams.cc | 7 +- rtengine/procparams.h | 1 + rtengine/rawimagesource.cc | 927 +++++++++++------- rtengine/rawimagesource.h | 14 +- rtengine/refreshmap.cc | 2 +- rtengine/rtthumbnail.cc | 2 +- rtengine/settings.h | 4 +- rtengine/simpleprocess.cc | 8 +- rtengine/spot.cc | 4 +- rtengine/stdimagesource.cc | 22 +- rtengine/stdimagesource.h | 8 +- rtgui/options.cc | 22 +- rtgui/paramsedited.cc | 6 + rtgui/paramsedited.h | 1 + rtgui/tonecurve.cc | 80 +- rtgui/tonecurve.h | 2 + 42 files changed, 1455 insertions(+), 497 deletions(-) create mode 100644 rtengine/linalgebra.h diff --git a/rtdata/languages/default b/rtdata/languages/default index 68fda352b..84b28c955 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1417,6 +1417,7 @@ HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values HISTORY_MSG_GAMUTMUNSEL;Gamut-Munsell HISTORY_MSG_HISTMATCHING;Auto-matched tone curve HISTORY_MSG_HLBL;Color propagation - blur +HISTORY_MSG_HLTH;Inpaint opposed - gain threshold HISTORY_MSG_ICL_LABGRIDCIEXY;Cie xy HISTORY_MSG_ICM_AINTENT;Abstract profile intent HISTORY_MSG_ICM_BLUX;Primaries Blue X @@ -2518,8 +2519,10 @@ TP_GRADIENT_STRENGTH_TOOLTIP;Filter strength in stops. TP_HLREC_BLEND;Blend TP_HLREC_CIELAB;CIELab Blending TP_HLREC_COLOR;Color Propagation +TP_HLREC_COLOROPP;Inpaint Opposed TP_HLREC_ENA_TOOLTIP;Could be activated by Auto Levels. TP_HLREC_HLBLUR;Blur +TP_HLREC_HLTH;Gain threshold TP_HLREC_LABEL;Highlight reconstruction TP_HLREC_LUMINANCE;Luminance Recovery TP_HLREC_METHOD;Method: diff --git a/rtdata/profiles/Auto-Matched Curve - ISO High.pp3 b/rtdata/profiles/Auto-Matched Curve - ISO High.pp3 index 99f0af8fe..16c9a71f5 100644 --- a/rtdata/profiles/Auto-Matched Curve - ISO High.pp3 +++ b/rtdata/profiles/Auto-Matched Curve - ISO High.pp3 @@ -4,7 +4,7 @@ HistogramMatching=true [HLRecovery] Enabled=true -Method=Blend +Method=Coloropp [Directional Pyramid Denoising] Enabled=true diff --git a/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3 b/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3 index c94077b21..e6c7fb96c 100644 --- a/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3 +++ b/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3 @@ -4,7 +4,7 @@ HistogramMatching=true [HLRecovery] Enabled=true -Method=Blend +Method=Coloropp [LensProfile] LcMode=lfauto diff --git a/rtdata/profiles/Auto-Matched Curve - ISO Medium.pp3 b/rtdata/profiles/Auto-Matched Curve - ISO Medium.pp3 index f9196bb30..ffb5587b9 100644 --- a/rtdata/profiles/Auto-Matched Curve - ISO Medium.pp3 +++ b/rtdata/profiles/Auto-Matched Curve - ISO Medium.pp3 @@ -4,7 +4,7 @@ HistogramMatching=true [HLRecovery] Enabled=true -Method=Blend +Method=Coloropp [Directional Pyramid Denoising] Enabled=true diff --git a/rtdata/profiles/Film Negative - Black and White.pp3 b/rtdata/profiles/Film Negative - Black and White.pp3 index ad2a38e1e..3bebe7e3c 100644 --- a/rtdata/profiles/Film Negative - Black and White.pp3 +++ b/rtdata/profiles/Film Negative - Black and White.pp3 @@ -11,7 +11,7 @@ Curve2=1;0;0;0.0397505754145333;0.020171771436200074;0.54669745433149319;0.69419 [HLRecovery] Enabled=false -Method=Blend +Method=Coloropp [Black & White] Enabled=true diff --git a/rtdata/profiles/Film Negative.pp3 b/rtdata/profiles/Film Negative.pp3 index 0ecac1d33..e76c61866 100644 --- a/rtdata/profiles/Film Negative.pp3 +++ b/rtdata/profiles/Film Negative.pp3 @@ -11,7 +11,7 @@ Curve2=1;0;0;0.0397505754145333;0.020171771436200074;0.54669745433149319;0.69419 [HLRecovery] Enabled=false -Method=Blend +Method=Coloropp [Crop] FixedRatio=false diff --git a/rtdata/profiles/Pop/Pop 1.pp3 b/rtdata/profiles/Pop/Pop 1.pp3 index 2152a268b..cbdf4ab5b 100644 --- a/rtdata/profiles/Pop/Pop 1.pp3 +++ b/rtdata/profiles/Pop/Pop 1.pp3 @@ -19,7 +19,7 @@ Curve2=0; [HLRecovery] Enabled=true -Method=Blend +Method=Coloropp [Luminance Curve] Enabled=true diff --git a/rtdata/profiles/Pop/Pop 2 Lab.pp3 b/rtdata/profiles/Pop/Pop 2 Lab.pp3 index 796aeb5ba..f4c01fd1b 100644 --- a/rtdata/profiles/Pop/Pop 2 Lab.pp3 +++ b/rtdata/profiles/Pop/Pop 2 Lab.pp3 @@ -19,7 +19,7 @@ Curve2=0; [HLRecovery] Enabled=true -Method=Blend +Method=Coloropp [Luminance Curve] Enabled=true diff --git a/rtdata/profiles/Pop/Pop 3 Skin.pp3 b/rtdata/profiles/Pop/Pop 3 Skin.pp3 index 650b2e189..ebce37b58 100644 --- a/rtdata/profiles/Pop/Pop 3 Skin.pp3 +++ b/rtdata/profiles/Pop/Pop 3 Skin.pp3 @@ -19,7 +19,7 @@ Curve2=0; [HLRecovery] Enabled=true -Method=Blend +Method=Coloropp [Luminance Curve] Enabled=true diff --git a/rtdata/profiles/Pop/Pop 4 Black-and-White.pp3 b/rtdata/profiles/Pop/Pop 4 Black-and-White.pp3 index 9faa32a0a..1e3527ceb 100644 --- a/rtdata/profiles/Pop/Pop 4 Black-and-White.pp3 +++ b/rtdata/profiles/Pop/Pop 4 Black-and-White.pp3 @@ -19,7 +19,7 @@ Curve2=0; [HLRecovery] Enabled=true -Method=Blend +Method=Coloropp [Black & White] Enabled=true diff --git a/rtdata/profiles/Standard Film Curve - ISO High.pp3 b/rtdata/profiles/Standard Film Curve - ISO High.pp3 index 4dd3a9b1d..42bbed6d3 100644 --- a/rtdata/profiles/Standard Film Curve - ISO High.pp3 +++ b/rtdata/profiles/Standard Film Curve - ISO High.pp3 @@ -6,7 +6,7 @@ Curve=1;0;0;0.11;0.089999999999999997;0.32000000000000001;0.42999999999999999;0. [HLRecovery] Enabled=true -Method=Blend +Method=Coloropp [Directional Pyramid Denoising] Enabled=true diff --git a/rtdata/profiles/Standard Film Curve - ISO Low.pp3 b/rtdata/profiles/Standard Film Curve - ISO Low.pp3 index 45fcca730..342b1c8d3 100644 --- a/rtdata/profiles/Standard Film Curve - ISO Low.pp3 +++ b/rtdata/profiles/Standard Film Curve - ISO Low.pp3 @@ -6,7 +6,7 @@ Curve=1;0;0;0.11;0.089999999999999997;0.32000000000000001;0.42999999999999999;0. [HLRecovery] Enabled=true -Method=Blend +Method=Coloropp [LensProfile] LcMode=lfauto diff --git a/rtdata/profiles/Standard Film Curve - ISO Medium.pp3 b/rtdata/profiles/Standard Film Curve - ISO Medium.pp3 index 4aff630f5..f3b292094 100644 --- a/rtdata/profiles/Standard Film Curve - ISO Medium.pp3 +++ b/rtdata/profiles/Standard Film Curve - ISO Medium.pp3 @@ -6,7 +6,7 @@ Curve=1;0;0;0.11;0.089999999999999997;0.32000000000000001;0.42999999999999999;0. [HLRecovery] Enabled=true -Method=Blend +Method=Coloropp [Directional Pyramid Denoising] Enabled=true diff --git a/rtengine/clutstore.cc b/rtengine/clutstore.cc index e3bd9c988..4c70ad951 100644 --- a/rtengine/clutstore.cc +++ b/rtengine/clutstore.cc @@ -57,7 +57,7 @@ bool loadFile( rtengine::procparams::ColorManagementParams icm; icm.workingProfile = working_color_space; - img_src.getImage(curr_wb, TR_NONE, img_float.get(), pp, rtengine::procparams::ToneCurveParams(), rtengine::procparams::RAWParams()); + img_src.getImage(curr_wb, TR_NONE, img_float.get(), pp, rtengine::procparams::ToneCurveParams(), rtengine::procparams::RAWParams(), 0); if (!working_color_space.empty()) { img_src.convertColorSpace(img_float.get(), icm, curr_wb); diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc index a4dd8a4d1..4ba47b25a 100644 --- a/rtengine/colortemp.cc +++ b/rtengine/colortemp.cc @@ -33,7 +33,7 @@ namespace rtengine { -static double cie_colour_match_jd2[97][3] = {//350nm to 830nm 5 nm J.Desmis 2° Standard Observer. +static const color_match_type cie_colour_match_jd2 = {//350nm to 830nm 5 nm J.Desmis 2° Standard Observer. {0.0000000, 0.000000, 0.000000}, {0.0000000, 0.000000, 0.000000}, {0.0001299, 0.0003917, 0.0006061}, {0.0002321, 0.000006965, 0.001086}, {0.0004149, 0.00001239, 0.001946}, {0.0007416, 0.00002202, 0.003846}, {0.001368, 0.000039, 0.006450001}, {0.002236, 0.000064, 0.01054999}, {0.004243, 0.000120, 0.02005001}, @@ -70,7 +70,7 @@ static double cie_colour_match_jd2[97][3] = {//350nm to 830nm 5 nm J.Desmis 2 }; -static const double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis 10° Standard Observer. +static const color_match_type cie_colour_match_jd = {//350nm to 830nm 5 nm J.Desmis 10° Standard Observer. {0.000000000000, 0.000000000000, 0.000000000000}, {0.000000000000, 0.000000000000, 0.000000000000}, {0.000000122200, 0.000000013398, 0.000000535027}, @@ -2963,15 +2963,16 @@ void ColorTemp::temp2mulxyz (double temp, const std::string &method, double &Xxy // We first test for specially handled methods const auto iterator = spectMap.find(method); + const auto &color_match = (settings->observer10 == true) ? cie_colour_match_jd : cie_colour_match_jd2; if (iterator != spectMap.end()) { - spectrum_to_xyz_preset(iterator->second, x, y, z); + spectrum_to_xyz_preset(iterator->second, x, y, z, color_match); } else { // otherwise we use the Temp+Green generic solution if (temp <= INITIALBLACKBODY) { // if temperature is between 2000K and 4000K we use blackbody, because there will be no Daylight reference below 4000K... // of course, the previous version of RT used the "magical" but wrong formula of U.Fuchs (Ufraw). - spectrum_to_xyz_blackbody(temp, x, y, z); + spectrum_to_xyz_blackbody(temp, x, y, z, color_match); } else { // from 4000K up to 25000K: using the D illuminant (daylight) which is standard double x_D, y_D; @@ -2990,7 +2991,7 @@ void ColorTemp::temp2mulxyz (double temp, const std::string &method, double &Xxy double interm = 0.0241 + 0.2562 * x_D - 0.734 * y_D; double m1 = (-1.3515 - 1.7703 * x_D + 5.9114 * y_D) / interm; double m2 = (0.03 - 31.4424 * x_D + 30.0717 * y_D) / interm; - spectrum_to_xyz_daylight(m1, m2, x, y, z); + spectrum_to_xyz_daylight(m1, m2, x, y, z, color_match); } } @@ -3169,17 +3170,19 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, float CRI_RT = 0.0, CRI[50]; float CRI_RTs = 0.0, CRIs[8]; + const auto &color_match = (settings->observer10 == true) ? cie_colour_match_jd : cie_colour_match_jd2; + for(int i = 0; i < N_c; i++) { - spectrum_to_color_xyz_preset(spec_color[i], spect_illum[illum + 3], XchkLamp[i], YchkLamp[i], ZchkLamp[i]); + spectrum_to_color_xyz_preset(spec_color[i], spect_illum[illum + 3], XchkLamp[i], YchkLamp[i], ZchkLamp[i], color_match); } //calculate XYZ for each color : for Blackbody and Daylight at tempw if(tempw <= INITIALBLACKBODY) { for(int i = 0; i < N_c; i++) { - spectrum_to_color_xyz_blackbody(spec_color[i], tempw, Xchk[i], Ychk[i], Zchk[i]); + spectrum_to_color_xyz_blackbody(spec_color[i], tempw, Xchk[i], Ychk[i], Zchk[i], color_match); } - spectrum_to_xyz_blackbody(tempw, x, y, z);//for white point + spectrum_to_xyz_blackbody(tempw, x, y, z, color_match);//for white point } else { // after 6600K (arbitrary) I use daylight...because ...but there is no lamp... double m11, m22, x_DD, y_DD, interm2; @@ -3197,10 +3200,10 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, m22 = (0.03 - 31.4424 * x_DD + 30.0717 * y_DD) / interm2; for(int i = 0; i < N_c; i++) { - spectrum_to_color_xyz_daylight(spec_color[i], m11, m22, Xchk[i], Ychk[i], Zchk[i]); + spectrum_to_color_xyz_daylight(spec_color[i], m11, m22, Xchk[i], Ychk[i], Zchk[i], color_match); } - spectrum_to_xyz_daylight(m11, m22, x, y, z); + spectrum_to_xyz_daylight(m11, m22, x, y, z, color_match); } if (settings->verbose) { @@ -3394,16 +3397,16 @@ I have increase precision used by J.Walker and pass to 350nm to 830nm And also add 10° standard observer */ -void ColorTemp::spectrum_to_xyz_daylight(double _m1, double _m2, double &x, double &y, double &z) +void ColorTemp::spectrum_to_xyz_daylight(double _m1, double _m2, double &x, double &y, double &z, const color_match_type &color_match) { int i; double lambda, X = 0, Y = 0, Z = 0, XYZ; for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) { double Me = daylight_spect(lambda, _m1, _m2); - X += Me * cie_colour_match_jd2[i][0]; - Y += Me * cie_colour_match_jd2[i][1]; - Z += Me * cie_colour_match_jd2[i][2]; + X += Me * color_match[i][0]; + Y += Me * color_match[i][1]; + Z += Me * color_match[i][2]; } XYZ = (X + Y + Z); @@ -3412,16 +3415,16 @@ void ColorTemp::spectrum_to_xyz_daylight(double _m1, double _m2, double &x, doub z = Z / XYZ; } -void ColorTemp::spectrum_to_xyz_blackbody(double _temp, double &x, double &y, double &z) +void ColorTemp::spectrum_to_xyz_blackbody(double _temp, double &x, double &y, double &z, const color_match_type &color_match) { int i; double lambda, X = 0, Y = 0, Z = 0, XYZ; for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) { double Me = blackbody_spect(lambda, _temp); - X += Me * cie_colour_match_jd2[i][0]; - Y += Me * cie_colour_match_jd2[i][1]; - Z += Me * cie_colour_match_jd2[i][2]; + X += Me * color_match[i][0]; + Y += Me * color_match[i][1]; + Z += Me * color_match[i][2]; } XYZ = (X + Y + Z); @@ -3430,7 +3433,7 @@ void ColorTemp::spectrum_to_xyz_blackbody(double _temp, double &x, double &y, do z = Z / XYZ; } -void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, double &y, double &z) +void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, double &y, double &z, const color_match_type &color_match) { int i; double lambda, X = 0, Y = 0, Z = 0, XYZ; @@ -3454,9 +3457,9 @@ void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, dou */ for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) { double Me = get_spectral_color(lambda, spec_intens); - X += Me * cie_colour_match_jd2[i][0]; - Y += Me * cie_colour_match_jd2[i][1]; - Z += Me * cie_colour_match_jd2[i][2]; + X += Me * color_match[i][0]; + Y += Me * color_match[i][1]; + Z += Me * color_match[i][2]; } XYZ = (X + Y + Z); @@ -3466,7 +3469,7 @@ void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, dou } //calculate XYZ from spectrum data (color) and illuminant : J.Desmis December 2011 -void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz) +void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz, const color_match_type &color_match) { int i; double lambda, X = 0, Y = 0, Z = 0, Yo = 0; @@ -3478,9 +3481,9 @@ void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const dou Me = get_spectral_color(lambda, spec_color); Mc = get_spectral_color(lambda, spec_intens); - X += Mc * cie_colour_match_jd2[i][0] * Me; - Y += Mc * cie_colour_match_jd2[i][1] * Me; - Z += Mc * cie_colour_match_jd2[i][2] * Me; + X += Mc * color_match[i][0] * Me; + Y += Mc * color_match[i][1] * Me; + Z += Mc * color_match[i][2] * Me; } for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) { @@ -3488,7 +3491,7 @@ void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const dou double Ms; Ms = get_spectral_color(lambda, spec_intens); - Yo += cie_colour_match_jd2[i][1] * Ms; + Yo += color_match[i][1] * Ms; } xx = X / Yo; @@ -3497,7 +3500,7 @@ void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const dou } //calculate XYZ from spectrum data (color) and illuminant : J.Desmis december 2011 -void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz) +void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz, const color_match_type &color_match) { int i; double lambda, X = 0, Y = 0, Z = 0; @@ -3505,9 +3508,9 @@ void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) { const double Me = spec_color[i]; const double Mc = daylight_spect(lambda, _m1, _m2); - X += Mc * cie_colour_match_jd2[i][0] * Me; - Y += Mc * cie_colour_match_jd2[i][1] * Me; - Z += Mc * cie_colour_match_jd2[i][2] * Me; + X += Mc * color_match[i][0] * Me; + Y += Mc * color_match[i][1] * Me; + Z += Mc * color_match[i][2] * Me; } xx = X / Y; @@ -3516,7 +3519,7 @@ void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double } //calculate XYZ from spectrum data (color) and illuminant : J.Desmis december 2011 -void ColorTemp::spectrum_to_color_xyz_blackbody(const double* spec_color, double _temp, double &xx, double &yy, double &zz) +void ColorTemp::spectrum_to_color_xyz_blackbody(const double* spec_color, double _temp, double &xx, double &yy, double &zz, const color_match_type &color_match) { int i; double lambda, X = 0, Y = 0, Z = 0; @@ -3524,9 +3527,9 @@ void ColorTemp::spectrum_to_color_xyz_blackbody(const double* spec_color, double for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) { const double Me = spec_color[i]; const double Mc = blackbody_spect(lambda, _temp); - X += Mc * cie_colour_match_jd2[i][0] * Me; - Y += Mc * cie_colour_match_jd2[i][1] * Me; - Z += Mc * cie_colour_match_jd2[i][2] * Me; + X += Mc * color_match[i][0] * Me; + Y += Mc * color_match[i][1] * Me; + Z += Mc * color_match[i][2] * Me; } xx = X / Y; @@ -3762,27 +3765,21 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float } if (settings->verbose) { - if (settings->itcwb_stdobserver10 == false) { + if (settings->itcwb_stdobserver10 == false) {//I will try to change settings by main printf("Use standard observer 2°\n"); } else { printf("Use standard observer 10°\n"); } } - if (settings->itcwb_stdobserver10 == true) { - for (int i = 0; i < 97; i++) { - cie_colour_match_jd2[i][0] = cie_colour_match_jd[i][0]; - cie_colour_match_jd2[i][1] = cie_colour_match_jd[i][1];; - cie_colour_match_jd2[i][2] = cie_colour_match_jd[i][2]; - } - } + const color_match_type &color_match = (settings->itcwb_stdobserver10 == true) ? cie_colour_match_jd : cie_colour_match_jd2; if (separated) { const double tempw = Txyz[repref].Tem; if (tempw <= INITIALBLACKBODY) { for (int i = 0; i < N_c; i++) { - spectrum_to_color_xyz_blackbody(spec_colorforxcyc[i], tempw, TX[i], TY[i], TZ[i]); + spectrum_to_color_xyz_blackbody(spec_colorforxcyc[i], tempw, TX[i], TY[i], TZ[i], color_match); } } else { double m11, m22, x_DD, y_DD, interm2; @@ -3801,7 +3798,7 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float m22 = (0.03 - 31.4424 * x_DD + 30.0717 * y_DD) / interm2; for (int i = 0; i < N_c; i++) { - spectrum_to_color_xyz_daylight(spec_colorforxcyc[i], m11, m22, TX[i], TY[i], TZ[i]); + spectrum_to_color_xyz_daylight(spec_colorforxcyc[i], m11, m22, TX[i], TY[i], TZ[i], color_match); } } } else { @@ -3810,7 +3807,7 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float if (tempw <= INITIALBLACKBODY) { for (int i = 0; i < N_c; i++) { - spectrum_to_color_xyz_blackbody(spec_colorforxcyc[i], tempw, Refxyz[i].Xref, Refxyz[i].Yref, Refxyz[i].Zref); + spectrum_to_color_xyz_blackbody(spec_colorforxcyc[i], tempw, Refxyz[i].Xref, Refxyz[i].Yref, Refxyz[i].Zref, color_match); } } else { double x_DD; @@ -3829,7 +3826,7 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float const double m22 = (0.03 - 31.4424 * x_DD + 30.0717 * y_DD) / interm2; for (int i = 0; i < N_c; i++) { - spectrum_to_color_xyz_daylight(spec_colorforxcyc[i], m11, m22, Refxyz[i].Xref, Refxyz[i].Yref, Refxyz[i].Zref); + spectrum_to_color_xyz_daylight(spec_colorforxcyc[i], m11, m22, Refxyz[i].Xref, Refxyz[i].Yref, Refxyz[i].Zref, color_match); } } diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h index 89c324490..78091f51d 100644 --- a/rtengine/colortemp.h +++ b/rtengine/colortemp.h @@ -26,6 +26,8 @@ namespace rtengine { +using color_match_type = double [97][3]; + constexpr double MINTEMP = 1500.0; constexpr double MAXTEMP = 60000.0; constexpr double MINGREEN = 0.02; @@ -375,13 +377,13 @@ public: static const double JDC468_greym13_325_spect[97]; static const double JDC468_greyf26_156_spect[97]; */ - static void spectrum_to_xyz_daylight (double _m1, double _m2, double &x, double &y, double &z); - static void spectrum_to_xyz_blackbody (double _temp, double &x, double &y, double &z); - static void spectrum_to_xyz_preset (const double* spec_intens, double &x, double &y, double &z); + static void spectrum_to_xyz_daylight (double _m1, double _m2, double &x, double &y, double &z, const color_match_type &color_match); + static void spectrum_to_xyz_blackbody (double _temp, double &x, double &y, double &z, const color_match_type &color_match); + static void spectrum_to_xyz_preset (const double* spec_intens, double &x, double &y, double &z, const color_match_type &color_match); - static void spectrum_to_color_xyz_daylight (const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz); - static void spectrum_to_color_xyz_blackbody (const double* spec_color, double _temp, double &xx, double &yy, double &zz); - static void spectrum_to_color_xyz_preset (const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz); + static void spectrum_to_color_xyz_daylight (const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz, const color_match_type &color_match); + static void spectrum_to_color_xyz_blackbody (const double* spec_color, double _temp, double &xx, double &yy, double &zz, const color_match_type &color_match); + static void spectrum_to_color_xyz_preset (const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz, const color_match_type &color_match); }; } diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index f4ac49fc4..8ddaa5f75 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -228,18 +228,18 @@ void Crop::update(int todo) if (settings->leveldnautsimpl == 1) { if (params.dirpyrDenoise.Cmethod == "MAN" || params.dirpyrDenoise.Cmethod == "PON") { PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip); - parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw); + parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0); } } else { if (params.dirpyrDenoise.C2method == "MANU") { PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip); - parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw); + parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0); } } if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "PRE") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "PREV")) { PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip); - parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw); + parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0); if ((!isDetailWindow) && parent->adnListener && skip == 1 && params.dirpyrDenoise.enabled) { float lowdenoise = 1.f; @@ -451,7 +451,7 @@ void Crop::update(int todo) for (int wcr = 0; wcr <= 2; wcr++) { for (int hcr = 0; hcr <= 2; hcr++) { PreviewProps ppP(coordW[wcr], coordH[hcr], crW, crH, 1); - parent->imgsrc->getImage(parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.raw); + parent->imgsrc->getImage(parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.raw, 0); // we only need image reduced to 1/4 here for (int ii = 0; ii < crH; ii += 2) { @@ -613,7 +613,7 @@ void Crop::update(int todo) // if (params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { //reinit origCrop after Auto PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip); - parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw); + parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0); } if ((todo & M_SPOT) && params.spot.enabled && !params.spot.entries.empty()) { @@ -749,7 +749,7 @@ void Crop::update(int todo) fattalCrop.reset(f); PreviewProps pp(0, 0, parent->fw, parent->fh, skip); int tr = getCoarseBitMask(params.coarse); - parent->imgsrc->getImage(parent->currWB, tr, f, pp, params.toneCurve, params.raw); + parent->imgsrc->getImage(parent->currWB, tr, f, pp, params.toneCurve, params.raw, 0); parent->imgsrc->convertColorSpace(f, params.icm, parent->currWB); if (params.dirpyrDenoise.enabled || params.filmNegative.enabled || params.spot.enabled) { diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index ae1813db9..c33dc4a9a 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -84,7 +84,7 @@ void getSpotAvgMax(ImageSource *imgsrc, ColorTemp currWB, const std::unique_ptr< } rtengine::Imagefloat spotImg(spotSize, spotSize); - imgsrc->getImage(currWB, tr, &spotImg, pp, params->toneCurve, params->raw); + imgsrc->getImage(currWB, tr, &spotImg, pp, params->toneCurve, params->raw, 0); auto avgMax = [spotSize, &spotImg](RGB & avg, RGB & max) -> void { avg = {}; diff --git a/rtengine/hilite_recon.cc b/rtengine/hilite_recon.cc index a45e5d345..07d1a7b7b 100644 --- a/rtengine/hilite_recon.cc +++ b/rtengine/hilite_recon.cc @@ -32,14 +32,15 @@ #include "opthelper.h" #include "rawimagesource.h" #include "rt_math.h" -//#define BENCHMARK -//#include "StopWatch.h" +#define BENCHMARK +#include "StopWatch.h" #include "guidedfilter.h" #include "settings.h" #include "gauss.h" #include "rescale.h" #include "iccstore.h" #include "color.h" +#include "linalgebra.h" namespace { @@ -301,7 +302,7 @@ using namespace procparams; void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue, int blur) { - // BENCHFUN + BENCHFUN double progress = 0.0; if (plistener) { @@ -1226,5 +1227,371 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue }// end of HLReconstruction + +//----------------------------------------------------------------------------- +// "inpaint opposed" algorithm taken from darktable +// +// (Very effective, very simple, very neat) +// +// Kudos to the original authors (@jenshannoschwalm from dt, in collaboration +// with @garagecoder and @Iain from gmic). +// +// Copyright and description of the original code follows +// +/* + Copyright (C) 2022 darktable developers. + + darktable 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. + + darktable 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 darktable. If not, see . +*/ + +/* The refavg values are calculated in raw-RGB-cube3 space + We calculate all color channels in the 3x3 photosite area, this can be understaood as a "superpixel", + the "asking" location is in the centre. + As this works for bayer and xtrans sensors we don't have a fixed ratio but calculate the average + for every color channel first. + refavg for one of red, green or blue is defined as means of both other color channels (opposing). + + The basic idea / observation for the _process_opposed algorithm is, the refavg is a good estimate + for any clipped color channel in the vast majority of images, working mostly fine both for small specular + highlighted spots and large areas. + + The correction via some sort of global chrominance further helps to correct color casts. + The chrominace data are taken from the areas morphologically very close to clipped data. + Failures of the algorithm (color casts) are in most cases related to + a) very large differences between optimal white balance coefficients vs what we have as D65 in the darktable pipeline + b) complicated lightings so the gradients are not well related + c) a wrong whitepoint setting in the rawprepare module. + d) the maths might not be best +*/ +//----------------------------------------------------------------------------- + +namespace { + +constexpr int HL_BORDER = 8; +constexpr float HL_POWERF = 3.0f; + +// void border_fill_zero(int *d, int width, int height) +// { +// for (int i = 0; i < HL_BORDER * width; i++) { +// d[i] = 0; +// } +// for (int i = (height - HL_BORDER - 1) * width; i < width*height; i++) { +// d[i] = 0; +// } +// for (int row = HL_BORDER; row < height - HL_BORDER; row++) { +// int *p1 = d + row*width; +// int *p2 = d + (row+1)*width - HL_BORDER; +// for(int i = 0; i < HL_BORDER; i++) { +// p1[i] = p2[i] = 0; +// } +// } +// } + + +int test_dilate(const int *img, int i, int w1) +{ + int retval = 0; + retval = img[i-w1-1] | img[i-w1] | img[i-w1+1] | + img[i-1] | img[i] | img[i+1] | + img[i+w1-1] | img[i+w1] | img[i+w1+1]; + if (retval) { + return retval; + } + + const size_t w2 = 2*w1; + retval = img[i-w2-1] | img[i-w2] | img[i-w2+1] | + img[i-w1-2] | img[i-w1+2] | + img[i-2] | img[i+2] | + img[i+w1-2] | img[i+w1+2] | + img[i+w2-1] | img[i+w2] | img[i+w2+1]; + if (retval) { + return retval; + } + + const size_t w3 = 3*w1; + retval = img[i-w3-2] | img[i-w3-1] | img[i-w3] | img[i-w3+1] | img[i-w3+2] | + img[i-w2-3] | img[i-w2-2] | img[i-w2+2] | img[i-w2+3] | + img[i-w1-3] | img[i-w1+3] | + img[i-3] | img[i+3] | + img[i+w1-3] | img[i+w1+3] | + img[i+w2-3] | img[i+w2-2] | img[i+w2+2] | img[i+w2+3] | + img[i+w3-2] | img[i+w3-1] | img[i+w3] | img[i+w3+1] | img[i+w3+2]; + return retval; +} + + +void dilating(const int *img, int *o, int w1, int height) +{ +#ifdef _OPENMP +# pragma omp parallel for +#endif + for (int row = HL_BORDER; row < height - HL_BORDER; row++) { + for (int col = HL_BORDER, i = row*w1 + col; col < w1 - HL_BORDER; col++, i++) { + o[i] = test_dilate(img, i, w1); + } + } +} + +} // namespace + +void RawImageSource::highlight_recovery_opposed(float scale_mul[3], const ColorTemp &wb, float gainth) +{ + BENCHFUN + + if (settings->verbose) { + std::cout << "Applying Highlight Recovery: Inpaint opposed" << std::endl; + } + + if (plistener) { + plistener->setProgressStr("PROGRESSBAR_HLREC"); + plistener->setProgress(0); + } + + double rr, gg, bb; + wb.getMultipliers(rr, gg, bb); + wbMul2Camera(rr, gg, bb); + + float gain = 1.2f * gainth; + + float clipval = 0.987f / gain; + const float scalecoeffs[3] = { + scale_mul[0] * float(rr) / 65535.f, + scale_mul[1] * float(gg) / 65535.f, + scale_mul[2] * float(bb) / 65535.f, + }; + const float clips[3] = { + clipval * float(rr), + clipval * float(gg), + clipval * float(bb) + }; + const float clipdark[3] = { + 0.03f * clips[0], + 0.125f * clips[1], + 0.03f * clips[2] + }; + + bool anyclipped = false; + float **chan[3] = { red, green, blue }; + + const float clipscale[3] = { + clips[0] / scalecoeffs[0], + clips[1] / scalecoeffs[1], + clips[2] / scalecoeffs[2] + }; + + int x1 = W, y1 = H, x2 = 0, y2 = 0; + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + for (int c = 0; c < 3; ++c) { + if (chan[c][y][x] >= clipscale[c]) { + anyclipped = true; + x1 = std::min(x, x1); + x2 = std::max(x, x2); + y1 = std::min(y, y1); + y2 = std::max(y, y2); + } + } + } + } + + if (!anyclipped) { + if (plistener) { + plistener->setProgress(1.0); + } + return; + } + + x1 = std::max(x1-1, 0); + x2 = std::min(x2+1, W-1); + y1 = std::max(y1-1, 0); + y2 = std::min(y2+1, H-1); + + const int cW = x2 - x1 + 1; + const int cH = y2 - y1 + 1; + +#ifdef _OPENMP +# pragma omp parallel for +#endif + for (int y = 0; y < cH; ++y) { + const int yy = y + y1; + for (int x = 0; x < cW; ++x) { + const int xx = x + x1; + for (int c = 0; c < 3; ++c) { + chan[c][yy][xx] *= scalecoeffs[c]; + } + } + } + + if (plistener) { + plistener->setProgress(0.1); + } + + multi_array2D tmp(cW, cH); + + const int pwidth = cW + 2 * HL_BORDER; + const int pheight = cH + 2 * HL_BORDER; + const int p_size = pwidth * pheight; + AlignedBuffer mask_vec(4 * p_size); + int *mask_buffer = mask_vec.data; + + const auto mask_val = + [&](int c, int y, int x) -> int & + { + return mask_buffer[c * p_size + (HL_BORDER + y) * pwidth + x + HL_BORDER]; + }; + + const auto set_refavg = + [&](int y, int x) -> bool + { + const int yy = y + y1; + const int xx = x + x1; + bool found = false; + for (int c = 0; c < 3 && !found; ++c) { + if (chan[c][yy][xx] >= clips[c]) { + found = true; + } + } + if (!found) { + return false; + } + + float mean[3] = { 0.0f, 0.0f, 0.0f }; + for (int dy = -1; dy < 2; dy++) { + for (int dx = -1; dx < 2; dx++) { + for (int c = 0; c < 3; ++c) { + mean[c] += std::max(0.0f, chan[c][yy+dy][xx+dx]); + } + } + } + for (int c = 0; c < 3; ++c) { + mean[c] = pow_F(mean[c] / 9.0f, 1.0f / HL_POWERF); + } + + const float croot_refavg[3] = { + 0.5f * (mean[1] + mean[2]), + 0.5f * (mean[0] + mean[2]), + 0.5f * (mean[0] + mean[1]) + }; + + for (int c = 0; c < 3; ++c) { + if (chan[c][yy][xx] >= clips[c]) { + tmp[c][y][x] = pow_F(croot_refavg[c], HL_POWERF); + mask_val(c, y, x) = 1; + } + } + return true; + }; + +#ifdef _OPENMP +# pragma omp parallel for +#endif + for (int y = 0; y < cH; ++y) { + const int yy = y + y1; + for (int x = 0; x < cW; ++x) { + const int xx = x + x1; + for (int c = 0; c < 3; ++c) { + tmp[c][y][x] = std::max(0.f, chan[c][yy][xx]); + } + + if ((x > 0) && (x < cW - 1) && (y > 0) && (y < cH - 1)) { + set_refavg(y, x); + } + } + } + + if (plistener) { + plistener->setProgress(0.3); + } + + for (size_t i = 0; i < 3; i++) { + int *mask = mask_buffer + i * p_size; + int *tmp = mask_buffer + 3 * p_size; + //border_fill_zero(mask, pwidth, pheight); + dilating(mask, tmp, pwidth, pheight); + memcpy(mask, tmp, p_size * sizeof(int)); + } + + float cr_sum[3] = { 0.f, 0.f, 0.f }; + int cr_cnt[3] = { 0, 0, 0 }; + +#ifdef _OPENMP +# pragma omp parallel for reduction(+ : cr_sum, cr_cnt) +#endif + for (int y = 1; y < cH-1; ++y) { + const int yy = y + y1; + for (int x = 1; x < cW-1; ++x) { + const int xx = x + x1; + for (int c = 0; c < 3; ++c) { + const float inval = std::max(0.0f, chan[c][yy][xx]); + if (mask_val(c, y, x) && (inval > clipdark[c]) && (inval < clips[c])) { + cr_sum[c] += inval - tmp[c][y][x]; + ++cr_cnt[c]; + } + } + } + } + + if (plistener) { + plistener->setProgress(0.6); + } + + float chrominance[3] = { + cr_sum[0] / std::max(1.f, float(cr_cnt[0])), + cr_sum[1] / std::max(1.f, float(cr_cnt[1])), + cr_sum[2] / std::max(1.f, float(cr_cnt[2])) + }; + +#ifdef _OPENMP +# pragma omp parallel for +#endif + for (int y = 0; y < cH; ++y) { + const int yy = y + y1; + for (int x = 0; x < cW; ++x) { + const int xx = x + x1; + for (int c = 0; c < 3; ++c) { + const float inval = std::max(0.0f, chan[c][yy][xx]); + if (inval >= clips[c]) { + chan[c][yy][xx] = std::max(inval, tmp[c][y][x] + chrominance[c]); + } + } + } + } + + if (plistener) { + plistener->setProgress(0.9); + } + +#ifdef _OPENMP +# pragma omp parallel for +#endif + for (int y = 0; y < cH; ++y) { + const int yy = y + y1; + for (int x = 0; x < cW; ++x) { + const int xx = x + x1; + for (int c = 0; c < 3; ++c) { + chan[c][yy][xx] /= scalecoeffs[c]; + } + } + } + + if (plistener) { + plistener->setProgress(1.0); + } +} + + + + } diff --git a/rtengine/iimage.h b/rtengine/iimage.h index 2c75a0d59..a544b454a 100644 --- a/rtengine/iimage.h +++ b/rtengine/iimage.h @@ -111,7 +111,7 @@ public: { rm = gm = bm = 1.0; } - virtual void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw) + virtual void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) { rm = gm = bm = 1.0; } diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index a8ea8f851..d6d22c269 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -109,7 +109,7 @@ public: virtual void getWBMults (const ColorTemp &ctemp, const procparams::RAWParams &raw, std::array& scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const = 0; // use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat* - virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hlp, const procparams::RAWParams &raw) = 0; + virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hlp, const procparams::RAWParams &raw, int opposed) = 0; virtual eSensorType getSensorType () const = 0; virtual bool isMono () const = 0; // true is ready to provide the AutoWB, i.e. when the image has been demosaiced for RawImageSource @@ -117,10 +117,10 @@ public: virtual void convertColorSpace (Imagefloat* image, const procparams::ColorManagementParams &cmp, const ColorTemp &wb) = 0; // DIRTY HACK: this method is derived in rawimagesource and strimagesource, but (...,RAWParams raw) will be used ONLY for raw images virtual void getAutoWBMultipliers (double &rm, double &gm, double &bm) = 0; - virtual void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double & greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw) = 0; + virtual void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double & greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) = 0; virtual ColorTemp getWB () const = 0; virtual ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) = 0; - virtual void WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw) = 0; + virtual void WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) = 0; virtual void getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w) = 0; virtual double getDefGain () const @@ -195,6 +195,9 @@ public: } virtual void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) = 0; virtual void captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) = 0; + virtual void wbMul2Camera(double &rm, double &gm, double &bm) = 0; + virtual void wbCamera2Mul(double &rm, double &gm, double &bm) = 0; + }; } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index ec5ffc8ef..cc2d75b3d 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -1,6 +1,6 @@ /* * This file is part of RawTherapee. - * + * * Copyright (c) 2004-2010 Gabor Horvath * * RawTherapee is free software: you can redistribute it and/or modify @@ -409,11 +409,13 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) if (imageTypeListener) { imageTypeListener->imageTypeChanged(imgsrc->isRAW(), imgsrc->getSensorType() == ST_BAYER, imgsrc->getSensorType() == ST_FUJI_XTRANS, imgsrc->isMono(), imgsrc->isGainMapSupported()); } - + bool iscolor = (params->toneCurve.method == "Color");// || params->toneCurve.method == "Coloropp"); if ((todo & M_RAW) || (!highDetailRawComputed && highDetailNeeded) - || (params->toneCurve.hrenabled && params->toneCurve.method != "Color" && imgsrc->isRGBSourceModified()) - || (!params->toneCurve.hrenabled && params->toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) { + // || (params->toneCurve.hrenabled && params->toneCurve.method != "Color" && imgsrc->isRGBSourceModified()) + // || (!params->toneCurve.hrenabled && params->toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) { + || (params->toneCurve.hrenabled && !iscolor && imgsrc->isRGBSourceModified()) + || (!params->toneCurve.hrenabled && iscolor && imgsrc->isRGBSourceModified())) { if (settings->verbose) { if (imgsrc->getSensorType() == ST_BAYER) { @@ -466,8 +468,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) if ((todo & M_RAW) || (!highDetailRawComputed && highDetailNeeded) - || (params->toneCurve.hrenabled && params->toneCurve.method != "Color" && imgsrc->isRGBSourceModified()) - || (!params->toneCurve.hrenabled && params->toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) { + // || (params->toneCurve.hrenabled && params->toneCurve.method != "Color" && imgsrc->isRGBSourceModified()) + // || (!params->toneCurve.hrenabled && params->toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) { + || (params->toneCurve.hrenabled && !iscolor && imgsrc->isRGBSourceModified()) + || (!params->toneCurve.hrenabled && iscolor && imgsrc->isRGBSourceModified())) { if (highDetailNeeded) { highDetailRawComputed = true; } else { @@ -510,8 +514,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } if (todo & (M_INIT | M_LINDENOISE | M_HDR)) { MyMutex::MyLock initLock(minit); // Also used in crop window - - imgsrc->HLRecovery_Global(params->toneCurve); // this handles Color HLRecovery + // imgsrc->HLRecovery_Global(params->toneCurve); // this handles Color HLRecovery if (settings->verbose) { @@ -538,7 +541,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) printf("tempref=%f greref=%f\n", tempref, greenref); } - imgsrc->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc, studgood, 0, 0, fh, fw, 0, 0, fh, fw, rm, gm, bm, params->wb, params->icm, params->raw); + imgsrc->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc, studgood, 0, 0, fh, fw, 0, 0, fh, fw, rm, gm, bm, params->wb, params->icm, params->raw, params->toneCurve); if (params->wb.method == "autitcgreen") { params->wb.temperature = tempitc; @@ -617,8 +620,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) PreviewProps pp(0, 0, fw, fh, scale); // Tells to the ImProcFunctions' tools what is the preview scale, which may lead to some simplifications ipf.setScale(scale); - - imgsrc->getImage(currWB, tr, orig_prev, pp, params->toneCurve, params->raw); + int inpaintopposed = 1;//force getimage to use inpaint-opposed if enable, only once + imgsrc->getImage(currWB, tr, orig_prev, pp, params->toneCurve, params->raw, inpaintopposed); if ((todo & M_SPOT) && params->spot.enabled && !params->spot.entries.empty()) { spotsDone = true; @@ -2462,7 +2465,7 @@ bool ImProcCoordinator::getAutoWB(double& temp, double& green, double equal, dou double greenitc = 1.; float studgood = 1000.f; double tempref, greenref; - imgsrc->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc, studgood, 0, 0, fh, fw, 0, 0, fh, fw, rm, gm, bm, params->wb, params->icm, params->raw); + imgsrc->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc, studgood, 0, 0, fh, fw, 0, 0, fh, fw, rm, gm, bm, params->wb, params->icm, params->raw, params->toneCurve); if (rm != -1) { autoWB.update(rm, gm, bm, equal, tempBias); @@ -2649,7 +2652,7 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a currWB = ColorTemp(); // = no white balance } - imgsrc->getImage(currWB, tr, im, pp, ppar.toneCurve, ppar.raw); + imgsrc->getImage(currWB, tr, im, pp, ppar.toneCurve, ppar.raw, 0); ImProcFunctions ipf(&ppar, true); if (ipf.needsTransform(fW, fH, imgsrc->getRotateDegree(), imgsrc->getMetaData())) { diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index bdc1b6db1..811e941e4 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -2128,7 +2128,7 @@ void ImProcFunctions::getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg, Imagefloat img(int(fw / SCALE + 0.5), int(fh / SCALE + 0.5)); const ProcParams neutral; - imgsrc->getImage(imgsrc->getWB(), TR_NONE, &img, pp, params->toneCurve, neutral.raw); + imgsrc->getImage(imgsrc->getWB(), TR_NONE, &img, pp, params->toneCurve, neutral.raw, 0); imgsrc->convertColorSpace(&img, params->icm, imgsrc->getWB()); float minVal = RT_INFINITY; float maxVal = -RT_INFINITY; diff --git a/rtengine/linalgebra.h b/rtengine/linalgebra.h new file mode 100644 index 000000000..32e44e147 --- /dev/null +++ b/rtengine/linalgebra.h @@ -0,0 +1,275 @@ +/* -*- C++ -*- + * This file is part of ART + * + * Copyright (c) 2022 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 + +namespace rtengine { + +template +class Vec3 { +public: + Vec3() { data_[0] = data_[1] = data_[2] = T(); } + Vec3(T a, T b, T c) { data_[0] = a; data_[1] = b; data_[2] = c; } + + template + Vec3(T2 const a[3]) { data_[0] = a[0]; data_[1] = a[1]; data_[2] = a[2]; } + + Vec3 &operator=(const Vec3 &a) = default; + + template + Vec3 &operator=(T2 const a[3]) + { + data_[0] = a[0]; data_[1] = a[1]; data_[2] = a[2]; + return *this; + } + + T operator[](int i) const { return data_[i]; } + T &operator[](int i) { return data_[i]; } + operator const T *() const { return data_; } + operator T *() { return data_; } + +private: + T data_[3]; +}; + +typedef Vec3 Vec3f; + + +template +class Mat33 { +public: + Mat33() + { + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + data_[i][j] = T(); + } + } + } + + Mat33(T a00, T a01, T a02, + T a10, T a11, T a12, + T a20, T a21, T a22) + { + data_[0][0] = a00; data_[0][1] = a01; data_[0][2] = a02; + data_[1][0] = a10; data_[1][1] = a11; data_[1][2] = a12; + data_[2][0] = a20; data_[2][1] = a21; data_[2][2] = a22; + } + + template + Mat33(const T2 m[3][3]) + { + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + data_[i][j] = m[i][j]; + } + } + } + + Mat33 &operator=(const Mat33 &m) = default; + + template + Mat33 &operator=(const T2 m[3][3]) + { + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + data_[i][j] = m[i][j]; + } + } + return *this; + } + + T const *operator[](int i) const { return data_[i]; } + T *operator[](int i) { return data_[i]; } + typedef const T(*Data)[3]; + operator Data() const { return data_; } + +private: + T data_[3][3]; +}; + + +typedef Mat33 Mat33f; + + +template +Mat33 identity() +{ + return Mat33(1, 0, 0, 0, 1, 0, 0, 0, 1); +} + + +template +Mat33 diagonal(T a, T b, T c) +{ + return Mat33(a, 0, 0, 0, b, 0, 0, 0, c); +} + + +template +Mat33 transpose(T const m[3][3]) +{ + return Mat33(m[0][0], m[1][0], m[2][0], + m[0][1], m[1][1], m[2][1], + m[0][2], m[1][2], m[2][2]); +} + +template +Mat33 transpose(const Mat33 &m) +{ + return transpose(static_cast::Data>(m)); +} + + +template +bool inverse(T const m[3][3], Mat33 &out) +{ + const T res00 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + const T res10 = m[2][0] * m[1][2] - m[1][0] * m[2][2]; + const T res20 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + const T det = m[0][0] * res00 + m[0][1] * res10 + m[0][2] * res20; + + if (std::abs(det) >= 1.0e-10) { + out[0][0] = res00 / det; + out[0][1] = (m[2][1] * m[0][2] - m[0][1] * m[2][2]) / det; + out[0][2] = (m[0][1] * m[1][2] - m[1][1] * m[0][2]) / det; + out[1][0] = res10 / det; + out[1][1] = (m[0][0] * m[2][2] - m[2][0] * m[0][2]) / det; + out[1][2] = (m[1][0] * m[0][2] - m[0][0] * m[1][2]) / det; + out[2][0] = res20 / det; + out[2][1] = (m[2][0] * m[0][1] - m[0][0] * m[2][1]) / det; + out[2][2] = (m[0][0] * m[1][1] - m[1][0] * m[0][1]) / det; + return true; + } else { + return false; + } +} + +template +Mat33 inverse(const Mat33 &m) +{ + Mat33 res; + inverse(static_cast::Data>(m), res); + return res; +} + +template +Mat33 inverse(T const m[3][3]) +{ + Mat33 res; + inverse(m, res); + return res; +} + +template +bool inverse(const Mat33 &m, Mat33 &out) +{ + return inverse(static_cast::Data>(m), out); +} + + +template +Mat33 dot_product(T const a[3][3], T const b[3][3]) +{ + Mat33 res; + + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + res[i][j] = 0; + + for (int k = 0; k < 3; ++k) { + res[i][j] += a[i][k] * b[k][j]; + } + } + } + + return res; +} + +template +Mat33 dot_product(const Mat33 &a, T const b[3][3]) +{ + return dot_product(static_cast::Data>(a), b); +} + +template +Mat33 dot_product(T const a[3][3], const Mat33 &b) +{ + return dot_product(a, static_cast::Data>(b)); +} + +template +Mat33 dot_product(const Mat33 &a, const Mat33 &b) +{ + return dot_product(static_cast::Data>(a), static_cast::Data>(b)); +} + + +template +Vec3 dot_product(T const a[3][3], T const b[3]) +{ + Vec3 res; + + for (int i = 0; i < 3; ++i) { + res[i] = 0; + for (int k = 0; k < 3; ++k) { + res[i] += a[i][k] * b[k]; + } + } + + return res; +} + + +template +Vec3 dot_product(const Mat33 &a, T const b[3]) +{ + return dot_product(static_cast::Data>(a), b); +} + +template +Vec3 dot_product(T const a[3][3], const Vec3 &b) +{ + return dot_product(a, static_cast(b)); +} + +template +Vec3 dot_product(const Mat33 &a, const Vec3 &b) +{ + return dot_product(static_cast::Data>(a), static_cast(b)); +} + + +template +Mat33 operator*(const Mat33 &m, T v) +{ + return Mat33(m[0][0] * v, m[0][1] * v, m[0][2] * v, + m[1][0] * v, m[1][1] * v, m[1][2] * v, + m[2][0] * v, m[2][1] * v, m[2][2] * v); +} + +template +Vec3 operator*(const Vec3 &a, T v) +{ + return Vec3(a[0] * v, a[1] * v, a[2] * v); +} + +} // namespace rtengine diff --git a/rtengine/perspectivecorrection.cc b/rtengine/perspectivecorrection.cc index 7a56ef5a8..f4428faf2 100644 --- a/rtengine/perspectivecorrection.cc +++ b/rtengine/perspectivecorrection.cc @@ -297,7 +297,7 @@ PerspectiveCorrection::Params PerspectiveCorrection::autocompute(ImageSource *sr neutral.raw.bayersensor.method = RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::FAST); neutral.raw.xtranssensor.method = RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FAST); neutral.icm.outputProfile = ColorManagementParams::NoICMString; - src->getImage(src->getWB(), tr, img.get(), pp, neutral.toneCurve, neutral.raw); + src->getImage(src->getWB(), tr, img.get(), pp, neutral.toneCurve, neutral.raw, 0); src->convertColorSpace(img.get(), pparams->icm, src->getWB()); neutral.commonTrans.autofill = false; // Ensures crop factor is correct. diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc index de1603f1c..1afe72c92 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -121,7 +121,7 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext double contrastThresholdDummy = 0.0; rawImage.demosaic(params.raw, false, contrastThresholdDummy); Imagefloat image(fw, fh); - rawImage.getImage (wb, TR_NONE, &image, pp, params.toneCurve, params.raw); + rawImage.getImage (wb, TR_NONE, &image, pp, params.toneCurve, params.raw, 0); rtengine::Image8 output(fw, fh); rawImage.convertColorSpace(&image, params.icm, wb); #ifdef _OPENMP diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index e6bdc9619..9323bd9e7 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -373,7 +373,7 @@ ToneCurveParams::ToneCurveParams() : autoexp(false), clip(0.02), hrenabled(false), - method("Blend"), + method("Coloropp"), expcomp(0), curve{ DCT_Linear @@ -390,6 +390,7 @@ ToneCurveParams::ToneCurveParams() : shcompr(50), hlcompr(0), hlbl(0), + hlth(1.0), hlcomprthresh(0), histmatching(false), fromHistMatching(false), @@ -416,6 +417,7 @@ bool ToneCurveParams::isPanningRelatedChange(const ToneCurveParams& other) const && shcompr == other.shcompr && hlcompr == other.hlcompr && hlbl == other.hlbl + && hlth == other.hlth && hlcomprthresh == other.hlcomprthresh && histmatching == other.histmatching && clampOOG == other.clampOOG); @@ -440,6 +442,7 @@ bool ToneCurveParams::operator ==(const ToneCurveParams& other) const && shcompr == other.shcompr && hlcompr == other.hlcompr && hlbl == other.hlbl + && hlth == other.hlth && hlcomprthresh == other.hlcomprthresh && histmatching == other.histmatching && fromHistMatching == other.fromHistMatching @@ -5912,6 +5915,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->toneCurve.hrenabled, "HLRecovery", "Enabled", toneCurve.hrenabled, keyFile); saveToKeyfile(!pedited || pedited->toneCurve.method, "HLRecovery", "Method", toneCurve.method, keyFile); saveToKeyfile(!pedited || pedited->toneCurve.hlbl, "HLRecovery", "Hlbl", toneCurve.hlbl, keyFile); + saveToKeyfile(!pedited || pedited->toneCurve.hlth, "HLRecovery", "Hlth", toneCurve.hlth, keyFile); const std::map tc_mapping = { {ToneCurveMode::STD, "Standard"}, @@ -7697,6 +7701,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "HLRecovery", "Enabled", pedited, toneCurve.hrenabled, pedited->toneCurve.hrenabled); assignFromKeyfile(keyFile, "HLRecovery", "Method", pedited, toneCurve.method, pedited->toneCurve.method); assignFromKeyfile(keyFile, "HLRecovery", "Hlbl", pedited, toneCurve.hlbl, pedited->toneCurve.hlbl); + assignFromKeyfile(keyFile, "HLRecovery", "Hlth", pedited, toneCurve.hlth, pedited->toneCurve.hlth); } if (keyFile.has_group("Channel Mixer")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index e86272b0a..33d95a619 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -299,6 +299,7 @@ struct ToneCurveParams { int shcompr; int hlcompr; // Highlight Recovery's compression int hlbl; // Highlight Recovery's compression + double hlth; // Highlight Recovery's threshold int hlcomprthresh; // Highlight Recovery's threshold bool histmatching; // histogram matching bool fromHistMatching; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 550c59e9c..7ff9c4d0f 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -468,6 +468,7 @@ RawImageSource::RawImageSource () { embProfile = nullptr; rgbSourceModified = false; + for (int i = 0; i < 4; ++i) { psRedBrightness[i] = psGreenBrightness[i] = psBlueBrightness[i] = 1.f; } @@ -639,6 +640,57 @@ float calculate_scale_mul(float scale_mul[4], const float pre_mul_[4], const flo return gain; } +void RawImageSource::wbMul2Camera(double &rm, double &gm, double &bm) +{ + double r = rm; + double g = gm; + double b = bm; + + auto imatrices = getImageMatrices(); + + if (imatrices) { + double rr = imatrices->cam_rgb[0][0] * r + imatrices->cam_rgb[0][1] * g + imatrices->cam_rgb[0][2] * b; + double gg = imatrices->cam_rgb[1][0] * r + imatrices->cam_rgb[1][1] * g + imatrices->cam_rgb[1][2] * b; + double bb = imatrices->cam_rgb[2][0] * r + imatrices->cam_rgb[2][1] * g + imatrices->cam_rgb[2][2] * b; + r = rr; + g = gg; + b = bb; + } + + rm = ri->get_pre_mul(0) / r; + gm = ri->get_pre_mul(1) / g; + bm = ri->get_pre_mul(2) / b; + + rm /= gm; + bm /= gm; + gm = 1.0; +} + + +void RawImageSource::wbCamera2Mul(double &rm, double &gm, double &bm) +{ + auto imatrices = getImageMatrices(); + + double r = ri->get_pre_mul(0) / rm; + double g = ri->get_pre_mul(1) / gm; + double b = ri->get_pre_mul(2) / bm; + + if (imatrices) { + double rr = imatrices->rgb_cam[0][0] * r + imatrices->rgb_cam[0][1] * g + imatrices->rgb_cam[0][2] * b; + double gg = imatrices->rgb_cam[1][0] * r + imatrices->rgb_cam[1][1] * g + imatrices->rgb_cam[1][2] * b; + double bb = imatrices->rgb_cam[2][0] * r + imatrices->rgb_cam[2][1] * g + imatrices->rgb_cam[2][2] * b; + r = rr; + g = gg; + b = bb; + } + + rm = r / g; + bm = b / g; + gm = 1.0; +} + + + void RawImageSource::getWBMults (const ColorTemp &ctemp, const RAWParams &raw, std::array& out_scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const { @@ -689,10 +741,9 @@ void RawImageSource::getWBMults (const ColorTemp &ctemp, const RAWParams &raw, s autoGainComp = camInitialGain / initialGain; } -void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw) -{ +void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw, int opposed) +{// added int opposed to force getimage to use inpaint-opposed if enable, only once MyMutex::MyLock lock(getImageMutex); - tran = defTransform (tran); // compute channel multipliers @@ -705,7 +756,9 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima gm = ri->get_pre_mul(1); bm = ri->get_pre_mul(2); } else { - ctemp.getMultipliers (r, g, b); + // ctemp.getMultipliers (r, g, b); + r = g = b = 1; + wbCamera2Mul(r, g, b); rm = imatrices.cam_rgb[0][0] * r + imatrices.cam_rgb[0][1] * g + imatrices.cam_rgb[0][2] * b; gm = imatrices.cam_rgb[1][0] * r + imatrices.cam_rgb[1][1] * g + imatrices.cam_rgb[1][2] * b; bm = imatrices.cam_rgb[2][0] * r + imatrices.cam_rgb[2][1] * g + imatrices.cam_rgb[2][2] * b; @@ -790,22 +843,52 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima int maxx = this->W, maxy = this->H, skip = pp.getSkip(); - // raw clip levels after white balance + bool iscolor = (hrp.method == "Color" || hrp.method == "Coloropp"); + const bool doClip = (chmax[0] >= clmax[0] || chmax[1] >= clmax[1] || chmax[2] >= clmax[2]) && !hrp.hrenabled && hrp.clampOOG; + bool doHr = (hrp.hrenabled && !iscolor); + if (hrp.hrenabled && iscolor) { + + if(hrp.method == "Coloropp" && opposed == 1) {//force Inpaint opposed if WB change, and opposed limited tne number to 1 + rgbSourceModified = false; + } + if (!rgbSourceModified) { + if(hrp.method == "Color") { + if (settings->verbose) { + printf ("Applying Highlight Recovery: Color propagation.\n"); + } + HLRecovery_inpaint (red, green, blue, hrp.hlbl); + } else if(hrp.method == "Coloropp" && ctemp.getTemp() >= 0) { + float s[3] = { rm, gm, bm }; + highlight_recovery_opposed(s, ctemp, hrp.hlth); + } + rgbSourceModified = true; + } + } + + // now apply the wb coefficients + if (ctemp.getTemp() >= 0) { + double r, g, b; + ctemp.getMultipliers(r, g, b); + wbMul2Camera(r, g, b); + + rm *= r; + gm *= g; + bm *= b; + } hlmax[0] = clmax[0] * rm; hlmax[1] = clmax[1] * gm; hlmax[2] = clmax[2] * bm; - const bool doClip = (chmax[0] >= clmax[0] || chmax[1] >= clmax[1] || chmax[2] >= clmax[2]) && !hrp.hrenabled && hrp.clampOOG; + const float expcomp = std::pow(2, ri->getBaselineExposure()); + rm *= expcomp; + gm *= expcomp; + bm *= expcomp; float area = skip * skip; rm /= area; gm /= area; bm /= area; - bool doHr = (hrp.hrenabled && hrp.method != "Color"); - const float expcomp = std::pow(2, ri->getBaselineExposure()); - rm *= expcomp; - gm *= expcomp; - bm *= expcomp; + #ifdef _OPENMP #pragma omp parallel if(!d1x) // omp disabled for D1x to avoid race conditions (see Issue 1088 http://code.google.com/p/rawtherapee/issues/detail?id=1088) @@ -1697,7 +1780,6 @@ void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &c rgbSourceModified = false; - if (cache) { if (!redCache) { redCache = new array2D(W, H); @@ -2396,7 +2478,6 @@ void RawImageSource::retinex(const ColorManagementParams& cmp, const RetinexPara } rgbSourceModified = false; // tricky handling for Color propagation - t5.set(); if (settings->verbose) { @@ -2442,16 +2523,17 @@ void RawImageSource::flush() void RawImageSource::HLRecovery_Global(const ToneCurveParams &hrp) { - if (hrp.hrenabled && hrp.method == "Color") { - if (!rgbSourceModified) { - if (settings->verbose) { - printf ("Applying Highlight Recovery: Color propagation...\n"); - } - - HLRecovery_inpaint (red, green, blue, hrp.hlbl); - rgbSourceModified = true; - } - } + // if (hrp.hrenabled && hrp.method == "Color") { + // if (!rgbSourceModified) { + // if (settings->verbose) { + // printf ("Applying Highlight Recovery: Color propagation...\n"); + // } +// + // HLRecovery_inpaint (red, green, blue, hrp.hlbl); +// +// rgbSourceModified = true; + // } +// } } @@ -3460,6 +3542,7 @@ bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embed // very effective to reduce (or remove) the magenta, but with levels of grey ! void RawImageSource::HLRecovery_blend(float* rin, float* gin, float* bin, int width, float maxval, float* hlmax) { + constexpr int ColorCount = 3; // Transform matrixes rgb>lab and back @@ -3684,6 +3767,7 @@ void RawImageSource::HLRecovery_CIELab (float* rin, float* gin, float* bin, floa void RawImageSource::hlRecovery (const std::string &method, float* red, float* green, float* blue, int width, float* hlmax) { +// BENCHFUN if (method == "Luminance") { HLRecovery_Luminance (red, green, blue, red, green, blue, width, 65535.0); @@ -3953,12 +4037,12 @@ void RawImageSource::getRowStartEnd (int x, int &start, int &end) } } - -static void histoxyY(int bfhitc, int bfwitc, const array2D & xc, const array2D & yc, const array2D & Yc, LUTf &xxx, LUTf &yyy, LUTf &YYY, LUTu &histxy) +static void histoxyY(int bfhitc, int bfwitc, const array2D & xc, const array2D & yc, const array2D & Yc, LUTf &xxx, LUTf &yyy, LUTf &YYY, LUTu &histxy, bool purp) { - //calculate histogram x y in a range of 190 colors - //this "choice" are guided by generally colors who are in nature skin, sky, etc. in those cases "steps" are small + // calculate histogram x y in a range of 236 colors + // this "choice" are guided by generally colors who are in nature skin, sky, etc. in those cases "steps" are small // of course we can change to be more precise + // purp enable or not purple color in xyY - approximation... #ifdef _OPENMP #pragma omp parallel #endif @@ -3971,434 +4055,528 @@ static void histoxyY(int bfhitc, int bfwitc, const array2D & xc, const ar yyythr.clear(); LUTf YYYthr(YYY.getSize()); YYYthr.clear(); + // bool purp = false; #ifdef _OPENMP #pragma omp for schedule(dynamic, 4) nowait #endif - for (int y = 0; y < bfhitc ; y++) { + + for (int y = 0; y < bfhitc ; y++) + { for (int x = 0; x < bfwitc ; x++) { int nh = -1; + if (xc[y][x] < 0.12f && xc[y][x] > 0.03f && yc[y][x] > 0.1f) { // near Prophoto if (yc[y][x] < 0.2f) { nh = 0; //blue hard - } else if (yc[y][x] < 0.3f) { + } else if (yc[y][x] < 0.25f) { nh = 1; - //blue - } else if (yc[y][x] < 0.4f) { + } else if (yc[y][x] < 0.3f) { nh = 2; - + //blue + } else if (yc[y][x] < 0.35f) { + nh = 3; + } else if (yc[y][x] < 0.4f) { + nh = 4; + } else if (yc[y][x] < 0.45f) { + nh = 5; } else if (yc[y][x] < 0.5f) { //blue green - nh = 3; + nh = 6; + } else if (yc[y][x] < 0.55f) { + nh = 7; } else if (yc[y][x] < 0.6f) { - nh = 4; + nh = 8; + } else if (yc[y][x] < 0.7f) { + nh = 9; } else if (yc[y][x] < 0.82f) { //green - nh = 5; + nh = 10; } } else if (xc[y][x] < 0.24f && yc[y][x] > 0.05f) { if (yc[y][x] < 0.2f) { - nh = 6; - } else if (yc[y][x] < 0.3f) { - nh = 7; - } else if (yc[y][x] < 0.4f) { - nh = 8; - } else if (yc[y][x] < 0.5f) { - nh = 9; - } else if (yc[y][x] < 0.6f) { - nh = 10; - } else if (yc[y][x] < 0.75f) { nh = 11; - } - } else if (xc[y][x] < 0.28f && yc[y][x] > 0.1f) {//blue sky and other - if (yc[y][x] < 0.2f) { - nh = 12; } else if (yc[y][x] < 0.25f) { + nh = 12; + } else if (yc[y][x] < 0.3f) { nh = 13; - } else if (yc[y][x] < 0.29f) { + } else if (yc[y][x] < 0.35f) { nh = 14; - } else if (yc[y][x] < 0.33f) { - nh = 15; - } else if (yc[y][x] < 0.37f) { - nh = 16; } else if (yc[y][x] < 0.4f) { - nh = 17; + nh = 15; } else if (yc[y][x] < 0.45f) { - nh = 18; + nh = 16; } else if (yc[y][x] < 0.5f) { - nh = 19; + nh = 17; + } else if (yc[y][x] < 0.55f) { + nh = 18; } else if (yc[y][x] < 0.6f) { + nh = 19; + } else if (yc[y][x] < 0.67f) { nh = 20; } else if (yc[y][x] < 0.75f) { nh = 21; } - } else if (xc[y][x] < 0.31f && yc[y][x] > 0.1f) {//near neutral others + } else if (xc[y][x] < 0.28f && yc[y][x] > 0.1f) {//blue sky and other if (yc[y][x] < 0.2f) { nh = 22; - } else if (yc[y][x] < 0.24f) { + } else if (yc[y][x] < 0.23f) { nh = 23; - } else if (yc[y][x] < 0.29f) { + } else if (yc[y][x] < 0.25f) { nh = 24; - } else if (yc[y][x] < 0.32f) { + } else if (yc[y][x] < 0.27f) { nh = 25; - } else if (yc[y][x] < 0.36f) { + } else if (yc[y][x] < 0.29f) { nh = 26; - } else if (yc[y][x] < 0.4f) { + } else if (yc[y][x] < 0.31f) { nh = 27; - } else if (yc[y][x] < 0.5f) { + } else if (yc[y][x] < 0.33f) { nh = 28; - } else if (yc[y][x] < 0.7f) { + } else if (yc[y][x] < 0.35f) { nh = 29; + } else if (yc[y][x] < 0.37f) { + nh = 30; + } else if (yc[y][x] < 0.4f) { + nh = 31; + } else if (yc[y][x] < 0.45f) { + nh = 32; + } else if (yc[y][x] < 0.5f) { + nh = 33; + } else if (yc[y][x] < 0.55f) { + nh = 34; + } else if (yc[y][x] < 0.6f) { + nh = 35; + } else if (yc[y][x] < 0.67f) { + nh = 36; + } else if (yc[y][x] < 0.75f) { + nh = 37; + } + } else if (xc[y][x] < 0.31f && yc[y][x] > 0.1f) {//near neutral others + if (yc[y][x] < 0.2f) { + nh = 38; + } else if (yc[y][x] < 0.22f) { + nh = 39; + } else if (yc[y][x] < 0.24f) { + nh = 40; + } else if (yc[y][x] < 0.26f) { + nh = 41; + } else if (yc[y][x] < 0.29f) { + nh = 42; + } else if (yc[y][x] < 0.32f) { + nh = 43; + } else if (yc[y][x] < 0.36f) { + nh = 44; + } else if (yc[y][x] < 0.4f) { + nh = 45; + } else if (yc[y][x] < 0.45f) { + nh = 46; + } else if (yc[y][x] < 0.5f) { + nh = 47; + } else if (yc[y][x] < 0.6f) { + nh = 48; + } else if (yc[y][x] < 0.7f) { + nh = 49; } } else if (xc[y][x] < 0.325f && yc[y][x] > 0.1f) {//neutral 34 if (yc[y][x] < 0.2f) { - nh = 30; + nh = 50; + } else if (yc[y][x] < 0.22f) { + nh = 51; } else if (yc[y][x] < 0.24f) { - nh = 31; + nh = 52; } else if (yc[y][x] < 0.29f) { - nh = 32; + nh = 53; } else if (yc[y][x] < 0.32f) { - nh = 33; + nh = 54; } else if (yc[y][x] < 0.33f) { - nh = 34; + nh = 55; } else if (yc[y][x] < 0.335f) { - nh = 35; + nh = 56; } else if (yc[y][x] < 0.34f) { - nh = 36; + nh = 57; } else if (yc[y][x] < 0.35f) { - nh = 37; + nh = 58; } else if (yc[y][x] < 0.37f) { - nh = 38; + nh = 59; } else if (yc[y][x] < 0.4f) { - nh = 39; + nh = 60; } else if (yc[y][x] < 0.45f) { - nh = 40; + nh = 61; } else if (yc[y][x] < 0.5f) { - nh = 41; + nh = 62; } else if (yc[y][x] < 0.55f) { - nh = 42; + nh = 63; + } else if (yc[y][x] < 0.6f) { + nh = 64; + } else if (yc[y][x] < 0.65f) { + nh = 65; } else if (yc[y][x] < 0.7f) { - nh = 43; + nh = 66; } } else if (xc[y][x] < 0.335f && yc[y][x] > 0.1f) {//neutral if (yc[y][x] < 0.2f) { - nh = 44; + nh = 67; + } else if (yc[y][x] < 0.22f) { + nh = 68; } else if (yc[y][x] < 0.24f) { - nh = 45; + nh = 69; + } else if (yc[y][x] < 0.27f) { + nh = 70; } else if (yc[y][x] < 0.29f) { - nh = 46; + nh = 71; } else if (yc[y][x] < 0.32f) { - nh = 47; + nh = 72; } else if (yc[y][x] < 0.33f) { - nh = 48; + nh = 73; } else if (yc[y][x] < 0.335f) { - nh = 49; + nh = 74; } else if (yc[y][x] < 0.34f) { - nh = 50; + nh = 75; } else if (yc[y][x] < 0.345f) { - nh = 51; + nh = 76; } else if (yc[y][x] < 0.35f) { - nh = 52; + nh = 77; } else if (yc[y][x] < 0.355f) { - nh = 53; + nh = 78; } else if (yc[y][x] < 0.36f) { - nh = 54; + nh = 79; } else if (yc[y][x] < 0.37f) { - nh = 55; + nh = 80; } else if (yc[y][x] < 0.38f) { - nh = 56; + nh = 81; } else if (yc[y][x] < 0.4f) { - nh = 57; + nh = 82; } else if (yc[y][x] < 0.45f) { - nh = 58; + nh = 83; } else if (yc[y][x] < 0.5f) { - nh = 59; + nh = 84; } else if (yc[y][x] < 0.55f) { - nh = 60; + nh = 85; + } else if (yc[y][x] < 0.6f) { + nh = 86; + } else if (yc[y][x] < 0.65f) { + nh = 87; } else if (yc[y][x] < 0.7f) { - nh = 61; + nh = 88; } } else if (xc[y][x] < 0.340f && yc[y][x] > 0.1f) {//neutral if (yc[y][x] < 0.2f) { - nh = 62; + nh = 89; + } else if (yc[y][x] < 0.22f) { + nh = 90; } else if (yc[y][x] < 0.24f) { - nh = 63; + nh = 91; } else if (yc[y][x] < 0.29f) { - nh = 64; + nh = 92; } else if (yc[y][x] < 0.32f) { - nh = 65; + nh = 93; } else if (yc[y][x] < 0.325f) { - nh = 66; + nh = 94; } else if (yc[y][x] < 0.33f) { - nh = 67; + nh = 95; } else if (yc[y][x] < 0.335f) { - nh = 68; + nh = 96; } else if (yc[y][x] < 0.34f) { - nh = 69; + nh = 97; } else if (yc[y][x] < 0.345f) { - nh = 70; + nh = 98; } else if (yc[y][x] < 0.35f) { - nh = 71; + nh = 99; } else if (yc[y][x] < 0.355f) { - nh = 72; + nh = 100; } else if (yc[y][x] < 0.36f) { - nh = 73; + nh = 101; } else if (yc[y][x] < 0.37f) { - nh = 74; + nh = 102; } else if (yc[y][x] < 0.38f) { - nh = 75; + nh = 103; } else if (yc[y][x] < 0.4f) { - nh = 76; + nh = 104; } else if (yc[y][x] < 0.45f) { - nh = 77; + nh = 105; } else if (yc[y][x] < 0.5f) { - nh = 78; + nh = 106; } else if (yc[y][x] < 0.55f) { - nh = 79; + nh = 107; + } else if (yc[y][x] < 0.6f) { + nh = 108; + } else if (yc[y][x] < 0.65f) { + nh = 109; } else if (yc[y][x] < 0.7f) { - nh = 80; + nh = 110; } } else if (xc[y][x] < 0.345f && yc[y][x] > 0.1f) {//neutral 37 if (yc[y][x] < 0.2f) { - nh = 81; + nh = 111; + } else if (yc[y][x] < 0.22f) { + nh = 112; } else if (yc[y][x] < 0.24f) { - nh = 82; + nh = 113; + } else if (yc[y][x] < 0.26f) { + nh = 114; } else if (yc[y][x] < 0.29f) { - nh = 83; + nh = 115; } else if (yc[y][x] < 0.32f) { - nh = 84; + nh = 116; } else if (yc[y][x] < 0.33f) { - nh = 85; + nh = 117; } else if (yc[y][x] < 0.335f) { - nh = 86; + nh = 118; } else if (yc[y][x] < 0.34f) { - nh = 87; + nh = 119; } else if (yc[y][x] < 0.345f) { - nh = 88; + nh = 120; } else if (yc[y][x] < 0.35f) { - nh = 89; + nh = 121; } else if (yc[y][x] < 0.355f) { - nh = 90; + nh = 122; } else if (yc[y][x] < 0.36f) { - nh = 91; + nh = 123; } else if (yc[y][x] < 0.37f) { - nh = 92; + nh = 124; } else if (yc[y][x] < 0.38f) { - nh = 93; + nh = 125; } else if (yc[y][x] < 0.39f) { - nh = 94; + nh = 126; } else if (yc[y][x] < 0.4f) { - nh = 95; + nh = 127; } else if (yc[y][x] < 0.42f) { - nh = 96; + nh = 128; } else if (yc[y][x] < 0.45f) { - nh = 97; + nh = 129; } else if (yc[y][x] < 0.48f) { - nh = 98; + nh = 130; } else if (yc[y][x] < 0.5f) { - nh = 99; + nh = 131; } else if (yc[y][x] < 0.55f) { - nh = 100; + nh = 132; } else if (yc[y][x] < 0.65f) { - nh = 101; + nh = 133; } } else if (xc[y][x] < 0.355f && yc[y][x] > 0.1f) {//neutral 37 if (yc[y][x] < 0.2f) { - nh = 102; + nh = 134; + } else if (yc[y][x] < 0.22f) { + nh = 135; } else if (yc[y][x] < 0.24f) { - nh = 103; + nh = 136; + } else if (yc[y][x] < 0.26f) { + nh = 137; } else if (yc[y][x] < 0.29f) { - nh = 104; + nh = 138; } else if (yc[y][x] < 0.32f) { - nh = 105; + nh = 139; } else if (yc[y][x] < 0.33f) { - nh = 106; + nh = 140; } else if (yc[y][x] < 0.335f) { - nh = 107; + nh = 141; } else if (yc[y][x] < 0.34f) { - nh = 108; + nh = 142; } else if (yc[y][x] < 0.345f) { - nh = 109; + nh = 143; } else if (yc[y][x] < 0.35f) { - nh = 110; + nh = 144; } else if (yc[y][x] < 0.355f) { - nh = 111; + nh = 145; } else if (yc[y][x] < 0.36f) { - nh = 112; + nh = 146; } else if (yc[y][x] < 0.37f) { - nh = 113; + nh = 147; } else if (yc[y][x] < 0.38f) { - nh = 114; + nh = 148; } else if (yc[y][x] < 0.39f) { - nh = 115; + nh = 149; } else if (yc[y][x] < 0.4f) { - nh = 116; + nh = 150; } else if (yc[y][x] < 0.42f) { - nh = 117; + nh = 151; } else if (yc[y][x] < 0.45f) { - nh = 118; + nh = 152; } else if (yc[y][x] < 0.48f) { - nh = 119; + nh = 153; } else if (yc[y][x] < 0.5f) { - nh = 120; + nh = 154; } else if (yc[y][x] < 0.55f) { - nh = 121; + nh = 155; + } else if (yc[y][x] < 0.6f) { + nh = 156; } else if (yc[y][x] < 0.65f) { - nh = 122; + nh = 157; } } else if (xc[y][x] < 0.365f && yc[y][x] > 0.15f) { //0.4 if (yc[y][x] < 0.2f) { - nh = 123; + nh = 158; + } else if (yc[y][x] < 0.22f) { + nh = 159; } else if (yc[y][x] < 0.24f) { - nh = 124; + nh = 160; + } else if (yc[y][x] < 0.26f) { + nh = 161; } else if (yc[y][x] < 0.29f) { - nh = 125; + nh = 162; } else if (yc[y][x] < 0.32f) { - nh = 126; + nh = 163; } else if (yc[y][x] < 0.33f) { - nh = 127; + nh = 164; } else if (yc[y][x] < 0.34f) { - nh = 128; + nh = 165; } else if (yc[y][x] < 0.35f) { - nh = 129; + nh = 166; } else if (yc[y][x] < 0.36f) { - nh = 130; + nh = 167; } else if (yc[y][x] < 0.37f) { - nh = 131; + nh = 168; } else if (yc[y][x] < 0.38f) { - nh = 132; + nh = 169; } else if (yc[y][x] < 0.39f) { - nh = 133; + nh = 170; } else if (yc[y][x] < 0.4f) { - nh = 134; + nh = 171; } else if (yc[y][x] < 0.42f) { - nh = 135; + nh = 172; } else if (yc[y][x] < 0.45f) { - nh = 136; + nh = 173; } else if (yc[y][x] < 0.5f) { - nh = 137; + nh = 174; } else if (yc[y][x] < 0.55f) { - nh = 138; + nh = 175; } else if (yc[y][x] < 0.63f) { - nh = 139; + nh = 176; } } else if (xc[y][x] < 0.405f && yc[y][x] > 0.15f) {//45 - if (yc[y][x] < 0.2f) { - nh = 140; - } else if (yc[y][x] < 0.24f) { - nh = 141; - } else if (yc[y][x] < 0.29f) { - nh = 142; - } else if (yc[y][x] < 0.32f) { - nh = 143; - } else if (yc[y][x] < 0.34f) { - nh = 144; - } else if (yc[y][x] < 0.37f) { - nh = 145; - } else if (yc[y][x] < 0.4f) { - nh = 146; - } else if (yc[y][x] < 0.45f) { - nh = 147; - } else if (yc[y][x] < 0.5f) { - nh = 148; - } else if (yc[y][x] < 0.55f) { - nh = 149; - } else if (yc[y][x] < 0.6f) { - nh = 150; - } - } else if (xc[y][x] < 0.445f && yc[y][x] > 0.15f) {//45 - if (yc[y][x] < 0.2f) { - nh = 151; - } else if (yc[y][x] < 0.24f) { - nh = 152; - } else if (yc[y][x] < 0.29f) { - nh = 153; - } else if (yc[y][x] < 0.32f) { - nh = 154; - } else if (yc[y][x] < 0.34f) { - nh = 155; - } else if (yc[y][x] < 0.37f) { - nh = 156; - } else if (yc[y][x] < 0.4f) { - nh = 157; - } else if (yc[y][x] < 0.45f) { - nh = 158; - } else if (yc[y][x] < 0.5f) { - nh = 159; - } else if (yc[y][x] < 0.55f) { - nh = 160; - } else if (yc[y][x] < 0.58f) { - nh = 161; - } - } else if (xc[y][x] < 0.495f && yc[y][x] > 0.15f) { - if (yc[y][x] < 0.2f) { - nh = 162; - } else if (yc[y][x] < 0.24f) { - nh = 163; - } else if (yc[y][x] < 0.29f) { - nh = 164; - } else if (yc[y][x] < 0.32f) { - nh = 165; - } else if (yc[y][x] < 0.34f) { - nh = 166; - } else if (yc[y][x] < 0.37f) { - nh = 167; - } else if (yc[y][x] < 0.4f) { - nh = 168; - } else if (yc[y][x] < 0.45f) { - nh = 169; - } else if (yc[y][x] < 0.5f) { - nh = 170; - } else if (yc[y][x] < 0.55f) { - nh = 171; - } - } else if (xc[y][x] < 0.545f && yc[y][x] > 0.15f) { - if (yc[y][x] < 0.2f) { - nh = 172; - } else if (yc[y][x] < 0.24f) { - nh = 173; - } else if (yc[y][x] < 0.29f) { - nh = 174; - } else if (yc[y][x] < 0.32f) { - nh = 175; - } else if (yc[y][x] < 0.34f) { - nh = 176; - } else if (yc[y][x] < 0.37f) { + if (yc[y][x] < 0.2f && purp) {//no take into account if purp = false nh = 177; - } else if (yc[y][x] < 0.4f) { + } else if (yc[y][x] < 0.22f && purp) { nh = 178; - } else if (yc[y][x] < 0.45f) { + } else if (yc[y][x] < 0.24f && purp) { nh = 179; - } else if (yc[y][x] < 0.5f) { + } else if (yc[y][x] < 0.26f && purp) { nh = 180; - } - } else if (xc[y][x] < 0.595f && yc[y][x] > 0.15f) { - if (yc[y][x] < 0.22f) { + } else if (yc[y][x] < 0.29f && purp) { nh = 181; - } else if (yc[y][x] < 0.25f) { + } else if (yc[y][x] < 0.32f) { nh = 182; - } else if (yc[y][x] < 0.3f) { + } else if (yc[y][x] < 0.34f) { nh = 183; - } else if (yc[y][x] < 0.35f) { + } else if (yc[y][x] < 0.37f) { nh = 184; } else if (yc[y][x] < 0.4f) { nh = 185; } else if (yc[y][x] < 0.45f) { nh = 186; + } else if (yc[y][x] < 0.5f) { + nh = 187; + } else if (yc[y][x] < 0.55f) { + nh = 188; + } else if (yc[y][x] < 0.6f) { + nh = 189; + } + } else if (xc[y][x] < 0.445f && yc[y][x] > 0.15f) {//45 + if (yc[y][x] < 0.2f && purp) { + nh = 190; + } else if (yc[y][x] < 0.22f && purp) { + nh = 191; + } else if (yc[y][x] < 0.24f && purp) { + nh = 192; + } else if (yc[y][x] < 0.26f && purp) { + nh = 193; + } else if (yc[y][x] < 0.29f && purp) { + nh = 194; + } else if (yc[y][x] < 0.32f && purp) { + nh = 195; + } else if (yc[y][x] < 0.34f && purp) { + nh = 196; + } else if (yc[y][x] < 0.37f) { + nh = 197; + } else if (yc[y][x] < 0.4f) { + nh = 198; + } else if (yc[y][x] < 0.45f) { + nh = 199; + } else if (yc[y][x] < 0.5f) { + nh = 200; + } else if (yc[y][x] < 0.55f) { + nh = 201; + } else if (yc[y][x] < 0.58f) { + nh = 202; + } + } else if (xc[y][x] < 0.495f && yc[y][x] > 0.15f) { + if (yc[y][x] < 0.2f && purp) { + nh = 203; + } else if (yc[y][x] < 0.22f && purp) { + nh = 204; + } else if (yc[y][x] < 0.24f && purp) { + nh = 205; + } else if (yc[y][x] < 0.26f && purp) { + nh = 206; + } else if (yc[y][x] < 0.29f && purp) { + nh = 207; + } else if (yc[y][x] < 0.32f && purp) { + nh = 208; + } else if (yc[y][x] < 0.34f && purp) { + nh = 209; + } else if (yc[y][x] < 0.37f) { + nh = 210; + } else if (yc[y][x] < 0.4f) { + nh = 211; + } else if (yc[y][x] < 0.45f) { + nh = 212; + } else if (yc[y][x] < 0.5f) { + nh = 213; + } else if (yc[y][x] < 0.55f) { + nh = 214; + } + } else if (xc[y][x] < 0.545f && yc[y][x] > 0.15f) { + if (yc[y][x] < 0.2f && purp) { + nh = 215; + } else if (yc[y][x] < 0.22f && purp) { + nh = 216; + } else if (yc[y][x] < 0.24f && purp) { + nh = 217; + } else if (yc[y][x] < 0.26f && purp) { + nh = 218; + } else if (yc[y][x] < 0.29f && purp) { + nh = 219; + } else if (yc[y][x] < 0.32f && purp) { + nh = 220; + } else if (yc[y][x] < 0.34f && purp) { + nh = 221; + } else if (yc[y][x] < 0.37f) { + nh = 222; + } else if (yc[y][x] < 0.4f) { + nh = 223; + } else if (yc[y][x] < 0.45f) { + nh = 224; + } else if (yc[y][x] < 0.5f) { + nh = 225; + } + } else if (xc[y][x] < 0.595f && yc[y][x] > 0.15f) { + if (yc[y][x] < 0.22f) { + nh = 226; + } else if (yc[y][x] < 0.25f) { + nh = 227; + } else if (yc[y][x] < 0.3f) { + nh = 228; + } else if (yc[y][x] < 0.35f) { + nh = 229; + } else if (yc[y][x] < 0.4f) { + nh = 230; + } else if (yc[y][x] < 0.45f) { + nh = 231; } } else if (xc[y][x] < 0.65f && yc[y][x] > 0.12f) { if (yc[y][x] < 0.25f) { - nh = 187; + nh = 232; } else if (yc[y][x] < 0.3f) { - nh = 188; + nh = 233; } else if (yc[y][x] < 0.35f) { - nh = 189; + nh = 234; } else if (yc[y][x] < 0.45f) { - nh = 190; + nh = 235; } } else if (xc[y][x] < 0.75f && yc[y][x] > 0.1f) { - nh = 191; + nh = 236; //191 } + if (nh >= 0) { histxythr[nh]++; xxxthr[nh] += xc[y][x]; @@ -4407,6 +4585,7 @@ static void histoxyY(int bfhitc, int bfwitc, const array2D & xc, const ar } } } + #ifdef _OPENMP #pragma omp critical #endif @@ -4431,24 +4610,28 @@ float static studentXY(const array2D & YYcurr, const array2D & ref somcurrY += YYcurr[i][tt]; //sum observations first group } + somcurrY *= 100.f; for (int i = 0; i < Nc; i++) { somreffY += reffYY[i][tt]; //sum observations second group } + somreffY *= 100.f; for (int i = 0; i < sizcurr; i++) { somcurr2Y += SQR(YYcurr[i][tt]); //sum sqr observations first group } + somcurr2Y *= SQR(100.f); for (int i = 0; i < Nc; i++) { somreff2Y += SQR(reffYY[i][tt]); //sum sqr observations second group } + somreff2Y *= SQR(100.f); const float somsqueccurrY = somcurr2Y - SQR(somcurrY) / sizcurr; @@ -4465,19 +4648,22 @@ float static studentXY(const array2D & YYcurr, const array2D & ref //student coeeficient } -void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, const ColorManagementParams &cmp, const RAWParams &raw, const WBParams & wbpar) + + + +void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, const ColorManagementParams &cmp, const RAWParams &raw, const WBParams & wbpar, const ToneCurveParams &hrp) { /* - Copyright (c) Jacques Desmis 6 - 2018 jdesmis@gmail.com + Copyright (c) Jacques Desmis 6 - 2018 jdesmis@gmail.com, update 1 - 2023 Copyright (c) Ingo Weyrich 3 - 2020 (heckflosse67@gmx.de) - This algorithm try to find temperature correlation between 20 to 201 color between 201 spectral color and about 20 to 55 color found in the image between 192, I just found the idea in the web "correlate with chroma" instead of RGB grey point,but I don't use any algo found on the web. + This algorithm try to find temperature correlation between 20 to 80 colors between 201 spectral color and about 20 to 55 color found in the image between 236, I just found the idea in the web "correlate with chroma" instead of RGB grey point,but I don't use any algo found on the web. I have test many many algorithms to find the first one that work :) Probably (sure) there are improvement to do... I have create a table temperature with temp and white point with 118 values between 2000K and 12000K we can obviously change these values, more...with different steps - I have create a table for tint (green)with 134 values between 0.4 to 4. + I have create a table for tint (green)with 134 values between 0.4 to 4. I have create or recuparate and transformed 201 spectral colors from Colorchecker24, others color and my 468 colors target, or from web flowers, etc. with a step of 5nm, I think it is large enough. I think this value of 201 is now complete: I tested correlation with 60, 90, 100, 120, 155...better student increase with number of color, but now it seems stabilized Of course we can increase this number :) @@ -4520,17 +4706,18 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double You can change parameters in option.cc Itcwb_thres : 34 by default ==> number of color used in final algorithm - between 10 and max 55 - Itcwb_sort : false by default, can improve algorithm if true, ==> sort value in something near chroma order, instead of histogram number + Itcwb_sorted : true by default, can improve algorithm if true, ==> sort value in something near chroma order, instead of histogram number Itcwb_greenrange : 0 amplitude of green variation - between 0 to 2 Itcwb_greendeltatemp : 1 - delta temp in green iterate loop for "extra" - between 0 to 4 - Itcwb_forceextra : false - if true force algorithm "extra" ("extra" is used when camera wbsettings are wrong) to all images + Itcwb_forceextra : true by default - if true force algorithm "extra" ("extra" is used when camera wbsettings are wrong) to all images Itcwb_sizereference : 3 by default, can be set to 5 ==> size of reference color compare to size of histogram real color itcwb_delta : 1 by default can be set between 0 to 5 ==> delta temp to build histogram xy - if camera temp is not probably good itcwb_stdobserver10 : true by default - use standard observer 10°, false = standard observer 2° - itcwb_precis : 5 by default - can be set to 3 or 9 - 3 best sampling but more time...9 "old" settings - but low differences in times with 3 instead of 9 about twice time 160ms instead of 80ms for a big raw file + itcwb_precis : 3 by default - can be set to 3 or 9 - 3 best sampling but more time...9 "old" settings - but low differences in times with 3 instead of 9 about twice time 160ms instead of 80ms for a big raw file + itcwb_nopurple : true default - allow to bypass highlight recovery and inpait opposed when need flowers and not purple due to highlights... */ -// BENCHFUN - + BENCHFUN + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix("sRGB"); const float wp[3][3] = { {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, @@ -4570,7 +4757,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double {0.590, 1.f}, {0.600, 1.f}, {0.610, 1.f}, - {0.620, 1.f}, + {0.620, 1.f},//extended range {0.630, 1.f}, {0.640, 1.f}, {0.650, 1.f}, @@ -4579,7 +4766,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double {0.680, 1.f}, {0.690, 1.f}, {0.700, 1.f}, - {0.714, 1.f}, + {0.714, 1.f},//usual range {0.727, 1.f}, {0.741, 1.f}, {0.755, 1.f}, @@ -4610,7 +4797,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double {0.971, 1.f}, {0.980, 1.f}, {0.990, 1.f}, - {1.000, 1.f},//55 + {1.000, 1.f},//55 reference {1.010, 1.f}, {1.020, 1.f}, {1.030, 1.f}, @@ -4641,14 +4828,14 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double {1.325, 1.f}, {1.350, 1.f}, {1.375, 1.f}, - {1.400, 1.f}, + {1.400, 1.f},//usual range {1.425, 1.f}, {1.450, 1.f}, {1.475, 1.f}, {1.500, 1.f}, {1.525, 1.f}, {1.550, 1.f}, - {1.575, 1.f}, + {1.575, 1.f},//extended range {1.600, 1.f}, {1.633, 1.f}, {1.666, 1.f}, @@ -4697,7 +4884,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double int end; } RangeGreen; - constexpr RangeGreen Rangestandard = {24, 86}; + constexpr RangeGreen Rangestandard = {24, 86};//usual green range constexpr RangeGreen Rangeextended = {15, 93}; const RangeGreen Rangemax = {0, N_g}; @@ -4778,7 +4965,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double {4927., 0.965414, 0.809229}, {4952., 0.964908, 0.814366}, {4977., 0.964415, 0.819412}, - {5002., 0.963934, 0.824438}, + {5002., 0.963934, 0.824438},//57 reference {5027., 0.963465, 0.829444}, {5052., 0.963008, 0.834429}, {5077., 0.962563, 0.839395}, @@ -4857,10 +5044,10 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double float gmm[N_t]; float bmm[N_t]; - constexpr int siza = 192;//size of histogram + constexpr int siza = 237; //192 untill 01/2023 size of histogram - //tempref and greenref are camera wb values. - // I used them by default to select good spectral values !! + // tempref and greenref are camera wb values. + // I used them by default to select good spectral values !! but they are changed after tempref = rtengine::min(tempref, 12000.0); int repref = 0; @@ -4874,7 +5061,8 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double //calculate R G B multiplier in function illuminant and temperature const bool isMono = (ri->getSensorType() == ST_FUJI_XTRANS && raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::MONO)) - || (ri->getSensorType() == ST_BAYER && raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::MONO)); + || (ri->getSensorType() == ST_BAYER && raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::MONO)); + for (int tt = 0; tt < N_t; ++tt) { double r, g, b; float rm, gm, bm; @@ -4924,19 +5112,27 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double } ; LUTu histxy(siza); //number of values for each pair xy + histxy.clear(); LUTf xxx(siza);//for color references calculated ==> max in images "like histogram" + xxx.clear(); + LUTf yyy(siza); + yyy.clear(); + LUTf YYY(siza);//not used directly, but necessary to keep good range + YYY.clear(); bool separated = true; + int w = -1; array2D reff_spect_yy_camera(N_t, 2 * Nc + 2); + array2D reff_spect_xx_camera(N_t, 2 * Nc + 2); //here we select the good spectral color inside the 113 values @@ -4965,6 +5161,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double #ifdef _OPENMP #pragma omp parallel for #endif + for (int y = 0; y < bfh ; ++y) { for (int x = 0; x < bfw ; ++x) { const float RR = rmm[rep] * redloc[y][x]; @@ -4973,6 +5170,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double Color::rgbxyY(RR, GG, BB, xc[y][x], yc[y][x], Yc[y][x], wp); } } + //histogram xy depend of temp...but in most cases D45 ..D65.. //calculate for this image the mean values for each family of color, near histogram x y (number) //xy vary from x 0..0.77 y 0..0.82 @@ -4982,8 +5180,14 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double // step about 0.02 x 0.32 0.34 y= 0.34 0.36 skin -- sky x 0.24 0.30 y 0.28 0.32 //big step about 0.2 - histoxyY(bfhitc, bfwitc, xc, yc, Yc, xxx, yyy, YYY, histxy); - //return histogram x and y for each temp and in a range of 158 colors (siza) + bool purp = true;//if inpaint-opposed or something else enable purp + + if (hrp.hrenabled && hrp.method == "Coloropp" && settings->itcwb_nopurple == true) {//we disabled (user) with settings if image are naturally with purple (flowers...) + purp = false; + } + + histoxyY(bfhitc, bfwitc, xc, yc, Yc, xxx, yyy, YYY, histxy, purp);//purp enable, enable purple color in WB + //return histogram x and y for each temp and in a range of 235 colors (siza) } // free some memory @@ -5014,15 +5218,19 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double int n4 = 0; int n15 = 0; int n30 = 0; + //part to improve //determined the number of colors who be used after for (int nh = 0; nh < siza; nh++) { if (Wbhis[nh].histnum < 30) { n30++; //keep only existing color but avoid to small + if (Wbhis[nh].histnum < 15) { n15++; //keep only existing color but avoid to small + if (Wbhis[nh].histnum < 4) { n4++; //keep only existing color but avoid to small + if (Wbhis[nh].histnum < 1) { n1++; //keep only existing color but avoid to small } @@ -5047,7 +5255,11 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double int sizcurr2ref = sizcurrref - ntr; const int sizcu30 = sizcurrref - n30; - const int sizcu4 = rtengine::min(sizcu30, 55); + const int sizcu4 = rtengine::min(sizcu30, 55);// + + if (settings->verbose) { + printf("ntr=%i sizcurr2ref=%i sizcu30=%i sizcu4=%i\n", ntr, sizcurr2ref, sizcu30, sizcu4); + } chrom wbchro[sizcu4]; const float swpr = Txyz[repref].XX + Txyz[repref].ZZ + 1.f; @@ -5062,6 +5274,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double } float estimchrom = 0.f; + //estimate chromaticity for references for (int nh = 0; nh < sizcu4; ++nh) { const float chxy = std::sqrt(SQR(xx_curref[nh][repref] - xwpr) + SQR(yy_curref[nh][repref] - ywpr)); @@ -5075,10 +5288,12 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double } estimchrom /= sizcu4; - if (settings->verbose) { + + if (settings->verbose) { printf("estimchrom=%f\n", estimchrom); } - if (settings->itcwb_sort) { //sort in ascending with chroma values + + if (settings->itcwb_sorted) { //sort in ascending with chroma values std::sort(wbchro, wbchro + sizcu4, wbchro[0]); } @@ -5105,7 +5320,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double for (int nb = 1; nb <= maxnb; ++nb) { //max 5 iterations for Itcwb_thres=33, after trial 3 is good in most cases but in some cases 5 for (int i = 0; i < w; ++i) { - float mindeltaE = 100000.f; + float mindeltaE = 100000.f;//we can change this value... int kN = 0; for (int j = 0; j < Nc ; j++) { @@ -5192,7 +5407,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double } } - if (extra) {//always used because I made this choice, brings better results + if (extra) {//always used if extra = true because I made this choice, brings better results struct Tempgreen { float student; int tempref; @@ -5206,14 +5421,15 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double for (int i = 0; i < N_g; ++i) {//init variables with Tgstud[i].student = 1000.f;//max value to initialize - Tgstud[i].tempref = 57;//5002K - Tgstud[i].greenref = 55;// 1.f + Tgstud[i].tempref = 57;//5002K position in the list + Tgstud[i].greenref = 55;// 1.f position in the list } const int dgoodref = rtengine::min(settings->itcwb_greendeltatemp, 4); const int scantempbeg = rtengine::max(goodref - (dgoodref + 1), 1); const int scantempend = rtengine::min(goodref + dgoodref, N_t - 1); + for (int gr = Rangegreenused.begin; gr < Rangegreenused.end; ++gr) { float minstudgr = 100000.f; int goodrefgr = 1; @@ -5249,6 +5465,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double const float BB = bmm[tt] * B_curref_reduc[i][repref]; Color::rgbxyY(RR, GG, BB, xxyycurr_reduc[2 * i][tt], xxyycurr_reduc[2 * i + 1][tt], unused, wp); } + //recalculate xy spectral now with good range of temp and green for (int j = 0; j < Nc ; ++j) { @@ -5257,6 +5474,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double } int kkg = -1; + for (int i = 0; i < Nc ; ++i) { if (good_spectral[i]) { kkg++; @@ -5264,6 +5482,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double reff_spect_xxyy[2 * kkg + 1][tt] = reff_spect_xxyy_prov[2 * i + 1][tt]; } } + //now we have good spectral data //calculate student correlation const float abstudgr = std::fabs(studentXY(xxyycurr_reduc, reff_spect_xxyy, 2 * w, 2 * kkg, tt)); @@ -5272,6 +5491,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double minstudgr = abstudgr; goodrefgr = tt; } + //found the values Tgstud[gr].tempref = goodrefgr; Tgstud[gr].greenref = gr; @@ -5282,48 +5502,35 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double std::sort(Tgstud, Tgstud + N_g, Tgstud[0]); - //now search the value of green the nearest of 1 with a good student value - // I take the 3 first values - //I admit a symetrie in green coefiicient for rgb multiplier...probably not exactly true - //perhaps we can used a Snedecor test ? but why...at least we have confidence interval > 90% - int greengood; - int greengoodprov; - int goodrefprov; - float studprov; - const int goodref0 = Tgstud[0].tempref; - const int greengood0 = Tgstud[0].greenref - 55;//55 green = 1 - const float stud0 = Tgstud[0].student; - const int goodref1 = Tgstud[1].tempref; - const float stud1 = Tgstud[1].student; - const int greengood1 = Tgstud[1].greenref - 55; - const int goodref2 = Tgstud[2].tempref; - const int greengood2 = Tgstud[2].greenref - 55; - const float stud2 = Tgstud[2].student; + // now search the value of green the nearest of 1 with a good student value, I think it is a good choice, perhaps no... + // I take the 5 first values + // I admit a symetrie in green coefiicient for rgb multiplier...probably not exactly true + // perhaps we can used a Snedecor test ? but why...at least we have confidence interval > 90% + int greengood = 55; - if (std::fabs(greengood2) < std::fabs(greengood1)) { - greengoodprov = greengood2; - goodrefprov = goodref2; - studprov = stud2; - } else { - greengoodprov = greengood1; - goodrefprov = goodref1; - studprov = stud1; + int maxkgood = 5;//we can change ...to test 3, 4, 5. High values perhaps less good student, but it is a compromise... + int mingood = std::min(std::fabs(Tgstud[0].greenref - 55), std::fabs(Tgstud[1].greenref - 55)); + for (int k = 2; k < maxkgood; ++k) { + mingood = std::min(std::fabs(mingood), std::fabs(Tgstud[k].greenref - 55)); } - if (std::fabs(greengoodprov) < std::fabs(greengood0)) { - goodref = goodrefprov; - greengood = greengoodprov + 55; - studgood = studprov; + for (int k = 0; k < maxkgood ; ++k) { + if (mingood == fabs(Tgstud[k].greenref - 55)) { + greengood = Tgstud[k].greenref ; + goodref = Tgstud[k].tempref; + studgood = Tgstud[k].student;; + } + } - } else { - goodref = goodref0; - greengood = greengood0 + 55; - studgood = stud0; + if (settings->verbose) { + printf("Student_0=%f Student_k= %f\n", Tgstud[0].student, Tgstud[maxkgood - 1].student); + printf("mingood=%i greeng=%i goodref=%i stud=%f\n", mingood, greengood, goodref, (double) studgood); } tempitc = Txyz[goodref].Tem; greenitc = gree[greengood].green; + if (estimchrom < 0.025f) { float ac = -2.40f * estimchrom + 0.06f;//small empirical correction, maximum 0.06 if chroma=0 for all image, currently for very low chroma +0.02 greenitc += ac; @@ -5337,13 +5544,14 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double if (!extra) { tempitc = Txyz[goodref].Tem; } + //now we have temp green and student if (settings->verbose) { printf("ITCWB tempitc=%f gritc=%f stud=%f \n", tempitc, greenitc, studgood); } } -void RawImageSource::WBauto(double & tempref, double & greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double & avg_rm, double & avg_gm, double & avg_bm, double & tempitc, double & greenitc, float & studgood, bool & twotimes, const WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const ColorManagementParams & cmp, const RAWParams & raw) +void RawImageSource::WBauto(double & tempref, double & greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double & avg_rm, double & avg_gm, double & avg_bm, double & tempitc, double & greenitc, float & studgood, bool & twotimes, const WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const ColorManagementParams & cmp, const RAWParams & raw, const ToneCurveParams &hrp) { // BENCHFUN //auto white balance @@ -5364,8 +5572,7 @@ void RawImageSource::WBauto(double & tempref, double & greenref, array2D } tempitc = 5000.; - - ItcWB(extra, tempref, greenref, tempitc, greenitc, studgood, redloc, greenloc, blueloc, bfw, bfh, avg_rm, avg_gm, avg_bm, cmp, raw, wbpar); + ItcWB(extra, tempref, greenref, tempitc, greenitc, studgood, redloc, greenloc, blueloc, bfw, bfh, avg_rm, avg_gm, avg_bm, cmp, raw, wbpar, hrp); } } @@ -5373,15 +5580,18 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int { // BENCHFUN //used by auto WB local to calculate red, green, blue in local region + int precision = 5; + if (settings->itcwb_precis == 5) { precision = 5; } else if (settings->itcwb_precis < 5) { - precision = 3; + precision = 3; } else if (settings->itcwb_precis > 5) { precision = 9; } + const int bfw = W / precision + ((W % precision) > 0 ? 1 : 0);// 5 arbitrary value can be change to 3 or 9 ; const int bfh = H / precision + ((H % precision) > 0 ? 1 : 0); @@ -5404,6 +5614,7 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int #ifdef _OPENMP #pragma omp parallel for reduction(+:avgL, nn) #endif + for (int i = 0; i < H; i ++) { for (int j = 0; j < W; j++) { const float LL = 0.299f * red[i][j] + 0.587f * green[i][j] + 0.114f * blue[i][j]; @@ -5411,6 +5622,7 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int nn++; } } + avgL /= nn; double vari = 0.f; @@ -5419,6 +5631,7 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int #ifdef _OPENMP #pragma omp parallel for reduction(+:vari, mm) #endif + for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) { const float LL = 0.299f * red[i][j] + 0.587f * green[i][j] + 0.114f * blue[i][j]; @@ -5432,8 +5645,10 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int #ifdef _OPENMP #pragma omp parallel for #endif + for (int i = 0; i < bfh; ++i) { const int ii = i * precision; + if (ii < H) { for (int j = 0, jj = 0; j < bfw; ++j, jj += precision) { redloc[i][j] = red[ii][jj] * multip; @@ -5444,7 +5659,7 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int } } -void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref, double & tempitc, double & greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double & rm, double & gm, double & bm, const WBParams & wbpar, const ColorManagementParams & cmp, const RAWParams & raw) +void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref, double & tempitc, double & greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double & rm, double & gm, double & bm, const WBParams & wbpar, const ColorManagementParams & cmp, const RAWParams & raw, const ToneCurveParams &hrp) { // BENCHFUN constexpr double clipHigh = 64000.0; @@ -5459,6 +5674,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref double avg_b = 0; int rn = 0, gn = 0, bn = 0; double avg_rm, avg_gm, avg_bm; + if (wbpar.method == "autold") { if (fuji) { for (int i = 32; i < H - 32; i++) { @@ -5468,7 +5684,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref for (int j = start; j < end; j++) { if (ri->getSensorType() != ST_BAYER) { - double dr = CLIP(initialGain * (rawData[i][3 * j] )); + double dr = CLIP(initialGain * (rawData[i][3 * j])); double dg = CLIP(initialGain * (rawData[i][3 * j + 1])); double db = CLIP(initialGain * (rawData[i][3 * j + 2])); @@ -5507,18 +5723,18 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref if (ri->getSensorType() == ST_FUJI_XTRANS) { const double compval = clipHigh / initialGain; #ifdef _OPENMP - #pragma omp parallel + #pragma omp parallel #endif { double avg_c[3] = {0.0}; int cn[3] = {0}; #ifdef _OPENMP - #pragma omp for schedule(dynamic,16) nowait + #pragma omp for schedule(dynamic,16) nowait #endif for (int i = 32; i < H - 32; i++) { for (int j = 32; j < W - 32; j++) { - // each loop read 1 rgb triplet value + // each loop read 1 rgb triplet value double d = rawData[i][j]; if (d > compval) { @@ -5532,7 +5748,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref } #ifdef _OPENMP - #pragma omp critical + #pragma omp critical #endif { avg_r += avg_c[0]; @@ -5549,9 +5765,9 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref } else { for (int i = 32; i < H - 32; i++) for (int j = 32; j < W - 32; j++) { - // each loop read 1 rgb triplet value + // each loop read 1 rgb triplet value - double dr = CLIP(initialGain * (rawData[i][3 * j] )); + double dr = CLIP(initialGain * (rawData[i][3 * j])); double dg = CLIP(initialGain * (rawData[i][3 * j + 1])); double db = CLIP(initialGain * (rawData[i][3 * j + 2])); @@ -5569,7 +5785,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref bn = rn; } } else { - //determine GRBG coset; (ey,ex) is the offset of the R subarray + //determine GRBG coset; (ey,ex) is the offset of the R subarray int ey, ex; if (ri->ISGREEN(0, 0)) { //first pixel is G @@ -5592,12 +5808,12 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref const double compval = clipHigh / initialGain; #ifdef _OPENMP - #pragma omp parallel for reduction(+:avg_r,avg_g,avg_b,rn,gn,bn) schedule(dynamic,8) + #pragma omp parallel for reduction(+:avg_r,avg_g,avg_b,rn,gn,bn) schedule(dynamic,8) #endif for (int i = 32; i < H - 32; i += 2) for (int j = 32; j < W - 32; j += 2) { - //average each Bayer quartet component individually if non-clipped + //average each Bayer quartet component individually if non-clipped double d[2][2]; d[0][0] = rawData[i][j]; d[0][1] = rawData[i][j + 1]; @@ -5636,17 +5852,18 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref if (wbpar.method == "autitcgreen") { bool twotimes = false; int precision = 5; + if (settings->itcwb_precis == 5) { precision = 5; } else if (settings->itcwb_precis < 5) { - precision = 3; + precision = 3; } else if (settings->itcwb_precis > 5) { precision = 9; } - + const int bfw = W / precision + ((W % precision) > 0 ? 1 : 0);// 5 arbitrary value can be change to 3 or 9 ; const int bfh = H / precision + ((H % precision) > 0 ? 1 : 0); - WBauto(tempref, greenref, redloc, greenloc, blueloc, bfw, bfh, avg_rm, avg_gm, avg_bm, tempitc, greenitc, studgood, twotimes, wbpar, begx, begy, yEn, xEn, cx, cy, cmp, raw); + WBauto(tempref, greenref, redloc, greenloc, blueloc, bfw, bfh, avg_rm, avg_gm, avg_bm, tempitc, greenitc, studgood, twotimes, wbpar, begx, begy, yEn, xEn, cx, cy, cmp, raw, hrp); } redloc(0, 0); @@ -5654,7 +5871,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref blueloc(0, 0); if (settings->verbose) { - printf ("AVG: %g %g %g\n", avg_r / std::max(1, rn), avg_g / std::max(1, gn), avg_b / std::max(1, bn)); + printf("AVG: %g %g %g\n", avg_r / std::max(1, rn), avg_g / std::max(1, gn), avg_b / std::max(1, bn)); } if (wbpar.method == "autitcgreen") { @@ -5673,7 +5890,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref } -void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) +void RawImageSource::getAutoWBMultipliers(double &rm, double &gm, double &bm) { // BENCHFUN constexpr double clipHigh = 64000.0; @@ -5710,7 +5927,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) for (int j = start; j < end; j++) { if (ri->getSensorType() != ST_BAYER) { - double dr = CLIP(initialGain * (rawData[i][3 * j] )); + double dr = CLIP(initialGain * (rawData[i][3 * j])); double dg = CLIP(initialGain * (rawData[i][3 * j + 1])); double db = CLIP(initialGain * (rawData[i][3 * j + 2])); @@ -5793,7 +6010,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) for (int j = 32; j < W - 32; j++) { // each loop read 1 rgb triplet value - double dr = CLIP(initialGain * (rawData[i][3 * j] )); + double dr = CLIP(initialGain * (rawData[i][3 * j])); double dg = CLIP(initialGain * (rawData[i][3 * j + 1])); double db = CLIP(initialGain * (rawData[i][3 * j + 2])); @@ -5875,7 +6092,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) } if (settings->verbose) { - printf ("AVG: %g %g %g\n", avg_r / std::max(1, rn), avg_g / std::max(1, gn), avg_b / std::max(1, bn)); + printf("AVG: %g %g %g\n", avg_r / std::max(1, rn), avg_g / std::max(1, gn), avg_b / std::max(1, bn)); } // return ColorTemp (pow(avg_r/rn, 1.0/6.0)*img_r, pow(avg_g/gn, 1.0/6.0)*img_g, pow(avg_b/bn, 1.0/6.0)*img_b); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index d7549fe71..fabea5ffc 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -112,7 +112,7 @@ protected: void hlRecovery(const std::string &method, float* red, float* green, float* blue, int width, float* hlmax); void transformRect(const PreviewProps &pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw); void transformPosition(int x, int y, int tran, int& tx, int& ty); - void ItcWB(bool extra, double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::WBParams & wbpar); + void ItcWB(bool extra, double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::WBParams & wbpar, const procparams::ToneCurveParams &hrp); unsigned FC(int row, int col) const; inline void getRowStartEnd (int x, int &start, int &end); @@ -141,12 +141,12 @@ public: void processFlatField(const procparams::RAWParams &raw, const RawImage *riFlatFile, array2D &rawData, const float black[4]); void copyOriginalPixels(const procparams::RAWParams &raw, RawImage *ri, const RawImage *riDark, RawImage *riFlatFile, array2D &rawData ); void scaleColors (int winx, int winy, int winw, int winh, const procparams::RAWParams &raw, array2D &rawData); // raw for cblack - void WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw) override; - void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw) override; + void WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override; + void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override; void getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w) override; void getWBMults (const ColorTemp &ctemp, const procparams::RAWParams &raw, std::array& scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const override; - void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw) override; + void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw, int opposed) override; eSensorType getSensorType () const override; bool isMono () const override; ColorTemp getWB () const override @@ -199,7 +199,8 @@ public: void MSR(float** luminance, float **originalLuminance, float **exLuminance, const LUTf& mapcurve, bool mapcontlutili, int width, int height, const procparams::RetinexParams &deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax); void HLRecovery_inpaint (float** red, float** green, float** blue, int blur); - static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval); + void highlight_recovery_opposed(float scale_mul[3], const ColorTemp &wb, float gainth); + static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval); static void HLRecovery_CIELab (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval, double cam[3][3], double icam[3][3]); static void HLRecovery_blend (float* rin, float* gin, float* bin, int width, float maxval, float* hlmax); static void init (); @@ -308,6 +309,9 @@ protected: void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override; void captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) override; void applyDngGainMap(const float black[4], const std::vector &gainMaps); +public: + void wbMul2Camera(double &rm, double &gm, double &bm) override; + void wbCamera2Mul(double &rm, double &gm, double &bm) override; }; } diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 3916adfbe..eb4a3f888 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -94,7 +94,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = { HDR, // EvCACorr, ALLNORAW, // EvHREnabled, 0, // EvHRAmount : obsolete, - ALLNORAW, // EvHRMethod, + ALLNORAW|M_RAW, // EvHRMethod, DEMOSAIC, // EvWProfile, OUTPUTPROFILE, // EvOProfile, ALLNORAW, // EvIProfile, diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 86f1c1372..84c33a734 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -349,7 +349,7 @@ Image8 *load_inspector_mode(const Glib::ustring &fname, RawMetaDataLocation &rml PreviewProps pp(0, 0, w, h, 1); Imagefloat tmp(w, h); - src.getImage(src.getWB(), TR_NONE, &tmp, pp, neutral.toneCurve, neutral.raw); + src.getImage(src.getWB(), TR_NONE, &tmp, pp, neutral.toneCurve, neutral.raw, 0); src.convertColorSpace(&tmp, neutral.icm, src.getWB()); Image8 *img = new Image8(w, h); diff --git a/rtengine/settings.h b/rtengine/settings.h index 1c8c73630..6e787a112 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.h @@ -44,6 +44,7 @@ public: bool monitorBPC; ///< Black Point Compensation for the Labimage->Monitor transform (directly, i.e. not soft-proofing and no WCS in between) bool autoMonitorProfile; ///< Try to auto-determine the correct monitor color profile bool autocielab; + bool observer10; bool rgbcurveslumamode_gamut;// controls gamut enforcement for RGB curves in lumamode bool verbose; Glib::ustring darkFramesPath; ///< The default directory for dark frames @@ -94,7 +95,7 @@ public: // bool showtooltip; int itcwb_thres; - bool itcwb_sort; + bool itcwb_sorted; int itcwb_greenrange; int itcwb_greendeltatemp; bool itcwb_forceextra; @@ -102,6 +103,7 @@ public: int itcwb_delta; bool itcwb_stdobserver10; int itcwb_precis; + bool itcwb_nopurple; //wavelet levels double edghi; double edglo; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index c542cf726..5de3b08b0 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -261,7 +261,7 @@ private: pl->setProgress(0.40); } - imgsrc->HLRecovery_Global(params.toneCurve); + // imgsrc->HLRecovery_Global(params.toneCurve); if (pl) { @@ -372,7 +372,7 @@ private: int beg_tileW = wcr * tileWskip + tileWskip / 2.f - crW / 2.f; int beg_tileH = hcr * tileHskip + tileHskip / 2.f - crH / 2.f; PreviewProps ppP(beg_tileW, beg_tileH, crW, crH, skipP); - imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw); + imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw, 0); //baseImg->getStdImage(currWB, tr, origCropPart, ppP, true, params.toneCurve); // we only need image reduced to 1/4 here @@ -596,7 +596,7 @@ private: for (int wcr = 0; wcr <= 2; wcr++) { for (int hcr = 0; hcr <= 2; hcr++) { PreviewProps ppP(coordW[wcr], coordH[hcr], crW, crH, 1); - imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw); + imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw, 0); //baseImg->getStdImage(currWB, tr, origCropPart, ppP, true, params.toneCurve); @@ -756,7 +756,7 @@ private: } baseImg = new Imagefloat(fw, fh); - imgsrc->getImage(currWB, tr, baseImg, pp, params.toneCurve, params.raw); + imgsrc->getImage(currWB, tr, baseImg, pp, params.toneCurve, params.raw, 1); if (pl) { pl->setProgress(0.50); diff --git a/rtengine/spot.cc b/rtengine/spot.cc index 5ed090712..09186a399 100644 --- a/rtengine/spot.cc +++ b/rtengine/spot.cc @@ -459,7 +459,7 @@ void ImProcFunctions::removeSpots (Imagefloat* img, ImageSource* imgsrc, const s } } - imgsrc->getImage(currWB, tr, srcSpotBox->getImage(), spp, params->toneCurve, params->raw); + imgsrc->getImage(currWB, tr, srcSpotBox->getImage(), spp, params->toneCurve, params->raw, 0); if (cmp) { imgsrc->convertColorSpace(srcImage, *cmp, currWB); } @@ -479,7 +479,7 @@ void ImProcFunctions::removeSpots (Imagefloat* img, ImageSource* imgsrc, const s dstImage->b(y, x) = 60000.f; } } - imgsrc->getImage(currWB, tr, dstSpotBox->getImage(), spp, params->toneCurve, params->raw); + imgsrc->getImage(currWB, tr, dstSpotBox->getImage(), spp, params->toneCurve, params->raw, 0); if (cmp) { imgsrc->convertColorSpace(dstImage, *cmp, currWB); } diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index 8cb8fa792..a3f2502f0 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -193,7 +193,7 @@ int StdImageSource::load (const Glib::ustring &fname) return 0; } -void StdImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw) +void StdImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw, int opposed) { // the code will use OpenMP as of now. @@ -311,11 +311,11 @@ void StdImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) } } -void StdImageSource::WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const ColorManagementParams &cmp, const RAWParams &raw) +void StdImageSource::WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const ColorManagementParams &cmp, const RAWParams &raw, const ToneCurveParams &hrp) { } -void StdImageSource::getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const WBParams & wbpar, const ColorManagementParams &cmp, const RAWParams &raw) +void StdImageSource::getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const WBParams & wbpar, const ColorManagementParams &cmp, const RAWParams &raw, const ToneCurveParams &hrp) { if (redAWBMul != -1.) { rm = redAWBMul; @@ -324,7 +324,7 @@ void StdImageSource::getAutoWBMultipliersitc(double &tempref, double &greenref, return; } - img->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc,studgood, begx, begy, yEn, xEn, cx, cy, bf_h, bf_w, rm, gm, bm, params->wb, params->icm, params->raw); + img->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc,studgood, begx, begy, yEn, xEn, cx, cy, bf_h, bf_w, rm, gm, bm, params->wb, params->icm, params->raw, params->toneCurve); redAWBMul = rm; greenAWBMul = gm; @@ -367,6 +367,20 @@ void StdImageSource::flush() { img->allocate(0, 0); }; +void StdImageSource::wbMul2Camera(double &rm, double &gm, double &bm) +{ + rm = 1.0 / rm; + gm = 1.0 / gm; + bm = 1.0 / bm; +} + + +void StdImageSource::wbCamera2Mul(double &rm, double &gm, double &bm) +{ + rm = 1.0 / rm; + gm = 1.0 / gm; + bm = 1.0 / bm; +} } diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index f83c58a04..90c4be654 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -58,7 +58,7 @@ public: int load (const Glib::ustring &fname) override; void getWBMults (const ColorTemp &ctemp, const procparams::RAWParams &raw, std::array& scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const override {}; - void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw) override; + void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw, int opposed) override; void getrgbloc (int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w) override {}; ColorTemp getWB () const override { @@ -66,8 +66,8 @@ public: } void getAutoWBMultipliers (double &rm, double &gm, double &bm) override; ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) override; - void WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw) override; - void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw) override; + void WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override; + void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override; eSensorType getSensorType() const override {return ST_NONE;} bool isMono() const override {return false;} @@ -123,6 +123,8 @@ public: void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override { R = G = B = 0;} + void wbMul2Camera(double &rm, double &gm, double &bm) override; + void wbCamera2Mul(double &rm, double &gm, double &bm) override; void flush () override; void captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) override {}; diff --git a/rtgui/options.cc b/rtgui/options.cc index 3ce97567c..66b9e92a1 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -594,6 +594,7 @@ void Options::setDefaults() rtSettings.monitorIntent = rtengine::RI_RELATIVE; rtSettings.monitorBPC = true; rtSettings.autocielab = false; + rtSettings.observer10 = false; rtSettings.autoMonitorProfile = false; rtSettings.adobe = "RTv2_Medium"; // put the name of yours profiles (here windows) rtSettings.prophoto = "RTv2_Large"; // these names appear in the menu "output profile" @@ -623,14 +624,15 @@ void Options::setDefaults() rtSettings.fftwsigma = true; //choice between sigma^2 or empirical formula rtSettings.itcwb_thres = 34;//between 10 to 55 - rtSettings.itcwb_sort = false; + rtSettings.itcwb_sorted = true; rtSettings.itcwb_greenrange = 0;//between 0 to 2 rtSettings.itcwb_greendeltatemp = 2;//between 0 and 4 rtSettings.itcwb_forceextra = true; rtSettings.itcwb_sizereference = 3;//between 1 and 5 rtSettings.itcwb_delta = 1;//between 0 and 5 rtSettings.itcwb_stdobserver10 = true; - rtSettings.itcwb_precis = 5;//3 or 5 or 9 + rtSettings.itcwb_precis = 3;//3 or 5 or 9 + rtSettings.itcwb_nopurple = true; // end locallab //wavelet @@ -1760,6 +1762,10 @@ void Options::readFromFile(Glib::ustring fname) rtSettings.autocielab = keyFile.get_boolean("Color Management", "Autocielab"); } + if (keyFile.has_key("Color Management", "Observer10")) { + rtSettings.observer10 = keyFile.get_boolean("Color Management", "Observer10"); + } + if (keyFile.has_key("Color Management", "CRI")) { rtSettings.CRI_color = keyFile.get_integer("Color Management", "CRI"); } @@ -1795,14 +1801,18 @@ void Options::readFromFile(Glib::ustring fname) rtSettings.itcwb_thres = keyFile.get_integer("Color Management", "Itcwb_thres"); } - if (keyFile.has_key("Color Management", "Itcwb_sort")) { - rtSettings.itcwb_sort = keyFile.get_boolean("Color Management", "Itcwb_sort"); + if (keyFile.has_key("Color Management", "Itcwb_sorted")) { + rtSettings.itcwb_sorted = keyFile.get_boolean("Color Management", "Itcwb_sorted"); } if (keyFile.has_key("Color Management", "Itcwb_forceextra")) { rtSettings.itcwb_forceextra = keyFile.get_boolean("Color Management", "Itcwb_forceextra"); } + if (keyFile.has_key("Color Management", "Itcwb_nopurple")) { + rtSettings.itcwb_nopurple = keyFile.get_boolean("Color Management", "Itcwb_nopurple"); + } + if (keyFile.has_key("Color Management", "Itcwb_stdobserver10")) { rtSettings.itcwb_stdobserver10 = keyFile.get_boolean("Color Management", "Itcwb_stdobserver10"); } @@ -2563,6 +2573,7 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_string("Color Management", "MonitorProfile", rtSettings.monitorProfile); keyFile.set_boolean("Color Management", "AutoMonitorProfile", rtSettings.autoMonitorProfile); keyFile.set_boolean("Color Management", "Autocielab", rtSettings.autocielab); + keyFile.set_boolean("Color Management", "Observer10", rtSettings.observer10); keyFile.set_boolean("Color Management", "RGBcurvesLumamode_Gamut", rtSettings.rgbcurveslumamode_gamut); keyFile.set_integer("Color Management", "Intent", rtSettings.monitorIntent); keyFile.set_boolean("Color Management", "MonitorBPC", rtSettings.monitorBPC); @@ -2596,10 +2607,11 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_double("Color Management", "CBDLlevel0", rtSettings.level0_cbdl); keyFile.set_double("Color Management", "CBDLlevel123", rtSettings.level123_cbdl); keyFile.set_integer("Color Management", "Itcwb_thres", rtSettings.itcwb_thres); - keyFile.set_boolean("Color Management", "Itcwb_sort", rtSettings.itcwb_sort); + keyFile.set_boolean("Color Management", "Itcwb_sorted", rtSettings.itcwb_sorted); keyFile.set_integer("Color Management", "Itcwb_greenrange", rtSettings.itcwb_greenrange); keyFile.set_integer("Color Management", "Itcwb_greendeltatemp", rtSettings.itcwb_greendeltatemp); keyFile.set_boolean("Color Management", "Itcwb_forceextra", rtSettings.itcwb_forceextra); + keyFile.set_boolean("Color Management", "Itcwb_nopurple", rtSettings.itcwb_nopurple); keyFile.set_integer("Color Management", "Itcwb_sizereference", rtSettings.itcwb_sizereference); keyFile.set_integer("Color Management", "Itcwb_delta", rtSettings.itcwb_delta); keyFile.set_boolean("Color Management", "Itcwb_stdobserver10", rtSettings.itcwb_stdobserver10); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 7d641d753..abd4e8608 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -48,6 +48,7 @@ void ParamsEdited::set(bool v) toneCurve.shcompr = v; toneCurve.hlcompr = v; toneCurve.hlbl = v; + toneCurve.hlth = v; toneCurve.hlcomprthresh = v; toneCurve.autoexp = v; toneCurve.clip = v; @@ -749,6 +750,7 @@ void ParamsEdited::initFrom(const std::vector& toneCurve.shcompr = toneCurve.shcompr && p.toneCurve.shcompr == other.toneCurve.shcompr; toneCurve.hlcompr = toneCurve.hlcompr && p.toneCurve.hlcompr == other.toneCurve.hlcompr; toneCurve.hlbl = toneCurve.hlbl && p.toneCurve.hlbl == other.toneCurve.hlbl; + toneCurve.hlth = toneCurve.hlth && p.toneCurve.hlth == other.toneCurve.hlth; toneCurve.hlcomprthresh = toneCurve.hlcomprthresh && p.toneCurve.hlcomprthresh == other.toneCurve.hlcomprthresh; toneCurve.autoexp = toneCurve.autoexp && p.toneCurve.autoexp == other.toneCurve.autoexp; toneCurve.clip = toneCurve.clip && p.toneCurve.clip == other.toneCurve.clip; @@ -2192,6 +2194,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.toneCurve.hlbl = mods.toneCurve.hlbl; } + if (toneCurve.hlth) { + toEdit.toneCurve.hlth = mods.toneCurve.hlth; + } + if (toneCurve.histmatching) { toEdit.toneCurve.histmatching = mods.toneCurve.histmatching; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 616e6d261..66db8346f 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -52,6 +52,7 @@ struct ToneCurveParamsEdited { bool shcompr; bool hlcompr; bool hlbl; + bool hlth; bool hlcomprthresh; bool autoexp; bool clip; diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index c39bd3bda..bf81c6f22 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -42,6 +42,7 @@ ToneCurve::ToneCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOSURE_LABEL EvHistMatchingBatch = m->newEvent(M_VOID, "HISTORY_MSG_HISTMATCHING"); EvClampOOG = m->newEvent(DARKFRAME, "HISTORY_MSG_CLAMPOOG"); EvHLbl = m->newEvent(DEMOSAIC, "HISTORY_MSG_HLBL"); + EvHLth = m->newEvent(DEMOSAIC, "HISTORY_MSG_HLTH"); CurveListener::setMulti(true); @@ -97,13 +98,14 @@ ToneCurve::ToneCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOSURE_LABEL method = Gtk::manage (new MyComboBoxText ()); method->append (M("TP_HLREC_LUMINANCE")); method->append (M("TP_HLREC_CIELAB")); - method->append (M("TP_HLREC_COLOR")); method->append (M("TP_HLREC_BLEND")); + method->append (M("TP_HLREC_COLOR")); + method->append (M("TP_HLREC_COLOROPP")); Gtk::Box *hrVBox; hrVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); hrVBox->set_spacing(2); - method->set_active(0); + method->set_active(4); Gtk::Frame* const hrFrame = Gtk::manage(new Gtk::Frame()); hrFrame->set_label_align(0.025, 0.5); hrFrame->set_label_widget(*hrenabled); @@ -113,9 +115,11 @@ ToneCurve::ToneCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOSURE_LABEL hlrbox->pack_start (*lab, Gtk::PACK_SHRINK); hlrbox->pack_start (*method); hlbl = Gtk::manage(new Adjuster(M("TP_HLREC_HLBLUR"), 0, 4, 1, 0)); + hlth = Gtk::manage(new Adjuster(M("TP_HLREC_HLTH"), 0.25, 1.75, 0.01, 1.)); hrVBox->pack_start(*hlrbox, Gtk::PACK_SHRINK); hrVBox->pack_start(*hlbl); + hrVBox->pack_start(*hlth); hrFrame->add(*hrVBox); pack_start(*hrFrame); @@ -223,6 +227,7 @@ ToneCurve::ToneCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOSURE_LABEL black->setAdjusterListener(this); hlcompr->setAdjusterListener(this); hlbl->setAdjusterListener(this); + hlth->setAdjusterListener(this); hlcomprthresh->setAdjusterListener(this); shcompr->setAdjusterListener(this); contrast->setAdjusterListener(this); @@ -254,6 +259,7 @@ void ToneCurve::read(const ProcParams* pp, const ParamsEdited* pedited) black->setValue(pp->toneCurve.black); hlcompr->setValue(pp->toneCurve.hlcompr); hlbl->setValue(pp->toneCurve.hlbl); + hlth->setValue(pp->toneCurve.hlth); hlcomprthresh->setValue(pp->toneCurve.hlcomprthresh); shcompr->setValue(pp->toneCurve.shcompr); @@ -283,6 +289,7 @@ void ToneCurve::read(const ProcParams* pp, const ParamsEdited* pedited) black->setEditedState(pedited->toneCurve.black ? Edited : UnEdited); hlcompr->setEditedState(pedited->toneCurve.hlcompr ? Edited : UnEdited); hlbl->setEditedState(pedited->toneCurve.hlbl ? Edited : UnEdited); + hlth->setEditedState(pedited->toneCurve.hlth ? Edited : UnEdited); hlcomprthresh->setEditedState(pedited->toneCurve.hlcomprthresh ? Edited : UnEdited); shcompr->setEditedState(pedited->toneCurve.shcompr ? Edited : UnEdited); brightness->setEditedState(pedited->toneCurve.brightness ? Edited : UnEdited); @@ -310,16 +317,18 @@ void ToneCurve::read(const ProcParams* pp, const ParamsEdited* pedited) hrenabled->set_active(pp->toneCurve.hrenabled); enaconn.block(false); - if (pedited && !pedited->toneCurve.method) { - method->set_active(4); - } else if (pp->toneCurve.method == "Luminance") { + if (pedited && !pedited->toneCurve.method) { + method->set_active(5); + } else if (pp->toneCurve.method == "Luminance") { method->set_active(0); } else if (pp->toneCurve.method == "CIELab blending") { method->set_active(1); - } else if (pp->toneCurve.method == "Color") { - method->set_active(2); } else if (pp->toneCurve.method == "Blend") { + method->set_active(2); + } else if (pp->toneCurve.method == "Color") { method->set_active(3); + } else if (pp->toneCurve.method == "Coloropp") { + method->set_active(4); } hrenabledChanged(); @@ -354,6 +363,7 @@ void ToneCurve::write(ProcParams* pp, ParamsEdited* pedited) pp->toneCurve.black = black->getValue(); pp->toneCurve.hlcompr = hlcompr->getValue(); pp->toneCurve.hlbl = hlbl->getValue(); + pp->toneCurve.hlth = hlth->getValue(); pp->toneCurve.hlcomprthresh = hlcomprthresh->getValue(); pp->toneCurve.shcompr = shcompr->getValue(); pp->toneCurve.brightness = brightness->getValue(); @@ -403,6 +413,7 @@ void ToneCurve::write(ProcParams* pp, ParamsEdited* pedited) pedited->toneCurve.black = black->getEditedState(); pedited->toneCurve.hlcompr = hlcompr->getEditedState(); pedited->toneCurve.hlbl = hlbl->getEditedState(); + pedited->toneCurve.hlth = hlth->getEditedState(); pedited->toneCurve.hlcomprthresh = hlcomprthresh->getEditedState(); pedited->toneCurve.shcompr = shcompr->getEditedState(); pedited->toneCurve.brightness = brightness->getEditedState(); @@ -414,7 +425,7 @@ void ToneCurve::write(ProcParams* pp, ParamsEdited* pedited) pedited->toneCurve.curve2 = !shape2->isUnChanged(); pedited->toneCurve.curveMode = toneCurveMode->get_active_row_number() != 6; pedited->toneCurve.curveMode2 = toneCurveMode2->get_active_row_number() != 6; - pedited->toneCurve.method = method->get_active_row_number() != 4; + pedited->toneCurve.method = method->get_active_row_number() != 5; pedited->toneCurve.hrenabled = !hrenabled->get_inconsistent(); pedited->toneCurve.histmatching = !histmatching->get_inconsistent(); pedited->toneCurve.fromHistMatching = true; @@ -428,9 +439,11 @@ void ToneCurve::write(ProcParams* pp, ParamsEdited* pedited) } else if (method->get_active_row_number() == 1) { pp->toneCurve.method = "CIELab blending"; } else if (method->get_active_row_number() == 2) { - pp->toneCurve.method = "Color"; - } else if (method->get_active_row_number() == 3) { pp->toneCurve.method = "Blend"; + } else if (method->get_active_row_number() == 3) { + pp->toneCurve.method = "Color"; + } else if (method->get_active_row_number() == 4) { + pp->toneCurve.method = "Coloropp"; } } @@ -454,15 +467,21 @@ void ToneCurve::hrenabledChanged() if (hrenabled->get_active()) { hlrbox->show(); hlrbox->set_sensitive(true); - if (method->get_active_row_number() == 2) { + if (method->get_active_row_number() == 3) { hlbl->show(); + hlth->hide(); + } else if (method->get_active_row_number() == 4){ + hlbl->hide(); + hlth->show(); } else { hlbl->hide(); - } + hlth->hide(); + } } else { hlrbox->show(); hlrbox->set_sensitive(false); hlbl->hide(); + hlth->hide(); } } @@ -487,11 +506,16 @@ void ToneCurve::hrenabledChanged() void ToneCurve::methodChanged() { - if (method->get_active_row_number() == 2) { + if (method->get_active_row_number() == 3) { hlbl->show(); - } else { + hlth->hide(); + } else if (method->get_active_row_number() == 4){ hlbl->hide(); - } + hlth->show(); + } else { + hlbl->hide(); + hlth->hide(); + } if (listener) { setHistmatching(false); if (hrenabled->get_active()) { @@ -513,6 +537,7 @@ void ToneCurve::setRaw(bool raw) disableListener(); method->set_sensitive(raw); hlbl->set_sensitive(raw); + hlth->set_sensitive(raw); hrenabled->set_sensitive(raw); histmatching->set_sensitive(raw); enableListener(); @@ -526,6 +551,7 @@ void ToneCurve::setDefaults(const ProcParams* defParams, const ParamsEdited* ped black->setDefault(defParams->toneCurve.black); hlcompr->setDefault(defParams->toneCurve.hlcompr); hlbl->setDefault(defParams->toneCurve.hlbl); + hlth->setDefault(defParams->toneCurve.hlth); hlcomprthresh->setDefault(defParams->toneCurve.hlcomprthresh); shcompr->setDefault(defParams->toneCurve.shcompr); contrast->setDefault(defParams->toneCurve.contrast); @@ -536,6 +562,7 @@ void ToneCurve::setDefaults(const ProcParams* defParams, const ParamsEdited* ped black->setDefaultEditedState(pedited->toneCurve.black ? Edited : UnEdited); hlcompr->setDefaultEditedState(pedited->toneCurve.hlcompr ? Edited : UnEdited); hlbl->setDefaultEditedState(pedited->toneCurve.hlbl ? Edited : UnEdited); + hlth->setDefaultEditedState(pedited->toneCurve.hlth ? Edited : UnEdited); hlcomprthresh->setDefaultEditedState(pedited->toneCurve.hlcomprthresh ? Edited : UnEdited); shcompr->setDefaultEditedState(pedited->toneCurve.shcompr ? Edited : UnEdited); brightness->setDefaultEditedState(pedited->toneCurve.brightness ? Edited : UnEdited); @@ -546,6 +573,7 @@ void ToneCurve::setDefaults(const ProcParams* defParams, const ParamsEdited* ped black->setDefaultEditedState(Irrelevant); hlcompr->setDefaultEditedState(Irrelevant); hlbl->setDefaultEditedState(Irrelevant); + hlth->setDefaultEditedState(Irrelevant); hlcomprthresh->setDefaultEditedState(Irrelevant); shcompr->setDefaultEditedState(Irrelevant); brightness->setDefaultEditedState(Irrelevant); @@ -660,6 +688,8 @@ void ToneCurve::adjusterChanged(Adjuster* a, double newval) listener->panelChanged(EvSaturation, costr); } else if (a == hlbl) { listener->panelChanged(EvHLbl, costr); + } else if (a == hlth) { + listener->panelChanged(EvHLth, costr); } else if (a == hlcompr) { listener->panelChanged(EvHLCompr, costr); @@ -695,6 +725,7 @@ void ToneCurve::neutral_pressed() expcomp->setValue(0); hlcompr->setValue(0); hlbl->setValue(0); + hlth->setValue(1.0); hlcomprthresh->setValue(0); brightness->setValue(0); black->setValue(0); @@ -707,6 +738,7 @@ void ToneCurve::neutral_pressed() hlrbox->show(); hlrbox->set_sensitive(false); hlbl->hide(); + hlth->hide(); } if (!black->getAddMode() && !batchMode) { @@ -841,6 +873,7 @@ void ToneCurve::waitForAutoExp() hrenabled->set_sensitive(false); method->set_sensitive(false); hlbl->set_sensitive(false); + hlth->set_sensitive(false); histmatching->set_sensitive(false); } @@ -853,6 +886,7 @@ void ToneCurve::enableAll() black->setEnabled(true); hlcompr->setEnabled(true); hlbl->setEnabled(true); + hlth->setEnabled(true); hlcomprthresh->setEnabled(true); shcompr->setEnabled(true); contrast->setEnabled(true); @@ -864,6 +898,7 @@ void ToneCurve::enableAll() hrenabled->set_sensitive(true); method->set_sensitive(true); hlbl->set_sensitive(true); + hlth->set_sensitive(true); histmatching->set_sensitive(true); } @@ -883,6 +918,7 @@ void ToneCurve::setBatchMode(bool batchMode) black->showEditedCB(); hlcompr->showEditedCB(); hlbl->showEditedCB(); + hlth->showEditedCB(); hlcomprthresh->showEditedCB(); shcompr->showEditedCB(); brightness->showEditedCB(); @@ -996,16 +1032,22 @@ void ToneCurve::autoExpChanged(double expcomp, int bright, int contr, int black, if (nextHLRecons) { hlrbox->show(); hlrbox->set_sensitive(true); - if (method->get_active_row_number() == 2) { + if (method->get_active_row_number() == 3) { hlbl->show(); - } else { + hlth->hide(); + } else if (method->get_active_row_number() == 4){ hlbl->hide(); - } + hlth->show(); + } else { + hlbl->hide(); + hlth->hide(); + } } else if (!batchMode) { hlrbox->show(); hlrbox->set_sensitive(false); hlbl->hide(); - } + hlth->hide(); + } if (!this->black->getAddMode() && !batchMode) { shcompr->set_sensitive(static_cast(this->black->getValue())); //at black=0 shcompr value has no effect diff --git a/rtgui/tonecurve.h b/rtgui/tonecurve.h index 7ba2178ac..7f0f1ef69 100644 --- a/rtgui/tonecurve.h +++ b/rtgui/tonecurve.h @@ -48,6 +48,7 @@ protected: sigc::connection enaconn; bool lasthrEnabled; Adjuster* hlbl; + Adjuster* hlth; Gtk::Box* abox; Gtk::Box* hlrbox; @@ -82,6 +83,7 @@ protected: rtengine::ProcEvent EvHistMatchingBatch; rtengine::ProcEvent EvClampOOG; rtengine::ProcEvent EvHLbl; + rtengine::ProcEvent EvHLth; // used temporarily in eventing double nextExpcomp; From 8047aded3ba4756233be0d4e833e535bdd6293f0 Mon Sep 17 00:00:00 2001 From: "U-PCSPECIALIST01\\jdesm" Date: Thu, 9 Feb 2023 16:15:42 +0100 Subject: [PATCH 24/24] remove BENCHFUN for inpaint-opposed color-propagation Itcwb --- rtengine/hilite_recon.cc | 4 ++-- rtengine/rawimagesource.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/hilite_recon.cc b/rtengine/hilite_recon.cc index 07d1a7b7b..f573ff015 100644 --- a/rtengine/hilite_recon.cc +++ b/rtengine/hilite_recon.cc @@ -302,7 +302,7 @@ using namespace procparams; void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue, int blur) { - BENCHFUN + //BENCHFUN double progress = 0.0; if (plistener) { @@ -1347,7 +1347,7 @@ void dilating(const int *img, int *o, int w1, int height) void RawImageSource::highlight_recovery_opposed(float scale_mul[3], const ColorTemp &wb, float gainth) { - BENCHFUN + //BENCHFUN if (settings->verbose) { std::cout << "Applying Highlight Recovery: Inpaint opposed" << std::endl; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 7ff9c4d0f..75757d325 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -4716,7 +4716,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double itcwb_precis : 3 by default - can be set to 3 or 9 - 3 best sampling but more time...9 "old" settings - but low differences in times with 3 instead of 9 about twice time 160ms instead of 80ms for a big raw file itcwb_nopurple : true default - allow to bypass highlight recovery and inpait opposed when need flowers and not purple due to highlights... */ - BENCHFUN + // BENCHFUN TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix("sRGB"); const float wp[3][3] = {