Issue 2047: "One-way communication file between RT and the Custom Profile Builder"

This commit is contained in:
Hombre
2013-11-17 18:14:14 +01:00
parent f56d567d93
commit 143aa6408c
13 changed files with 248 additions and 56 deletions

View File

@@ -750,6 +750,9 @@ PREFERENCES_CLIPPINGIND;Clipping Indication
PREFERENCES_CMETRICINTENT;Colorimetric intent PREFERENCES_CMETRICINTENT;Colorimetric intent
PREFERENCES_CUSTPROFBUILDHINT;Executable (or script) file called when a new initial processing profile should be generated for an image.\nReceives command line parameters to allow a rules-based processing profile generation:\n[raw/JPG path] [default processing profile path] [RT's cache folder path] [f-number] [exposure in secs] [focal length in mm] [ISO] [lens] [camera make] [camera model]\n\n<b>WARNING:</b> You are responsible of using double quotes where necessary if you're using paths containing spaces. PREFERENCES_CUSTPROFBUILDHINT;Executable (or script) file called when a new initial processing profile should be generated for an image.\nReceives command line parameters to allow a rules-based processing profile generation:\n[raw/JPG path] [default processing profile path] [RT's cache folder path] [f-number] [exposure in secs] [focal length in mm] [ISO] [lens] [camera make] [camera model]\n\n<b>WARNING:</b> You are responsible of using double quotes where necessary if you're using paths containing spaces.
PREFERENCES_CUSTPROFBUILDPATH;Executable path PREFERENCES_CUSTPROFBUILDPATH;Executable path
PREFERENCES_CUSTPROFBUILDKEYFORMAT;Keys format
PREFERENCES_CUSTPROFBUILDKEYFORMAT_TID;TagID
PREFERENCES_CUSTPROFBUILDKEYFORMAT_NAME;Name
PREFERENCES_CUSTPROFBUILD;Custom Processing Profile Builder PREFERENCES_CUSTPROFBUILD;Custom Processing Profile Builder
PREFERENCES_CUTOVERLAYBRUSH;Crop mask color/transparency PREFERENCES_CUTOVERLAYBRUSH;Crop mask color/transparency
PREFERENCES_D50;5000K PREFERENCES_D50;5000K

View File

@@ -215,6 +215,23 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
#define FISBLUE(filter,row,col) \ #define FISBLUE(filter,row,col) \
((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==2 || !filter) ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==2 || !filter)
RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname)
{
RawMetaDataLocation rml;
rml.exifBase = -1;
rml.ciffBase = -1;
rml.ciffLength = -1;
RawImage ri(fname);
int r = ri.loadRaw(false);
if( !r ){
rml.exifBase = ri.get_exifBase();
rml.ciffBase = ri.get_ciffBase();
rml.ciffLength = ri.get_ciffLen();
}
return rml;
}
Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate) Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate)
{ {
RawImage *ri= new RawImage (fname); RawImage *ri= new RawImage (fname);

View File

@@ -83,6 +83,7 @@ namespace rtengine {
static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate); static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate);
static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate); static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate);
static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq); static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq);
static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname);
void getCamWB (double& temp, double& green); void getCamWB (double& temp, double& green);
void getAutoWB (double& temp, double& green, double equal); void getAutoWB (double& temp, double& green, double equal);

View File

@@ -16,6 +16,8 @@ ELSE (WIN32)
${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS}) ${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS})
ENDIF (WIN32) ENDIF (WIN32)
include_directories (BEFORE "${CMAKE_CURRENT_BINARY_DIR}")
IF (BUILD_SHARED_LIBS) IF (BUILD_SHARED_LIBS)
INSTALL(TARGETS rtexif DESTINATION ${LIBDIR}) INSTALL(TARGETS rtexif DESTINATION ${LIBDIR})
ENDIF (BUILD_SHARED_LIBS) ENDIF (BUILD_SHARED_LIBS)

