diff --git a/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc index 8bdda29ec..08010f50f 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -26,6 +26,61 @@ #include "rtlensfun.h" #include "settings.h" + +namespace +{ + +bool isCStringIn(const char *str, const char *const *list) +{ + for (auto element_ptr = list; *element_ptr; element_ptr++) { + if (!strcmp(str, *element_ptr)) { + return true; + } + } + return false; +} + +bool isNextLensCropFactorBetter(const lfLens *current_lens, const lfCamera *camera, float next_lens_crop_factor) +{ + if (!current_lens) { + // No current lens, so next lens's crop factor is + // automatically better. + return true; + } + + const float current_lens_crop_factor = current_lens->CropFactor; + + if (!camera) { + // Favor the smaller crop factor for maximum coverage. + return current_lens_crop_factor > next_lens_crop_factor; + } + + const float camera_crop_factor = camera->CropFactor; + + if (current_lens_crop_factor > camera_crop_factor) { + // Current lens's data does not cover the entire camera + // sensor. Any lens's data with a smaller crop factor is + // better. + return current_lens->CropFactor > next_lens_crop_factor; + } + + // Current lens's data covers the entire camera sensor. A lens + // with data from a larger crop factor will be more precise, but + // also must not be larger than the camera sensor's crop factor + // to maintain full coverage. + return current_lens->CropFactor < next_lens_crop_factor && + next_lens_crop_factor <= camera_crop_factor; +} + +bool isNextLensBetter(const lfCamera *camera, const lfLens *current_lens, const lfLens &next_lens, const Glib::ustring &lens_name, const Glib::ustring &next_lens_name) +{ + return isNextLensCropFactorBetter(current_lens, camera, next_lens.CropFactor) && + lens_name == next_lens_name && + (!camera || isCStringIn(camera->Mount, next_lens.Mounts)); +} + +} // namespace + namespace rtengine { @@ -461,20 +516,25 @@ LFCamera LFDatabase::findCamera(const Glib::ustring &make, const Glib::ustring & } -LFLens LFDatabase::findLens(const LFCamera &camera, const Glib::ustring &name) const +LFLens LFDatabase::findLens(const LFCamera &camera, const Glib::ustring &name, bool autoMatch) const { LFLens ret; if (data_ && !name.empty()) { MyMutex::MyLock lock(lfDBMutex); - if (!camera.data_) { + if (!autoMatch) { // Only the lens name provided. Try to find exact match by name. LFLens candidate; + LFLens bestCandidate; + for (auto lens_list = data_->GetLenses(); lens_list[0]; lens_list++) { candidate.data_ = lens_list[0]; - if (name == candidate.getLens()) { - return candidate; + if (isNextLensBetter(camera.data_, bestCandidate.data_, *(candidate.data_), name, candidate.getLens())) { + bestCandidate.data_ = candidate.data_; } } + if (bestCandidate.data_) { + return bestCandidate; + } } const auto find_lens_from_name = [](const lfDatabase *database, const lfCamera *cam, const Glib::ustring &lens_name) { auto found = database->FindLenses(cam, nullptr, lens_name.c_str()); @@ -576,12 +636,7 @@ std::unique_ptr LFDatabase::findModifier( } const LFCamera c = findCamera(make, model, lensProf.lfAutoMatch()); - const LFLens l = findLens( - lensProf.lfAutoMatch() - ? c - : LFCamera(), - lens - ); + const LFLens l = findLens(c, lens, lensProf.lfAutoMatch()); bool swap_xy = false; if (rawRotationDeg >= 0) { diff --git a/rtengine/rtlensfun.h b/rtengine/rtlensfun.h index bcce77f34..1d941246f 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -121,7 +121,7 @@ public: std::vector getCameras() const; std::vector getLenses() const; LFCamera findCamera(const Glib::ustring &make, const Glib::ustring &model, bool autoMatch) const; - LFLens findLens(const LFCamera &camera, const Glib::ustring &name) const; + LFLens findLens(const LFCamera &camera, const Glib::ustring &name, bool autoMatch) const; std::unique_ptr findModifier( const procparams::LensProfParams &lensProf, diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 0e17b3f40..5f42a1cde 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -251,7 +251,7 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa if (pp->lensProf.lfAutoMatch()) { if (metadata) { - const LFLens l = db->findLens(c, metadata->getLens()); + const LFLens l = db->findLens(c, metadata->getLens(), true); setLensfunLens(l.getLens()); } } else if (pp->lensProf.lfManual()) { @@ -522,7 +522,7 @@ void LensProfilePanel::onCorrModeChanged(const Gtk::RadioButton* rbChanged) } else if (metadata) { const LFDatabase* const db = LFDatabase::getInstance(); const LFCamera c = db->findCamera(metadata->getMake(), metadata->getModel(), true); - const LFLens l = db->findLens(c, metadata->getLens()); + const LFLens l = db->findLens(c, metadata->getLens(), true); setLensfunCamera(c.getMake(), c.getModel()); setLensfunLens(l.getLens()); } @@ -808,7 +808,7 @@ void LensProfilePanel::updateLensfunWarning() return; } - const LFLens l = db->findLens(LFCamera(), (*itl)[lf->lensfunModelLens.lens]); + const LFLens l = db->findLens(c, (*itl)[lf->lensfunModelLens.lens], false); const float lenscrop = l.getCropFactor(); const float camcrop = c.getCropFactor();