diff --git a/rtdata/languages/default b/rtdata/languages/default index 6934ec469..f4719f45b 100755 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -750,6 +750,9 @@ PREFERENCES_CLIPPINGIND;Clipping Indication 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\nWARNING: You are responsible of using double quotes where necessary if you're using paths containing spaces. PREFERENCES_CUSTPROFBUILDPATH;Executable path +PREFERENCES_CUSTPROFBUILDKEYFORMAT;Keys format +PREFERENCES_CUSTPROFBUILDKEYFORMAT_TID;TagID +PREFERENCES_CUSTPROFBUILDKEYFORMAT_NAME;Name PREFERENCES_CUSTPROFBUILD;Custom Processing Profile Builder PREFERENCES_CUTOVERLAYBRUSH;Crop mask color/transparency PREFERENCES_D50;5000K diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index e75e0ba02..8b54c5711 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -215,6 +215,23 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL #define FISBLUE(filter,row,col) \ ((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) { RawImage *ri= new RawImage (fname); diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index fc0219d5f..669b33083 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -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* 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 RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname); void getCamWB (double& temp, double& green); void getAutoWB (double& temp, double& green, double equal); diff --git a/rtexif/CMakeLists.txt b/rtexif/CMakeLists.txt index 6fa05c032..54db707d5 100644 --- a/rtexif/CMakeLists.txt +++ b/rtexif/CMakeLists.txt @@ -16,6 +16,8 @@ ELSE (WIN32) ${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS}) ENDIF (WIN32) +include_directories (BEFORE "${CMAKE_CURRENT_BINARY_DIR}") + IF (BUILD_SHARED_LIBS) INSTALL(TARGETS rtexif DESTINATION ${LIBDIR}) ENDIF (BUILD_SHARED_LIBS) diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 2f376e295..c55779605 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -25,7 +25,11 @@ #include #include +#include "../rtgui/cacheimagedata.h" #include "rtexif.h" +#include "../rtengine/safegtk.h" +#include "../rtgui/version.h" +#include "../rtgui/ppversion.h" 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 tagDirList; + std::vector 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; inameToString (); + 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) { // look up if it already exists: diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index b50723256..4dd816186 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -28,6 +28,9 @@ #include #include #include "../rtengine/procparams.h" +#include "../rtengine/safekeyfile.h" + +class CacheImageData; namespace rtexif { @@ -54,7 +57,6 @@ inline void sset4 (int v, unsigned char *s, ByteOrder order); inline float int_to_float (int i); short int int2_to_signed (short unsigned int i); - struct TIFFHeader { unsigned short byteOrder; @@ -92,6 +94,7 @@ class TagDirectory { const TagAttrib* attribs; // descriptor table to decode the tags ByteOrder order; // byte order TagDirectory* parent; // parent directory (NULL if root) + static Glib::ustring getDumpKey (int tagID, const Glib::ustring tagName); public: TagDirectory (); @@ -125,7 +128,9 @@ class TagDirectory { virtual TagDirectory* clone (TagDirectory* parent); 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 (); }; diff --git a/rtgui/main.cc b/rtgui/main.cc index 24b453c7f..de0fdf86f 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -92,7 +92,7 @@ int main(int argc, char **argv) setlocale(LC_ALL,""); // 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(); gdk_threads_set_lock_functions(G_CALLBACK(myGdkLockEnter), (G_CALLBACK(myGdkLockLeave))); diff --git a/rtgui/options.cc b/rtgui/options.cc index 7e241e3eb..e88db465a 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -617,16 +617,18 @@ if (keyFile.has_group ("Output")) { } if (keyFile.has_group ("Profiles")) { - 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", "LoadSaveProfilePath")) loadSaveProfilePath = keyFile.get_string ("Profiles", "LoadSaveProfilePath"); - 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", "FilledProfile")) filledProfile = keyFile.get_boolean ("Profiles", "FilledProfile"); - 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", "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", "Directory")) profilePath = keyFile.get_string ("Profiles", "Directory"); + 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", "RawDefault")) defProfRaw = keyFile.get_string ("Profiles", "RawDefault"); + 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", "SaveParamsWithFile")) saveParamsFile = keyFile.get_boolean ("Profiles", "SaveParamsWithFile"); + 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", "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")) { @@ -948,7 +950,8 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_boolean ("Profiles", "SaveParamsWithFile", saveParamsFile); keyFile.set_boolean ("Profiles", "SaveParamsToCache", saveParamsCache); 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_integer ("GUI", "WindowWidth", windowWidth); diff --git a/rtgui/options.h b/rtgui/options.h index 093ce67a2..e77f98e22 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -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 PPLoadLocation {PLL_Cache=0, PLL_Input=1}; +enum CPBKeyType {CPBKT_TID=0, CPBKT_NAME=1, CPBKT_TID_NAME=2}; namespace rtengine { class SafeKeyFile; @@ -155,7 +156,8 @@ class Options { Glib::ustring gimpDir; Glib::ustring psDir; 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 maxThumbnailHeight; std::size_t maxCacheEntries; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index b96cdb952..369969dea 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -372,6 +372,25 @@ Gtk::Widget* Preferences::getProcParamsPanel () { fpp->add (*vbpp); 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::VBox* vbdp = Gtk::manage (new Gtk::VBox ()); vbdp->set_border_width (4); @@ -812,26 +831,6 @@ Gtk::Widget* Preferences::getGeneralPanel () { 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); tconn = theme->signal_changed().connect( sigc::mem_fun(*this, &Preferences::themeChanged) ); @@ -1143,7 +1142,8 @@ void Preferences::storePreferences () { else if (edOther->get_active ()) 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.autoMonitorProfile = cbAutoMonProfile->get_active (); @@ -1286,7 +1286,9 @@ void Preferences::fillPreferences () { #endif 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) sdcurrent->set_active (); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index 0b77b03b0..587682d6b 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -141,6 +141,7 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener { Gtk::CheckButton* ckbInternalThumbIfUntouched; Gtk::Entry* txtCustProfBuilderPath; + Gtk::ComboBoxText* custProfBuilderLabelType; Gtk::CheckButton* ckbHistogramPositionLeft; Gtk::CheckButton* ckbShowProfileSelector; diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index ef9475781..e6940ae76 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -191,11 +191,22 @@ const ProcParams& Thumbnail::getProcParamsU () { return pparams; // there is no valid pp to return, but we have to return something } -/* - * Create default params on demand and returns a new updatable object +/** @brief 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) + * + * @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) { + + 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 ProcParams* ldprof = NULL; @@ -203,26 +214,44 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu const CacheImageData* cfs=getCacheImageData(); Glib::ustring defaultPparamsPath = options.findProfilePath(defProf); - if (!options.customProfileBuilder.empty() && !defaultPparamsPath.empty() && (!hasProcParams() || forceCPB) && cfs && cfs->exifValid) { - // For the filename etc. do NOT use streams, since they are not UTF8 safe - Glib::ustring cmdLine = options.customProfileBuilder + Glib::ustring(" \"") + fname + Glib::ustring("\" \"") - + (defaultPparamsPath == DEFPROFILE_INTERNAL ? "Neutral" : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension)) + Glib::ustring("\" "); + if (!options.CPBPath.empty() && !defaultPparamsPath.empty() && (!hasProcParams() || forceCPB) && cfs && cfs->exifValid) { + // First generate the communication file, with general values and EXIF metadata + rtengine::ImageMetaData* imageMetaData; + 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) - printf("Custom profile builder's command line: %s\n", Glib::ustring(cmdLine + strm.str()).c_str()); - bool success = safe_spawn_command_line_sync (cmdLine + strm.str()); + printf("Custom profile builder's command line: %s\n", Glib::ustring(cmdLine).c_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 if (success) loadProcParams(); + + if (safe_file_test(tmpFileName, Glib::FILE_TEST_EXISTS )) safe_g_remove (tmpFileName); + + if (imageMetaData) delete imageMetaData; } if (returnParams && hasProcParams()) { diff --git a/tools/RTProfileBuilderSample.cs b/tools/RTProfileBuilderSample.cs index 1b0dd028a..20a3b8e1c 100644 --- a/tools/RTProfileBuilderSample.cs +++ b/tools/RTProfileBuilderSample.cs @@ -10,8 +10,16 @@ using System.Collections.Specialized; #endregion // *** 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: // 1. Modify the GetCorrectedSettings function below according to your needs.