From a04b3eefbaa88b38917d257337d3cc861b3adbad Mon Sep 17 00:00:00 2001 From: Hombre Date: Mon, 13 Feb 2017 23:38:05 +0100 Subject: [PATCH] Adding rawtherapee-cli.exe, '-q' (quick start mode) added Standard rawtherapee.exe now has almost no command line options left. Use '-h' to see options for each executables. --- CMakeLists.txt | 1 + rtengine/CMakeLists.txt | 2 +- rtengine/dcp.cc | 21 +- rtengine/dcp.h | 4 +- rtengine/iccstore.cc | 12 +- rtengine/iccstore.h | 2 +- rtengine/icons.cc | 120 ++++++++++ rtengine/icons.h | 33 +++ rtengine/init.cc | 5 +- rtengine/rawimagesource.cc | 3 + rtengine/rtengine.h | 5 +- rtgui/CMakeLists.txt | 34 ++- rtgui/edit.cc | 12 +- rtgui/edit.h | 2 - rtgui/editwindow.cc | 3 +- rtgui/guiutils.cc | 39 +--- rtgui/guiutils.h | 6 +- rtgui/main-cli.cc | 135 ++++++++---- rtgui/main.cc | 441 +------------------------------------ rtgui/options.cc | 4 +- rtgui/options.h | 2 +- rtgui/pathutils.cc | 48 ++++ rtgui/pathutils.h | 34 +++ rtgui/preferences.cc | 5 +- rtgui/rtimage.cc | 100 +-------- rtgui/rtimage.h | 3 - rtgui/rtwindow.cc | 3 +- 27 files changed, 436 insertions(+), 643 deletions(-) create mode 100644 rtengine/icons.cc create mode 100644 rtengine/icons.h create mode 100644 rtgui/pathutils.cc create mode 100644 rtgui/pathutils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ee54705f6..eed53e527 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,6 +230,7 @@ pkg_check_modules (GTK REQUIRED gtk+-3.0>=3.16) pkg_check_modules (GLIB2 REQUIRED glib-2.0>=2.44) pkg_check_modules (GLIBMM REQUIRED glibmm-2.4>=2.44) pkg_check_modules (GTKMM REQUIRED gtkmm-3.0>=3.16) +pkg_check_modules (CAIROMM REQUIRED cairomm-1.0) pkg_check_modules (GIO REQUIRED gio-2.0>=2.44) pkg_check_modules (GIOMM REQUIRED giomm-2.4>=2.44) pkg_check_modules (GTHREAD REQUIRED gthread-2.0>=2.44) diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 477ccecae..eb9abe828 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -13,7 +13,7 @@ set (RTENGINESOURCEFILES colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc fast_demo.cc amaze_demosaic_RT.cc CA_correct_RT.cc cfa_linedn_RT.cc green_equil_RT.cc hilite_recon.cc expo_before_b.cc stdimagesource.cc myfile.cc iccjpeg.cc improccoordinator.cc pipettebuffer.cc coord.cc processingjob.cc rtthumbnail.cc utils.cc labimage.cc slicer.cc cieimage.cc - iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc ipvibrance.cc + iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc ipvibrance.cc icons.cc imagedimensions.cc jpeg_ijg/jpeg_memsrc.cc jdatasrc.cc iimage.cc EdgePreservingDecomposition.cc cplx_wavelet_dec.cc FTblockDN.cc PF_correct_RT.cc previewimage.cc ipwavelet.cc diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index a597fa8db..86e348c75 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -406,6 +406,7 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : has_tone_curve(false), has_baseline_exposure_offset(false), will_interpolate(false), + valid(false), baseline_exposure_offset(0.0) { constexpr int tiff_float_size = 4; @@ -691,6 +692,11 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : FILE* const file = g_fopen(filename.c_str(), "rb"); + if (file == nullptr) { + printf ("Unable to load DCP profile '%s' !", filename.c_str()); + return; + } + std::unique_ptr tagDir(ExifManager::parseTIFF(file, false)); Tag* tag = tagDir->getTag(toUnderlying(TagKey::CALIBRATION_ILLUMINANT_1)); @@ -738,6 +744,7 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : if (!tag) { std::cerr << "DCP '" << filename << "' is missing 'ColorMatrix1'. Skipped." << std::endl; + fclose(file); return; } @@ -935,6 +942,8 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : if (file) { fclose(file); } + + valid = true; } DCPProfile::~DCPProfile() @@ -1683,13 +1692,18 @@ void DCPProfile::hsdApply(const HsdTableInfo& table_info, const std::vectorisValid()) { // Add profile profile_cache[filename] = res; + if (options.rtSettings.verbose) { + printf("DCP profile '%s' loaded from disk\n", filename.c_str()); + } return res; } diff --git a/rtengine/dcp.h b/rtengine/dcp.h index 8b781ce6b..215137ac8 100644 --- a/rtengine/dcp.h +++ b/rtengine/dcp.h @@ -75,6 +75,7 @@ public: bool getHasBaselineExposureOffset() const; Illuminants getIlluminants() const; + bool isValid(); void apply( Imagefloat* img, @@ -130,6 +131,7 @@ private: bool has_tone_curve; bool has_baseline_exposure_offset; bool will_interpolate; + bool valid; Matrix forward_matrix_1; Matrix forward_matrix_2; double temperature_1; @@ -152,7 +154,7 @@ class DCPStore final : public: static DCPStore* getInstance(); - void init(const Glib::ustring& rt_profile_dir); + void init(const Glib::ustring& rt_profile_dir, bool loadAll = true); bool isValidDCPFileName(const Glib::ustring& filename) const; diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index 16ae455b6..2898f48c8 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -767,7 +767,7 @@ uint8_t ICCStore::getProofIntents (cmsHPROFILE profile) const } // Reads all profiles from the given profiles dir -void ICCStore::init (const Glib::ustring& usrICCDir, const Glib::ustring& rtICCDir) +void ICCStore::init (const Glib::ustring& usrICCDir, const Glib::ustring& rtICCDir, bool loadAll) { MyMutex::MyLock lock (mutex_); @@ -776,15 +776,19 @@ void ICCStore::init (const Glib::ustring& usrICCDir, const Glib::ustring& rtICCD profilesDir = Glib::build_filename (rtICCDir, "output"); fileProfiles.clear(); fileProfileContents.clear(); - loadProfiles (profilesDir, &fileProfiles, &fileProfileContents, nullptr, false); - loadProfiles (usrICCDir, &fileProfiles, &fileProfileContents, nullptr, false); + if (loadAll) { + loadProfiles (profilesDir, &fileProfiles, &fileProfileContents, nullptr, false); + loadProfiles (usrICCDir, &fileProfiles, &fileProfileContents, nullptr, false); + } // Input profiles // Load these to different areas, since the short name (e.g. "NIKON D700" may overlap between system/user and RT dir) stdProfilesDir = Glib::build_filename (rtICCDir, "input"); fileStdProfiles.clear(); fileStdProfilesFileNames.clear(); - loadProfiles (stdProfilesDir, nullptr, nullptr, &fileStdProfilesFileNames, true); + if (loadAll) { + loadProfiles (stdProfilesDir, nullptr, nullptr, &fileStdProfilesFileNames, true); + } } // Determine the first monitor default profile of operating system, if selected diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h index 58ddfdbc9..ae4026b28 100644 --- a/rtengine/iccstore.h +++ b/rtengine/iccstore.h @@ -92,7 +92,7 @@ public: static ICCStore* getInstance (); - void init (const Glib::ustring& usrICCDir, const Glib::ustring& stdICCDir); + void init (const Glib::ustring& usrICCDir, const Glib::ustring& stdICCDir, bool loadAll); static void getGammaArray(const procparams::ColorManagementParams &icm, GammaValues &ga); static cmsHPROFILE makeStdGammaProfile (cmsHPROFILE iprof); diff --git a/rtengine/icons.cc b/rtengine/icons.cc new file mode 100644 index 000000000..2c5075007 --- /dev/null +++ b/rtengine/icons.cc @@ -0,0 +1,120 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * Copyright (c) 2011 Jean-Christophe FRISCH + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#include "icons.h" + +#include + +namespace rtengine +{ + +std::vector imagePaths; + +bool loadIconSet(const Glib::ustring& iconSet) +{ + try { + + Glib::KeyFile keyFile; + keyFile.load_from_file (iconSet); + + auto iconSetDir = keyFile.get_string ("General", "Iconset"); + + if (!iconSetDir.empty ()) { + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "actions")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir)); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "devices")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "places")); + } + + iconSetDir = keyFile.get_string ("General", "FallbackIconset"); + + if (!iconSetDir.empty ()) { + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "actions")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir)); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "devices")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "places")); + } + + return true; + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to load icon set \"" << iconSet << "\": " << exception.what() << std::endl; + } + + return false; + + } +} + +Glib::ustring findIconAbsolutePath (const Glib::ustring& iconName) +{ + try { + + for (const auto& imagePath : imagePaths) { + const auto iconPath = Glib::build_filename(imagePath, iconName); + + if (Glib::file_test(iconPath, Glib::FILE_TEST_IS_REGULAR)) { + return iconPath; + } + } + + } catch(const Glib::Exception&) {} + + if (options.rtSettings.verbose) { + std::cerr << "Icon \"" << iconName << "\" could not be found!" << std::endl; + } + + return Glib::ustring(); +} + +void setPaths (const Options& options) +{ + // TODO: Forcing the Dark theme, so reading the icon set files is useless for now... + + /*Glib::ustring iconSet; + + // Either use the system icon set or the one specified in the options. + if (options.useSystemTheme) { + iconSet = Glib::build_filename (argv0, "themes", "system.iconset"); + } else { + iconSet = Glib::build_filename (argv0, "themes", options.theme + ".iconset"); + } + + imagePaths.clear (); + + if (!loadIconSet (iconSet)) { + // If the preferred icon set is unavailable, fall back to the default icon set. + loadIconSet (Glib::build_filename (argv0, "themes", "Default.iconset")); + }*/ + + imagePaths.clear (); + + imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark")); + imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark", "actions")); + imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark", "devices")); + imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark", "places")); + + // The images folder is the second fallback solution. + imagePaths.push_back (Glib::build_filename(argv0, "images")); +} + +} diff --git a/rtengine/icons.h b/rtengine/icons.h new file mode 100644 index 000000000..9f6654a9c --- /dev/null +++ b/rtengine/icons.h @@ -0,0 +1,33 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * 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 . + */ +#ifndef _ICONS_ +#define _ICONS_ + +#include +#include "../rtgui/options.h" + +namespace rtengine +{ + +Glib::ustring findIconAbsolutePath (const Glib::ustring& iconName); +void setPaths (const Options& options); + +} + +#endif diff --git a/rtengine/init.cc b/rtengine/init.cc index 27edd976b..66ff5baf6 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -37,15 +37,14 @@ const Settings* settings; MyMutex* lcmsMutex = nullptr; -int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir) +int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir, bool loadAll) { settings = s; - iccStore->init (s->iccDirectory, baseDir + "/iccprofiles"); + iccStore->init (s->iccDirectory, baseDir + "/iccprofiles", loadAll); iccStore->findDefaultMonitorProfile(); DCPStore::getInstance()->init (baseDir + "/dcpprofiles"); CameraConstantsStore::getInstance ()->init (baseDir, userSettingsDir); - profileStore.init (); ProcParams::init (); Color::init (); PerceptualToneCurve::init (); diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 049c509f5..6dd71a7e3 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -894,6 +894,9 @@ DCPProfile *RawImageSource::getDCP(const ColorManagementParams &cmp, ColorTemp & findInputProfile(cmp.input, nullptr, (static_cast(getMetaData()))->getCamera(), &dcpProf, dummy); if (dcpProf == nullptr) { + if (settings->verbose) { + printf("Can't load DCP profile '%s'!\n", cmp.input.c_str()); + } return nullptr; } diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 61c779fb7..43fcbf06f 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -435,8 +435,9 @@ public: * @brief Initializes the RT engine * @param s is a struct of basic settings * @param baseDir base directory of RT's installation dir - * @param userSettingsDir RT's base directory in the user's settings dir */ -int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir); + * @param userSettingsDir RT's base directory in the user's settings dir + * @param loadAll if false, don't load the various dependencies (profiles, HALDClut files, ...), they'll be loaded from disk each time they'll be used (launching time improvement) */ +int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir, bool loadAll = true); /** Cleanup the RT engine (static variables) */ void cleanup (); diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index ad896041f..e7c1c6ffa 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -1,5 +1,10 @@ +# common source files for both CLI and non-CLI execautables +set (CLISOURCEFILES + paramsedited.cc options.cc multilangmgr.cc pathutils.cc edit.cc threadutils.cc + #cachemanager.cc cacheimagedata.cc + main-cli.cc) -set (BASESOURCEFILES +set (NONCLISOURCEFILES editwindow.cc batchtoolpanelcoord.cc paramsedited.cc cropwindow.cc previewhandler.cc previewwindow.cc navigator.cc indclippedpanel.cc previewmodepanel.cc filterpanel.cc exportpanel.cc cursormanager.cc rtwindow.cc renamedlg.cc recentbrowser.cc placesbrowser.cc filepanel.cc editorpanel.cc batchqueuepanel.cc ilabel.cc thumbbrowserbase.cc adjuster.cc filebrowserentry.cc filebrowser.cc filethumbnailbuttonset.cc @@ -21,7 +26,7 @@ set (BASESOURCEFILES preferences.cc profilepanel.cc saveasdlg.cc saveformatpanel.cc soundman.cc splash.cc thumbnail.cc tonecurve.cc toolbar.cc - guiutils.cc threadutils.cc zoompanel.cc toolpanelcoord.cc + pathutils.cc guiutils.cc threadutils.cc zoompanel.cc toolpanelcoord.cc thumbbrowserentrybase.cc batchqueueentry.cc batchqueue.cc lwbutton.cc lwbuttonset.cc batchqueuebuttonset.cc browserfilter.cc exiffiltersettings.cc @@ -41,7 +46,8 @@ if (APPLE) set (EXTRA_INCDIR ${EXTRA_INCDIR} ${MacIntegration_INCLUDE_DIRS}) endif (APPLE) if (WIN32) - set (EXTRA_SRC windirmonitor.cc myicon.rc) + set (EXTRA_SRC_CLI myicon.rc) + set (EXTRA_SRC_NONCLI myicon.rc windirmonitor.cc) set (EXTRA_LIB_RTGUI winmm) include_directories (${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${GIOMM_INCLUDE_DIRS}) @@ -61,14 +67,26 @@ endif (WIN32) # create config.h which defines where data are stored configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/config.h") -add_executable (rth ${EXTRA_SRC} ${BASESOURCEFILES}) -add_dependencies (rth AboutFile) +# create new executables targets +add_executable (rth ${EXTRA_SRC_NONCLI} ${NONCLISOURCEFILES}) +add_executable (rth-cli ${EXTRA_SRC_CLI} ${CLISOURCEFILES}) +# add dependencies to executables targets +add_dependencies (rth AboutFile) +add_dependencies (rth-cli AboutFile) + +# set executables targets properties, i.e. output filename and compile flags set_target_properties (rth PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" OUTPUT_NAME rawtherapee) -#target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${EXTRA_LIB} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES} -# ${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${IPTCDATA_LIBRARIES}) +set_target_properties (rth-cli PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" OUTPUT_NAME rawtherapee-cli) + +# add linked libraries dependencies to executables targets target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES} ${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${EXPAT_LIBRARIES} ${FFTW3F_LIBRARIES} ${IPTCDATA_LIBRARIES} ${CANBERRA-GTK_LIBRARIES} ${EXTRA_LIB_RTGUI}) -install (TARGETS rth DESTINATION ${BINDIR}) +target_link_libraries (rth-cli rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES} + ${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${CAIROMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${EXPAT_LIBRARIES} + ${FFTW3F_LIBRARIES} ${IPTCDATA_LIBRARIES} ${EXTRA_LIB_RTGUI}) +# install executables +install (TARGETS rth DESTINATION ${BINDIR}) +install (TARGETS rth-cli DESTINATION ${BINDIR}) diff --git a/rtgui/edit.cc b/rtgui/edit.cc index 58d856bb5..2f9b5eeef 100644 --- a/rtgui/edit.cc +++ b/rtgui/edit.cc @@ -18,7 +18,7 @@ */ #include "edit.h" -#include "rtimage.h" +#include "../rtengine/icons.h" ObjectMOBuffer::ObjectMOBuffer(EditDataProvider *dataProvider) : objectMap(nullptr), objectMode(OM_255), dataProvider(dataProvider) {} @@ -834,23 +834,23 @@ OPIcon::OPIcon(Glib::ustring normalImage, Glib::ustring activeImage, Glib::ustri Glib::ustring draggedImage, Glib::ustring insensitiveImage, DrivenPoint drivenPoint) : drivenPoint(drivenPoint) { if (!normalImage.empty()) { - normalImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(normalImage) ); + normalImg = Cairo::ImageSurface::create_from_png( rtengine::findIconAbsolutePath(normalImage) ); } if (!prelightImage.empty()) { - prelightImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(prelightImage) ); + prelightImg = Cairo::ImageSurface::create_from_png( rtengine::findIconAbsolutePath(prelightImage) ); } if (!activeImage.empty()) { - activeImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(activeImage) ); + activeImg = Cairo::ImageSurface::create_from_png( rtengine::findIconAbsolutePath(activeImage) ); } if (!draggedImage.empty()) { - draggedImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(draggedImage) ); + draggedImg = Cairo::ImageSurface::create_from_png( rtengine::findIconAbsolutePath(draggedImage) ); } if (!insensitiveImage.empty()) { - insensitiveImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(insensitiveImage) ); + insensitiveImg = Cairo::ImageSurface::create_from_png( rtengine::findIconAbsolutePath(insensitiveImage) ); } } diff --git a/rtgui/edit.h b/rtgui/edit.h index e28a6acec..eeeca694d 100644 --- a/rtgui/edit.h +++ b/rtgui/edit.h @@ -409,10 +409,8 @@ private: Cairo::RefPtr draggedImg; Cairo::RefPtr insensitiveImg; - static void setPaths(Options &opt); static void updateImages(); void changeImage(Glib::ustring &newImage); - static Glib::ustring findIconAbsolutePath(const Glib::ustring &iconFName); void drawImage (const Cairo::RefPtr &img, Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); void drawMOImage (const Cairo::RefPtr &img, Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); void drivenPointToRectangle(const rtengine::Coord &pos, rtengine::Coord &topLeft, rtengine::Coord &bottomRight, int W, int H); diff --git a/rtgui/editwindow.cc b/rtgui/editwindow.cc index 355c22876..1d08ac783 100644 --- a/rtgui/editwindow.cc +++ b/rtgui/editwindow.cc @@ -23,6 +23,7 @@ #include #include "rtimage.h" #include "threadutils.h" +#include "../rtengine/icons.h" // Check if the system has more than one display and option is set bool EditWindow::isMultiDisplayEnabled() @@ -59,7 +60,7 @@ EditWindow::EditWindow (RTWindow* p) : parent(p) , isFullscreen(false) { Glib::ustring fName = "rt-logo-tiny.png"; - Glib::ustring fullPath = RTImage::findIconAbsolutePath(fName); + Glib::ustring fullPath = rtengine::findIconAbsolutePath(fName); try { set_default_icon_from_file (fullPath); diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index 43bfc11b0..e637314cc 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -22,6 +22,7 @@ #include "options.h" #include "../rtengine/rt_math.h" #include "../rtengine/utils.h" +#include "../rtengine/icons.h" #include "rtimage.h" #include "multilangmgr.h" @@ -169,34 +170,6 @@ void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, } } -Glib::ustring removeExtension (const Glib::ustring& filename) -{ - - Glib::ustring bname = Glib::path_get_basename(filename); - size_t lastdot = bname.find_last_of ('.'); - size_t lastwhitespace = bname.find_last_of (" \t\f\v\n\r"); - - if (lastdot != bname.npos && (lastwhitespace == bname.npos || lastdot > lastwhitespace)) { - return filename.substr (0, filename.size() - (bname.size() - lastdot)); - } else { - return filename; - } -} - -Glib::ustring getExtension (const Glib::ustring& filename) -{ - - Glib::ustring bname = Glib::path_get_basename(filename); - size_t lastdot = bname.find_last_of ('.'); - size_t lastwhitespace = bname.find_last_of (" \t\f\v\n\r"); - - if (lastdot != bname.npos && (lastwhitespace == bname.npos || lastdot > lastwhitespace)) { - return filename.substr (filename.size() - (bname.size() - lastdot) + 1, filename.npos); - } else { - return ""; - } -} - bool confirmOverwrite (Gtk::Window& parent, const std::string& filename) { bool safe = true; @@ -542,11 +515,11 @@ void ExpanderBox::hideBox() void MyExpander::init() { - inconsistentPBuf = Gdk::Pixbuf::create_from_file(RTImage::findIconAbsolutePath("expanderInconsistent.png")); - enabledPBuf = Gdk::Pixbuf::create_from_file(RTImage::findIconAbsolutePath("expanderEnabled.png")); - disabledPBuf = Gdk::Pixbuf::create_from_file(RTImage::findIconAbsolutePath("expanderDisabled.png")); - openedPBuf = Gdk::Pixbuf::create_from_file(RTImage::findIconAbsolutePath("expanderOpened.png")); - closedPBuf = Gdk::Pixbuf::create_from_file(RTImage::findIconAbsolutePath("expanderClosed.png")); + inconsistentPBuf = Gdk::Pixbuf::create_from_file(rtengine::findIconAbsolutePath("expanderInconsistent.png")); + enabledPBuf = Gdk::Pixbuf::create_from_file(rtengine::findIconAbsolutePath("expanderEnabled.png")); + disabledPBuf = Gdk::Pixbuf::create_from_file(rtengine::findIconAbsolutePath("expanderDisabled.png")); + openedPBuf = Gdk::Pixbuf::create_from_file(rtengine::findIconAbsolutePath("expanderOpened.png")); + closedPBuf = Gdk::Pixbuf::create_from_file(rtengine::findIconAbsolutePath("expanderClosed.png")); } MyExpander::MyExpander(bool useEnabled, Gtk::Widget* titleWidget) : diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index e5919c9e4..5005b6f3c 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -27,11 +27,13 @@ #include #include +// for convenience... +#include "pathutils.h" + + Glib::ustring escapeHtmlChars(const Glib::ustring &src); bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference = true); void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh); -Glib::ustring removeExtension (const Glib::ustring& filename); -Glib::ustring getExtension (const Glib::ustring& filename); bool confirmOverwrite (Gtk::Window& parent, const std::string& filename); void writeFailed (Gtk::Window& parent, const std::string& filename); void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int imh, int startx, int starty, double scale, const rtengine::procparams::CropParams& cparams, bool drawGuide = true, bool useBgColor = true, bool fullImageVisible = true); diff --git a/rtgui/main-cli.cc b/rtgui/main-cli.cc index 33627e514..1e35e00c6 100644 --- a/rtgui/main-cli.cc +++ b/rtgui/main-cli.cc @@ -33,6 +33,7 @@ #include #include #include "options.h" +#include "../rtengine/icons.h" #include "soundman.h" #include "rtimage.h" #include "version.h" @@ -82,29 +83,6 @@ Glib::ustring fname_to_utf8 (const char* fname) } -// This recursive mutex will be used by gdk_threads_enter/leave instead of a simple mutex -#ifdef WIN32 -static Glib::RecMutex myGdkRecMutex; -#else -static Glib::Threads::RecMutex myGdkRecMutex; -#endif - -static void myGdkLockEnter() -{ - myGdkRecMutex.lock(); -} -static void myGdkLockLeave() -{ - // Automatic gdk_flush for non main tread -#if AUTO_GDK_FLUSH - //if (Glib::Thread::self() != mainThread) { - // gdk_flush(); - //} - -#endif - myGdkRecMutex.unlock(); -} - /* Process line command options * Returns * 0 if process in batch has executed @@ -115,14 +93,13 @@ static void myGdkLockLeave() * -3 if at least one required procparam file was not found */ int processLineParams( int argc, char **argv ); +bool dontLoadCache( int argc, char **argv ); + int main(int argc, char **argv) { setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); // to set decimal point to "." - Glib::init(); // called by Gtk::Main, but this may be important for thread handling, so we call it ourselves now - gdk_threads_set_lock_functions(G_CALLBACK(myGdkLockEnter), (G_CALLBACK(myGdkLockLeave))); - gdk_threads_init(); Gio::init (); //mainThread = Glib::Threads::Thread::self(); @@ -169,11 +146,15 @@ int main(int argc, char **argv) licensePath = LICENCE_SEARCH_PATH; #endif - if (!Options::load ()) { + bool quickstart = dontLoadCache(argc, argv); + + if (!Options::load (quickstart)) { printf("Fatal error!\nThe RT_SETTINGS and/or RT_PATH environment variables are set, but use a relative path. The path must be absolute!\n"); return -2; } + rtengine::setPaths(options); + TIFFSetWarningHandler(nullptr); // avoid annoying message boxes #ifndef WIN32 @@ -185,25 +166,87 @@ int main(int argc, char **argv) #endif -#if not RT_CMDLINE - extProgStore->init(); - SoundManager::init(); +#ifdef WIN32 + bool consoleOpened = false; + + if (argc > 1 || options.rtSettings.verbose) { + if (options.rtSettings.verbose || ( !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_EXISTS ) && !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_IS_DIR))) { + bool stdoutRedirectedtoFile = (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == 0x0001); + bool stderrRedirectedtoFile = (GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == 0x0001); + + // no console, if stdout and stderr both are redirected to file + if( !(stdoutRedirectedtoFile && stderrRedirectedtoFile)) { + // check if parameter -w was passed. + // We have to do that in this step, because it controls whether to open a console to show the output of following steps + bool Console = true; + + for(int i = 1; i < argc; i++) + if(!strcmp(argv[i], "-w")) { + Console = false; + break; + } + + if(Console) { + AllocConsole(); + AttachConsole( GetCurrentProcessId() ) ; + // Don't allow CTRL-C in console to terminate RT + SetConsoleCtrlHandler( NULL, true ); + // Set title of console + char consoletitle[128]; + sprintf(consoletitle, "RawTherapee %s Console", VERSION); + SetConsoleTitle(consoletitle); + // increase size of screen buffer + COORD c; + c.X = 200; + c.Y = 1000; + SetConsoleScreenBufferSize( GetStdHandle( STD_OUTPUT_HANDLE ), c ); + // Disable console-Cursor + CONSOLE_CURSOR_INFO cursorInfo; + cursorInfo.dwSize = 100; + cursorInfo.bVisible = false; + SetConsoleCursorInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &cursorInfo ); + + if(!stdoutRedirectedtoFile) { + freopen( "CON", "w", stdout ) ; + } + + if(!stderrRedirectedtoFile) { + freopen( "CON", "w", stderr ) ; + } + + freopen( "CON", "r", stdin ) ; + + consoleOpened = true; + + // printing RT's version in every case, particularly useful for the 'verbose' mode, but also for the batch processing + std::cout << "RawTherapee, version " << VERSION << ", command line" << std::endl; + std::cout << "WARNING: closing this window will close RawTherapee!" << std::endl << std::endl; + } + } + } + } #endif - // printing RT's version in all case, particularly useful for the 'verbose' mode, but also for the batch processing - std::cout << "RawTherapee, version " << VERSION << std::endl; - if (argc > 1) { - int ret = processLineParams( argc, argv); + int ret = 0; - if( ret <= 0 ) { - return ret; - } + // printing RT's version in all case, particularly useful for the 'verbose' mode, but also for the batch processing + std::cout << "RawTherapee, version " << VERSION << ", command line" << std::endl; + if (argc > 1) { + ret = processLineParams(argc, argv); } else { std::cout << "Terminating without anything to do." << std::endl; } - return 0; +#ifdef WIN32 + if(consoleOpened) { + printf("Press any key to exit RawTherapee\n"); + FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); + getch(); + } +#endif + + return ret; } void deleteProcParams(std::vector &pparams) @@ -217,6 +260,18 @@ void deleteProcParams(std::vector &pparam return; } + +bool dontLoadCache( int argc, char **argv ) +{ + for( int iArg = 1; iArg < argc; iArg++) { + if( argv[iArg][0] == '-' && argv[iArg][1] == 'q' ) { + return true; + } + } + + return false; +} + int processLineParams( int argc, char **argv ) { rtengine::procparams::PartialProfile *rawParams = nullptr, *imgParams = nullptr; @@ -292,6 +347,9 @@ int processLineParams( int argc, char **argv ) useDefault = true; break; + case 'q': + break; + case 'Y': overwriteFiles = true; break; @@ -432,6 +490,7 @@ int processLineParams( int argc, char **argv ) std::cout << "Options:" << std::endl; std::cout << " " << Glib::path_get_basename(argv[0]) << " [-o |-O ] [-s|-S] [-p [-p ...] ] [-d] [ -j[1-100] [-js<1-3>] | [-b<8|16>] [-t[z] | [-n]] ] [-Y] -c " << std::endl; std::cout << std::endl; + std::cout << " -q Quick Start mode : do not load cached files to speedup start time." << std::endl; std::cout << " -c Specify one or more input files." << std::endl; std::cout << " -c must be the last option." << std::endl; std::cout << " -o | Set output file or folder." << std::endl; diff --git a/rtgui/main.cc b/rtgui/main.cc index f27a0f32f..689d108c2 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -28,6 +28,7 @@ #include #include #include +#include "../rtengine/icons.h" #include "rtwindow.h" #include #include @@ -179,6 +180,7 @@ int main(int argc, char **argv) return -2; } + profileStore.init (); extProgStore->init(); SoundManager::init(); @@ -300,8 +302,8 @@ int main(int argc, char **argv) Glib::RefPtr defaultIconTheme = Gtk::IconTheme::get_default(); defaultIconTheme->append_search_path(icon_path); - RTImage::setPaths(options); - MyExpander::init(); // has to stay AFTER RTImage::setPaths + rtengine::setPaths(options); + MyExpander::init(); // has to stay AFTER rtengine::setPaths // ------- loading theme files @@ -410,185 +412,11 @@ void deleteProcParams(std::vector &pparam int processLineParams( int argc, char **argv ) { - rtengine::procparams::PartialProfile *rawParams = nullptr, *imgParams = nullptr; - std::vector inputFiles; - Glib::ustring outputPath = ""; - std::vector processingParams; - bool outputDirectory = false; - bool overwriteFiles = false; - bool sideProcParams = false; - bool copyParamsFile = false; - bool skipIfNoSidecar = false; - bool useDefault = false; - unsigned int sideCarFilePos = 0; - int compression = 92; - int subsampling = 3; - int bits = -1; - std::string outputType = ""; unsigned errors = 0; for( int iArg = 1; iArg < argc; iArg++) { if( argv[iArg][0] == '-' ) { switch( argv[iArg][1] ) { - case 'O': - copyParamsFile = true; - - case 'o': // outputfile or dir - if( iArg + 1 < argc ) { - iArg++; - outputPath = fname_to_utf8 (argv[iArg]); - - if( Glib::file_test (outputPath, Glib::FILE_TEST_IS_DIR)) { - outputDirectory = true; - } - } - - break; - - case 'p': // processing parameters for all inputs; all set procparams are required, so - - // RT stop if any of them can't be loaded for any reason. - if( iArg + 1 < argc ) { - iArg++; - Glib::ustring fname = fname_to_utf8 (argv[iArg]); - - if (fname.at(0) == '-') { - std::cerr << "Error: filename missing next to the -p switch" << std::endl; - deleteProcParams(processingParams); - return -3; - } - - rtengine::procparams::PartialProfile* currentParams = new rtengine::procparams::PartialProfile(true); - - if (!(currentParams->load ( fname ))) { - processingParams.push_back(currentParams); - } else { - std::cerr << "Error: \"" << fname << "\" not found" << std::endl; - deleteProcParams(processingParams); - return -3; - } - } - - break; - - case 'S': - skipIfNoSidecar = true; - - case 's': // Processing params next to file (file extension appended) - sideProcParams = true; - sideCarFilePos = processingParams.size(); - break; - - case 'd': - useDefault = true; - break; - - case 'Y': - overwriteFiles = true; - break; - - case 'j': - if (strlen(argv[iArg]) > 2 && argv[iArg][2] == 's') { - if (strlen(argv[iArg]) == 3) { - std::cerr << "Error: the -js switch requires a mandatory value!" << std::endl; - deleteProcParams(processingParams); - return -3; - } - - // looking for the subsampling parameter - sscanf(&argv[iArg][3], "%d", &subsampling); - - if (subsampling < 1 || subsampling > 3) { - std::cerr << "Error: the value accompanying the -js switch has to be in the [1-3] range!" << std::endl; - deleteProcParams(processingParams); - return -3; - } - } else { - outputType = "jpg"; - sscanf(&argv[iArg][2], "%d", &compression); - - if (compression < 0 || compression > 100) { - std::cerr << "Error: the value accompanying the -j switch has to be in the [0-100] range!" << std::endl; - deleteProcParams(processingParams); - return -3; - } - } - - break; - - case 'b': - sscanf(&argv[iArg][2], "%d", &bits); - - if (bits != 8 && bits != 16) { - std::cerr << "Error: specify -b8 for 8-bit or -b16 for 16-bit output." << std::endl; - deleteProcParams(processingParams); - return -3; - } - - break; - - case 't': - outputType = "tif"; - compression = ((argv[iArg][2] != 'z') ? 0 : 1); - break; - - case 'n': - outputType = "png"; - compression = -1; - break; - - case 'c': // MUST be last option - while (iArg + 1 < argc) { - iArg++; - - const auto argument = fname_to_utf8 (argv[iArg]); - - if (Glib::file_test (argument, Glib::FILE_TEST_IS_REGULAR)) { - inputFiles.emplace_back (argument); - continue; - } - - if (Glib::file_test (argument, Glib::FILE_TEST_IS_DIR)) { - - auto dir = Gio::File::create_for_path (argument); - if (!dir || !dir->query_exists()) { - continue; - } - - try { - - auto enumerator = dir->enumerate_children (); - - while (auto file = enumerator->next_file ()) { - - const auto fileName = Glib::build_filename (argument, file->get_name ()); - - if (Glib::file_test (fileName, Glib::FILE_TEST_IS_DIR)) { - continue; - } - - // skip files without extension and sidecar files - auto lastdot = fileName.find_last_of('.'); - if (lastdot == Glib::ustring::npos) { - continue; - } - - if (fileName.substr (lastdot).compare (paramFileExtension) == 0) { - continue; - } - - inputFiles.emplace_back (fileName); - } - - } catch (Glib::Exception&) {} - - continue; - } - - std::cerr << "\"" << argument << "\" is neither a regular file nor a directory." << std::endl; - } - - break; #ifdef WIN32 case 'w': // This case is handled outside this function @@ -615,86 +443,17 @@ int processLineParams( int argc, char **argv ) std::cout << "Usage:" << std::endl; std::cout << " " << Glib::path_get_basename(argv[0]) << " Start File Browser inside folder." << std::endl; std::cout << " " << Glib::path_get_basename(argv[0]) << " Start Image Editor with file." << std::endl; - std::cout << " " << Glib::path_get_basename(argv[0]) << " -c | Convert files in batch with default parameters." << std::endl; - std::cout << " " << Glib::path_get_basename(argv[0]) << " -c | Convert files in batch with your own settings." << std::endl; std::cout << std::endl; + std::cout << "Options:" << std::endl; #ifdef WIN32 std::cout << " -w Do not open the Windows console" << std::endl; - std::cout << std::endl; #endif - std::cout << "Options:" << std::endl; - std::cout << " " << Glib::path_get_basename(argv[0]) << " [-o |-O ] [-s|-S] [-p [-p ...] ] [-d] [ -j[1-100] [-js<1-3>] | [-b<8|16>] [-t[z] | [-n]] ] [-Y] -c " << std::endl; - std::cout << std::endl; - std::cout << " -c Specify one or more input files." << std::endl; - std::cout << " -c must be the last option." << std::endl; - std::cout << " -o | Set output file or folder." << std::endl; - std::cout << " Saves output file alongside input file if -o is not specified." << std::endl; - std::cout << " -O | Set output file or folder and copy " << pparamsExt << " file into it." << std::endl; - std::cout << " Saves output file alongside input file if -O is not specified." << std::endl; - std::cout << " -s Use the existing sidecar file to build the processing parameters," << std::endl; - std::cout << " e.g. for photo.raw there should be a photo.raw." << pparamsExt << " file in the same folder." << std::endl; - std::cout << " If the sidecar file does not exist, neutral values will be used." << std::endl; - std::cout << " -S Like -s but skip if the sidecar file does not exist." << std::endl; - std::cout << " -p Specify processing profile to be used for all conversions." << std::endl; - std::cout << " You can specify as many sets of \"-p \" options as you like," << std::endl; - std::cout << " each will be built on top of the previous one, as explained below." << std::endl; - std::cout << " -d Use the default raw or non-raw processing profile as set in" << std::endl; - std::cout << " Preferences > Image Processing > Default Processing Profile" << std::endl; - std::cout << " -j[1-100] Specify output to be JPEG (default, if -t and -n are not set)." << std::endl; - std::cout << " Optionally, specify compression 1-100 (default value: 92)." << std::endl; - std::cout << " -js<1-3> Specify the JPEG chroma subsampling parameter, where:" << std::endl; - std::cout << " 1 = Best compression: 2x2, 1x1, 1x1 (4:2:0)" << std::endl; - std::cout << " Chroma halved vertically and horizontally." << std::endl; - std::cout << " 2 = Balanced (default): 2x1, 1x1, 1x1 (4:2:2)" << std::endl; - std::cout << " Chroma halved horizontally." << std::endl; - std::cout << " 3 = Best quality: 1x1, 1x1, 1x1 (4:4:4)" << std::endl; - std::cout << " No chroma subsampling." << std::endl; - std::cout << " -b<8|16> Specify bit depth per channel (default value: 16 for TIFF, 8 for PNG)." << std::endl; - std::cout << " Only applies to TIFF and PNG output, JPEG is always 8." << std::endl; - std::cout << " -t[z] Specify output to be TIFF." << std::endl; - std::cout << " Uncompressed by default, or deflate compression with 'z'." << std::endl; - std::cout << " -n Specify output to be compressed PNG." << std::endl; - std::cout << " Compression is hard-coded to 6." << std::endl; - std::cout << " -Y Overwrite output if present." << std::endl; - std::cout << std::endl; - std::cout << "Your " << pparamsExt << " files can be incomplete, RawTherapee will build the final values as follows:" << std::endl; - std::cout << " 1- A new processing profile is created using neutral values," << std::endl; - std::cout << " 2- If the \"-d\" option is set, the values are overridden by those found in" << std::endl; - std::cout << " the default raw or non-raw processing profile." << std::endl; - std::cout << " 3- If one or more \"-p\" options are set, the values are overridden by those" << std::endl; - std::cout << " found in these processing profiles." << std::endl; - std::cout << " 4- If the \"-s\" or \"-S\" options are set, the values are finally overridden by those" << std::endl; - std::cout << " found in the sidecar files." << std::endl; - std::cout << " The processing profiles are processed in the order specified on the command line." << std::endl; + std::cout << " -h -? Display this help message" << std::endl; return -1; } } } else { argv1 = fname_to_utf8 (argv[iArg]); - - if( outputDirectory ) { - options.savePathFolder = outputPath; - options.saveUsePathTemplate = false; - } else { - options.saveUsePathTemplate = true; - - if (options.savePathTemplate.empty()) - // If the save path template is empty, we use its default value - { - options.savePathTemplate = "%p1/converted/%f"; - } - } - - if (outputType == "jpg") { - options.saveFormat.format = outputType; - options.saveFormat.jpegQuality = compression; - options.saveFormat.jpegSubSamp = subsampling; - } else if (outputType == "tif") { - options.saveFormat.format = outputType; - } else if (outputType == "png") { - options.saveFormat.format = outputType; - } - break; } } @@ -703,193 +462,5 @@ int processLineParams( int argc, char **argv ) return 1; } - if( inputFiles.empty() ) { - return 2; - } - - if (useDefault) { - rawParams = new rtengine::procparams::PartialProfile(true, true); - Glib::ustring profPath = options.findProfilePath(options.defProfRaw); - - if (options.is_defProfRawMissing() || profPath.empty() || rawParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfRaw.substr(5) + paramFileExtension))) { - std::cerr << "Error: default raw processing profile not found" << std::endl; - rawParams->deleteInstance(); - delete rawParams; - deleteProcParams(processingParams); - return -3; - } - - imgParams = new rtengine::procparams::PartialProfile(true); - profPath = options.findProfilePath(options.defProfImg); - - if (options.is_defProfImgMissing() || profPath.empty() || imgParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfImg.substr(5) + paramFileExtension))) { - std::cerr << "Error: default non-raw processing profile not found" << std::endl; - imgParams->deleteInstance(); - delete imgParams; - rawParams->deleteInstance(); - delete rawParams; - deleteProcParams(processingParams); - return -3; - } - } - - for( size_t iFile = 0; iFile < inputFiles.size(); iFile++) { - - // Has to be reinstanciated at each profile to have a ProcParams object with default values - rtengine::procparams::ProcParams currentParams; - - Glib::ustring inputFile = inputFiles[iFile]; - std::cout << "Processing: " << inputFile << std::endl; - - rtengine::InitialImage* ii = nullptr; - rtengine::ProcessingJob* job = nullptr; - int errorCode; - bool isRaw = false; - - Glib::ustring outputFile; - - if( outputType.empty() ) { - outputType = "jpg"; - } - - if( outputPath.empty() ) { - Glib::ustring s = inputFile; - Glib::ustring::size_type ext = s.find_last_of('.'); - outputFile = s.substr(0, ext) + "." + outputType; - } else if( outputDirectory ) { - Glib::ustring s = Glib::path_get_basename( inputFile ); - Glib::ustring::size_type ext = s.find_last_of('.'); - outputFile = outputPath + "/" + s.substr(0, ext) + "." + outputType; - } else { - Glib::ustring s = outputPath; - Glib::ustring::size_type ext = s.find_last_of('.'); - outputFile = s.substr(0, ext) + "." + outputType; - } - - if( inputFile == outputFile) { - std::cerr << "Cannot overwrite: " << inputFile << std::endl; - continue; - } - - if( !overwriteFiles && Glib::file_test( outputFile , Glib::FILE_TEST_EXISTS ) ) { - std::cerr << outputFile << " already exists: use -Y option to overwrite. This image has been skipped." << std::endl; - continue; - } - - // Load the image - isRaw = true; - Glib::ustring ext = getExtension (inputFile); - - if (ext.lowercase() == "jpg" || ext.lowercase() == "jpeg" || ext.lowercase() == "tif" || ext.lowercase() == "tiff" || ext.lowercase() == "png") { - isRaw = false; - } - - ii = rtengine::InitialImage::load ( inputFile, isRaw, &errorCode, nullptr ); - - if (!ii) { - errors++; - std::cerr << "Error loading file: " << inputFile << std::endl; - continue; - } - - if (useDefault) { - if (isRaw) { - std::cout << " Merging default raw processing profile" << std::endl; - rawParams->applyTo(¤tParams); - } else { - std::cout << " Merging default non-raw processing profile" << std::endl; - imgParams->applyTo(¤tParams); - } - } - - bool sideCarFound = false; - unsigned int i = 0; - - // Iterate the procparams file list in order to build the final ProcParams - do { - if (sideProcParams && i == sideCarFilePos) { - // using the sidecar file - Glib::ustring sideProcessingParams = inputFile + paramFileExtension; - - // the "load" method don't reset the procparams values anymore, so values found in the procparam file override the one of currentParams - if( !Glib::file_test( sideProcessingParams, Glib::FILE_TEST_EXISTS ) || currentParams.load ( sideProcessingParams )) { - std::cerr << "Warning: sidecar file requested but not found for: " << sideProcessingParams << std::endl; - } else { - sideCarFound = true; - std::cout << " Merging sidecar procparams" << std::endl; - } - } - - if( processingParams.size() > i ) { - std::cout << " Merging procparams #" << i << std::endl; - processingParams[i]->applyTo(¤tParams); - } - - i++; - } while (i < processingParams.size() + (sideProcParams ? 1 : 0)); - - if( sideProcParams && !sideCarFound && skipIfNoSidecar ) { - delete ii; - errors++; - std::cerr << "Error: no sidecar procparams found for: " << inputFile << std::endl; - continue; - } - - job = rtengine::ProcessingJob::create (ii, currentParams); - - if( !job ) { - errors++; - std::cerr << "Error creating processing for: " << inputFile << std::endl; - ii->decreaseRef(); - continue; - } - - // Process image - rtengine::IImage16* resultImage = rtengine::processImage (job, errorCode, nullptr, options.tunnelMetaData); - - if( !resultImage ) { - errors++; - std::cerr << "Error processing: " << inputFile << std::endl; - rtengine::ProcessingJob::destroy( job ); - continue; - } - - // save image to disk - if( outputType == "jpg" ) { - errorCode = resultImage->saveAsJPEG( outputFile, compression, subsampling ); - } else if( outputType == "tif" ) { - errorCode = resultImage->saveAsTIFF( outputFile, bits, compression == 0 ); - } else if( outputType == "png" ) { - errorCode = resultImage->saveAsPNG( outputFile, compression, bits ); - } else { - errorCode = resultImage->saveToFile (outputFile); - } - - if(errorCode) { - errors++; - std::cerr << "Error saving to: " << outputFile << std::endl; - } else { - if( copyParamsFile ) { - Glib::ustring outputProcessingParams = outputFile + paramFileExtension; - currentParams.save( outputProcessingParams ); - } - } - - ii->decreaseRef(); - resultImage->free(); - } - - if (imgParams) { - imgParams->deleteInstance(); - delete imgParams; - } - - if (rawParams) { - rawParams->deleteInstance(); - delete rawParams; - } - - deleteProcParams(processingParams); - return errors > 0 ? -2 : 0; } diff --git a/rtgui/options.cc b/rtgui/options.cc index 2b8203728..390778063 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -2177,7 +2177,7 @@ int Options::saveToFile (Glib::ustring fname) } } -bool Options::load () +bool Options::load (bool lightweight) { // Find the application data path @@ -2338,7 +2338,7 @@ bool Options::load () langMgr.load (localeTranslation, new MultiLangMgr (languageTranslation, new MultiLangMgr (defaultTranslation))); - rtengine::init (&options.rtSettings, argv0, rtdir); + rtengine::init (&options.rtSettings, argv0, rtdir, !lightweight); return true; } diff --git a/rtgui/options.h b/rtgui/options.h index 446e8d2cc..54c457cf6 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -306,7 +306,7 @@ public: void setDefaults (); int readFromFile (Glib::ustring fname); int saveToFile (Glib::ustring fname); - static bool load (); + static bool load (bool lightweight = false); static void save (); // if multiUser=false, send back the global profile path diff --git a/rtgui/pathutils.cc b/rtgui/pathutils.cc new file mode 100644 index 000000000..21c452d4c --- /dev/null +++ b/rtgui/pathutils.cc @@ -0,0 +1,48 @@ +/* + * This file is part of RawTherapee. + * + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#include "pathutils.h" + + +Glib::ustring removeExtension (const Glib::ustring& filename) +{ + + Glib::ustring bname = Glib::path_get_basename(filename); + size_t lastdot = bname.find_last_of ('.'); + size_t lastwhitespace = bname.find_last_of (" \t\f\v\n\r"); + + if (lastdot != bname.npos && (lastwhitespace == bname.npos || lastdot > lastwhitespace)) { + return filename.substr (0, filename.size() - (bname.size() - lastdot)); + } else { + return filename; + } +} + +Glib::ustring getExtension (const Glib::ustring& filename) +{ + + Glib::ustring bname = Glib::path_get_basename(filename); + size_t lastdot = bname.find_last_of ('.'); + size_t lastwhitespace = bname.find_last_of (" \t\f\v\n\r"); + + if (lastdot != bname.npos && (lastwhitespace == bname.npos || lastdot > lastwhitespace)) { + return filename.substr (filename.size() - (bname.size() - lastdot) + 1, filename.npos); + } else { + return ""; + } +} diff --git a/rtgui/pathutils.h b/rtgui/pathutils.h new file mode 100644 index 000000000..ce58103b9 --- /dev/null +++ b/rtgui/pathutils.h @@ -0,0 +1,34 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * 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 . + */ +#ifndef __PATH_UTILS_ +#define __PATH_UTILS_ + +#include +#include +#include "../rtengine/rtengine.h" +#include "../rtengine/coord.h" +#include "rtimage.h" +#include +#include + +// Removed from guiutils because used by rawtherapee-cli +Glib::ustring removeExtension (const Glib::ustring& filename); +Glib::ustring getExtension (const Glib::ustring& filename); + +#endif diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 04f3b1fe1..bcd8540fc 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -22,6 +22,7 @@ #include "splash.h" #include "cachemanager.h" #include "addsetids.h" +#include "../rtengine/icons.h" #include "../rtengine/dfmanager.h" #include "../rtengine/ffmanager.h" #include @@ -2026,7 +2027,7 @@ void Preferences::cancelPressed () { // set the initial theme back if (themeFNames.at(theme->get_active_row_number ()).longFName != options.theme) { - RTImage::setPaths(options); + rtengine::setPaths(options); RTImage::updateImages(); switchThemeTo(options.theme); } @@ -2079,7 +2080,7 @@ void Preferences::themeChanged () { moptions.theme = themeFNames.at(theme->get_active_row_number ()).longFName; - RTImage::setPaths(moptions); + rtengine::setPaths(moptions); RTImage::updateImages(); switchThemeTo(moptions.theme); } diff --git a/rtgui/rtimage.cc b/rtgui/rtimage.cc index 464123b0f..16e8e3286 100644 --- a/rtgui/rtimage.cc +++ b/rtgui/rtimage.cc @@ -23,51 +23,13 @@ #include #include "options.h" +#include "../rtengine/icons.h" namespace { -std::vector imagePaths; std::map> pixbufCache; -bool loadIconSet(const Glib::ustring& iconSet) -{ - try { - - Glib::KeyFile keyFile; - keyFile.load_from_file (iconSet); - - auto iconSetDir = keyFile.get_string ("General", "Iconset"); - - if (!iconSetDir.empty ()) { - imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "actions")); - imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir)); - imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "devices")); - imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "places")); - } - - iconSetDir = keyFile.get_string ("General", "FallbackIconset"); - - if (!iconSetDir.empty ()) { - imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "actions")); - imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir)); - imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "devices")); - imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "places")); - } - - return true; - - } catch (const Glib::Exception& exception) { - - if (options.rtSettings.verbose) { - std::cerr << "Failed to load icon set \"" << iconSet << "\": " << exception.what() << std::endl; - } - - return false; - - } -} - } RTImage::RTImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName) : Gtk::Image() @@ -90,7 +52,7 @@ void RTImage::changeImage (const Glib::ustring& imageName) auto iterator = pixbufCache.find (imageName); if (iterator == pixbufCache.end ()) { - const auto imagePath = findIconAbsolutePath (imageName); + const auto imagePath = rtengine::findIconAbsolutePath (imageName); const auto pixbuf = Gdk::Pixbuf::create_from_file (imagePath); iterator = pixbufCache.emplace (imageName, pixbuf).first; @@ -102,70 +64,18 @@ void RTImage::changeImage (const Glib::ustring& imageName) void RTImage::updateImages() { for (auto& entry : pixbufCache) { - const auto imagePath = findIconAbsolutePath (entry.first); + const auto imagePath = rtengine::findIconAbsolutePath (entry.first); entry.second = Gdk::Pixbuf::create_from_file (imagePath); } } -Glib::ustring RTImage::findIconAbsolutePath (const Glib::ustring& iconName) -{ - try { - - for (const auto& imagePath : imagePaths) { - const auto iconPath = Glib::build_filename(imagePath, iconName); - - if (Glib::file_test(iconPath, Glib::FILE_TEST_IS_REGULAR)) { - return iconPath; - } - } - - } catch(const Glib::Exception&) {} - - if (options.rtSettings.verbose) { - std::cerr << "Icon \"" << iconName << "\" could not be found!" << std::endl; - } - - return Glib::ustring(); -} - -void RTImage::setPaths (const Options& options) -{ - // TODO: Forcing the Dark theme, so reading the icon set files is useless for now... - - /*Glib::ustring iconSet; - - // Either use the system icon set or the one specified in the options. - if (options.useSystemTheme) { - iconSet = Glib::build_filename (argv0, "themes", "system.iconset"); - } else { - iconSet = Glib::build_filename (argv0, "themes", options.theme + ".iconset"); - } - - imagePaths.clear (); - - if (!loadIconSet (iconSet)) { - // If the preferred icon set is unavailable, fall back to the default icon set. - loadIconSet (Glib::build_filename (argv0, "themes", "Default.iconset")); - }*/ - - imagePaths.clear (); - - imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark")); - imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark", "actions")); - imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark", "devices")); - imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark", "places")); - - // The images folder is the second fallback solution. - imagePaths.push_back (Glib::build_filename(argv0, "images")); -} - Glib::RefPtr RTImage::createFromFile (const Glib::ustring& fileName) { Glib::RefPtr pixbuf; try { - const auto filePath = findIconAbsolutePath (fileName); + const auto filePath = rtengine::findIconAbsolutePath (fileName); if (!filePath.empty ()) { pixbuf = Gdk::Pixbuf::create_from_file (filePath); @@ -188,7 +98,7 @@ Cairo::RefPtr RTImage::createFromPng (const Glib::ustring& try { - const auto filePath = findIconAbsolutePath (fileName); + const auto filePath = rtengine::findIconAbsolutePath (fileName); if (!filePath.empty()) { surface = Cairo::ImageSurface::create_from_png (Glib::locale_from_utf8 (filePath)); diff --git a/rtgui/rtimage.h b/rtgui/rtimage.h index cfc7a5fa1..0286d990b 100644 --- a/rtgui/rtimage.h +++ b/rtgui/rtimage.h @@ -34,9 +34,6 @@ public: void changeImage (const Glib::ustring& imageName); static void updateImages (); - static Glib::ustring findIconAbsolutePath (const Glib::ustring& iconName); - static void setPaths (const Options& options); - static Glib::RefPtr createFromFile (const Glib::ustring& fileName); static Cairo::RefPtr createFromPng (const Glib::ustring& fileName); }; diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index 9fc593d22..be7a68b25 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -24,6 +24,7 @@ #include "cursormanager.h" #include "rtimage.h" #include "whitebalance.h" +#include "../rtengine/icons.h" #if defined(__APPLE__) static gboolean @@ -93,7 +94,7 @@ RTWindow::RTWindow () ProfilePanel::init (this); Glib::ustring fName = "rt-logo-small.png"; - Glib::ustring fullPath = RTImage::findIconAbsolutePath(fName); + Glib::ustring fullPath = rtengine::findIconAbsolutePath(fName); try { set_default_icon_from_file (fullPath);