diff --git a/CMakeLists.txt b/CMakeLists.txt index 13ba209bf..01865fcf7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -445,6 +445,34 @@ if(UNIX) install(FILES rawtherapee.appdata.xml DESTINATION "${APPDATADIR}") endif() +# check whether the used version of lensfun has lfDatabase::LoadDirectory +include(CheckCXXSourceCompiles) +set(CMAKE_REQUIRED_INCLUDES ${LENSFUN_INCLUDE_DIRS}) +set(CMAKE_REQUIRED_LIBRARIES) +foreach(l ${LENSFUN_LIBRARIES}) + if(LENSFUN_LIBRARY_DIRS) + # the NO_DEFAULT_PATH is to make sure we find the lensfun version we + # want, and not the system's one (e.g. if we have a custom version + # installed in a non-standard location) + find_library(_l ${l} PATHS ${LENSFUN_LIBRARY_DIRS} NO_DEFAULT_PATH) + else() + # LENSFUN_LIBRARY_DIRS can be empty if lensfun is installed in the + # default path. In this case, adding NO_DEFAULT_PATH would make + # find_library fail... + find_library(_l ${l}) + endif() + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${_l}) +endforeach() +check_cxx_source_compiles( + "#include +int main() +{ + lfDatabase *db = 0; + bool b = db->LoadDirectory(0); + return 0; +}" LENSFUN_HAS_LOAD_DIRECTORY) + + add_subdirectory(rtexif) add_subdirectory(rtengine) add_subdirectory(rtgui) diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 32d7a4179..db8ce6d6c 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -22,6 +22,7 @@ link_directories("${PROJECT_SOURCE_DIR}/rtexif" ${GTHREAD_LIBRARY_DIRS} ${IPTCDATA_LIBRARY_DIRS} ${LCMS_LIBRARY_DIRS} + ${LENSFUN_LIBRARY_DIRS} ) set(CAMCONSTSFILE "camconst.json") @@ -114,6 +115,11 @@ set(RTENGINESOURCEFILES rtlensfun.cc ) +if(LENSFUN_HAS_LOAD_DIRECTORY) + set_source_files_properties(rtlensfun.cc PROPERTIES COMPILE_DEFINITIONS RT_LENSFUN_HAS_LOAD_DIRECTORY) +endif() + + if(NOT WITH_SYSTEM_KLT) set(RTENGINESOURCEFILES ${RTENGINESOURCEFILES} klt/convolve.cc diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 5bda02f86..0976278f0 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -2930,9 +2930,13 @@ void CLASS kodak_65000_load_raw() pred[0] = pred[1] = 0; len = MIN (256, width-col); ret = kodak_65000_decode (buf, len); - for (i=0; i < len; i++) - if ((RAW(row,col+i) = curve[ret ? buf[i] : - (pred[i & 1] += buf[i])]) >> 12) derror(); + for (i=0; i < len; i++) { + int idx = ret ? buf[i] : (pred[i & 1] += buf[i]); + if(idx >=0 && idx <= 0xffff) { + if ((RAW(row,col+i) = curve[idx]) >> 12) derror(); + } else + derror(); + } } } diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 48dd6a92b..d7c4146fb 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -1752,9 +1752,7 @@ bool check_need_larger_crop_for_lcp_distortion (int fw, int fh, int x, int y, in return false; } - return (params.lensProf.useDist && - (params.lensProf.useLensfun || - params.lensProf.lcpFile.length() > 0)); + return (params.lensProf.useDist && (params.lensProf.useLensfun() || params.lensProf.useLcp())); } } // namespace diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index a99864c7d..92ff0c3d6 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -3822,7 +3822,7 @@ void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int & LensCorrection *pLCPMap = nullptr; - if (params.lensProf.lcpFile.length() && imgsrc->getMetaData()->getFocalLen() > 0) { + if (params.lensProf.useLcp() && imgsrc->getMetaData()->getFocalLen() > 0) { const std::shared_ptr pLCPProf = LCPStore::getInstance()->getProfile (params.lensProf.lcpFile); if (pLCPProf) pLCPMap = new LCPMapper (pLCPProf, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 49b6b7d24..712e1353b 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -204,7 +204,7 @@ public: ImProcFunctions (const ProcParams* iparams, bool imultiThread = true) : monitorTransform (nullptr), lab2outputTransform (nullptr), output2monitorTransform (nullptr), params (iparams), scale (1), multiThread (imultiThread), lumimul{} {} ~ImProcFunctions (); - + bool needsLuminanceOnly() { return !(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP() || needsLensfun()) && (needsVignetting() || needsPCVignetting() || needsGradient());} void setScale (double iscale); bool needsTransform (); diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index bfd01b301..d3e6ca759 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -307,7 +307,7 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, std::unique_ptr pLCPMap; if (needsLensfun()) { - pLCPMap = std::move(LFDatabase::findModifier(params->lensProf, metadata, oW, oH, params->coarse, rawRotationDeg)); + pLCPMap = LFDatabase::findModifier(params->lensProf, metadata, oW, oH, params->coarse, rawRotationDeg); } else if (needsLCP()) { // don't check focal length to allow distortion correction for lenses without chip const std::shared_ptr pLCPProf = LCPStore::getInstance()->getProfile (params->lensProf.lcpFile); @@ -1015,12 +1015,12 @@ bool ImProcFunctions::needsVignetting () bool ImProcFunctions::needsLCP () { - return params->lensProf.lcpFile.length() > 0 && !needsLensfun(); + return params->lensProf.useLcp(); } bool ImProcFunctions::needsLensfun() { - return params->lensProf.useLensfun; + return params->lensProf.useLensfun(); } bool ImProcFunctions::needsTransform () diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index dcb6c8d65..e09044077 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -52,6 +52,7 @@ const int br = (int) options.rtSettings.bot_right; const int tl = (int) options.rtSettings.top_left; const int bl = (int) options.rtSettings.bot_left; +const char *LensProfParams::methodstring[static_cast(LensProfParams::LcMode::LCP) + 1u] = {"none", "lfauto", "lfmanual", "lcp"}; const char *RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::numMethods] = {"amaze", "igv", "lmmse", "eahd", "hphd", "vng4", "dcb", "ahd", "fast", "mono", "none", "pixelshift" }; const char *RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::numMethods] = {"3-pass (best)", "1-pass (medium)", "fast", "mono", "none" }; @@ -919,11 +920,10 @@ void ToneCurveParams::setDefaults() void LensProfParams::setDefaults() { + lcMode = LcMode::NONE; lcpFile = ""; useDist = useVign = true; useCA = false; - useLensfun = false; - lfAutoMatch = true; lfCameraMake = ""; lfCameraModel = ""; lfLens = ""; @@ -2816,6 +2816,10 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b } // lens profile + if (!pedited || pedited->lensProf.lcMode) { + keyFile.set_string ("LensProfile", "LcMode", lensProf.getMethodString (lensProf.lcMode)); + } + if (!pedited || pedited->lensProf.lcpFile) { keyFile.set_string ("LensProfile", "LCPFile", relativePathIfInside (fname, fnameAbsolute, lensProf.lcpFile)); } @@ -2832,12 +2836,6 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b keyFile.set_boolean ("LensProfile", "UseCA", lensProf.useCA); } - if (!pedited || pedited->lensProf.useLensfun) { - keyFile.set_boolean("LensProfile", "UseLensfun", lensProf.useLensfun); - } - if (!pedited || pedited->lensProf.lfAutoMatch) { - keyFile.set_boolean("LensProfile", "LFAutoMatch", lensProf.lfAutoMatch); - } if (!pedited || pedited->lensProf.lfCameraMake) { keyFile.set_string("LensProfile", "LFCameraMake", lensProf.lfCameraMake); } @@ -7187,12 +7185,24 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited) // lens profile if (keyFile.has_group ("LensProfile")) { + if (keyFile.has_key ("LensProfile", "LcMode")) { + lensProf.lcMode = lensProf.getMethodNumber (keyFile.get_string ("LensProfile", "LcMode")); + + if (pedited) { + pedited->lensProf.lcMode = true; + } + } + if (keyFile.has_key ("LensProfile", "LCPFile")) { lensProf.lcpFile = expandRelativePath (fname, "", keyFile.get_string ("LensProfile", "LCPFile")); if (pedited) { pedited->lensProf.lcpFile = true; } + + if(ppVersion < 327 && !lensProf.lcpFile.empty()) { + lensProf.lcMode = LensProfParams::LcMode::LCP; + } } if (keyFile.has_key ("LensProfile", "UseDistortion")) { @@ -7219,20 +7229,6 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited) } } - if (keyFile.has_key("LensProfile", "UseLensfun")) { - lensProf.useLensfun = keyFile.get_boolean("LensProfile", "UseLensfun"); - if (pedited) { - pedited->lensProf.useLensfun = true; - } - } - - if (keyFile.has_key("LensProfile", "LFAutoMatch")) { - lensProf.lfAutoMatch = keyFile.get_boolean("LensProfile", "LFAutoMatch"); - if (pedited) { - pedited->lensProf.lfAutoMatch = true; - } - } - if (keyFile.has_key("LensProfile", "LFCameraMake")) { lensProf.lfCameraMake = keyFile.get_string("LensProfile", "LFCameraMake"); if (pedited) { @@ -9865,12 +9861,11 @@ bool ProcParams::operator== (const ProcParams& other) && rotate.degree == other.rotate.degree && commonTrans.autofill == other.commonTrans.autofill && distortion.amount == other.distortion.amount + && lensProf.lcMode == other.lensProf.lcMode && lensProf.lcpFile == other.lensProf.lcpFile && lensProf.useDist == other.lensProf.useDist && lensProf.useVign == other.lensProf.useVign && lensProf.useCA == other.lensProf.useCA - && lensProf.useLensfun == other.lensProf.useLensfun - && lensProf.lfAutoMatch == other.lensProf.lfAutoMatch && lensProf.lfCameraMake == other.lensProf.lfCameraMake && lensProf.lfCameraModel == other.lensProf.lfCameraModel && lensProf.lfLens == other.lensProf.lfLens diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 4d8089d47..fe00a9632 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -834,10 +834,17 @@ class LensProfParams { public: + enum class LcMode { + NONE, // No lens correction + LENSFUNAUTOMATCH, // Lens correction using auto matched lensfun database entry + LENSFUNMANUAL, // Lens correction using manually selected lensfun database entry + LCP // Lens correction using lcp file + }; + + static const char *methodstring[static_cast(LcMode::LCP) + 1u]; + LcMode lcMode; Glib::ustring lcpFile; bool useDist, useVign, useCA; - bool useLensfun; - bool lfAutoMatch; Glib::ustring lfCameraMake; Glib::ustring lfCameraModel; Glib::ustring lfLens; @@ -847,6 +854,41 @@ public: setDefaults(); } void setDefaults(); + + bool useLensfun() const + { + return lcMode == LcMode::LENSFUNAUTOMATCH || lcMode == LcMode::LENSFUNMANUAL; + } + + bool lfAutoMatch() const + { + return lcMode == LcMode::LENSFUNAUTOMATCH; + } + + bool useLcp() const + { + return lcMode == LcMode::LCP && lcpFile.length() > 0; + } + + bool lfManual() const + { + return lcMode == LcMode::LENSFUNMANUAL; + } + + Glib::ustring getMethodString(LcMode mode) const + { + return methodstring[static_cast(mode)]; + } + + LcMode getMethodNumber(const Glib::ustring &mode) const + { + for(size_t i = 0; i <= static_cast(LcMode::LCP); ++i) { + if(methodstring[i] == mode) { + return static_cast(i); + } + } + return LcMode::NONE; + } }; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 06c4a80c4..3ebcfe6fd 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1865,8 +1865,8 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le // Correct vignetting of lens profile if (!hasFlatField && lensProf.useVign) { std::unique_ptr pmap; - if (lensProf.useLensfun) { - pmap = std::move(LFDatabase::findModifier(lensProf, idata, W, H, coarse, -1)); + if (lensProf.useLensfun()) { + pmap = LFDatabase::findModifier(lensProf, idata, W, H, coarse, -1); } else { const std::shared_ptr pLCPProf = LCPStore::getInstance()->getProfile(lensProf.lcpFile); diff --git a/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc index a352613ab..2f47ec1a3 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -267,7 +267,12 @@ bool LFDatabase::init(const Glib::ustring &dbdir) std::cout << "..." << std::flush; } - bool ok = dbdir.empty() ? (instance_.data_->Load() == LF_NO_ERROR) : instance_.data_->LoadDirectory(dbdir.c_str()); + bool ok = false; + if (dbdir.empty()) { + ok = (instance_.data_->Load() == LF_NO_ERROR); + } else { + ok = instance_.LoadDirectory(dbdir.c_str()); + } if (settings->verbose) { std::cout << (ok ? "OK" : "FAIL") << std::endl; @@ -277,6 +282,43 @@ bool LFDatabase::init(const Glib::ustring &dbdir) } +bool LFDatabase::LoadDirectory(const char *dirname) +{ +#if RT_LENSFUN_HAS_LOAD_DIRECTORY + return instance_.data_->LoadDirectory(dirname); +#else + // backported from lensfun 0.3.x + bool database_found = false; + + GDir *dir = g_dir_open (dirname, 0, NULL); + if (dir) + { + GPatternSpec *ps = g_pattern_spec_new ("*.xml"); + if (ps) + { + const gchar *fn; + while ((fn = g_dir_read_name (dir))) + { + size_t sl = strlen (fn); + if (g_pattern_match (ps, sl, fn, NULL)) + { + gchar *ffn = g_build_filename (dirname, fn, NULL); + /* Ignore errors */ + if (data_->Load (ffn) == LF_NO_ERROR) + database_found = true; + g_free (ffn); + } + } + g_pattern_spec_free (ps); + } + g_dir_close (dir); + } + + return database_found; +#endif +} + + LFDatabase::LFDatabase(): data_(nullptr) { @@ -395,7 +437,7 @@ std::unique_ptr LFDatabase::findModifier(const LensProfParams &lensP const LFDatabase *db = getInstance(); Glib::ustring make, model, lens; float focallen = idata->getFocalLen(); - if (lensProf.lfAutoMatch) { + if (lensProf.lfAutoMatch()) { if (focallen <= 0) { return nullptr; } @@ -408,7 +450,7 @@ std::unique_ptr LFDatabase::findModifier(const LensProfParams &lensP lens = lensProf.lfLens; } LFCamera c = db->findCamera(make, model); - LFLens l = db->findLens(lensProf.lfAutoMatch ? c : LFCamera(), lens); + LFLens l = db->findLens(lensProf.lfAutoMatch() ? c : LFCamera(), lens); if (focallen <= 0 && l.data_ && l.data_->MinFocal == l.data_->MaxFocal) { focallen = l.data_->MinFocal; } diff --git a/rtengine/rtlensfun.h b/rtengine/rtlensfun.h index a4ff17ae9..303c9a45a 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -46,7 +46,7 @@ public: bool isCACorrectionAvailable() const override; void correctCA(double &x, double &y, int channel) const override; void processVignetteLine(int width, int y, float *line) const override; - void processVignetteLine3Channels(int width, int y, float *line) const; + void processVignetteLine3Channels(int width, int y, float *line) const override; Glib::ustring getDisplayString() const; @@ -117,6 +117,8 @@ private: float focalLen, float aperture, float focusDist, int width, int height, bool swap_xy) const; LFDatabase(); + bool LoadDirectory(const char *dirname); + static LFDatabase instance_; lfDatabase *data_; }; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index fca686fc9..ceb1bb8bc 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -819,11 +819,17 @@ private: // perform transform (excepted resizing) if (ipf.needsTransform()) { - Imagefloat* trImg = new Imagefloat (fw, fh); - ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh, + Imagefloat* trImg = nullptr; + if (ipf.needsLuminanceOnly()) { + trImg = baseImg; + } else { + trImg = new Imagefloat (fw, fh); + } ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh, imgsrc->getMetaData(), imgsrc->getRotateDegree(), true); - delete baseImg; - baseImg = trImg; + if(trImg != baseImg) { + delete baseImg; + baseImg = trImg; + } } } diff --git a/rtexif/CMakeLists.txt b/rtexif/CMakeLists.txt index 820f682a4..9747b03fb 100644 --- a/rtexif/CMakeLists.txt +++ b/rtexif/CMakeLists.txt @@ -3,11 +3,11 @@ add_dependencies(rtexif UpdateInfo) if(WIN32) include_directories(${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS}) - link_directories(. "${PROJECT_SOURCE_DIR}/rtexif" ${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS}) + link_directories(. "${PROJECT_SOURCE_DIR}/rtexif" ${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${LENSFUN_LIBRARY_DIRS}) else() set_target_properties(rtexif PROPERTIES COMPILE_FLAGS " -fPIC") include_directories(${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS}) - link_directories(${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS}) + link_directories(${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${LENSFUN_LIBRARY_DIRS}) endif() include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 99f1eb352..1fad0644b 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -180,6 +180,7 @@ if(WIN32) ${GLIBMM_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} + ${LENSFUN_LIBRARY_DIRS} ) else() include_directories(${EXTRA_INCDIR} @@ -212,6 +213,7 @@ else() ${GTK_LIBRARY_DIRS} ${IPTCDATA_LIBRARY_DIRS} ${LCMS_LIBRARY_DIRS} + ${LENSFUN_LIBRARY_DIRS} ) endif() diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index f1835be89..f3e6189ba 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1722,7 +1722,7 @@ void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) } } -bool EditorPanel::idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf) +bool EditorPanel::idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf, rtengine::procparams::ProcParams &pparams) { rtengine::IImage16* img = pc->returnValue(); delete pc; @@ -1736,13 +1736,13 @@ bool EditorPanel::idle_saveImage (ProgressConnector *pc, Gl if (sf.format == "tif") ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImage16::saveAsTIFF), fname, sf.tiffBits, sf.tiffUncompressed), - sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf)); + sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf, pparams)); else if (sf.format == "png") ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImage16::saveAsPNG), fname, sf.pngCompression, sf.pngBits), - sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf)); + sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf, pparams)); else if (sf.format == "jpg") ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImage16::saveAsJPEG), fname, sf.jpegQuality, sf.jpegSubSamp), - sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf)); + sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf, pparams)); else { delete ld; } @@ -1762,7 +1762,7 @@ bool EditorPanel::idle_saveImage (ProgressConnector *pc, Gl return false; } -bool EditorPanel::idle_imageSaved (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf) +bool EditorPanel::idle_imageSaved (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf, rtengine::procparams::ProcParams &pparams) { img->free (); @@ -1771,11 +1771,8 @@ bool EditorPanel::idle_imageSaved (ProgressConnector *pc, rtengine::IImage1 // save processing parameters, if needed if (sf.saveParams) { - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); // We keep the extension to avoid overwriting the profile when we have // the same output filename with different extension - //pparams.save (removeExtension (fname) + ".out" + paramFileExtension); pparams.save (fname + ".out" + paramFileExtension); } } else { @@ -1892,7 +1889,7 @@ void EditorPanel::saveAsPressed () ProgressConnector *ld = new ProgressConnector(); ld->startFunc (sigc::bind (sigc::ptr_fun (&rtengine::processImage), job, err, parent->getProgressListener(), options.tunnelMetaData, false ), - sigc::bind (sigc::mem_fun ( *this, &EditorPanel::idle_saveImage ), ld, fnameOut, sf )); + sigc::bind (sigc::mem_fun ( *this, &EditorPanel::idle_saveImage ), ld, fnameOut, sf, pparams)); saveimgas->set_sensitive (false); sendtogimp->set_sensitive (false); } diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 286905bf5..9c063661a 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -146,8 +146,8 @@ private: void close (); BatchQueueEntry* createBatchQueueEntry (); - bool idle_imageSaved (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf); - bool idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf); + bool idle_imageSaved (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf, rtengine::procparams::ProcParams &pparams); + bool idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf, rtengine::procparams::ProcParams &pparams); bool idle_sendToGimp ( ProgressConnector *pc, Glib::ustring fname); bool idle_sentToGimp (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring filename); diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index bb9138461..f95e27321 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -33,6 +33,7 @@ LensProfilePanel::LFDbHelper *LensProfilePanel::lf(nullptr); LensProfilePanel::LensProfilePanel () : FoldableToolPanel(this, "lensprof", M("TP_LENSPROFILE_LABEL")), + lcModeChanged(false), lcpFileChanged(false), useDistChanged(false), useVignChanged(false), @@ -122,10 +123,6 @@ LensProfilePanel::LensProfilePanel () : hbLCPFile->pack_start(*fcbLCPFile); - btnReset = Gtk::manage(new Gtk::Button()); - btnReset->set_image (*Gtk::manage(new RTImage ("gtk-cancel.png"))); - hbLCPFile->pack_start(*btnReset, Gtk::PACK_SHRINK, 4); - pack_start(*hbLCPFile, Gtk::PACK_SHRINK, 4); ckbUseDist = Gtk::manage (new Gtk::CheckButton (M("TP_LENSPROFILE_USEDIST"))); @@ -136,7 +133,6 @@ LensProfilePanel::LensProfilePanel () : pack_start (*ckbUseCA, Gtk::PACK_SHRINK, 4); conLCPFile = fcbLCPFile->signal_file_set().connect( sigc::mem_fun(*this, &LensProfilePanel::onLCPFileChanged), true); - btnReset->signal_clicked().connect( sigc::mem_fun(*this, &LensProfilePanel::onLCPFileReset), true); conUseDist = ckbUseDist->signal_toggled().connect( sigc::mem_fun(*this, &LensProfilePanel::onUseDistChanged) ); ckbUseVign->signal_toggled().connect( sigc::mem_fun(*this, &LensProfilePanel::onUseVignChanged) ); ckbUseCA->signal_toggled().connect( sigc::mem_fun(*this, &LensProfilePanel::onUseCAChanged) ); @@ -163,32 +159,33 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa } corrLensfunAuto->set_sensitive(true); - - if (pp->lensProf.useLensfun) { - if (pp->lensProf.lfAutoMatch) { + + switch(pp->lensProf.lcMode) { + case procparams::LensProfParams::LcMode::LCP : + corrLcpFile->set_active(true); + break; + case procparams::LensProfParams::LcMode::LENSFUNAUTOMATCH : corrLensfunAuto->set_active(true); - } else { + break; + case procparams::LensProfParams::LcMode::LENSFUNMANUAL : corrLensfunManual->set_active(true); - } - } else if (!pp->lensProf.lcpFile.empty() && LCPStore::getInstance()->isValidLCPFileName(pp->lensProf.lcpFile)) { - corrLcpFile->set_active(true); + break; + case procparams::LensProfParams::LcMode::NONE : + corrOff->set_active(true); + } + + if (pp->lensProf.lcpFile.empty()) { + Glib::ustring lastFolder = fcbLCPFile->get_current_folder(); + fcbLCPFile->set_current_folder(lastFolder); + fcbLCPFile->set_filename(lastFolder + "/."); + bindCurrentFolder(*fcbLCPFile, options.lastLensProfileDir); + updateDisabled(false); + } else if (LCPStore::getInstance()->isValidLCPFileName(pp->lensProf.lcpFile)) { fcbLCPFile->set_filename (pp->lensProf.lcpFile); updateDisabled(true); } else { - Glib::ustring fname = fcbLCPFile->get_filename(); - - if (!pp->lensProf.lcpFile.empty()) { - fcbLCPFile->unselect_filename(fname); - } else { - Glib::ustring lastFolder = fcbLCPFile->get_current_folder(); - fcbLCPFile->set_current_folder(lastFolder); - fcbLCPFile->set_filename(lastFolder + "/."); - bindCurrentFolder(*fcbLCPFile, options.lastLensProfileDir); - } - + fcbLCPFile->unselect_filename(fcbLCPFile->get_filename()); updateDisabled(false); - - corrOff->set_active(true); } ckbUseDist->set_active (pp->lensProf.useDist); @@ -203,14 +200,14 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa l = db->findLens(c, metadata->getLens()); } - if (!setLensfunCamera(pp->lensProf.lfCameraMake, pp->lensProf.lfCameraModel) && pp->lensProf.lfAutoMatch) { + if (!setLensfunCamera(pp->lensProf.lfCameraMake, pp->lensProf.lfCameraModel) && !pp->lensProf.lfManual()) { setLensfunCamera(c.getMake(), c.getModel()); } - if (!setLensfunLens(pp->lensProf.lfLens) && pp->lensProf.lfAutoMatch) { + if (!setLensfunLens(pp->lensProf.lfLens) && !pp->lensProf.lfManual()) { setLensfunLens(l.getLens()); } - lcpFileChanged = useDistChanged = useVignChanged = useCAChanged = false; + lcModeChanged = lcpFileChanged = useDistChanged = useVignChanged = useCAChanged = false; useLensfunChanged = lensfunAutoChanged = lensfunCameraChanged = lensfunLensChanged = false; if (!batchMode && !checkLensfunCanCorrect(true)) { @@ -276,7 +273,17 @@ void LensProfilePanel::setRawMeta(bool raw, const rtengine::ImageMetaData* pMeta void LensProfilePanel::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - if (corrLcpFile->get_active() && LCPStore::getInstance()->isValidLCPFileName(fcbLCPFile->get_filename())) { + if (corrLcpFile->get_active()) { + pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LCP; + } else if(corrLensfunManual->get_active()) { + pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LENSFUNMANUAL; + } else if(corrLensfunAuto->get_active()) { + pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LENSFUNAUTOMATCH; + } else if(corrOff->get_active()) { + pp->lensProf.lcMode = procparams::LensProfParams::LcMode::NONE; + } + + if (LCPStore::getInstance()->isValidLCPFileName(fcbLCPFile->get_filename())) { pp->lensProf.lcpFile = fcbLCPFile->get_filename(); } else { pp->lensProf.lcpFile = ""; @@ -286,8 +293,6 @@ void LensProfilePanel::write( rtengine::procparams::ProcParams* pp, ParamsEdited pp->lensProf.useVign = ckbUseVign->get_active(); pp->lensProf.useCA = ckbUseCA->get_active(); - pp->lensProf.useLensfun = corrLensfunAuto->get_active() || corrLensfunManual->get_active(); - pp->lensProf.lfAutoMatch = corrLensfunAuto->get_active(); auto itc = lensfunCameras->get_active(); if (itc) { pp->lensProf.lfCameraMake = (*itc)[lf->lensfunModelCam.make]; @@ -304,6 +309,7 @@ void LensProfilePanel::write( rtengine::procparams::ProcParams* pp, ParamsEdited } if (pedited) { + pedited->lensProf.lcMode = lcModeChanged; pedited->lensProf.lcpFile = lcpFileChanged; pedited->lensProf.useDist = useDistChanged; pedited->lensProf.useVign = useVignChanged; @@ -332,22 +338,6 @@ void LensProfilePanel::onLCPFileChanged() } } -void LensProfilePanel::onLCPFileReset() -{ - lcpFileChanged = true; - - fcbLCPFile->unselect_filename(fcbLCPFile->get_filename()); - updateDisabled(false); - - - if (listener) { - disableListener(); - corrOff->set_active(true); - enableListener(); - listener->panelChanged (EvLCPFile, M("GENERAL_NONE")); - } -} - void LensProfilePanel::onUseDistChanged() { useDistChanged = true; @@ -563,7 +553,7 @@ void LensProfilePanel::onCorrModeChanged() mode = M("GENERAL_UNCHANGED"); } - + lcModeChanged = true; updateLensfunWarning(); if (listener) { @@ -579,7 +569,6 @@ bool LensProfilePanel::checkLensfunCanCorrect(bool automatch) } rtengine::procparams::ProcParams lpp; write(&lpp); - lpp.lensProf.lfAutoMatch = automatch; std::unique_ptr mod(LFDatabase::findModifier(lpp.lensProf, metadata, 100, 100, lpp.coarse, -1)); return mod.get() != nullptr; } diff --git a/rtgui/lensprofile.h b/rtgui/lensprofile.h index aca8f16ef..1b1554cab 100644 --- a/rtgui/lensprofile.h +++ b/rtgui/lensprofile.h @@ -32,9 +32,8 @@ protected: MyFileChooserButton *fcbLCPFile; Gtk::CheckButton *ckbUseDist, *ckbUseVign, *ckbUseCA; Gtk::HBox *hbLCPFile; - Gtk::Button *btnReset; Gtk::Label *lLCPFileHead; - bool lcpFileChanged, useDistChanged, useVignChanged, useCAChanged; + bool lcModeChanged, lcpFileChanged, useDistChanged, useVignChanged, useCAChanged; sigc::connection conLCPFile, conUseDist, conUseVign, conUseCA; void updateDisabled(bool enable); bool allowFocusDep; @@ -98,7 +97,6 @@ public: void setRawMeta (bool raw, const rtengine::ImageMetaData* pMeta); void onLCPFileChanged (); - void onLCPFileReset (); void onUseDistChanged(); void onUseVignChanged(); void onUseCAChanged(); diff --git a/rtgui/main.cc b/rtgui/main.cc index cd7158845..48f3f2cc7 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -641,7 +641,7 @@ int main (int argc, char **argv) printf ("Error: -gimp requires two arguments\n"); return 1; } - } else if (!remote && Glib::file_test (argv1, Glib::FILE_TEST_EXISTS)) { + } else if (!remote && Glib::file_test(argv1, Glib::FILE_TEST_EXISTS) && !Glib::file_test(argv1, Glib::FILE_TEST_IS_DIR)) { simpleEditor = true; } diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 0fac5c97d..ccbd2148b 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -287,6 +287,7 @@ void ParamsEdited::set (bool v) commonTrans.autofill = v; rotate.degree = v; distortion.amount = v; + lensProf.lcMode = v; lensProf.lcpFile = v; lensProf.useDist = v; lensProf.useVign = v; @@ -922,12 +923,13 @@ void ParamsEdited::initFrom (const std::vector commonTrans.autofill = commonTrans.autofill && p.commonTrans.autofill == other.commonTrans.autofill; rotate.degree = rotate.degree && p.rotate.degree == other.rotate.degree; distortion.amount = distortion.amount && p.distortion.amount == other.distortion.amount; + lensProf.lcMode = lensProf.lcMode && p.lensProf.lcMode == other.lensProf.lcMode; lensProf.lcpFile = lensProf.lcpFile && p.lensProf.lcpFile == other.lensProf.lcpFile; lensProf.useDist = lensProf.useDist && p.lensProf.useDist == other.lensProf.useDist; lensProf.useVign = lensProf.useVign && p.lensProf.useVign == other.lensProf.useVign; lensProf.useCA = lensProf.useCA && p.lensProf.useCA == other.lensProf.useCA; - lensProf.useLensfun = lensProf.useLensfun && p.lensProf.useLensfun == other.lensProf.useLensfun; - lensProf.lfAutoMatch = lensProf.lfAutoMatch && p.lensProf.lfAutoMatch == other.lensProf.lfAutoMatch; + lensProf.useLensfun = lensProf.useLensfun && p.lensProf.useLensfun() == other.lensProf.useLensfun(); + lensProf.lfAutoMatch = lensProf.lfAutoMatch && p.lensProf.lfAutoMatch() == other.lensProf.lfAutoMatch(); lensProf.lfCameraMake = lensProf.lfCameraMake && p.lensProf.lfCameraMake == other.lensProf.lfCameraMake; lensProf.lfCameraModel = lensProf.lfCameraModel && p.lensProf.lfCameraModel == other.lensProf.lfCameraModel; lensProf.lfLens = lensProf.lfLens && p.lensProf.lfLens == other.lensProf.lfLens; @@ -2253,6 +2255,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.distortion.amount = dontforceSet && options.baBehav[ADDSET_DIST_AMOUNT] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount; } + if (lensProf.lcMode) { + toEdit.lensProf.lcMode = mods.lensProf.lcMode; + } + if (lensProf.lcpFile) { toEdit.lensProf.lcpFile = mods.lensProf.lcpFile; } @@ -2269,14 +2275,6 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.lensProf.useCA = mods.lensProf.useCA; } - if (lensProf.useLensfun) { - toEdit.lensProf.useLensfun = mods.lensProf.useLensfun; - } - - if (lensProf.lfAutoMatch) { - toEdit.lensProf.lfAutoMatch = mods.lensProf.lfAutoMatch; - } - if (lensProf.lfCameraMake) { toEdit.lensProf.lfCameraMake = mods.lensProf.lfCameraMake; } @@ -3603,7 +3601,7 @@ bool RAWParamsEdited::isUnchanged() const bool LensProfParamsEdited::isUnchanged() const { - return lcpFile && useVign && lfLens; + return lcMode && lcpFile && useVign && lfLens; } bool RetinexParamsEdited::isUnchanged() const diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index aa9a19eb2..8557d4288 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -526,6 +526,7 @@ class LensProfParamsEdited public: bool lcpFile, useDist, useVign, useCA; bool useLensfun, lfAutoMatch, lfCameraMake, lfCameraModel, lfLens; + bool lcMode; bool isUnchanged() const; }; diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h index 6a695416e..d2e9be090 100644 --- a/rtgui/ppversion.h +++ b/rtgui/ppversion.h @@ -2,11 +2,13 @@ #define _PPVERSION_ // This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes -#define PPVERSION 326 +#define PPVERSION 327 #define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified /* Log of version changes + 327 2017-09-15 + [Profiles Lens Correction] Added Lensfun 326 2015-07-26 [Exposure] Added 'Perceptual' tone curve mode 325 2015-07-23