View File

@@ -25,7 +25,11 @@
#include <sstream> #include <sstream>
#include <stdint.h> #include <stdint.h>
#include "../rtgui/cacheimagedata.h"
#include "rtexif.h" #include "rtexif.h"
#include "../rtengine/safegtk.h"
#include "../rtgui/version.h"
#include "../rtgui/ppversion.h"
using namespace std; using namespace std;
@@ -175,6 +179,121 @@ void TagDirectory::printAll (unsigned int level) const {
} }
} }
/** @brief Dump the TagDirectory and its sub-directories to the file 'fname'
*
* This method has been created to dump the metadata for the Custom Profile Builders.
* It contains an [RT General] section to communicate some parameters, then the TagDirectory follows.
*
* The key is composed as follow: "010F_Make", i.e. "tag number or ID _ tag name"
* Entries like:
*
* 927C_MakerNotesSony=$subdir
*
* indicates that this tag refer to a sub-directory. RT's Keywords begins with $, where & is the first char of the value.
* $subdir is the only keyword so far.
*
* You'll have then to check for the [EXIF/927C_MakerNotesSony] section, given that the root section
* is named [EXIF].
*
* WARNING: Some string will be sanitized, i.e. the new line char will be replaced by "\n". You'll
* have to check for this escape string if you want a correct display of the value, but your KeyFile module
* will most likely handle that automatically for you.
*
* @param commFNname Absolute path of the temporary communication file's name
* @param commFNname Absolute path of the image's file name
* @param commFNname Absolute path of the output profiles's file name
* @param defaultPParams absolute or relative path (to the application's folder) of the default ProcParams to use
* @param cfs pointer to a CacheImageData object that will contain common values
* @param flagMode will tell whether the Custom Profile Builder is called for on flagging event or for real development
* @param keyfile The KeyFile object to dump to. Has to be NULL (default value) on first call!
* @param tagDirName Name of the current TagDirectory (full path, i.e. "EXIF/MakerNotes/LensInfo"). Can be empty on first call, "EXIF" will then be used
*
* @return True if everything went fine, false otherwise
*/
bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, const CacheImageData* cfs, const bool flagMode,
rtengine::SafeKeyFile *keyFile, Glib::ustring tagDirName) const
{
rtengine::SafeKeyFile *kf;
if (!keyFile)
kf = new rtengine::SafeKeyFile();
else
kf = keyFile;
if (!kf)
return false;
if (!keyFile || tagDirName.empty())
tagDirName = "EXIF";
std::vector<const TagDirectory *> tagDirList;
std::vector<Glib::ustring> tagDirPaths;
FILE *f;
if (!keyFile) {
// open the file in write mode
f = safe_g_fopen (commFName, "wt");
if (f==NULL) {
printf("TagDirectory::keyFileDump(\"%s\") >>> Error: unable to open file with write access!\n", commFName.c_str());
delete kf;
return false;
}
kf->set_string ("RT General", "CachePath", options.cacheBaseDir);
kf->set_string ("RT General", "AppVersion", VERSION);
kf->set_integer("RT General", "ProcParamsVersion", PPVERSION);
kf->set_string ("RT General", "ImageFileName", imageFName);
kf->set_string ("RT General", "OutputProfileFileName", profileFName);
kf->set_string ("RT General", "DefaultProcParams", defaultPParams);
kf->set_boolean("RT General", "FlaggingMode", flagMode);
kf->set_double ("Common Data", "FNumber", cfs->fnumber);
kf->set_double ("Common Data", "Shutter", cfs->shutter);
kf->set_double ("Common Data", "FocalLength", cfs->focalLen);
kf->set_integer("Common Data", "ISO", cfs->iso);
kf->set_string ("Common Data", "Lens", cfs->lens);
kf->set_string ("Common Data", "Make", cfs->camMake);
kf->set_string ("Common Data", "Model", cfs->camModel);
}
// recursively iterate over the tag list
for (size_t i=0; i<tags.size(); i++) {
std::string tagName = tags[i]->nameToString ();
if (tags[i]->isDirectory())
for (int j=0; tags[i]->getDirectory(j); j++) {
// Accumulating the TagDirectories to dump later
tagDirPaths.push_back( Glib::ustring( tagDirName + "/" + getDumpKey(tags[i]->getID(), tagName) ) );
tagDirList.push_back(tags[i]->getDirectory(j));
kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), "$subdir");
}
else {
kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), tags[i]->valueToString());
}
}
// dumping the sub-directories
for (size_t i=0; i< tagDirList.size(); i++)
tagDirList.at(i)->CPBDump(commFName, imageFName, profileFName, defaultPParams, cfs, flagMode, kf, tagDirPaths.at(i));
if (!keyFile) {
fprintf (f, "%s", kf->to_data().c_str());
fclose (f);
delete kf;
}
return true;
}
Glib::ustring TagDirectory::getDumpKey (int tagID, const Glib::ustring tagName) {
Glib::ustring key;
if (options.CPBKeys == CPBKT_TID || options.CPBKeys == CPBKT_TID_NAME)
key = Glib::ustring(Glib::ustring::format(std::fixed, std::hex, std::setfill(L'0'), std::setw(4), tagID));
if (options.CPBKeys == CPBKT_TID_NAME)
key += Glib::ustring("_");
if (options.CPBKeys == CPBKT_TID_NAME || options.CPBKeys == CPBKT_NAME)
key += Glib::ustring(tagName);
return key;
}
void TagDirectory::addTag (Tag* tag) { void TagDirectory::addTag (Tag* tag) {
// look up if it already exists: // look up if it already exists:

View File

@@ -28,6 +28,9 @@
#include <cstdlib> #include <cstdlib>
#include <cmath> #include <cmath>
#include "../rtengine/procparams.h" #include "../rtengine/procparams.h"
#include "../rtengine/safekeyfile.h"
class CacheImageData;
namespace rtexif { namespace rtexif {
@@ -54,7 +57,6 @@ inline void sset4 (int v, unsigned char *s, ByteOrder order);
inline float int_to_float (int i); inline float int_to_float (int i);
short int int2_to_signed (short unsigned int i); short int int2_to_signed (short unsigned int i);
struct TIFFHeader { struct TIFFHeader {
unsigned short byteOrder; unsigned short byteOrder;
@@ -92,6 +94,7 @@ class TagDirectory {
const TagAttrib* attribs; // descriptor table to decode the tags const TagAttrib* attribs; // descriptor table to decode the tags
ByteOrder order; // byte order ByteOrder order; // byte order
TagDirectory* parent; // parent directory (NULL if root) TagDirectory* parent; // parent directory (NULL if root)
static Glib::ustring getDumpKey (int tagID, const Glib::ustring tagName);
public: public:
TagDirectory (); TagDirectory ();
@@ -125,7 +128,9 @@ class TagDirectory {
virtual TagDirectory* clone (TagDirectory* parent); virtual TagDirectory* clone (TagDirectory* parent);
virtual void applyChange (std::string field, std::string value); virtual void applyChange (std::string field, std::string value);
virtual void printAll (unsigned int level=0) const; // reentrant debug function, keep level=0 on first call ! virtual void printAll (unsigned int level=0) const; // reentrant debug function, keep level=0 on first call !
virtual bool CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams,
const CacheImageData* cfs, const bool flagMode, rtengine::SafeKeyFile *keyFile=NULL, Glib::ustring tagDirName="") const;
virtual void sort (); virtual void sort ();
}; };

View File

@@ -92,7 +92,7 @@ int main(int argc, char **argv)
setlocale(LC_ALL,""); setlocale(LC_ALL,"");
// Uncomment the following line if you want to use the "--g-fatal-warnings" command line flag // Uncomment the following line if you want to use the "--g-fatal-warnings" command line flag
//gtk_init (&argc, &argv); gtk_init (&argc, &argv);
Glib::thread_init(); Glib::thread_init();
gdk_threads_set_lock_functions(G_CALLBACK(myGdkLockEnter), (G_CALLBACK(myGdkLockLeave))); gdk_threads_set_lock_functions(G_CALLBACK(myGdkLockEnter), (G_CALLBACK(myGdkLockLeave)));

View File

@@ -617,16 +617,18 @@ if (keyFile.has_group ("Output")) {
} }
if (keyFile.has_group ("Profiles")) { if (keyFile.has_group ("Profiles")) {
if (keyFile.has_key ("Profiles", "Directory")) profilePath = keyFile.get_string ("Profiles", "Directory"); if (keyFile.has_key ("Profiles", "Directory")) profilePath = keyFile.get_string ("Profiles", "Directory");
if (keyFile.has_key ("Profiles", "UseBundledProfiles")) useBundledProfiles = keyFile.get_boolean ("Profiles", "UseBundledProfiles"); if (keyFile.has_key ("Profiles", "UseBundledProfiles")) useBundledProfiles = keyFile.get_boolean ("Profiles", "UseBundledProfiles");
if (keyFile.has_key ("Profiles", "LoadSaveProfilePath")) loadSaveProfilePath = keyFile.get_string ("Profiles", "LoadSaveProfilePath"); if (keyFile.has_key ("Profiles", "LoadSaveProfilePath")) loadSaveProfilePath = keyFile.get_string ("Profiles", "LoadSaveProfilePath");
if (keyFile.has_key ("Profiles", "RawDefault")) defProfRaw = keyFile.get_string ("Profiles", "RawDefault"); if (keyFile.has_key ("Profiles", "RawDefault")) defProfRaw = keyFile.get_string ("Profiles", "RawDefault");
if (keyFile.has_key ("Profiles", "ImgDefault")) defProfImg = keyFile.get_string ("Profiles", "ImgDefault"); if (keyFile.has_key ("Profiles", "ImgDefault")) defProfImg = keyFile.get_string ("Profiles", "ImgDefault");
if (keyFile.has_key ("Profiles", "FilledProfile")) filledProfile = keyFile.get_boolean ("Profiles", "FilledProfile"); if (keyFile.has_key ("Profiles", "FilledProfile")) filledProfile = keyFile.get_boolean ("Profiles", "FilledProfile");
if (keyFile.has_key ("Profiles", "SaveParamsWithFile")) saveParamsFile = keyFile.get_boolean ("Profiles", "SaveParamsWithFile"); if (keyFile.has_key ("Profiles", "SaveParamsWithFile")) saveParamsFile = keyFile.get_boolean ("Profiles", "SaveParamsWithFile");
if (keyFile.has_key ("Profiles", "SaveParamsToCache")) saveParamsCache = keyFile.get_boolean ("Profiles", "SaveParamsToCache"); if (keyFile.has_key ("Profiles", "SaveParamsToCache")) saveParamsCache = keyFile.get_boolean ("Profiles", "SaveParamsToCache");
if (keyFile.has_key ("Profiles", "LoadParamsFromLocation")) paramsLoadLocation = (PPLoadLocation)keyFile.get_integer ("Profiles", "LoadParamsFromLocation"); if (keyFile.has_key ("Profiles", "LoadParamsFromLocation")) paramsLoadLocation = (PPLoadLocation)keyFile.get_integer ("Profiles", "LoadParamsFromLocation");
if (keyFile.has_key ("Profiles", "CustomProfileBuilder")) customProfileBuilder = keyFile.get_string ("Profiles", "CustomProfileBuilder"); if (keyFile.has_key ("Profiles", "CustomProfileBuilder")) CPBPath = keyFile.get_string ("Profiles", "CustomProfileBuilder"); // for backward compatibility only
if (keyFile.has_key ("Profiles", "CustomProfileBuilderPath")) CPBPath = keyFile.get_string ("Profiles", "CustomProfileBuilderPath");
if (keyFile.has_key ("Profiles", "CustomProfileBuilderKeys")) CPBKeys = (CPBKeyType)keyFile.get_integer ("Profiles", "CustomProfileBuilderKeys");
} }
if (keyFile.has_group ("File Browser")) { if (keyFile.has_group ("File Browser")) {
@@ -948,7 +950,8 @@ int Options::saveToFile (Glib::ustring fname) {
keyFile.set_boolean ("Profiles", "SaveParamsWithFile", saveParamsFile); keyFile.set_boolean ("Profiles", "SaveParamsWithFile", saveParamsFile);
keyFile.set_boolean ("Profiles", "SaveParamsToCache", saveParamsCache); keyFile.set_boolean ("Profiles", "SaveParamsToCache", saveParamsCache);
keyFile.set_integer ("Profiles", "LoadParamsFromLocation", paramsLoadLocation); keyFile.set_integer ("Profiles", "LoadParamsFromLocation", paramsLoadLocation);
keyFile.set_string ("Profiles", "CustomProfileBuilder", customProfileBuilder); keyFile.set_string ("Profiles", "CustomProfileBuilderPath", CPBPath);
keyFile.set_integer ("Profiles", "CustomProfileBuilderKeys", CPBKeys);
keyFile.set_string ("GUI", "Font", font); keyFile.set_string ("GUI", "Font", font);
keyFile.set_integer ("GUI", "WindowWidth", windowWidth); keyFile.set_integer ("GUI", "WindowWidth", windowWidth);

View File

@@ -53,6 +53,7 @@ class SaveFormat {
enum ThFileType {FT_Invalid=-1, FT_None=0, FT_Raw=1, FT_Jpeg=2, FT_Tiff=3, FT_Png=4, FT_Custom=5, FT_Tiff16=6, FT_Png16=7, FT_Custom16=8}; enum ThFileType {FT_Invalid=-1, FT_None=0, FT_Raw=1, FT_Jpeg=2, FT_Tiff=3, FT_Png=4, FT_Custom=5, FT_Tiff16=6, FT_Png16=7, FT_Custom16=8};
enum PPLoadLocation {PLL_Cache=0, PLL_Input=1}; enum PPLoadLocation {PLL_Cache=0, PLL_Input=1};
enum CPBKeyType {CPBKT_TID=0, CPBKT_NAME=1, CPBKT_TID_NAME=2};
namespace rtengine { namespace rtengine {
class SafeKeyFile; class SafeKeyFile;
@@ -155,7 +156,8 @@ class Options {
Glib::ustring gimpDir; Glib::ustring gimpDir;
Glib::ustring psDir; Glib::ustring psDir;
Glib::ustring customEditorProg; Glib::ustring customEditorProg;
Glib::ustring customProfileBuilder; Glib::ustring CPBPath; // Custom Profile Builder's path
CPBKeyType CPBKeys; // Custom Profile Builder's key type
int editorToSendTo; int editorToSendTo;
int maxThumbnailHeight; int maxThumbnailHeight;
std::size_t maxCacheEntries; std::size_t maxCacheEntries;

View File

@@ -372,6 +372,25 @@ Gtk::Widget* Preferences::getProcParamsPanel () {
fpp->add (*vbpp); fpp->add (*vbpp);
mvbpp->pack_start (*fpp, Gtk::PACK_SHRINK, 4); mvbpp->pack_start (*fpp, Gtk::PACK_SHRINK, 4);
// Custom profile builder box
Gtk::Frame* cpfrm = Gtk::manage( new Gtk::Frame (M("PREFERENCES_CUSTPROFBUILD")) );
Gtk::Label* cplab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CUSTPROFBUILDPATH")+":", Gtk::ALIGN_LEFT) );
txtCustProfBuilderPath = Gtk::manage( new Gtk::Entry () );
txtCustProfBuilderPath->set_tooltip_markup (M("PREFERENCES_CUSTPROFBUILDHINT"));
Gtk::Label* cpltypelab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CUSTPROFBUILDKEYFORMAT")+":", Gtk::ALIGN_LEFT) );
custProfBuilderLabelType = Gtk::manage (new Gtk::ComboBoxText ());
custProfBuilderLabelType->append_text (M("PREFERENCES_CUSTPROFBUILDKEYFORMAT_TID"));
custProfBuilderLabelType->append_text (M("PREFERENCES_CUSTPROFBUILDKEYFORMAT_NAME"));
custProfBuilderLabelType->append_text (M("PREFERENCES_CUSTPROFBUILDKEYFORMAT_TID") + "_" + M("PREFERENCES_CUSTPROFBUILDKEYFORMAT_NAME"));
Gtk::Table* cpbt = Gtk::manage (new Gtk::Table (2, 2));
cpbt->set_border_width(4);
cpbt->attach (*cplab, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
cpbt->attach (*txtCustProfBuilderPath, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
cpbt->attach (*cpltypelab, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 2, 2);
cpbt->attach (*custProfBuilderLabelType, 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
cpfrm->add (*cpbt);
mvbpp->pack_start (*cpfrm, Gtk::PACK_SHRINK, 4);
Gtk::Frame* fdp = Gtk::manage (new Gtk::Frame (M("PREFERENCES_PROFILEHANDLING"))); Gtk::Frame* fdp = Gtk::manage (new Gtk::Frame (M("PREFERENCES_PROFILEHANDLING")));
Gtk::VBox* vbdp = Gtk::manage (new Gtk::VBox ()); Gtk::VBox* vbdp = Gtk::manage (new Gtk::VBox ());
vbdp->set_border_width (4); vbdp->set_border_width (4);
@@ -812,26 +831,6 @@ Gtk::Widget* Preferences::getGeneralPanel () {
mvbsd->pack_start (*fdg, Gtk::PACK_SHRINK, 4); mvbsd->pack_start (*fdg, Gtk::PACK_SHRINK, 4);
// Custom profile builder box
Gtk::Frame* cpfrm = Gtk::manage( new Gtk::Frame (M("PREFERENCES_CUSTPROFBUILD")) );
Gtk::HBox* cphb = Gtk::manage( new Gtk::HBox () );
cphb->set_border_width (4);
cphb->set_spacing (4);
Gtk::Label* cplab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CUSTPROFBUILDPATH")+":") );
cphb->pack_start (*cplab, Gtk::PACK_SHRINK,4);
txtCustProfBuilderPath = Gtk::manage( new Gtk::Entry () );
txtCustProfBuilderPath->set_tooltip_markup (M("PREFERENCES_CUSTPROFBUILDHINT"));
cphb->set_tooltip_markup (M("PREFERENCES_CUSTPROFBUILDHINT"));
cphb->pack_start (*txtCustProfBuilderPath);
cpfrm->add (*cphb);
mvbsd->pack_start (*cpfrm, Gtk::PACK_SHRINK, 4);
mvbsd->set_border_width (4); mvbsd->set_border_width (4);
tconn = theme->signal_changed().connect( sigc::mem_fun(*this, &Preferences::themeChanged) ); tconn = theme->signal_changed().connect( sigc::mem_fun(*this, &Preferences::themeChanged) );
@@ -1143,7 +1142,8 @@ void Preferences::storePreferences () {
else if (edOther->get_active ()) else if (edOther->get_active ())
moptions.editorToSendTo = 3; moptions.editorToSendTo = 3;
moptions.customProfileBuilder = txtCustProfBuilderPath->get_text(); moptions.CPBPath = txtCustProfBuilderPath->get_text();
moptions.CPBKeys = CPBKeyType(custProfBuilderLabelType->get_active_row_number());
moptions.rtSettings.monitorProfile = monProfile->get_filename (); moptions.rtSettings.monitorProfile = monProfile->get_filename ();
moptions.rtSettings.autoMonitorProfile = cbAutoMonProfile->get_active (); moptions.rtSettings.autoMonitorProfile = cbAutoMonProfile->get_active ();
@@ -1286,7 +1286,9 @@ void Preferences::fillPreferences () {
#endif #endif
editorToSendTo->set_text (moptions.customEditorProg); editorToSendTo->set_text (moptions.customEditorProg);
txtCustProfBuilderPath->set_text(moptions.customProfileBuilder); txtCustProfBuilderPath->set_text(moptions.CPBPath);
custProfBuilderLabelType->set_active(moptions.CPBKeys);
if (moptions.startupDir==STARTUPDIR_CURRENT) if (moptions.startupDir==STARTUPDIR_CURRENT)
sdcurrent->set_active (); sdcurrent->set_active ();

View File

@@ -141,6 +141,7 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener {
Gtk::CheckButton* ckbInternalThumbIfUntouched; Gtk::CheckButton* ckbInternalThumbIfUntouched;
Gtk::Entry* txtCustProfBuilderPath; Gtk::Entry* txtCustProfBuilderPath;
Gtk::ComboBoxText* custProfBuilderLabelType;
Gtk::CheckButton* ckbHistogramPositionLeft; Gtk::CheckButton* ckbHistogramPositionLeft;
Gtk::CheckButton* ckbShowProfileSelector; Gtk::CheckButton* ckbShowProfileSelector;

View File

@@ -191,11 +191,22 @@ const ProcParams& Thumbnail::getProcParamsU () {
return pparams; // there is no valid pp to return, but we have to return something return pparams; // there is no valid pp to return, but we have to return something
} }
/* /** @brief Create default params on demand and returns a new updatable object
* Create default params on demand and returns a new updatable object *
* The loaded profile may be partial, but it return a complete ProcParams (i.e. without ParamsEdited) * The loaded profile may be partial, but it return a complete ProcParams (i.e. without ParamsEdited)
*
* @param returnParams Ask to return a pointer to a ProcParams object if true
* @param forceCPB True if the Custom Profile Builder has to be invoked, False if the CPB has to be invoked if the profile doesn't
* exist yet. It depends on other conditions too
* @param flaggingMode True if the ProcParams will be created because the file browser is being flagging an image
* (rang, to trash, color labels). This parameter is passed to the CPB.
*
* @return Return a pointer to a ProcPamas structure to be updated if returnParams is true and if everything went fine, NULL otherwise.
*/ */
rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool returnParams, bool forceCPB, bool flaggingMode) { rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool returnParams, bool forceCPB, bool flaggingMode) {
static int index=0; // Will act as unique identifier during the session
// try to load the last saved parameters from the cache or from the paramfile file // try to load the last saved parameters from the cache or from the paramfile file
ProcParams* ldprof = NULL; ProcParams* ldprof = NULL;
@@ -203,26 +214,44 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu
const CacheImageData* cfs=getCacheImageData(); const CacheImageData* cfs=getCacheImageData();
Glib::ustring defaultPparamsPath = options.findProfilePath(defProf); Glib::ustring defaultPparamsPath = options.findProfilePath(defProf);
if (!options.customProfileBuilder.empty() && !defaultPparamsPath.empty() && (!hasProcParams() || forceCPB) && cfs && cfs->exifValid) { if (!options.CPBPath.empty() && !defaultPparamsPath.empty() && (!hasProcParams() || forceCPB) && cfs && cfs->exifValid) {
// For the filename etc. do NOT use streams, since they are not UTF8 safe // First generate the communication file, with general values and EXIF metadata
Glib::ustring cmdLine = options.customProfileBuilder + Glib::ustring(" \"") + fname + Glib::ustring("\" \"") rtengine::ImageMetaData* imageMetaData;
+ (defaultPparamsPath == DEFPROFILE_INTERNAL ? "Neutral" : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension)) + Glib::ustring("\" "); if (getType()==FT_Raw) {
rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname);
imageMetaData = rtengine::ImageMetaData::fromFile (fname, &metaData);
}
else
imageMetaData = rtengine::ImageMetaData::fromFile (fname, NULL);
Glib::ustring tmpFileName( Glib::build_filename(options.cacheBaseDir, Glib::ustring::compose("CPB_temp_%1.txt", index++)) );
const rtexif::TagDirectory* exifDir=NULL;
if (imageMetaData && (exifDir = imageMetaData->getExifData())) {
Glib::ustring outFName;
if (options.paramsLoadLocation==PLL_Input)
outFName = fname+paramFileExtension;
else
outFName = getCacheFileName("profiles")+paramFileExtension;
exifDir->CPBDump(tmpFileName, fname, outFName,
defaultPparamsPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension),
cfs,
flaggingMode);
}
// For the filename etc. do NOT use streams, since they are not UTF8 safe
Glib::ustring cmdLine = options.CPBPath + Glib::ustring(" \"") + tmpFileName + Glib::ustring("\" \"");
// ustring doesn't know int etc formatting, so take these via (unsafe) stream
std::ostringstream strm;
strm << Glib::ustring("\"") << options.cacheBaseDir.c_str() << Glib::ustring("\" ");
strm << flaggingMode << Glib::ustring(" ");
strm << cfs->fnumber << Glib::ustring(" ") << cfs->shutter << Glib::ustring(" ");
strm << cfs->focalLen << Glib::ustring(" ") << cfs->iso << Glib::ustring(" \"");
strm << cfs->lens << Glib::ustring("\" \"") << cfs->camMake << Glib::ustring("\"");
strm << Glib::ustring(" \"") << cfs->camModel << Glib::ustring("\"");
if (options.rtSettings.verbose) if (options.rtSettings.verbose)
printf("Custom profile builder's command line: %s\n", Glib::ustring(cmdLine + strm.str()).c_str()); printf("Custom profile builder's command line: %s\n", Glib::ustring(cmdLine).c_str());
bool success = safe_spawn_command_line_sync (cmdLine + strm.str()); bool success = safe_spawn_command_line_sync (cmdLine);
// Now they SHOULD be there (and potentially "partial"), so try to load them and store it as a full procparam // Now they SHOULD be there (and potentially "partial"), so try to load them and store it as a full procparam
if (success) loadProcParams(); if (success) loadProcParams();
if (safe_file_test(tmpFileName, Glib::FILE_TEST_EXISTS )) safe_g_remove (tmpFileName);
if (imageMetaData) delete imageMetaData;
} }
if (returnParams && hasProcParams()) { if (returnParams && hasProcParams()) {

View File

@@ -10,8 +10,16 @@ using System.Collections.Specialized;
#endregion #endregion
// *** Raw Therapee sample Custom Profile builder (version 2013-08-12) *** // *** Raw Therapee sample Custom Profile builder (version 2013-08-12) ***
// WARNING: PP3 format may change in the future versions! If this happens there will probably be no automatic migration path, you'll have to adjust on your own. //
// This is a sample, and therefore not supported by the RT team (just by oduis) //
// WARNING: The command line parameters has changed since this file has been created by Oduis. The new mechanism involves a
// temporary communication file (.ini style) to provide system parameters and metadata read by RawTherapee. This script has
// to be updated by some C# developer in order to work.
//
//
// WARNING: PP3 format may change in the future versions! If this happens there will probably be no automatic migration path,
// you'll have to adjust on your own. This is a sample, and therefore not supported by the RT team (just by oduis)
//
// //
// How to use: // How to use:
// 1. Modify the GetCorrectedSettings function below according to your needs. // 1. Modify the GetCorrectedSettings function below according to your needs.