/* -*- 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 . */ #include "../rtengine/dynamicprofile.h" #include #include using namespace rtengine; using namespace rtengine::procparams; namespace { const int ISO_MAX = 512000; 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 &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 &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 &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 &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 (options.rtSettings.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 (options.rtSettings.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"); } catch (Glib::KeyFileError &) { dynamicRules.pop_back(); } } std::sort (dynamicRules.begin(), dynamicRules.end()); rulesLoaded = true; return true; } bool DynamicProfileRules::storeRules() { if (options.rtSettings.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); } return kf.save_to_file (Glib::build_filename (Options::rtdir, "dynamicprofile.cfg")); } const std::vector &DynamicProfileRules::getRules() { if (!rulesLoaded) { loadRules(); } return dynamicRules; } void DynamicProfileRules::setRules (const std::vector &r) { dynamicRules = r; }