diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 86e348c75..b97f913e7 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -1709,6 +1709,11 @@ void DCPStore::init(const Glib::ustring& rt_profile_dir, bool loadAll) file_std_profiles.clear(); + if (!loadAll) { + profileDir.assign (rt_profile_dir); + return; + } + if (!rt_profile_dir.empty()) { std::deque dirs = { rt_profile_dir @@ -1731,10 +1736,8 @@ void DCPStore::init(const Glib::ustring& rt_profile_dir, bool loadAll) return; } - dirname += '/'; - for (const Glib::ustring& sname : *dir) { - const Glib::ustring fname = dirname + sname; + const Glib::ustring fname = Glib::build_filename(dirname, sname); if (!Glib::file_test(fname, Glib::FILE_TEST_IS_DIR)) { // File @@ -1797,15 +1800,25 @@ DCPProfile* DCPStore::getProfile(const Glib::ustring& filename) const return nullptr; } -DCPProfile* DCPStore::getStdProfile(const Glib::ustring& cam_short_name) const +DCPProfile* DCPStore::getStdProfile(const Glib::ustring& requested_cam_short_name) const { - const Glib::ustring name = cam_short_name.uppercase(); + const Glib::ustring name = requested_cam_short_name.uppercase(); // Warning: do NOT use map.find(), since it does not seem to work reliably here - for (const auto& file_std_profile : file_std_profiles) + for (const auto& file_std_profile : file_std_profiles) { if (file_std_profile.first == name) { return getProfile(file_std_profile.second); } + } + + // profile not found, looking if we're in loadAll=false mode + if (!profileDir.empty()) { + const Glib::ustring fname = Glib::build_filename(profileDir, requested_cam_short_name + Glib::ustring(".dcp")); + + if (Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) { + return getProfile(fname); + } + } return nullptr; } diff --git a/rtengine/dcp.h b/rtengine/dcp.h index 215137ac8..5a6858099 100644 --- a/rtengine/dcp.h +++ b/rtengine/dcp.h @@ -165,6 +165,7 @@ private: DCPStore() = default; mutable MyMutex mutex; + Glib::ustring profileDir; // these contain standard profiles from RT. keys are all in uppercase, file path is value std::map file_std_profiles; diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index 2898f48c8..7bc21d5d4 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -36,6 +36,7 @@ namespace rtengine { extern const Settings* settings; +// not recursive void loadProfiles (const Glib::ustring& dirName, std::map* profiles, std::map* profileContents, @@ -96,6 +97,60 @@ void loadProfiles (const Glib::ustring& dirName, } catch (Glib::Exception&) {} } +// version dedicated to single profile load when loadAll==false (cli version "-q" mode) +bool loadProfile (Glib::ustring profile, const Glib::ustring dirName, + std::map* profiles, + std::map* profileContents) +{ + if (dirName.empty () || profiles == nullptr) { + return false; + } + + try { + + Glib::Dir dir (dirName); + + for (Glib::DirIterator entry = dir.begin (); entry != dir.end (); ++entry) { + + const Glib::ustring fileName = *entry; + + if (fileName.size () < 4) { + continue; + } + + const Glib::ustring extension = fileName.substr (fileName.size () - 4).casefold (); + + if (extension.compare (".icc") != 0 && extension.compare (".icm") != 0) { + continue; + } + + const Glib::ustring filePath = Glib::build_filename (dirName, fileName); + + if (!Glib::file_test (filePath, Glib::FILE_TEST_IS_REGULAR)) { + continue; + } + + Glib::ustring name = fileName.substr (0, fileName.size() - 4); + + if (name == profile) { + const ProfileContent content (filePath); + const cmsHPROFILE profile = content.toProfile (); + + if (profile) { + profiles->insert (std::make_pair (name, profile)); + + if (profileContents) { + profileContents->insert (std::make_pair (name, content)); + } + return true; + } + } + } + } catch (Glib::Exception&) {} + + return false; +} + inline void getSupportedIntent (cmsHPROFILE profile, cmsUInt32Number intent, cmsUInt32Number direction, uint8_t& result) { if (cmsIsIntentSupported (profile, intent, direction)) { @@ -305,6 +360,7 @@ ICCStore* ICCStore::getInstance () } ICCStore::ICCStore () : + loadAll(true), xyz (createXYZProfile ()), srgb (cmsCreate_sRGBProfile ()) { @@ -674,7 +730,7 @@ bool ICCStore::outputProfileExist (const Glib::ustring& name) const return fileProfiles.find(name) != fileProfiles.end(); } -cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) const +cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) { MyMutex::MyLock lock (mutex_); @@ -695,12 +751,21 @@ cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) const return profile; } + } else if (!loadAll) { + // look for a standard profile + if (!loadProfile (name, profilesDir, &fileProfiles, &fileProfileContents)) { + loadProfile (name, userICCDir, &fileProfiles, &fileProfileContents); + } + const ProfileMap::const_iterator r = fileProfiles.find (name); + if (r != fileProfiles.end ()) { + return r->second; + } } return nullptr; } -cmsHPROFILE ICCStore::getStdProfile (const Glib::ustring& name) const +cmsHPROFILE ICCStore::getStdProfile (const Glib::ustring& name) { const Glib::ustring nameUpper = name.uppercase (); @@ -712,6 +777,15 @@ cmsHPROFILE ICCStore::getStdProfile (const Glib::ustring& name) const // return profile from store if (r != fileStdProfiles.end ()) { return r->second; + } else if (!loadAll) { + // directory not scanned, so looking and adding now... + if (!loadProfile (name, profilesDir, &fileProfiles, &fileProfileContents)) { + loadProfile (name, userICCDir, &fileProfiles, &fileProfileContents); + } + const ProfileMap::const_iterator r = fileProfiles.find (name); + if (r != fileProfiles.end ()) { + return r->second; + } } // profile is not yet in store @@ -745,21 +819,21 @@ ProfileContent ICCStore::getContent (const Glib::ustring& name) const return r != fileProfileContents.end () ? r->second : ProfileContent(); } -uint8_t ICCStore::getInputIntents (cmsHPROFILE profile) const +uint8_t ICCStore::getInputIntents (cmsHPROFILE profile) { MyMutex::MyLock lock (mutex_); return getSupportedIntents (profile, LCMS_USED_AS_INPUT); } -uint8_t ICCStore::getOutputIntents (cmsHPROFILE profile) const +uint8_t ICCStore::getOutputIntents (cmsHPROFILE profile) { MyMutex::MyLock lock (mutex_); return getSupportedIntents (profile, LCMS_USED_AS_OUTPUT); } -uint8_t ICCStore::getProofIntents (cmsHPROFILE profile) const +uint8_t ICCStore::getProofIntents (cmsHPROFILE profile) { MyMutex::MyLock lock (mutex_); @@ -772,13 +846,16 @@ void ICCStore::init (const Glib::ustring& usrICCDir, const Glib::ustring& rtICCD MyMutex::MyLock lock (mutex_); + this->loadAll = loadAll; + // RawTherapee's profiles take precedence if a user's profile of the same name exists profilesDir = Glib::build_filename (rtICCDir, "output"); + userICCDir = usrICCDir; fileProfiles.clear(); fileProfileContents.clear(); if (loadAll) { loadProfiles (profilesDir, &fileProfiles, &fileProfileContents, nullptr, false); - loadProfiles (usrICCDir, &fileProfiles, &fileProfileContents, nullptr, false); + loadProfiles (userICCDir, &fileProfiles, &fileProfileContents, nullptr, false); } // Input profiles diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h index ae4026b28..5d8ccd5f0 100644 --- a/rtengine/iccstore.h +++ b/rtengine/iccstore.h @@ -65,6 +65,7 @@ class ICCStore // these contain profiles from user/system directory (supplied on init) Glib::ustring profilesDir; + Glib::ustring userICCDir; ProfileMap fileProfiles; ContentMap fileProfileContents; @@ -75,6 +76,8 @@ class ICCStore Glib::ustring defaultMonitorProfile; + bool loadAll; + const cmsHPROFILE xyz; const cmsHPROFILE srgb; @@ -102,8 +105,8 @@ public: // Main monitors standard profile name, from OS void findDefaultMonitorProfile (); - cmsHPROFILE getDefaultMonitorProfile () const; - Glib::ustring getDefaultMonitorProfileName () const; + cmsHPROFILE getDefaultMonitorProfile (); + Glib::ustring getDefaultMonitorProfileName (); cmsHPROFILE workingSpace (const Glib::ustring& name) const; cmsHPROFILE workingSpaceGamma (const Glib::ustring& name) const; @@ -111,8 +114,8 @@ public: TMatrix workingSpaceInverseMatrix (const Glib::ustring& name) const; bool outputProfileExist (const Glib::ustring& name) const; - cmsHPROFILE getProfile (const Glib::ustring& name) const; - cmsHPROFILE getStdProfile (const Glib::ustring& name) const; + cmsHPROFILE getProfile (const Glib::ustring& name); + cmsHPROFILE getStdProfile (const Glib::ustring& name); ProfileContent getContent (const Glib::ustring& name) const; cmsHPROFILE getXYZProfile () const; @@ -121,13 +124,13 @@ public: std::vector getProfiles (const ProfileType type = ProfileType::MONITOR) const; std::vector getProfilesFromDir (const Glib::ustring& dirName) const; - uint8_t getInputIntents (cmsHPROFILE profile) const; - uint8_t getOutputIntents (cmsHPROFILE profile) const; - uint8_t getProofIntents (cmsHPROFILE profile) const; + uint8_t getInputIntents (cmsHPROFILE profile); + uint8_t getOutputIntents (cmsHPROFILE profile); + uint8_t getProofIntents (cmsHPROFILE profile); - uint8_t getInputIntents (const Glib::ustring& name) const; - uint8_t getOutputIntents (const Glib::ustring& name) const; - uint8_t getProofIntents (const Glib::ustring& name) const; + uint8_t getInputIntents (const Glib::ustring& name); + uint8_t getOutputIntents (const Glib::ustring& name); + uint8_t getProofIntents (const Glib::ustring& name); }; #define iccStore ICCStore::getInstance() @@ -143,27 +146,27 @@ inline ProfileContent::~ProfileContent () delete [] data; } -inline cmsHPROFILE ICCStore::getDefaultMonitorProfile () const +inline cmsHPROFILE ICCStore::getDefaultMonitorProfile () { return getProfile (defaultMonitorProfile); } -inline Glib::ustring ICCStore::getDefaultMonitorProfileName () const +inline Glib::ustring ICCStore::getDefaultMonitorProfileName () { return defaultMonitorProfile; } -inline uint8_t ICCStore::getInputIntents (const Glib::ustring &name) const +inline uint8_t ICCStore::getInputIntents (const Glib::ustring &name) { return getInputIntents (getProfile (name)); } -inline uint8_t ICCStore::getOutputIntents (const Glib::ustring &name) const +inline uint8_t ICCStore::getOutputIntents (const Glib::ustring &name) { return getOutputIntents (getProfile (name)); } -inline uint8_t ICCStore::getProofIntents (const Glib::ustring &name) const +inline uint8_t ICCStore::getProofIntents (const Glib::ustring &name) { return getProofIntents (getProfile (name)); } diff --git a/rtengine/init.cc b/rtengine/init.cc index 66ff5baf6..d6bba9f2b 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -40,9 +40,9 @@ MyMutex* lcmsMutex = nullptr; int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir, bool loadAll) { settings = s; - iccStore->init (s->iccDirectory, baseDir + "/iccprofiles", loadAll); + iccStore->init (s->iccDirectory, Glib::build_filename (baseDir, "iccprofiles"), loadAll); iccStore->findDefaultMonitorProfile(); - DCPStore::getInstance()->init (baseDir + "/dcpprofiles"); + DCPStore::getInstance()->init (Glib::build_filename (baseDir, "dcpprofiles"), loadAll); CameraConstantsStore::getInstance ()->init (baseDir, userSettingsDir); ProcParams::init (); diff --git a/rtgui/options.cc b/rtgui/options.cc index 72ce93335..95bb59061 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -2315,7 +2315,7 @@ bool Options::load (bool lightweight) // out which are the parent translations. Furthermore, there must be a file for each locale () -- you cannot have // 'French (CA)' unless there is a file 'French'. - Glib::ustring defaultTranslation = argv0 + "/languages/default"; + Glib::ustring defaultTranslation = Glib::build_filename (argv0, "languages", "default"); Glib::ustring languageTranslation = ""; Glib::ustring localeTranslation = ""; @@ -2327,11 +2327,11 @@ bool Options::load (bool lightweight) std::vector langPortions = Glib::Regex::split_simple (" ", options.language); if (langPortions.size() >= 1) { - languageTranslation = argv0 + "/languages/" + langPortions.at (0); + languageTranslation = Glib::build_filename (argv0, "languages", langPortions.at (0)); } if (langPortions.size() >= 2) { - localeTranslation = argv0 + "/languages/" + options.language; + localeTranslation = Glib::build_filename (argv0, "languages", options.language); } }