commit e293f0890866ddf934ba1a9dd9fa372364766bb3 Author: Bezierr <harald.aust@web.de> Date: Tue Aug 23 16:16:23 2022 +0200 Added comment commit 20a50b248dc110eeb4b526c7242920a68216c88c Author: Bezierr <harald.aust@web.de> 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 <harald.aust@web.de> 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 <harald.aust@web.de> 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 <harald.aust@web.de> 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.
294 lines
8.3 KiB
C++
294 lines
8.3 KiB
C++
/* -*- C++ -*-
|
|
* This file is part of RawTherapee.
|
|
*
|
|
* Copyright (c) 2017 Alberto Griggio
|
|
*
|
|
* RawTherapee is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* RawTherapee is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "dynamicprofile.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <glibmm/regex.h>
|
|
#include <glibmm/fileutils.h>
|
|
#include <glibmm/miscutils.h>
|
|
#include <glibmm/keyfile.h>
|
|
|
|
#include "rtengine.h"
|
|
#include "../rtgui/options.h"
|
|
|
|
using namespace rtengine;
|
|
using namespace rtengine::procparams;
|
|
|
|
namespace
|
|
{
|
|
|
|
const int ISO_MAX = 819200;
|
|
const double FNUMBER_MAX = 100.0;
|
|
const double FOCALLEN_MAX = 10000.0;
|
|
const double SHUTTERSPEED_MAX = 1000.0;
|
|
const double EXPCOMP_MIN = -20.0;
|
|
const double EXPCOMP_MAX = 20.0;
|
|
|
|
} // namespace
|
|
|
|
DynamicProfileRules dynamicProfileRules;
|
|
|
|
bool DynamicProfileRule::Optional::operator() (const Glib::ustring &val) const
|
|
{
|
|
if (!enabled) {
|
|
return true;
|
|
}
|
|
|
|
if (value.find ("re:") == 0) {
|
|
// this is a regexp
|
|
return Glib::Regex::match_simple (value.substr (3), val, Glib::REGEX_CASELESS);
|
|
} else {
|
|
// normal string comparison
|
|
return value.casefold() == val.casefold();
|
|
}
|
|
}
|
|
|
|
|
|
DynamicProfileRule::DynamicProfileRule():
|
|
serial_number (0),
|
|
iso (0, ISO_MAX),
|
|
fnumber (0, FNUMBER_MAX),
|
|
focallen (0, FOCALLEN_MAX),
|
|
shutterspeed (0, SHUTTERSPEED_MAX),
|
|
expcomp (EXPCOMP_MIN, EXPCOMP_MAX)
|
|
{
|
|
}
|
|
|
|
|
|
bool DynamicProfileRule::operator< (const DynamicProfileRule &other) const
|
|
{
|
|
return serial_number < other.serial_number;
|
|
}
|
|
|
|
|
|
bool DynamicProfileRule::matches (const rtengine::FramesMetaData *im) const
|
|
{
|
|
return (iso (im->getISOSpeed())
|
|
&& fnumber (im->getFNumber())
|
|
&& focallen (im->getFocalLen())
|
|
&& shutterspeed (im->getShutterSpeed())
|
|
&& expcomp (im->getExpComp())
|
|
&& camera (im->getCamera())
|
|
&& lens (im->getLens())
|
|
&& imagetype(im->getImageType(0)));
|
|
}
|
|
|
|
namespace
|
|
{
|
|
|
|
void get_int_range (DynamicProfileRule::Range<int> &dest,
|
|
const Glib::KeyFile &kf, const Glib::ustring &group,
|
|
const Glib::ustring &key)
|
|
{
|
|
try {
|
|
int min = kf.get_integer (group, key + "_min");
|
|
int max = kf.get_integer (group, key + "_max");
|
|
|
|
if (min <= max) {
|
|
dest.min = min;
|
|
dest.max = max;
|
|
}
|
|
} catch (Glib::KeyFileError &e) {
|
|
}
|
|
}
|
|
|
|
|
|
void get_double_range (DynamicProfileRule::Range<double> &dest,
|
|
const Glib::KeyFile &kf, const Glib::ustring &group,
|
|
const Glib::ustring &key)
|
|
{
|
|
try {
|
|
double min = kf.get_double (group, key + "_min");
|
|
double max = kf.get_double (group, key + "_max");
|
|
|
|
if (min <= max) {
|
|
dest.min = min;
|
|
dest.max = max;
|
|
}
|
|
} catch (Glib::KeyFileError &e) {
|
|
}
|
|
}
|
|
|
|
|
|
void get_optional (DynamicProfileRule::Optional &dest,
|
|
const Glib::KeyFile &kf, const Glib::ustring &group,
|
|
const Glib::ustring &key)
|
|
{
|
|
try {
|
|
bool e = kf.get_boolean (group, key + "_enabled");
|
|
|
|
if (e) {
|
|
Glib::ustring s = kf.get_string (group, key + "_value");
|
|
dest.enabled = e;
|
|
dest.value = s;
|
|
}
|
|
} catch (Glib::KeyFileError &) {
|
|
}
|
|
}
|
|
|
|
void set_int_range (Glib::KeyFile &kf, const Glib::ustring &group,
|
|
const Glib::ustring &key,
|
|
const DynamicProfileRule::Range<int> &val)
|
|
{
|
|
kf.set_integer (group, key + "_min", val.min);
|
|
kf.set_integer (group, key + "_max", val.max);
|
|
}
|
|
|
|
void set_double_range (Glib::KeyFile &kf, const Glib::ustring &group,
|
|
const Glib::ustring &key,
|
|
const DynamicProfileRule::Range<double> &val)
|
|
{
|
|
kf.set_double (group, key + "_min", val.min);
|
|
kf.set_double (group, key + "_max", val.max);
|
|
}
|
|
|
|
void set_optional (Glib::KeyFile &kf, const Glib::ustring &group,
|
|
const Glib::ustring &key,
|
|
const DynamicProfileRule::Optional &val)
|
|
{
|
|
kf.set_boolean (group, key + "_enabled", val.enabled);
|
|
kf.set_string (group, key + "_value", val.value);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool DynamicProfileRules::loadRules()
|
|
{
|
|
dynamicRules.clear();
|
|
Glib::KeyFile kf;
|
|
|
|
try {
|
|
if (!kf.load_from_file (Glib::build_filename (Options::rtdir, "dynamicprofile.cfg"))) {
|
|
return false;
|
|
}
|
|
} catch (Glib::Error &e) {
|
|
return false;
|
|
}
|
|
|
|
if (settings->verbose) {
|
|
printf ("loading dynamic profiles...\n");
|
|
}
|
|
|
|
auto groups = kf.get_groups();
|
|
|
|
for (auto group : groups) {
|
|
// groups are of the form "rule N", where N is a positive integer
|
|
if (group.find ("rule ") != 0) {
|
|
return false;
|
|
}
|
|
|
|
std::istringstream buf (group.c_str() + 5);
|
|
int serial = 0;
|
|
|
|
if (! (buf >> serial) || !buf.eof()) {
|
|
return false;
|
|
}
|
|
|
|
if (settings->verbose) {
|
|
printf (" loading rule %d\n", serial);
|
|
}
|
|
|
|
dynamicRules.emplace_back (DynamicProfileRule());
|
|
DynamicProfileRule &rule = dynamicRules.back();
|
|
rule.serial_number = serial;
|
|
get_int_range (rule.iso, kf, group, "iso");
|
|
get_double_range (rule.fnumber, kf, group, "fnumber");
|
|
get_double_range (rule.focallen, kf, group, "focallen");
|
|
get_double_range (rule.shutterspeed, kf, group, "shutterspeed");
|
|
get_double_range (rule.expcomp, kf, group, "expcomp");
|
|
get_optional (rule.camera, kf, group, "camera");
|
|
get_optional (rule.lens, kf, group, "lens");
|
|
get_optional (rule.imagetype, kf, group, "imagetype");
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
std::sort (dynamicRules.begin(), dynamicRules.end());
|
|
rulesLoaded = true;
|
|
return true;
|
|
}
|
|
|
|
bool DynamicProfileRules::storeRules()
|
|
{
|
|
if (settings->verbose) {
|
|
printf ("saving dynamic profiles...\n");
|
|
}
|
|
|
|
Glib::KeyFile kf;
|
|
|
|
for (auto &rule : dynamicRules) {
|
|
std::ostringstream buf;
|
|
buf << "rule " << rule.serial_number;
|
|
Glib::ustring group = buf.str();
|
|
set_int_range (kf, group, "iso", rule.iso);
|
|
set_double_range (kf, group, "fnumber", rule.fnumber);
|
|
set_double_range (kf, group, "focallen", rule.focallen);
|
|
set_double_range (kf, group, "shutterspeed", rule.shutterspeed);
|
|
set_double_range (kf, group, "expcomp", rule.expcomp);
|
|
set_optional (kf, group, "camera", rule.camera);
|
|
set_optional (kf, group, "lens", rule.lens);
|
|
set_optional (kf, group, "imagetype", rule.imagetype);
|
|
kf.set_string (group, "profilepath", rule.profilepath);
|
|
}
|
|
|
|
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<DynamicProfileRule> &DynamicProfileRules::getRules()
|
|
{
|
|
if (!rulesLoaded) {
|
|
loadRules();
|
|
}
|
|
|
|
return dynamicRules;
|
|
}
|
|
|
|
void DynamicProfileRules::setRules (const std::vector<DynamicProfileRule> &r)
|
|
{
|
|
dynamicRules = r;
|
|
}
|