From 1450b9bb7aebcff58389415f21db1b0af3f78989 Mon Sep 17 00:00:00 2001 From: Bezierr Date: Wed, 20 Jul 2022 12:14:05 +0200 Subject: [PATCH 1/9] Camera and Lens profiles directories In "Preferences", added the possibility to define a "Camera profiles directory" and a "Lens profiles directory" as base paths which enable storing relative paths in the .pp3 files. --- rtdata/languages/default | 2 ++ rtengine/procparams.cc | 36 ++++++++++++++++++++++++++++++++---- rtengine/settings.h | 2 ++ rtgui/options.cc | 19 +++++++++++++++++++ rtgui/options.h | 2 ++ rtgui/preferences.cc | 29 +++++++++++++++++++++++++++-- rtgui/preferences.h | 2 ++ 7 files changed, 86 insertions(+), 6 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index c50b49ddf..d67e6a12b 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1845,6 +1845,7 @@ PREFERENCES_CACHECLEAR_SAFETY;Only files in the cache are cleared. Processing pr PREFERENCES_CACHEMAXENTRIES;Maximum number of cache entries PREFERENCES_CACHEOPTS;Cache Options PREFERENCES_CACHETHUMBHEIGHT;Maximum thumbnail height +PREFERENCES_CAMERAPROFILESDIR;Camera profiles directory PREFERENCES_CHUNKSIZES;Tiles per thread PREFERENCES_CHUNKSIZE_RAW_AMAZE;AMaZE demosaic PREFERENCES_CHUNKSIZE_RAW_CA;Raw CA correction @@ -1927,6 +1928,7 @@ PREFERENCES_INTENT_SATURATION;Saturation PREFERENCES_INTERNALTHUMBIFUNTOUCHED;Show embedded JPEG thumbnail if raw is unedited PREFERENCES_LANG;Language PREFERENCES_LANGAUTODETECT;Use system language +PREFERENCES_LENSPROFILESDIR;Lens profiles directory PREFERENCES_MAXRECENTFOLDERS;Maximum number of recent folders PREFERENCES_MENUGROUPEXTPROGS;Group "Open with" PREFERENCES_MENUGROUPFILEOPERATIONS;Group "File operations" diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 9a9e4fef1..30a2e303c 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -6287,7 +6287,14 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // Lens profile saveToKeyfile(!pedited || pedited->lensProf.lcMode, "LensProfile", "LcMode", lensProf.getMethodString(lensProf.lcMode), keyFile); - saveToKeyfile(!pedited || pedited->lensProf.lcpFile, "LensProfile", "LCPFile", relativePathIfInside(fname, fnameAbsolute, lensProf.lcpFile), keyFile); + if (options.rtSettings.lensProfilesPath.empty() + || !Glib::path_is_absolute(options.rtSettings.lensProfilesPath)) { + saveToKeyfile(!pedited || pedited->lensProf.lcpFile, "LensProfile", "LCPFile", relativePathIfInside(fname, fnameAbsolute, lensProf.lcpFile), keyFile); + } else { + // if the "lens profiles directory" in Preferences exists and is an absolute path, try to save + // the path to the LCP file as relative to this directory + saveToKeyfile(!pedited || pedited->lensProf.lcpFile, "LensProfile", "LCPFile", relativePathIfInside(options.rtSettings.lensProfilesPath + G_DIR_SEPARATOR_S, false, lensProf.lcpFile), keyFile); + } saveToKeyfile(!pedited || pedited->lensProf.useDist, "LensProfile", "UseDistortion", lensProf.useDist, keyFile); saveToKeyfile(!pedited || pedited->lensProf.useVign, "LensProfile", "UseVignette", lensProf.useVign, keyFile); saveToKeyfile(!pedited || pedited->lensProf.useCA, "LensProfile", "UseCA", lensProf.useCA, keyFile); @@ -7108,7 +7115,14 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->prsharpening.deconviter, "PostResizeSharpening", "DeconvIterations", prsharpening.deconviter, keyFile); // Color management - saveToKeyfile(!pedited || pedited->icm.inputProfile, "Color Management", "InputProfile", relativePathIfInside(fname, fnameAbsolute, icm.inputProfile), keyFile); + if (options.rtSettings.cameraProfilesPath.empty() + || !Glib::path_is_absolute(options.rtSettings.cameraProfilesPath)) { + saveToKeyfile(!pedited || pedited->icm.inputProfile, "Color Management", "InputProfile", relativePathIfInside(fname, fnameAbsolute, icm.inputProfile), keyFile); + } else { + // if the "camera profiles directory" in Preferences exists and is an absolute path, try to save + // the path to the Custom Input Profile as relative to this directory + saveToKeyfile(!pedited || pedited->icm.inputProfile, "Color Management", "InputProfile", relativePathIfInside(options.rtSettings.cameraProfilesPath + G_DIR_SEPARATOR_S, false, icm.inputProfile), keyFile); + } saveToKeyfile(!pedited || pedited->icm.toneCurve, "Color Management", "ToneCurve", icm.toneCurve, keyFile); saveToKeyfile(!pedited || pedited->icm.applyLookTable, "Color Management", "ApplyLookTable", icm.applyLookTable, keyFile); saveToKeyfile(!pedited || pedited->icm.applyBaselineExposureOffset, "Color Management", "ApplyBaselineExposureOffset", icm.applyBaselineExposureOffset, keyFile); @@ -8320,7 +8334,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) } if (keyFile.has_key("LensProfile", "LCPFile")) { - lensProf.lcpFile = expandRelativePath(fname, "", keyFile.get_string("LensProfile", "LCPFile")); + if (options.rtSettings.lensProfilesPath.empty() + || !Glib::path_is_absolute(options.rtSettings.lensProfilesPath)) { + lensProf.lcpFile = expandRelativePath(fname, "", keyFile.get_string("LensProfile", "LCPFile")); + } else { + // if the "lens profiles directory" in Preferences exists and is an absolute path, + // use it as a prefix if the path to the LCP file is relative + lensProf.lcpFile = expandRelativePath(options.rtSettings.lensProfilesPath + G_DIR_SEPARATOR_S, "", keyFile.get_string("LensProfile", "LCPFile")); + } if (pedited) { pedited->lensProf.lcpFile = true; @@ -9350,7 +9371,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group("Color Management")) { if (keyFile.has_key("Color Management", "InputProfile")) { - icm.inputProfile = expandRelativePath(fname, "file:", keyFile.get_string("Color Management", "InputProfile")); + if (options.rtSettings.cameraProfilesPath.empty() + || !Glib::path_is_absolute(options.rtSettings.cameraProfilesPath)) { + icm.inputProfile = expandRelativePath(fname, "file:", keyFile.get_string("Color Management", "InputProfile")); + } else { + // if the "camera profiles directory" in Preferences exists and is an absolute path, + // use it as a prefix if the path to the Custom Input Profile is relative + icm.inputProfile = expandRelativePath(options.rtSettings.cameraProfilesPath + G_DIR_SEPARATOR_S, "file:", keyFile.get_string("Color Management", "InputProfile")); + } if (pedited) { pedited->icm.inputProfile = true; diff --git a/rtengine/settings.h b/rtengine/settings.h index bc49a2281..19d3b6ed6 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.h @@ -48,6 +48,8 @@ public: bool verbose; Glib::ustring darkFramesPath; ///< The default directory for dark frames Glib::ustring flatFieldsPath; ///< The default directory for flat fields + Glib::ustring cameraProfilesPath; ///< The default directory for camera profiles + Glib::ustring lensProfilesPath; ///< The default directory for lens profiles Glib::ustring adobe; // filename of AdobeRGB1998 profile (default to the bundled one) Glib::ustring prophoto; // filename of Prophoto profile (default to the bundled one) diff --git a/rtgui/options.cc b/rtgui/options.cc index fc543709f..fd9e87c8d 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -566,6 +566,9 @@ void Options::setDefaults() rtSettings.darkFramesPath = ""; rtSettings.flatFieldsPath = ""; + rtSettings.cameraProfilesPath = ""; + rtSettings.lensProfilesPath = ""; + #ifdef WIN32 const gchar* sysRoot = g_getenv("SystemRoot"); // Returns e.g. "c:\Windows" @@ -663,6 +666,8 @@ void Options::setDefaults() lastIccDir = rtSettings.iccDirectory; lastDarkframeDir = rtSettings.darkFramesPath; lastFlatfieldDir = rtSettings.flatFieldsPath; + lastCameraProfilesDir = rtSettings.cameraProfilesPath; + lastLensProfilesDir = rtSettings.lensProfilesPath; // rtSettings.bw_complementary = true; // There is no reasonable default for curves. We can still suppose that they will take place // in a subdirectory of the user's own ProcParams presets, i.e. in a subdirectory @@ -791,6 +796,14 @@ void Options::readFromFile(Glib::ustring fname) rtSettings.flatFieldsPath = keyFile.get_string("General", "FlatFieldsPath"); } + if (keyFile.has_key("General", "CameraProfilesPath")) { + rtSettings.cameraProfilesPath = keyFile.get_string("General", "CameraProfilesPath"); + } + + if (keyFile.has_key("General", "LensProfilesPath")) { + rtSettings.lensProfilesPath = keyFile.get_string("General", "LensProfilesPath"); + } + if (keyFile.has_key("General", "Verbose")) { rtSettings.verbose = keyFile.get_boolean("General", "Verbose"); } @@ -2047,6 +2060,8 @@ void Options::readFromFile(Glib::ustring fname) safeDirGet(keyFile, "Dialogs", "LastIccDir", lastIccDir); safeDirGet(keyFile, "Dialogs", "LastDarkframeDir", lastDarkframeDir); safeDirGet(keyFile, "Dialogs", "LastFlatfieldDir", lastFlatfieldDir); + safeDirGet(keyFile, "Dialogs", "LastCameraProfilesDir", lastCameraProfilesDir); + safeDirGet(keyFile, "Dialogs", "LastLensProfilesDir", lastLensProfilesDir); safeDirGet(keyFile, "Dialogs", "LastRgbCurvesDir", lastRgbCurvesDir); safeDirGet(keyFile, "Dialogs", "LastLabCurvesDir", lastLabCurvesDir); safeDirGet(keyFile, "Dialogs", "LastRetinexDir", lastRetinexDir); @@ -2150,6 +2165,8 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_string("General", "Version", RTVERSION); keyFile.set_string("General", "DarkFramesPath", rtSettings.darkFramesPath); keyFile.set_string("General", "FlatFieldsPath", rtSettings.flatFieldsPath); + keyFile.set_string("General", "CameraProfilesPath", rtSettings.cameraProfilesPath); + keyFile.set_string("General", "LensProfilesPath", rtSettings.lensProfilesPath); keyFile.set_boolean("General", "Verbose", rtSettings.verbose); keyFile.set_integer("General", "Cropsleep", rtSettings.cropsleep); keyFile.set_double("General", "Reduchigh", rtSettings.reduchigh); @@ -2484,6 +2501,8 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_string("Dialogs", "LastIccDir", lastIccDir); keyFile.set_string("Dialogs", "LastDarkframeDir", lastDarkframeDir); keyFile.set_string("Dialogs", "LastFlatfieldDir", lastFlatfieldDir); + keyFile.set_string("Dialogs", "LastCameraProfilesDir", lastCameraProfilesDir); + keyFile.set_string("Dialogs", "LastLensProfilesDir", lastLensProfilesDir); keyFile.set_string("Dialogs", "LastRgbCurvesDir", lastRgbCurvesDir); keyFile.set_string("Dialogs", "LastLabCurvesDir", lastLabCurvesDir); keyFile.set_string("Dialogs", "LastRetinexDir", lastRetinexDir); diff --git a/rtgui/options.h b/rtgui/options.h index bc5e41c91..6385709db 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -432,6 +432,8 @@ public: Glib::ustring lastIccDir; Glib::ustring lastDarkframeDir; Glib::ustring lastFlatfieldDir; + Glib::ustring lastCameraProfilesDir; + Glib::ustring lastLensProfilesDir; Glib::ustring lastRgbCurvesDir; Glib::ustring lastLabCurvesDir; Glib::ustring lastRetinexDir; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index c6c2eb61b..a4c7410da 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -589,6 +589,7 @@ Gtk::Widget* Preferences::getImageProcessingPanel () Gtk::Grid* dirgrid = Gtk::manage(new Gtk::Grid()); setExpandAlignProperties(dirgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + // Dark Frames Dir Gtk::Label *dfLab = Gtk::manage(new Gtk::Label(M("PREFERENCES_DIRDARKFRAMES") + ":")); setExpandAlignProperties(dfLab, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); darkFrameDir = Gtk::manage(new MyFileChooserButton(M("PREFERENCES_DIRDARKFRAMES"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); @@ -602,7 +603,7 @@ Gtk::Widget* Preferences::getImageProcessingPanel () dfconn = darkFrameDir->signal_selection_changed().connect ( sigc::mem_fun (*this, &Preferences::darkFrameChanged)); - // FLATFIELD + // Flatfield Dir Gtk::Label *ffLab = Gtk::manage(new Gtk::Label(M("PREFERENCES_FLATFIELDSDIR") + ":")); setExpandAlignProperties(ffLab, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); flatFieldDir = Gtk::manage(new MyFileChooserButton(M("PREFERENCES_FLATFIELDSDIR"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); @@ -628,6 +629,25 @@ Gtk::Widget* Preferences::getImageProcessingPanel () dirgrid->attach_next_to(*clutsDir, *clutsDirLabel, Gtk::POS_RIGHT, 1, 1); dirgrid->attach_next_to(*clutsRestartNeeded, *clutsDir, Gtk::POS_RIGHT, 1, 1); + //Camera Profiles Dir + Gtk::Label *cameraProfilesDirLabel = Gtk::manage(new Gtk::Label(M("PREFERENCES_CAMERAPROFILESDIR") + ":")); + setExpandAlignProperties(cameraProfilesDirLabel, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + cameraProfilesDir = Gtk::manage(new MyFileChooserButton(M("PREFERENCES_CAMERAPROFILESDIR"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); + setExpandAlignProperties(cameraProfilesDir, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + + dirgrid->attach_next_to(*cameraProfilesDirLabel, *clutsDirLabel, Gtk::POS_BOTTOM, 1, 1); + dirgrid->attach_next_to(*cameraProfilesDir, *cameraProfilesDirLabel, Gtk::POS_RIGHT, 1, 1); + + //Lens Profiles Dir + Gtk::Label *lensProfilesDirLabel = Gtk::manage(new Gtk::Label(M("PREFERENCES_LENSPROFILESDIR") + ":")); + setExpandAlignProperties(lensProfilesDirLabel, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + lensProfilesDir = Gtk::manage(new MyFileChooserButton(M("PREFERENCES_LENSPROFILESDIR"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); + setExpandAlignProperties(lensProfilesDir, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + + dirgrid->attach_next_to(*lensProfilesDirLabel, *cameraProfilesDirLabel, Gtk::POS_BOTTOM, 1, 1); + dirgrid->attach_next_to(*lensProfilesDir, *lensProfilesDirLabel, Gtk::POS_RIGHT, 1, 1); + + //Pack directories to Image Processing panel cdf->add(*dirgrid); vbImageProcessing->pack_start (*cdf, Gtk::PACK_SHRINK, 4 ); @@ -1889,8 +1909,9 @@ void Preferences::storePreferences() moptions.rtSettings.darkFramesPath = darkFrameDir->get_filename(); moptions.rtSettings.flatFieldsPath = flatFieldDir->get_filename(); - moptions.clutsDir = clutsDir->get_filename(); + moptions.rtSettings.cameraProfilesPath = cameraProfilesDir->get_filename(); + moptions.rtSettings.lensProfilesPath = lensProfilesDir->get_filename(); moptions.baBehav.resize(ADDSET_PARAM_NUM); @@ -2162,6 +2183,10 @@ void Preferences::fillPreferences() flatFieldChanged(); clutsDir->set_current_folder(moptions.clutsDir); + + cameraProfilesDir->set_current_folder(moptions.rtSettings.cameraProfilesPath); + + lensProfilesDir->set_current_folder(moptions.rtSettings.lensProfilesPath); addc.block(true); setc.block(true); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index dfe1e008d..6b0d372af 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -112,6 +112,8 @@ class Preferences final : MyFileChooserButton* darkFrameDir; MyFileChooserButton* flatFieldDir; MyFileChooserButton* clutsDir; + MyFileChooserButton* cameraProfilesDir; + MyFileChooserButton* lensProfilesDir; Gtk::Label *dfLabel; Gtk::Label *ffLabel; From a974fc06f3d06e9cd28c649c38a78104cc7a40d1 Mon Sep 17 00:00:00 2001 From: Bezierr Date: Wed, 27 Jul 2022 16:50:30 +0200 Subject: [PATCH 2/9] replaceBackslash for lens profiles and camera profiles directories When saving .pp3, replace all "\\" by "/" in paths for LCPFile and InputProfile, so they are compatible between Windows and Linux. --- rtengine/procparams.cc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 30a2e303c..afce81e7a 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -42,6 +42,19 @@ using namespace std; namespace { +Glib::ustring replaceBackslash(Glib::ustring path) +{ + size_t pos; + + pos = path.find("\\"); + while (pos != string::npos) { + path.replace(pos, 1, "/"); + pos = path.find("\\", pos); + } + return path; +} + + Glib::ustring expandRelativePath(const Glib::ustring &procparams_fname, const Glib::ustring &prefix, Glib::ustring embedded_fname) { if (embedded_fname.empty() || !Glib::path_is_absolute(procparams_fname)) { @@ -6293,7 +6306,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo } else { // if the "lens profiles directory" in Preferences exists and is an absolute path, try to save // the path to the LCP file as relative to this directory - saveToKeyfile(!pedited || pedited->lensProf.lcpFile, "LensProfile", "LCPFile", relativePathIfInside(options.rtSettings.lensProfilesPath + G_DIR_SEPARATOR_S, false, lensProf.lcpFile), keyFile); + saveToKeyfile(!pedited || pedited->lensProf.lcpFile, "LensProfile", "LCPFile", replaceBackslash(relativePathIfInside(options.rtSettings.lensProfilesPath + G_DIR_SEPARATOR_S, false, lensProf.lcpFile)), keyFile); } saveToKeyfile(!pedited || pedited->lensProf.useDist, "LensProfile", "UseDistortion", lensProf.useDist, keyFile); saveToKeyfile(!pedited || pedited->lensProf.useVign, "LensProfile", "UseVignette", lensProf.useVign, keyFile); @@ -7121,7 +7134,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo } else { // if the "camera profiles directory" in Preferences exists and is an absolute path, try to save // the path to the Custom Input Profile as relative to this directory - saveToKeyfile(!pedited || pedited->icm.inputProfile, "Color Management", "InputProfile", relativePathIfInside(options.rtSettings.cameraProfilesPath + G_DIR_SEPARATOR_S, false, icm.inputProfile), keyFile); + saveToKeyfile(!pedited || pedited->icm.inputProfile, "Color Management", "InputProfile", replaceBackslash(relativePathIfInside(options.rtSettings.cameraProfilesPath + G_DIR_SEPARATOR_S, false, icm.inputProfile)), keyFile); } saveToKeyfile(!pedited || pedited->icm.toneCurve, "Color Management", "ToneCurve", icm.toneCurve, keyFile); saveToKeyfile(!pedited || pedited->icm.applyLookTable, "Color Management", "ApplyLookTable", icm.applyLookTable, keyFile); From 1c95dfe099768801fc2df3692f5b0b413c66d542 Mon Sep 17 00:00:00 2001 From: Bezierr Date: Fri, 29 Jul 2022 15:29:35 +0200 Subject: [PATCH 3/9] In filmSimulation.clutFilename, use "/" or "\" depending on OS For OS-independent use of .pp3 files: If OS is WIN32, replace any "/" in filmSimulation.clutFilename with "\\". If OS is not WIN32, replace any "\\" in filmSimulation.clutFilename with "/". --- rtengine/procparams.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index afce81e7a..e875124e3 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -9978,7 +9978,23 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group("Film Simulation")) { assignFromKeyfile(keyFile, "Film Simulation", "Enabled", pedited, filmSimulation.enabled, pedited->filmSimulation.enabled); - assignFromKeyfile(keyFile, "Film Simulation", "ClutFilename", pedited, filmSimulation.clutFilename, pedited->filmSimulation.clutFilename); + assignFromKeyfile(keyFile, "Film Simulation", "ClutFilename", pedited, filmSimulation.clutFilename, pedited->filmSimulation.clutFilename); + #if defined (WIN32) + // if this is Windows, replace any "/" in the filename with "\\" + size_t pos = filmSimulation.clutFilename.find("/"); + while (pos != string::npos) { + filmSimulation.clutFilename.replace(pos, 1, "\\"); + pos = filmSimulation.clutFilename.find("/", pos); + } + #endif + #if !defined (WIN32) + // if this is not Windows, replace any "\\" in the filename with "/" + size_t pos = filmSimulation.clutFilename.find("\\"); + while (pos != string::npos) { + filmSimulation.clutFilename.replace(pos, 1, "/"); + pos = filmSimulation.clutFilename.find("\\", pos); + } + #endif if (keyFile.has_key("Film Simulation", "Strength")) { if (ppVersion < 321) { From 24f5d85c8d2cb57c4405ddbc573167f52dc2d69a Mon Sep 17 00:00:00 2001 From: Bezierr Date: Tue, 23 Aug 2022 16:27:47 +0200 Subject: [PATCH 4/9] Squashed commit of the following: commit e293f0890866ddf934ba1a9dd9fa372364766bb3 Author: Bezierr Date: Tue Aug 23 16:16:23 2022 +0200 Added comment commit 20a50b248dc110eeb4b526c7242920a68216c88c Author: Bezierr Date: Tue Aug 23 14:35:47 2022 +0200 Follow dynamicprofile.cfg symlink instead of overwriting it If dynamicprofile.cfg is a symlink, write the contents to this symlink's target instead of overwriting it. commit bad2f8c37a0d27e612150dce3219593b2f996f9c Author: Bezierr Date: Thu Aug 11 17:20:08 2022 +0200 Make dynamicprofile.cfg OS independent dynamicprofile.cfg contains OS-dependent paths to the profiles. To fix this, replace "/" or "\", depending on OS, with the correct delimiter. commit cd84120876be111c23dac5376eb5b6f6cb0a7328 Author: Bezierr Date: Thu Aug 11 16:33:39 2022 +0200 Relative paths also for Dark Frame and Flat File (a) Extended the "relative path" functionality to the (already existing, but apparently not used) directories for FlatField and DarkFrame (b) Simpler, cleaner implementation commit a338b8726451323505bb4cff1888c562fd88929d Author: Bezierr Date: Sun Aug 7 18:03:46 2022 +0200 Preference of RAW path over rtSettings path (a) Give path relative to a camera or lens profile in the same folder as the raw file precendence over path relative to rtSettings. (b) Replace backslash/slash when reading file paths, not when writing them. --- rtengine/dynamicprofile.cc | 26 ++++++++- rtengine/procparams.cc | 116 ++++++++++++++++++++----------------- rtgui/options.cc | 4 +- 3 files changed, 89 insertions(+), 57 deletions(-) diff --git a/rtengine/dynamicprofile.cc b/rtengine/dynamicprofile.cc index 28516a1ee..db1baf4b8 100644 --- a/rtengine/dynamicprofile.cc +++ b/rtengine/dynamicprofile.cc @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -218,6 +219,22 @@ bool DynamicProfileRules::loadRules() try { rule.profilepath = kf.get_string (group, "profilepath"); + #if defined (WIN32) + // if this is Windows, replace any "/" in the path with "\\" + int pos = rule.profilepath.find("/"); + while (pos != -1) { + rule.profilepath.replace(pos, 1, "\\"); + pos = rule.profilepath.find("/", pos); + } + #endif + #if !defined (WIN32) + // if this is not Windows, replace any "\\" in the path with "/" + int pos = rule.profilepath.find("\\"); + while (pos != -1) { + rule.profilepath.replace(pos, 1, "/"); + pos = rule.profilepath.find("\\", pos); + } + #endif } catch (Glib::KeyFileError &) { dynamicRules.pop_back(); } @@ -251,7 +268,14 @@ bool DynamicProfileRules::storeRules() kf.set_string (group, "profilepath", rule.profilepath); } - return kf.save_to_file (Glib::build_filename (Options::rtdir, "dynamicprofile.cfg")); + std::string fn = Glib::build_filename (Options::rtdir, "dynamicprofile.cfg"); + if (Glib::file_test(fn, Glib::FILE_TEST_IS_SYMLINK)) { + // file is symlink; use target instead + // symlinks apparently are not recognízed on Windows + return kf.save_to_file (g_file_read_link (fn.c_str(), NULL)); + } else { + return kf.save_to_file (fn); + } } const std::vector &DynamicProfileRules::getRules() diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index e875124e3..c787c7b0c 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -42,19 +42,6 @@ using namespace std; namespace { -Glib::ustring replaceBackslash(Glib::ustring path) -{ - size_t pos; - - pos = path.find("\\"); - while (pos != string::npos) { - path.replace(pos, 1, "/"); - pos = path.find("\\", pos); - } - return path; -} - - Glib::ustring expandRelativePath(const Glib::ustring &procparams_fname, const Glib::ustring &prefix, Glib::ustring embedded_fname) { if (embedded_fname.empty() || !Glib::path_is_absolute(procparams_fname)) { @@ -77,6 +64,40 @@ Glib::ustring expandRelativePath(const Glib::ustring &procparams_fname, const Gl return absPath; } +Glib::ustring expandRelativePath2(const Glib::ustring &procparams_fname, const Glib::ustring &procparams_fname2, const Glib::ustring &prefix, Glib::ustring embedded_fname) +{ + #if defined (WIN32) + // if this is Windows, replace any "/" in the filename with "\\" + size_t pos = embedded_fname.find("/"); + while (pos != string::npos) { + embedded_fname.replace(pos, 1, "\\"); + pos = embedded_fname.find("/", pos); + } + #endif + #if !defined (WIN32) + // if this is not Windows, replace any "\\" in the filename with "/" + size_t pos = embedded_fname.find("\\"); + while (pos != string::npos) { + embedded_fname.replace(pos, 1, "/"); + pos = embedded_fname.find("\\", pos); + } + #endif + + // if embedded_fname is not already an absolute path, + // try to convert it using procparams_fname (the directory of the raw file) as prefix + Glib::ustring rPath = expandRelativePath(procparams_fname, prefix, embedded_fname); + if (rPath.length() >= prefix.length() + && !Glib::file_test(rPath.substr(prefix.length()), Glib::FILE_TEST_IS_REGULAR) + && !procparams_fname2.empty() + && Glib::path_is_absolute(procparams_fname2)) { + // embedded_fname is not a valid path; + // try with procparams_fname2 (the path defined in Preferences) as a prefix + rPath = expandRelativePath(procparams_fname2 + G_DIR_SEPARATOR_S, prefix, embedded_fname); + } + return(rPath); +} + + Glib::ustring relativePathIfInside(const Glib::ustring &procparams_fname, bool fnameAbsolute, Glib::ustring embedded_fname) { if (fnameAbsolute || embedded_fname.empty() || !Glib::path_is_absolute(procparams_fname)) { @@ -105,6 +126,25 @@ Glib::ustring relativePathIfInside(const Glib::ustring &procparams_fname, bool f return prefix + embedded_fname.substr(dir1.length()); } +Glib::ustring relativePathIfInside2(const Glib::ustring &procparams_fname, const Glib::ustring &procparams_fname2, bool fnameAbsolute, Glib::ustring embedded_fname) +{ + // try to convert embedded_fname to a path relative to procparams_fname + // (the directory of the raw file) + // (note: fnameAbsolute seems to be always true, so this will never return a relative path) + Glib::ustring rPath = relativePathIfInside(procparams_fname, fnameAbsolute, embedded_fname); + if ((Glib::path_is_absolute(rPath) + || (rPath.length() >= 5 && rPath.substr(0, 5) == "file:" && Glib::path_is_absolute(rPath.substr(5)))) + && !procparams_fname2.empty() + && Glib::path_is_absolute(procparams_fname2)) { + // if path is not relative to the directory of the raw file, + // try to convert embedded_fname to a path relative to procparams_fname2 + // (the path defined in Preferences) + rPath = relativePathIfInside(procparams_fname2 + G_DIR_SEPARATOR_S, false, embedded_fname); + } + return(rPath); +} + + void getFromKeyfile( const Glib::KeyFile& keyfile, const Glib::ustring& group_name, @@ -6300,14 +6340,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // Lens profile saveToKeyfile(!pedited || pedited->lensProf.lcMode, "LensProfile", "LcMode", lensProf.getMethodString(lensProf.lcMode), keyFile); - if (options.rtSettings.lensProfilesPath.empty() - || !Glib::path_is_absolute(options.rtSettings.lensProfilesPath)) { - saveToKeyfile(!pedited || pedited->lensProf.lcpFile, "LensProfile", "LCPFile", relativePathIfInside(fname, fnameAbsolute, lensProf.lcpFile), keyFile); - } else { - // if the "lens profiles directory" in Preferences exists and is an absolute path, try to save - // the path to the LCP file as relative to this directory - saveToKeyfile(!pedited || pedited->lensProf.lcpFile, "LensProfile", "LCPFile", replaceBackslash(relativePathIfInside(options.rtSettings.lensProfilesPath + G_DIR_SEPARATOR_S, false, lensProf.lcpFile)), keyFile); - } + saveToKeyfile(!pedited || pedited->lensProf.lcpFile, "LensProfile", "LCPFile", relativePathIfInside2(fname, options.rtSettings.lensProfilesPath, fnameAbsolute, lensProf.lcpFile), keyFile); saveToKeyfile(!pedited || pedited->lensProf.useDist, "LensProfile", "UseDistortion", lensProf.useDist, keyFile); saveToKeyfile(!pedited || pedited->lensProf.useVign, "LensProfile", "UseVignette", lensProf.useVign, keyFile); saveToKeyfile(!pedited || pedited->lensProf.useCA, "LensProfile", "UseCA", lensProf.useCA, keyFile); @@ -7128,14 +7161,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->prsharpening.deconviter, "PostResizeSharpening", "DeconvIterations", prsharpening.deconviter, keyFile); // Color management - if (options.rtSettings.cameraProfilesPath.empty() - || !Glib::path_is_absolute(options.rtSettings.cameraProfilesPath)) { - saveToKeyfile(!pedited || pedited->icm.inputProfile, "Color Management", "InputProfile", relativePathIfInside(fname, fnameAbsolute, icm.inputProfile), keyFile); - } else { - // if the "camera profiles directory" in Preferences exists and is an absolute path, try to save - // the path to the Custom Input Profile as relative to this directory - saveToKeyfile(!pedited || pedited->icm.inputProfile, "Color Management", "InputProfile", replaceBackslash(relativePathIfInside(options.rtSettings.cameraProfilesPath + G_DIR_SEPARATOR_S, false, icm.inputProfile)), keyFile); - } + saveToKeyfile(!pedited || pedited->icm.inputProfile, "Color Management", "InputProfile", relativePathIfInside2(fname, options.rtSettings.cameraProfilesPath, fnameAbsolute, icm.inputProfile), keyFile); saveToKeyfile(!pedited || pedited->icm.toneCurve, "Color Management", "ToneCurve", icm.toneCurve, keyFile); saveToKeyfile(!pedited || pedited->icm.applyLookTable, "Color Management", "ApplyLookTable", icm.applyLookTable, keyFile); saveToKeyfile(!pedited || pedited->icm.applyBaselineExposureOffset, "Color Management", "ApplyBaselineExposureOffset", icm.applyBaselineExposureOffset, keyFile); @@ -7507,9 +7533,9 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->colorToning.labregionsShowMask, "ColorToning", "LabRegionsShowMask", colorToning.labregionsShowMask, keyFile); // Raw - saveToKeyfile(!pedited || pedited->raw.darkFrame, "RAW", "DarkFrame", relativePathIfInside(fname, fnameAbsolute, raw.dark_frame), keyFile); + saveToKeyfile(!pedited || pedited->raw.darkFrame, "RAW", "DarkFrame", relativePathIfInside2(fname, options.rtSettings.darkFramesPath, fnameAbsolute, raw.dark_frame), keyFile); saveToKeyfile(!pedited || pedited->raw.df_autoselect, "RAW", "DarkFrameAuto", raw.df_autoselect, keyFile); - saveToKeyfile(!pedited || pedited->raw.ff_file, "RAW", "FlatFieldFile", relativePathIfInside(fname, fnameAbsolute, raw.ff_file), keyFile); + saveToKeyfile(!pedited || pedited->raw.ff_file, "RAW", "FlatFieldFile", relativePathIfInside2(fname, options.rtSettings.flatFieldsPath, fnameAbsolute, raw.ff_file), keyFile); saveToKeyfile(!pedited || pedited->raw.ff_AutoSelect, "RAW", "FlatFieldAutoSelect", raw.ff_AutoSelect, keyFile); saveToKeyfile(!pedited || pedited->raw.ff_BlurRadius, "RAW", "FlatFieldBlurRadius", raw.ff_BlurRadius, keyFile); saveToKeyfile(!pedited || pedited->raw.ff_BlurType, "RAW", "FlatFieldBlurType", raw.ff_BlurType, keyFile); @@ -8347,14 +8373,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) } if (keyFile.has_key("LensProfile", "LCPFile")) { - if (options.rtSettings.lensProfilesPath.empty() - || !Glib::path_is_absolute(options.rtSettings.lensProfilesPath)) { - lensProf.lcpFile = expandRelativePath(fname, "", keyFile.get_string("LensProfile", "LCPFile")); - } else { - // if the "lens profiles directory" in Preferences exists and is an absolute path, - // use it as a prefix if the path to the LCP file is relative - lensProf.lcpFile = expandRelativePath(options.rtSettings.lensProfilesPath + G_DIR_SEPARATOR_S, "", keyFile.get_string("LensProfile", "LCPFile")); - } + lensProf.lcpFile = expandRelativePath2(fname, options.rtSettings.lensProfilesPath, "", keyFile.get_string("LensProfile", "LCPFile")); if (pedited) { pedited->lensProf.lcpFile = true; @@ -9384,20 +9403,12 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group("Color Management")) { if (keyFile.has_key("Color Management", "InputProfile")) { - if (options.rtSettings.cameraProfilesPath.empty() - || !Glib::path_is_absolute(options.rtSettings.cameraProfilesPath)) { - icm.inputProfile = expandRelativePath(fname, "file:", keyFile.get_string("Color Management", "InputProfile")); - } else { - // if the "camera profiles directory" in Preferences exists and is an absolute path, - // use it as a prefix if the path to the Custom Input Profile is relative - icm.inputProfile = expandRelativePath(options.rtSettings.cameraProfilesPath + G_DIR_SEPARATOR_S, "file:", keyFile.get_string("Color Management", "InputProfile")); - } + icm.inputProfile = expandRelativePath2(fname, options.rtSettings.cameraProfilesPath, "file:", keyFile.get_string("Color Management", "InputProfile")); if (pedited) { pedited->icm.inputProfile = true; } - } - + } assignFromKeyfile(keyFile, "Color Management", "ToneCurve", pedited, icm.toneCurve, pedited->icm.toneCurve); assignFromKeyfile(keyFile, "Color Management", "ApplyLookTable", pedited, icm.applyLookTable, pedited->icm.applyLookTable); assignFromKeyfile(keyFile, "Color Management", "ApplyBaselineExposureOffset", pedited, icm.applyBaselineExposureOffset, pedited->icm.applyBaselineExposureOffset); @@ -10169,23 +10180,20 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group("RAW")) { if (keyFile.has_key("RAW", "DarkFrame")) { - raw.dark_frame = expandRelativePath(fname, "", keyFile.get_string("RAW", "DarkFrame")); + raw.dark_frame = expandRelativePath2(fname, options.rtSettings.darkFramesPath, "", keyFile.get_string("RAW", "DarkFrame")); if (pedited) { pedited->raw.darkFrame = true; } } - assignFromKeyfile(keyFile, "RAW", "DarkFrameAuto", pedited, raw.df_autoselect, pedited->raw.df_autoselect); - if (keyFile.has_key("RAW", "FlatFieldFile")) { - raw.ff_file = expandRelativePath(fname, "", keyFile.get_string("RAW", "FlatFieldFile")); + raw.ff_file = expandRelativePath2(fname, options.rtSettings.flatFieldsPath, "", keyFile.get_string("RAW", "FlatFieldFile")); if (pedited) { pedited->raw.ff_file = true; } } - assignFromKeyfile(keyFile, "RAW", "FlatFieldAutoSelect", pedited, raw.ff_AutoSelect, pedited->raw.ff_AutoSelect); assignFromKeyfile(keyFile, "RAW", "FlatFieldBlurRadius", pedited, raw.ff_BlurRadius, pedited->raw.ff_BlurRadius); assignFromKeyfile(keyFile, "RAW", "FlatFieldBlurType", pedited, raw.ff_BlurType, pedited->raw.ff_BlurType); diff --git a/rtgui/options.cc b/rtgui/options.cc index fd9e87c8d..b4729f9d5 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -659,8 +659,8 @@ void Options::setDefaults() rtSettings.leveldnliss = 0; rtSettings.leveldnautsimpl = 0; -// rtSettings.colortoningab =0.7; -//rtSettings.decaction =0.3; +// rtSettings.colortoningab =0.7; +// rtSettings.decaction =0.3; // rtSettings.ciebadpixgauss=false; rtSettings.rgbcurveslumamode_gamut = true; lastIccDir = rtSettings.iccDirectory; From 136bc371546b878fc6c8133f8f92ad6de8131b89 Mon Sep 17 00:00:00 2001 From: Bezierr Date: Thu, 1 Sep 2022 14:48:29 +0200 Subject: [PATCH 5/9] Change according to review --- rtengine/dynamicprofile.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rtengine/dynamicprofile.cc b/rtengine/dynamicprofile.cc index db1baf4b8..64dc14d3c 100644 --- a/rtengine/dynamicprofile.cc +++ b/rtengine/dynamicprofile.cc @@ -221,16 +221,16 @@ bool DynamicProfileRules::loadRules() rule.profilepath = kf.get_string (group, "profilepath"); #if defined (WIN32) // if this is Windows, replace any "/" in the path with "\\" - int pos = rule.profilepath.find("/"); - while (pos != -1) { + size_t pos = rule.profilepath.find("/"); + while (pos != Glib::ustring::npos) { rule.profilepath.replace(pos, 1, "\\"); pos = rule.profilepath.find("/", pos); } #endif #if !defined (WIN32) // if this is not Windows, replace any "\\" in the path with "/" - int pos = rule.profilepath.find("\\"); - while (pos != -1) { + size_t pos = rule.profilepath.find("\\"); + while (pos != Glib::ustring::npos) { rule.profilepath.replace(pos, 1, "/"); pos = rule.profilepath.find("\\", pos); } From 223b136082ba2d61273058351232a6b37ea7a283 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sat, 25 Mar 2023 12:11:19 -0700 Subject: [PATCH 6/9] Fix Windows workflow Adwaita error Update paths to match those of the Adwaita icon theme library. --- .github/workflows/windows.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index a14c23993..4ab10212c 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -178,15 +178,15 @@ jobs: echo "Copying Adwaita theme." mkdir -p "$BUILD_DIR/share/icons/Adwaita" cd 'share/icons/Adwaita/' - mkdir -p "$BUILD_DIR/share/icons/Adwaita/scalable" + mkdir -p "$BUILD_DIR/share/icons/Adwaita/symbolic" cp -r \ - "scalable/actions" \ - "scalable/devices" \ - "scalable/mimetypes" \ - "scalable/places" \ - "scalable/status" \ - "scalable/ui" \ - "$BUILD_DIR/share/icons/Adwaita/scalable" + "symbolic/actions" \ + "symbolic/devices" \ + "symbolic/mimetypes" \ + "symbolic/places" \ + "symbolic/status" \ + "symbolic/ui" \ + "$BUILD_DIR/share/icons/Adwaita/symbolic" cp 'index.theme' "$BUILD_DIR/share/icons/Adwaita" mkdir -p "$BUILD_DIR/share/icons/Adwaita/cursors" cp -r \ From ae4de4701f5b0d8303d67e15822f453f99d3f02a Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Sun, 6 Dec 2020 09:37:34 +0100 Subject: [PATCH 7/9] Fix color-cast regression Fix checking of existence of second masked area. Issue #6720. --- rtengine/camconst.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index 64fc4d4ba..5cb56b2ae 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -224,7 +224,7 @@ CameraConst* CameraConst::parseEntry(const void *cJSON_, const char *make_model) const auto get_masked_areas = [](int w, int h, const cJSON *ji, CameraConst *cc) -> bool { - std::array, 2> rm; + std::array, 2> rm = {}; if (ji->type != cJSON_Array) { //fprintf(stderr, "\"masked_areas\" must be an array\n"); @@ -505,7 +505,15 @@ bool CameraConst::has_rawMask(int raw_width, int raw_height, int idx) const return false; } - return raw_mask.find(std::make_pair(raw_width, raw_height)) != raw_mask.end() || raw_mask.find(std::make_pair(0, 0)) != raw_mask.end(); + auto it = raw_mask.find(std::make_pair(raw_width, raw_height)); + if (it == raw_mask.end()) { + it = raw_mask.find(std::make_pair(0, 0)); + } + if (it != raw_mask.end()) { + return (it->second[idx][0] | it->second[idx][1] | it->second[idx][2] | it->second[idx][3]) != 0; + } else { + return false; + } } From 1abbfceb8e5a241efc12e28cff9f5e9a1d6e0b97 Mon Sep 17 00:00:00 2001 From: Bezierr Date: Mon, 27 Mar 2023 13:23:21 +0200 Subject: [PATCH 8/9] Name added to AUTHORS.txt As suggested by Lawrence37 --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 059bdce17..3d16899a6 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -5,6 +5,7 @@ Project initiator: Development contributors, in last name alphabetical order: + Harald Aust Roel Baars Martin Burri Pierre Cabrera From 1dbd9818cf6d0c2b8b77bb29ccc721cc86d096af Mon Sep 17 00:00:00 2001 From: Lawrence37 <45837045+Lawrence37@users.noreply.github.com> Date: Mon, 3 Apr 2023 20:16:39 -0700 Subject: [PATCH 9/9] Set AppImage runner to Ubuntu 20.04 Ubuntu 18.04 is no longer available in GitHub Actions. --- .github/workflows/appimage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 8fd7608f9..9ad9a6cbd 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -14,7 +14,7 @@ env: publish_pre_dev_labels: '[]' jobs: build: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: