merged dev into locallab_dev
This commit is contained in:
@@ -50,6 +50,7 @@ set(RTENGINESOURCEFILES
|
||||
dfmanager.cc
|
||||
diagonalcurves.cc
|
||||
dirpyr_equalizer.cc
|
||||
dynamicprofile.cc
|
||||
expo_before_b.cc
|
||||
fast_demo.cc
|
||||
ffmanager.cc
|
||||
@@ -99,6 +100,7 @@ set(RTENGINESOURCEFILES
|
||||
previewimage.cc
|
||||
processingjob.cc
|
||||
procparams.cc
|
||||
profilestore.cc
|
||||
rawimage.cc
|
||||
rawimagesource.cc
|
||||
refreshmap.cc
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include "../rtgui/cachemanager.h"
|
||||
#include "../rtgui/cacheimagedata.h"
|
||||
#include "../rtgui/md5helper.h"
|
||||
|
||||
//#include <chrono>
|
||||
// "ceil" rounding
|
||||
@@ -838,11 +837,7 @@ void Crop::update (int todo)
|
||||
if (needslocal ) {
|
||||
// if (tyty ) {
|
||||
|
||||
CacheManager* cachemgr;
|
||||
|
||||
CacheImageData cfs;
|
||||
cfs.md5 = cachemgr->getMD5 (parent->imgsrc->getFileName());
|
||||
std::string mdfive = cfs.md5;
|
||||
std::string mdfive = getMD5 (parent->imgsrc->getFileName());
|
||||
|
||||
Glib::ustring pop = options.cacheBaseDir + "/mip/";
|
||||
|
||||
|
||||
261
rtengine/dynamicprofile.cc
Normal file
261
rtengine/dynamicprofile.cc
Normal file
@@ -0,0 +1,261 @@
|
||||
/* -*- 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../rtengine/dynamicprofile.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <glibmm/regex.h>
|
||||
|
||||
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::ImageMetaData *im) const
|
||||
{
|
||||
return (iso (im->getISOSpeed())
|
||||
&& fnumber (im->getFNumber())
|
||||
&& focallen (im->getFocalLen())
|
||||
&& shutterspeed (im->getShutterSpeed())
|
||||
&& expcomp (im->getExpComp())
|
||||
&& camera (im->getCamera())
|
||||
&& lens (im->getLens()));
|
||||
}
|
||||
|
||||
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 (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");
|
||||
|
||||
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);
|
||||
kf.set_string (group, "profilepath", rule.profilepath);
|
||||
}
|
||||
|
||||
return kf.save_to_file (Glib::build_filename (Options::rtdir, "dynamicprofile.cfg"));
|
||||
}
|
||||
|
||||
const std::vector<DynamicProfileRule> &DynamicProfileRules::getRules()
|
||||
{
|
||||
if (!rulesLoaded) {
|
||||
loadRules();
|
||||
}
|
||||
|
||||
return dynamicRules;
|
||||
}
|
||||
|
||||
void DynamicProfileRules::setRules (const std::vector<DynamicProfileRule> &r)
|
||||
{
|
||||
dynamicRules = r;
|
||||
}
|
||||
79
rtengine/dynamicprofile.h
Normal file
79
rtengine/dynamicprofile.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* -*- 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _DYNAMICPROFILE_H_
|
||||
#define _DYNAMICPROFILE_H_
|
||||
|
||||
#include <glibmm.h>
|
||||
#include <vector>
|
||||
#include "../rtgui/options.h"
|
||||
|
||||
class DynamicProfileRule
|
||||
{
|
||||
public:
|
||||
template <class T>
|
||||
struct Range {
|
||||
T min;
|
||||
T max;
|
||||
explicit Range (T l = T(), T u = T()): min (l), max (u) {}
|
||||
|
||||
bool operator() (T val) const
|
||||
{
|
||||
return val >= min && val <= max;
|
||||
}
|
||||
};
|
||||
|
||||
struct Optional {
|
||||
Glib::ustring value;
|
||||
bool enabled;
|
||||
explicit Optional (const Glib::ustring v = "", bool e = false):
|
||||
value (v), enabled (e) {}
|
||||
|
||||
bool operator() (const Glib::ustring &val) const;
|
||||
};
|
||||
|
||||
DynamicProfileRule();
|
||||
bool matches (const rtengine::ImageMetaData *im) const;
|
||||
bool operator< (const DynamicProfileRule &other) const;
|
||||
|
||||
int serial_number;
|
||||
Range<int> iso;
|
||||
Range<double> fnumber;
|
||||
Range<double> focallen;
|
||||
Range<double> shutterspeed;
|
||||
Range<double> expcomp;
|
||||
Optional camera;
|
||||
Optional lens;
|
||||
Glib::ustring profilepath;
|
||||
};
|
||||
|
||||
class DynamicProfileRules
|
||||
{
|
||||
protected:
|
||||
/** cache for dynamic profile rules */
|
||||
std::vector<DynamicProfileRule> dynamicRules;
|
||||
bool rulesLoaded;
|
||||
|
||||
public:
|
||||
bool loadRules();
|
||||
bool storeRules();
|
||||
const std::vector<DynamicProfileRule> &getRules();
|
||||
void setRules (const std::vector<DynamicProfileRule> &r);
|
||||
};
|
||||
|
||||
#endif // _DYNAMICPROFILE_H_
|
||||
@@ -26,8 +26,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "../rtgui/cachemanager.h"
|
||||
#include "../rtgui/cacheimagedata.h"
|
||||
#include "../rtgui/md5helper.h"
|
||||
|
||||
#include "iccstore.h"
|
||||
#ifdef _OPENMP
|
||||
@@ -736,11 +735,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
|
||||
*/
|
||||
|
||||
bool isascii = true;
|
||||
CacheManager* cachemgr;
|
||||
|
||||
CacheImageData cfs;
|
||||
cfs.md5 = cachemgr->getMD5 (imgsrc->getFileName());
|
||||
std::string mdfive = cfs.md5;
|
||||
std::string mdfive = getMD5 (imgsrc->getFileName());
|
||||
|
||||
|
||||
Glib::ustring datainterm = imgsrc->getFileName() + ".ii";//extansion ii arbitrary to test if mip file is possible
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "../rtgui/profilestorecombobox.h"
|
||||
#include "rtengine.h"
|
||||
#include "iccstore.h"
|
||||
#include "dcp.h"
|
||||
@@ -27,7 +28,7 @@
|
||||
#include "dfmanager.h"
|
||||
#include "ffmanager.h"
|
||||
#include "rtthumbnail.h"
|
||||
#include "../rtgui/profilestore.h"
|
||||
#include "profilestore.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
namespace rtengine
|
||||
@@ -40,6 +41,7 @@ MyMutex* lcmsMutex = nullptr;
|
||||
int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir, bool loadAll)
|
||||
{
|
||||
settings = s;
|
||||
ProfileStore::getInstance()->init (loadAll);
|
||||
ICCStore::getInstance()->init (s->iccDirectory, Glib::build_filename (baseDir, "iccprofiles"), loadAll);
|
||||
DCPStore::getInstance()->init (Glib::build_filename (baseDir, "dcpprofiles"), loadAll);
|
||||
|
||||
|
||||
535
rtengine/profilestore.cc
Normal file
535
rtengine/profilestore.cc
Normal file
@@ -0,0 +1,535 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "profilestore.h"
|
||||
|
||||
#include "dynamicprofile.h"
|
||||
#include "../rtgui/options.h"
|
||||
#include "../rtgui/multilangmgr.h"
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
ProfileStore::ProfileStore () : storeState (STORESTATE_NOTINITIALIZED), internalDefaultProfile (nullptr), internalDefaultEntry (nullptr), internalDynamicEntry (nullptr), loadAll (true)
|
||||
{
|
||||
internalDefaultProfile = new AutoPartialProfile();
|
||||
internalDefaultProfile->set (true);
|
||||
}
|
||||
|
||||
ProfileStore* ProfileStore::getInstance()
|
||||
{
|
||||
static ProfileStore instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
|
||||
bool ProfileStore::init (bool loadAll)
|
||||
{
|
||||
if (storeState == STORESTATE_DELETED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->loadAll = loadAll;
|
||||
|
||||
if (storeState == STORESTATE_NOTINITIALIZED && loadAll) {
|
||||
storeState = STORESTATE_BEINGINITIALIZED;
|
||||
_parseProfiles ();
|
||||
storeState = STORESTATE_INITIALIZED;
|
||||
}
|
||||
|
||||
return storeState == STORESTATE_INITIALIZED;
|
||||
}
|
||||
|
||||
ProfileStore::~ProfileStore ()
|
||||
{
|
||||
if (storeState == STORESTATE_NOTINITIALIZED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This lock prevent object's suppression while scanning the directories
|
||||
storeState = STORESTATE_DELETED;
|
||||
|
||||
{
|
||||
MyMutex::MyLock lock (parseMutex);
|
||||
|
||||
clearProfileList ();
|
||||
partProfiles.clear ();
|
||||
clearFileList();
|
||||
delete internalDefaultProfile;
|
||||
delete internalDefaultEntry;
|
||||
delete internalDynamicEntry;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Public method to parse the profiles' directories
|
||||
* Since there's a race condition in the multithreaded environment on this object,
|
||||
* parseProfiles may need to ask for initialization of this object, and then will
|
||||
* ask a mutex lock on it, has it been initialized by this call or not
|
||||
*
|
||||
* This method will scan the directory tree again and update the profile list. When finished,
|
||||
* the listeners will be called in order to update with the new list
|
||||
*/
|
||||
void ProfileStore::parseProfiles ()
|
||||
{
|
||||
|
||||
for (auto listener : listeners) {
|
||||
listener->storeCurrentValue();
|
||||
}
|
||||
|
||||
init (true); // safe even if already initialized
|
||||
|
||||
for (auto listener : listeners) {
|
||||
listener->updateProfileList();
|
||||
listener->restoreValue();
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileStore::_parseProfiles ()
|
||||
{
|
||||
// clear loaded profiles
|
||||
folders.clear();
|
||||
clearFileList();
|
||||
clearProfileList ();
|
||||
|
||||
folders.push_back ("<<< ROOT >>>"); // Fake path, so parentFolderId == 0 will be used to attach a ProfileStoreEntry to the root container, not sub-menu
|
||||
|
||||
Glib::ustring p1 = options.getUserProfilePath();
|
||||
Glib::ustring p2 = options.getGlobalProfilePath();
|
||||
bool displayLevel0 = options.useBundledProfiles && !p1.empty() && !p2.empty() && p1 != p2;
|
||||
|
||||
Glib::ustring virtualPath ("${U}");
|
||||
Glib::ustring currDir ("${U}");
|
||||
parseDir (p1, virtualPath, currDir, 0, 0, displayLevel0);
|
||||
|
||||
if (displayLevel0) {
|
||||
virtualPath = "${G}";
|
||||
currDir = "${G}";
|
||||
parseDir (p2, virtualPath, currDir, 0, 0, displayLevel0);
|
||||
}
|
||||
|
||||
// sort profiles
|
||||
std::sort (entries.begin(), entries.end(), SortProfiles() );
|
||||
|
||||
// entries and partProfiles are empty, but the entry and profiles already exist (they have survived to clearFileList and clearProfileList)
|
||||
if (!internalDefaultEntry) {
|
||||
internalDefaultEntry = new ProfileStoreEntry (Glib::ustring ("(") + M ("PROFILEPANEL_PINTERNAL") + Glib::ustring (")"), PSET_FILE, 0, 0);
|
||||
}
|
||||
|
||||
entries.push_back (internalDefaultEntry);
|
||||
partProfiles[internalDefaultEntry] = internalDefaultProfile;
|
||||
|
||||
if (!internalDynamicEntry) {
|
||||
internalDynamicEntry = new ProfileStoreEntry (Glib::ustring ("(") + M ("PROFILEPANEL_PDYNAMIC") + Glib::ustring (")"), PSET_FILE, 0, 0);
|
||||
// do not add it to the entries. This is here only for the preferences dialog
|
||||
}
|
||||
|
||||
// Check if the default profiles has been found.
|
||||
if (findEntryFromFullPathU (options.defProfRaw) == nullptr) {
|
||||
options.setDefProfRawMissing (true);
|
||||
|
||||
if (options.rtSettings.verbose) {
|
||||
printf ("WARNING: Default profile \"%s\" for raw images not found!\n", options.defProfRaw.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (findEntryFromFullPathU (options.defProfImg) == nullptr) {
|
||||
options.setDefProfImgMissing (true);
|
||||
|
||||
if (options.rtSettings.verbose) {
|
||||
printf ("WARNING: Default profile \"%s\" for standard images not found!\n", options.defProfImg.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @return Returns true if some files has been found (directories are ignored)
|
||||
bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath, Glib::ustring& currDir, unsigned int parentId, unsigned char level, bool displayLevel0)
|
||||
{
|
||||
bool fileFound = false;
|
||||
|
||||
// reload the available profiles from the profile dir
|
||||
if (!realPath.empty() && Glib::file_test (realPath, Glib::FILE_TEST_EXISTS) && Glib::file_test (realPath, Glib::FILE_TEST_IS_DIR)) {
|
||||
unsigned int folder = 0; // folder's own Id
|
||||
|
||||
// add this entry to the folder list
|
||||
folders.push_back (virtualPath);
|
||||
folder = (unsigned int) (folders.size()) - 1;
|
||||
|
||||
if (level > 0 || displayLevel0) {
|
||||
// replace the virtual folder name by a localized text
|
||||
if (currDir == "${U}") {
|
||||
currDir = M ("PROFILEPANEL_MYPROFILES");
|
||||
} else if (currDir == "${G}") {
|
||||
currDir = M ("PROFILEPANEL_GLOBALPROFILES");
|
||||
}
|
||||
|
||||
// add this localized text to the file list
|
||||
entries.push_back ( new ProfileStoreEntry (currDir, PSET_FOLDER, parentId, folder) );
|
||||
}
|
||||
|
||||
// walking through the directory
|
||||
Glib::Dir* dir = nullptr;
|
||||
dir = new Glib::Dir (realPath);
|
||||
|
||||
for (Glib::DirIterator i = dir->begin(); i != dir->end(); ++i) {
|
||||
currDir = *i;
|
||||
|
||||
if (currDir == "." || currDir == "..") {
|
||||
continue;
|
||||
}
|
||||
|
||||
Glib::ustring fname = Glib::build_filename (realPath, currDir);
|
||||
|
||||
if (Glib::file_test (fname, Glib::FILE_TEST_IS_DIR)) {
|
||||
Glib::ustring vp (Glib::build_filename (virtualPath, currDir));
|
||||
Glib::ustring rp (Glib::build_filename (realPath, currDir));
|
||||
fileFound = parseDir (rp, vp, currDir, folder, level + 1, 0);
|
||||
} else {
|
||||
size_t lastdot = currDir.find_last_of ('.');
|
||||
|
||||
if (lastdot != Glib::ustring::npos && lastdot == currDir.length() - 4 && currDir.substr (lastdot).casefold() == paramFileExtension) {
|
||||
// file found
|
||||
if ( options.rtSettings.verbose ) {
|
||||
printf ("Processing file %s...", fname.c_str());
|
||||
}
|
||||
|
||||
Glib::ustring name = currDir.substr (0, lastdot);
|
||||
|
||||
// create the partial profile
|
||||
AutoPartialProfile *pProf = new AutoPartialProfile();
|
||||
int res = pProf->load (fname);
|
||||
|
||||
if (!res && pProf->pparams->ppVersion >= 220) {
|
||||
fileFound = true;
|
||||
|
||||
if ( options.rtSettings.verbose ) {
|
||||
printf ("OK\n");
|
||||
}
|
||||
|
||||
// adding this file to the list
|
||||
ProfileStoreEntry* filePSE = new ProfileStoreEntry (name, PSET_FILE, folder, 0);
|
||||
entries.push_back (filePSE);
|
||||
|
||||
// map the partial profile
|
||||
partProfiles[filePSE] = pProf;
|
||||
//partProfiles.insert( std::pair<ProfileStoreEntry*, rtengine::procparams::AutoPartialProfile*> (filePSE, pProf) );
|
||||
} else if ( options.rtSettings.verbose ) {
|
||||
printf ("failed!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete dir;
|
||||
}
|
||||
|
||||
if (!fileFound && (level > 0 || displayLevel0)) {
|
||||
// no files found in this level, we delete the subdirectory entry
|
||||
folders.pop_back();
|
||||
entries.pop_back();
|
||||
}
|
||||
|
||||
return fileFound;
|
||||
}
|
||||
|
||||
int ProfileStore::findFolderId (const Glib::ustring &path)
|
||||
{
|
||||
// initialization must have been done when calling this
|
||||
for (std::vector<Glib::ustring>::iterator i = folders.begin(); i != folders.end(); ++i) {
|
||||
if (*i == path) {
|
||||
return i - folders.begin();
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** @brief Return the ProfileStoreEntry object that match the given file and path
|
||||
*
|
||||
* @param fullPath Path of the file; the filename may end by the standard extension,
|
||||
* but have to begin with a virtual location ( ${G} or ${U} )
|
||||
* Will return null on invalid path or if the entry can't be found
|
||||
*/
|
||||
const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU (Glib::ustring path)
|
||||
{
|
||||
if (path.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (storeState == STORESTATE_NOTINITIALIZED) {
|
||||
parseProfiles();
|
||||
}
|
||||
|
||||
if (path == DEFPROFILE_INTERNAL || path == DEFPROFILE_DYNAMIC) {
|
||||
return internalDefaultEntry;
|
||||
}
|
||||
|
||||
// consistently apply casefold() to make sure dot position is correct
|
||||
const Glib::ustring casefolded_path = path.casefold();
|
||||
const Glib::ustring::size_type lastdot_pos = casefolded_path.find_last_of ('.');
|
||||
|
||||
if (
|
||||
lastdot_pos != Glib::ustring::npos
|
||||
&& lastdot_pos <= casefolded_path.size() - 4
|
||||
&& !casefolded_path.compare (lastdot_pos, 4, paramFileExtension)
|
||||
) {
|
||||
// removing the extension
|
||||
// now use dot position without casefold()
|
||||
path = path.substr (0, path.find_last_of ('.'));
|
||||
}
|
||||
|
||||
// dir separator may come from options file and may be \ or /, we convert them to G_DIR_SEPARATOR_S
|
||||
if (path.size() > 4 && (path[4] == '/' || path[4] == '\\')) {
|
||||
path = path.substr (0, 4) + G_DIR_SEPARATOR_S + path.substr (5);
|
||||
}
|
||||
|
||||
// removing the filename
|
||||
Glib::ustring fName = Glib::path_get_basename (path);
|
||||
|
||||
if (!fName.empty()) {
|
||||
path = path.substr (0, path.length() - fName.length());
|
||||
} else {
|
||||
// path is malformed, returning NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
path = Glib::path_get_dirname (path);
|
||||
|
||||
// 1. find the path in the folder list
|
||||
int parentFolderId = findFolderId (path);
|
||||
|
||||
if (parentFolderId == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 2. find the entry that match the given filename and parentFolderId
|
||||
if (parentFolderId >= 0) {
|
||||
for (auto entry : entries) {
|
||||
if (entry->parentFolderId == parentFolderId && entry->label == fName) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/** Protected version of findEntryFromFullPathU */
|
||||
const ProfileStoreEntry* ProfileStore::findEntryFromFullPath (Glib::ustring path)
|
||||
{
|
||||
MyMutex::MyLock lock (parseMutex);
|
||||
return findEntryFromFullPathU (path);
|
||||
}
|
||||
|
||||
const PartialProfile* ProfileStore::getProfile (Glib::ustring path)
|
||||
{
|
||||
|
||||
if (storeState == STORESTATE_NOTINITIALIZED) {
|
||||
parseProfiles();
|
||||
}
|
||||
|
||||
const ProfileStoreEntry *pse = findEntryFromFullPath (path);
|
||||
|
||||
if (!pse) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return getProfile (pse);
|
||||
}
|
||||
|
||||
const PartialProfile* ProfileStore::getProfile (const ProfileStoreEntry* entry)
|
||||
{
|
||||
|
||||
if (storeState == STORESTATE_NOTINITIALIZED) {
|
||||
parseProfiles();
|
||||
}
|
||||
|
||||
MyMutex::MyLock lock (parseMutex);
|
||||
|
||||
if (entry == internalDefaultEntry) {
|
||||
return internalDefaultProfile;
|
||||
}
|
||||
|
||||
std::map<const ProfileStoreEntry*, rtengine::procparams::AutoPartialProfile*>::iterator iter = partProfiles.find (entry);
|
||||
|
||||
if (iter != partProfiles.end()) {
|
||||
return iter->second;
|
||||
} else {
|
||||
// This shouldn't happen!
|
||||
#ifndef NDEBUG
|
||||
printf ("WARNING! Profile not found!\n");
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Get a pointer to the profile's vector list
|
||||
*
|
||||
* This method grants you unique access to the vector list through Mutex locking.
|
||||
* When you're done with the file list, you MUST call the releaseFileList method to release the lock.
|
||||
*/
|
||||
const std::vector<const ProfileStoreEntry*>* ProfileStore::getFileList ()
|
||||
{
|
||||
|
||||
if (storeState == STORESTATE_NOTINITIALIZED) {
|
||||
parseProfiles();
|
||||
}
|
||||
|
||||
parseMutex.lock();
|
||||
|
||||
return &entries;
|
||||
}
|
||||
|
||||
void ProfileStore::releaseFileList()
|
||||
{
|
||||
parseMutex.unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Send back a pointer to the default procparams for raw or standard images.
|
||||
* If the profile doesn't already exist in the profile list,
|
||||
* it will add it with default internal values, so this method never fails
|
||||
*/
|
||||
const ProcParams* ProfileStore::getDefaultProcParams (bool isRaw)
|
||||
{
|
||||
|
||||
//Note: the mutex is locked in getProfile, called below
|
||||
// eventual initialization is done there too
|
||||
|
||||
const PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg);
|
||||
|
||||
if (!pProf) {
|
||||
pProf = internalDefaultProfile;
|
||||
}
|
||||
|
||||
return pProf->pparams;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send back a pointer to the default partial profile for raw or standard images.
|
||||
* If it doesn't already exist in the profile list, it will add it with default internal values,
|
||||
* so this method will never fails
|
||||
*/
|
||||
const PartialProfile* ProfileStore::getDefaultPartialProfile (bool isRaw)
|
||||
{
|
||||
|
||||
//Note: the mutex is locked in getProfile, called below
|
||||
// eventual initialization is done there too
|
||||
|
||||
const PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg);
|
||||
|
||||
if (!pProf) {
|
||||
pProf = internalDefaultProfile;
|
||||
}
|
||||
|
||||
return pProf;
|
||||
}
|
||||
|
||||
const Glib::ustring ProfileStore::getPathFromId (int folderId)
|
||||
{
|
||||
// initialization must have been done when calling this
|
||||
return folders.at (folderId);
|
||||
}
|
||||
|
||||
|
||||
void ProfileStore::clearFileList()
|
||||
{
|
||||
for (auto entry : entries) {
|
||||
if (entry != internalDefaultEntry) {
|
||||
delete entry;
|
||||
}
|
||||
}
|
||||
|
||||
entries.clear();
|
||||
}
|
||||
|
||||
void ProfileStore::clearProfileList()
|
||||
{
|
||||
for (auto partProfile : partProfiles) {
|
||||
if (partProfile.second != internalDefaultProfile) {
|
||||
delete partProfile.second;
|
||||
}
|
||||
}
|
||||
|
||||
partProfiles.clear();
|
||||
}
|
||||
|
||||
void ProfileStore::addListener (ProfileStoreListener *listener)
|
||||
{
|
||||
listeners.push_back (listener);
|
||||
}
|
||||
|
||||
void ProfileStore::removeListener (ProfileStoreListener *listener)
|
||||
{
|
||||
listeners.remove (listener);
|
||||
}
|
||||
|
||||
void ProfileStore::dumpFolderList()
|
||||
{
|
||||
printf ("Folder list:\n------------\n");
|
||||
|
||||
for (unsigned int i = 0; i < folders.size(); i++) {
|
||||
printf (" #%3ud - %s\n", i, folders.at (i).c_str());
|
||||
}
|
||||
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
PartialProfile *ProfileStore::loadDynamicProfile (const ImageMetaData *im)
|
||||
{
|
||||
if (storeState == STORESTATE_NOTINITIALIZED) {
|
||||
parseProfiles();
|
||||
}
|
||||
|
||||
PartialProfile *ret = new PartialProfile (true, true);
|
||||
|
||||
if (!rulesLoaded) {
|
||||
loadRules();
|
||||
}
|
||||
|
||||
for (auto rule : dynamicRules) {
|
||||
if (rule.matches (im)) {
|
||||
if (options.rtSettings.verbose) {
|
||||
printf ("found matching profile %s\n", rule.profilepath.c_str());
|
||||
}
|
||||
|
||||
const PartialProfile *p = getProfile (rule.profilepath);
|
||||
|
||||
if (p != nullptr) {
|
||||
p->applyTo (ret->pparams);
|
||||
} else {
|
||||
printf ("ERROR loading matching profile from: %s\n", rule.profilepath.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ProfileStoreEntry::ProfileStoreEntry() : label (""), type (PSET_FOLDER), parentFolderId (0), folderId (0) {}
|
||||
|
||||
ProfileStoreEntry::ProfileStoreEntry (Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder) : label (label), type (type), parentFolderId (parentFolder), folderId (folder) {}
|
||||
|
||||
void ProfileStoreEntry::setValues (Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder)
|
||||
{
|
||||
this->label = label;
|
||||
this->type = type;
|
||||
parentFolderId = parentFolder;
|
||||
folderId = folder;
|
||||
}
|
||||
|
||||
197
rtengine/profilestore.h
Normal file
197
rtengine/profilestore.h
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _PROFILESTORE_
|
||||
#define _PROFILESTORE_
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <glibmm.h>
|
||||
|
||||
#include "rtengine.h"
|
||||
#include "noncopyable.h"
|
||||
#include "dynamicprofile.h"
|
||||
|
||||
|
||||
// forward decl
|
||||
class DynamicProfileRule;
|
||||
class DynamicProfileRules;
|
||||
|
||||
/** @brief This will implement callback functions for the ProfileStore
|
||||
*
|
||||
*/
|
||||
class ProfileStoreListener
|
||||
{
|
||||
|
||||
public:
|
||||
virtual ~ProfileStoreListener() {}
|
||||
|
||||
/** @brief Called whenever the current value has to be stored before update. */
|
||||
virtual void storeCurrentValue() {}
|
||||
/** @brief Called whenever the file list has been updated and the content of the listener has to be updated. */
|
||||
virtual void updateProfileList() = 0;
|
||||
/** @brief Called whenever the profile list has changed and the old value have to be restored (if possible). */
|
||||
virtual void restoreValue() {}
|
||||
};
|
||||
|
||||
/// @brief ProfileStoreEntry type (folder or file)
|
||||
typedef enum PSE_TYPE {
|
||||
PSET_FOLDER,
|
||||
PSET_FILE
|
||||
} PSEType;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Entry of the profiles store, consisting of a type (folder/file) & label.
|
||||
*
|
||||
* Will be used as key element in the name / PartialProfile mapping
|
||||
*/
|
||||
class ProfileStoreEntry
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
Glib::ustring label; /// Label to be used in menu or combobox = profile's filename
|
||||
PSEType type; /// either PSET_FOLDER or PSET_FILE
|
||||
unsigned short parentFolderId; /// index of the element's path in the folder list; id == 0 is reserved
|
||||
unsigned short folderId; /// index of the folder's own path in the folder list; will be null for file entries
|
||||
|
||||
/** @brief Create a new ProfileStoreLabel with null values, that will have to be set later with setValues or the copy operator
|
||||
*/
|
||||
ProfileStoreEntry();
|
||||
|
||||
/** @brief Create a new ProfileStoreLabel with values
|
||||
* @param label Label to be used in menu or combobox; also used as profile's filename
|
||||
* @param type either PSET_FOLDER or PSET_FILE
|
||||
* @param parentFolder index of the elements's path in the folder list
|
||||
* @param folder index of the folder's own path in the folder list
|
||||
*/
|
||||
ProfileStoreEntry (Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder);
|
||||
|
||||
/** @brief Set the values of the object after its instantiation
|
||||
* @param label Label to be used in menu or combobox; also used as profile's filename
|
||||
* @param type either PSET_FOLDER or PSET_FILE
|
||||
* @param parentFolder index of the elements's path in the folder list
|
||||
* @param folder index of the folder's own path in the folder list
|
||||
*/
|
||||
void setValues (Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder);
|
||||
};
|
||||
|
||||
|
||||
/** @brief Store the profiles bundled with RawTharapee and created by the user.
|
||||
*
|
||||
* This store can be queried by the GUI to display a Tree of the profiles available
|
||||
* in the user's and system's profile directory and subdirectories.
|
||||
*/
|
||||
class ProfileStore : public rtengine::NonCopyable, public DynamicProfileRules
|
||||
{
|
||||
|
||||
typedef enum {
|
||||
STORESTATE_NOTINITIALIZED,
|
||||
STORESTATE_LIGHTWEIGHT,
|
||||
STORESTATE_BEINGINITIALIZED,
|
||||
STORESTATE_INITIALIZED,
|
||||
STORESTATE_DELETED
|
||||
} StoreState;
|
||||
|
||||
private:
|
||||
struct SortProfiles {
|
||||
bool operator () (const ProfileStoreEntry* const a1, const ProfileStoreEntry* const a2)
|
||||
{
|
||||
return a1->parentFolderId == a2->parentFolderId ? a1->label < a2->label : a1->parentFolderId < a2->parentFolderId;
|
||||
}
|
||||
};
|
||||
|
||||
MyMutex parseMutex;
|
||||
StoreState storeState;
|
||||
rtengine::procparams::AutoPartialProfile *internalDefaultProfile;
|
||||
ProfileStoreEntry *internalDefaultEntry;
|
||||
ProfileStoreEntry *internalDynamicEntry;
|
||||
|
||||
/** Alphabetically ordered list of folder and files through Gtk::Label sub-class;
|
||||
* ready to be used in Menu and Combobox
|
||||
* The first element (#0) will be a fake path so ProfileStoreEntry can be attached to the root container */
|
||||
std::vector<Glib::ustring> folders;
|
||||
|
||||
/** Alphabetically ordered list of folder and files through Gtk::Label derived class;
|
||||
* ready to be used in Menu and Combobox */
|
||||
std::vector<const ProfileStoreEntry*> entries;
|
||||
|
||||
/** List of PartialProfiles from the indexed files */
|
||||
std::map<const ProfileStoreEntry*, rtengine::procparams::AutoPartialProfile*> partProfiles;
|
||||
|
||||
/** List of the client of this store */
|
||||
std::list<ProfileStoreListener*> listeners;
|
||||
|
||||
/** whereas we have to load all profile at init time or one by one upon request */
|
||||
bool loadAll;
|
||||
|
||||
/** @brief Method to recursively parse a profile folder with a level depth arbitrarily limited to 3
|
||||
*
|
||||
* @param realPath current full path of the scanned directory ; e.g.: ~/MyProfiles/
|
||||
* @param virtualPath current full path that will be saved in "options" ; must start with either ${U} or ${G},
|
||||
* standing for User's and Global's (RT) profile folder, respectively
|
||||
* @param currDir name of the directory to scan; it's the last element of the virtualPath
|
||||
* @param parentId path entry of the parent folder
|
||||
* @param level current level of the directory tree
|
||||
* @param displayLevel0 if true, level 0 is created in order to have a User's and Bundled profiles separation (i.e. 2 root directories are expected)
|
||||
* if false, only one root directory is expected
|
||||
*/
|
||||
bool parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath, Glib::ustring& currDir, unsigned int parentId, unsigned char level, bool displayLevel0);
|
||||
void _parseProfiles ();
|
||||
void clearFileList ();
|
||||
void clearProfileList ();
|
||||
const ProfileStoreEntry* findEntryFromFullPathU (Glib::ustring path);
|
||||
|
||||
public:
|
||||
|
||||
ProfileStore();
|
||||
~ProfileStore();
|
||||
|
||||
static ProfileStore* getInstance();
|
||||
|
||||
bool init (bool loadAll = true);
|
||||
void parseProfiles ();
|
||||
int findFolderId (const Glib::ustring &path);
|
||||
const ProfileStoreEntry* findEntryFromFullPath (Glib::ustring path);
|
||||
const rtengine::procparams::PartialProfile* getProfile (Glib::ustring path);
|
||||
const rtengine::procparams::PartialProfile* getProfile (const ProfileStoreEntry* entry);
|
||||
const std::vector<const ProfileStoreEntry*>* getFileList ();
|
||||
void releaseFileList ();
|
||||
const rtengine::procparams::ProcParams* getDefaultProcParams (bool isRaw);
|
||||
const rtengine::procparams::PartialProfile* getDefaultPartialProfile (bool isRaw);
|
||||
const Glib::ustring getPathFromId (int folderId);
|
||||
const ProfileStoreEntry* getInternalDefaultPSE()
|
||||
{
|
||||
return internalDefaultEntry;
|
||||
}
|
||||
|
||||
const ProfileStoreEntry* getInternalDynamicPSE()
|
||||
{
|
||||
return internalDynamicEntry;
|
||||
}
|
||||
|
||||
void addListener (ProfileStoreListener *listener);
|
||||
void removeListener (ProfileStoreListener *listener);
|
||||
|
||||
rtengine::procparams::PartialProfile* loadDynamicProfile (const rtengine::ImageMetaData *im);
|
||||
|
||||
void dumpFolderList();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -32,8 +32,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "../rtgui/cachemanager.h"
|
||||
#include "../rtgui/cacheimagedata.h"
|
||||
#include "../rtgui/md5helper.h"
|
||||
|
||||
|
||||
#undef THREAD_PRIORITY_NORMAL
|
||||
@@ -1025,11 +1024,8 @@ private:
|
||||
if (params.locallab.enabled) {
|
||||
MyTime t1, t2;
|
||||
t1.set();
|
||||
CacheManager* cachemgr;
|
||||
|
||||
CacheImageData cfs;
|
||||
cfs.md5 = cachemgr->getMD5 (imgsrc->getFileName());
|
||||
std::string mdfive = cfs.md5;
|
||||
std::string mdfive = getMD5 (imgsrc->getFileName());
|
||||
|
||||
Glib::ustring pop = options.cacheBaseDir + "/mip/";
|
||||
|
||||
@@ -2137,11 +2133,12 @@ private:
|
||||
|
||||
params.wavelet.strength *= scale_factor;
|
||||
params.dirpyrDenoise.luma *= scale_factor;
|
||||
params.dirpyrDenoise.Ldetail += (100 - params.dirpyrDenoise.Ldetail) * scale_factor;
|
||||
//params.dirpyrDenoise.smethod = "shal";
|
||||
for (auto &p : params.dirpyrDenoise.lcurve) {
|
||||
p *= scale_factor;
|
||||
//params.dirpyrDenoise.Ldetail += (100 - params.dirpyrDenoise.Ldetail) * scale_factor;
|
||||
auto &lcurve = params.dirpyrDenoise.lcurve;
|
||||
for (size_t i = 2; i < lcurve.size(); i += 4) {
|
||||
lcurve[i] *= min(scale_factor * 2, 1.0);
|
||||
}
|
||||
noiseLCurve.Set(lcurve);
|
||||
const char *medmethods[] = { "soft", "33", "55soft", "55", "77", "99" };
|
||||
if (params.dirpyrDenoise.median) {
|
||||
auto &key = params.dirpyrDenoise.methodmed == "RGB" ? params.dirpyrDenoise.rgbmethod : params.dirpyrDenoise.medmethod;
|
||||
|
||||
Reference in New Issue
Block a user