diff --git a/rtengine/procevents.h b/rtengine/procevents.h index cf7f50704..4623b600b 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -511,6 +511,10 @@ enum ProcEvent { EvCATgreensc = 481, EvCATybscen = 482, EvCATAutoyb = 483, + // profiled lens correction new events + EvLensCorrMode = 484, + EvLensCorrLensfunCamera = 488, + EvLensCorrLensfunLens = 489, NUMOFEVENTS diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 5400a2e47..74eda6110 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -510,8 +510,10 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // EvCATtempsc LUMINANCECURVE, // EvCATgreensc LUMINANCECURVE, // EvCATybscen - LUMINANCECURVE // EvCATAutoyb - + LUMINANCECURVE, // EvCATAutoyb + DARKFRAME, // EvLensCorrMode + DARKFRAME, // EvLensCorrLensfunCamera + DARKFRAME // EvLensCorrLensfunLens }; diff --git a/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc index f546fe445..31392698d 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -215,17 +215,16 @@ std::vector LFDatabase::getCameras() const } -std::vector LFDatabase::getLenses(const LFCamera &camera) const +std::vector LFDatabase::getLenses() const { std::vector ret; if (data_) { - auto lenses = data_->FindLenses(camera.data_, NULL, "", LF_SEARCH_LOOSE /*| LF_SEARCH_SORT_AND_UNIQUIFY*/); + auto lenses = data_->GetLenses(); while (*lenses) { ret.emplace_back(LFLens()); ret.back().data_ = *lenses; ++lenses; } - lf_free(lenses); } return ret; } diff --git a/rtengine/rtlensfun.h b/rtengine/rtlensfun.h index 4e3280de9..d02535623 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -85,7 +85,7 @@ public: ~LFDatabase(); std::vector getCameras() const; - std::vector getLenses(const LFCamera &camera) const; + std::vector getLenses() const; LFCamera findCamera(const Glib::ustring &make, const Glib::ustring &model) const; LFLens findLens(const LFCamera &camera, const Glib::ustring &name) const; LFModifier *getModifier(const LFCamera &camera, const LFLens &lens, diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 0855ef03f..82e156199 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -22,15 +22,66 @@ #include "../rtengine/lcp.h" #include #include "rtimage.h" +#include "../rtengine/rtlensfun.h" +#include +#include using namespace rtengine; using namespace rtengine::procparams; -LensProfilePanel::LensProfilePanel () : FoldableToolPanel(this, "lensprof", M("TP_LENSPROFILE_LABEL")), lcpFileChanged(false), useDistChanged(false), useVignChanged(false), useCAChanged(false), isRaw(true), lensgeomLcpFill(nullptr) +LensProfilePanel::LensProfilePanel () : + FoldableToolPanel(this, "lensprof", M("TP_LENSPROFILE_LABEL")), + lcpFileChanged(false), + useDistChanged(false), + useVignChanged(false), + useCAChanged(false), + isRaw(true), + lensgeomLcpFill(nullptr), + useLensfunChanged(false), + lensfunAutoChanged(false), + lensfunCameraChanged(false), + lensfunLensChanged(false) { - hbLCPFile = Gtk::manage(new Gtk::HBox()); + corrOff = Gtk::manage(new Gtk::RadioButton(M("LENSPROFILE_CORRECTION_OFF"))); + pack_start(*corrOff); - lLCPFileHead = Gtk::manage(new Gtk::Label(M("GENERAL_FILE"))); + corrGroup = corrOff->get_group(); + + corrLensfunAuto = Gtk::manage(new Gtk::RadioButton(corrGroup, M("LENSPROFILE_CORRECTION_AUTOMATCH"))); + pack_start(*corrLensfunAuto); + + corrLensfunManual = Gtk::manage(new Gtk::RadioButton(corrGroup, M("LENSPROFILE_CORRECTION_MANUAL"))); + pack_start(*corrLensfunManual); + + lensfunCameraModel = Gtk::TreeStore::create(lensfunModelCam); + lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens); + + lensfunCameras = Gtk::manage(new MyComboBox()); + lensfunCameras->set_model(lensfunCameraModel); + lensfunCameras->pack_start(lensfunModelCam.model); + lensfunLenses = Gtk::manage(new MyComboBox()); + lensfunLenses->set_model(lensfunLensModel); + lensfunLenses->pack_start(lensfunModelLens.lens); + + Gtk::HBox *hb = Gtk::manage(new Gtk::HBox()); + hb->pack_start(*Gtk::manage(new Gtk::Label(M("LENSFUN_CAMERA"))), Gtk::PACK_SHRINK, 4); + hb->pack_start(*lensfunCameras); + pack_start(*hb); + + fillLensfunCameras(); + + hb = Gtk::manage(new Gtk::HBox()); + hb->pack_start(*Gtk::manage(new Gtk::Label(M("LENSFUN_LENS"))), Gtk::PACK_SHRINK, 4); + hb->pack_start(*lensfunLenses); + pack_start(*hb); + + fillLensfunLenses(); + + corrLcpFile = Gtk::manage(new Gtk::RadioButton(corrGroup)); + hbLCPFile = Gtk::manage(new Gtk::HBox()); + hbLCPFile->pack_start(*corrLcpFile, Gtk::PACK_SHRINK); + + lLCPFileHead = Gtk::manage(new Gtk::Label(M("LENSPROFILE_CORRECTION_LCPFILE"))); hbLCPFile->pack_start(*lLCPFileHead, Gtk::PACK_SHRINK, 4); fcbLCPFile = Gtk::manage(new MyFileChooserButton(M("TP_LENSPROFILE_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); @@ -74,6 +125,13 @@ LensProfilePanel::LensProfilePanel () : FoldableToolPanel(this, "lensprof", M("T ckbUseVign->signal_toggled().connect( sigc::mem_fun(*this, &LensProfilePanel::onUseVignChanged) ); ckbUseCA->signal_toggled().connect( sigc::mem_fun(*this, &LensProfilePanel::onUseCAChanged) ); + lensfunCameras->signal_changed().connect(sigc::mem_fun(*this, &LensProfilePanel::onLensfunCameraChanged)); + lensfunLenses->signal_changed().connect(sigc::mem_fun(*this, &LensProfilePanel::onLensfunLensChanged)); + corrOff->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged)); + corrLensfunAuto->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged)); + corrLensfunManual->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged)); + corrLcpFile->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged)); + allowFocusDep = true; } @@ -82,7 +140,15 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa disableListener (); conUseDist.block(true); - if (!pp->lensProf.lcpFile.empty() && lcpStore->isValidLCPFileName(pp->lensProf.lcpFile)) { + corrOff->set_active(true); + if (pp->lensProf.useLensfun) { + if (pp->lensProf.lfAutoMatch) { + corrLensfunAuto->set_active(true); + } else { + corrLensfunManual->set_active(true); + } + } else if (!pp->lensProf.lcpFile.empty() && lcpStore->isValidLCPFileName(pp->lensProf.lcpFile)) { + corrLcpFile->set_active(true); fcbLCPFile->set_filename (pp->lensProf.lcpFile); updateDisabled(true); } else { @@ -104,7 +170,48 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa ckbUseVign->set_active (pp->lensProf.useVign && isRaw); ckbUseCA->set_active (pp->lensProf.useCA && isRaw); + if (!pp->lensProf.lfCameraMake.empty() && !pp->lensProf.lfCameraModel.empty()) { + // search for the active row + for (auto row : lensfunCameraModel->children()) { + if (row[lensfunModelCam.make] == pp->lensProf.lfCameraMake) { + auto &c = row.children(); + for (auto it = c.begin(), end = c.end(); it != end; ++it) { + auto &childrow = *it; + if (childrow[lensfunModelCam.model] == pp->lensProf.lfCameraModel) { + lensfunCameras->set_active(it); + break; + } + } + break; + } + } + } + + if (!pp->lensProf.lfLens.empty()) { + // search for the active row + auto pos = pp->lensProf.lfLens.find_first_of(' '); + Glib::ustring make = "(Unknown)"; + if (pos != Glib::ustring::npos) { + make = pp->lensProf.lfLens.substr(0, pos); + } + + for (auto row : lensfunCameraModel->children()) { + if (row[lensfunModelLens.lens] == make) { + auto &c = row.children(); + for (auto it = c.begin(), end = c.end(); it != end; ++it) { + auto &childrow = *it; + if (childrow[lensfunModelLens.lens] == pp->lensProf.lfLens) { + lensfunLenses->set_active(it); + break; + } + } + break; + } + } + } + lcpFileChanged = useDistChanged = useVignChanged = useCAChanged = false; + useLensfunChanged = lensfunAutoChanged = lensfunCameraChanged = lensfunLensChanged = false; enableListener (); conUseDist.block(false); @@ -128,7 +235,7 @@ void LensProfilePanel::setRawMeta(bool raw, const rtengine::ImageMetaData* pMeta void LensProfilePanel::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - if (lcpStore->isValidLCPFileName(fcbLCPFile->get_filename())) { + if (corrLcpFile->get_active() && lcpStore->isValidLCPFileName(fcbLCPFile->get_filename())) { pp->lensProf.lcpFile = fcbLCPFile->get_filename(); } else { pp->lensProf.lcpFile = ""; @@ -138,11 +245,33 @@ 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)[lensfunModelCam.make]; + pp->lensProf.lfCameraModel = (*itc)[lensfunModelCam.model]; + } else { + pp->lensProf.lfCameraMake = ""; + pp->lensProf.lfCameraModel = ""; + } + auto itl = lensfunLenses->get_active(); + if (itl) { + pp->lensProf.lfLens = (*itl)[lensfunModelLens.lens]; + } else { + pp->lensProf.lfLens = ""; + } + if (pedited) { pedited->lensProf.lcpFile = lcpFileChanged; pedited->lensProf.useDist = useDistChanged; pedited->lensProf.useVign = useVignChanged; pedited->lensProf.useCA = useCAChanged; + pedited->lensProf.useLensfun = useLensfunChanged; + pedited->lensProf.lfAutoMatch = lensfunAutoChanged; + pedited->lensProf.lfCameraMake = lensfunCameraChanged; + pedited->lensProf.lfCameraModel = lensfunCameraChanged; + pedited->lensProf.lfLens = lensfunLensChanged; } } @@ -199,3 +328,146 @@ void LensProfilePanel::updateDisabled(bool enable) ckbUseVign->set_sensitive(enable && isRaw); ckbUseCA->set_sensitive(enable && allowFocusDep); } + +void LensProfilePanel::setBatchMode(bool yes) +{ + FoldableToolPanel::setBatchMode(yes); +} + + +void LensProfilePanel::fillLensfunCameras() +{ + std::map> camnames; + auto camlist = LFDatabase::getInstance()->getCameras(); + for (auto &c : camlist) { + camnames[c.getMake()].insert(c.getModel()); + } + for (auto &p : camnames) { + Gtk::TreeModel::Row row = *(lensfunCameraModel->append()); + row[lensfunModelCam.make] = p.first; + row[lensfunModelCam.model] = ""; + for (auto &c : p.second) { + Gtk::TreeModel::Row child = *(lensfunCameraModel->append(row.children())); + child[lensfunModelCam.make] = p.first; + child[lensfunModelCam.model] = c; + } + } +} + + +void LensProfilePanel::fillLensfunLenses() +{ + std::map> lenses; + auto lenslist = LFDatabase::getInstance()->getLenses(); + for (auto &l : lenslist) { + auto name = l.getDisplayString(); + auto pos = name.find_first_of(' '); + Glib::ustring make = "(Unknown)"; + if (pos != Glib::ustring::npos) { + make = name.substr(0, pos); + } + lenses[make].insert(name); + } + for (auto &p : lenses) { + Gtk::TreeModel::Row row = *(lensfunLensModel->append()); + row[lensfunModelLens.lens] = p.first; + for (auto &c : p.second) { + Gtk::TreeModel::Row child = *(lensfunLensModel->append(row.children())); + child[lensfunModelLens.lens] = c; + } + } +} + + +void LensProfilePanel::onLensfunCameraChanged() +{ + auto iter = lensfunCameras->get_active(); + + if (iter) { + lensfunCameraChanged = true; + + if (listener) { + Glib::ustring name = (*iter)[lensfunModelCam.model]; + listener->panelChanged(EvLensCorrLensfunCamera, name); + } + } +} + + +void LensProfilePanel::onLensfunLensChanged() +{ + auto iter = lensfunLenses->get_active(); + + if (iter) { + lensfunLensChanged = true; + + if (listener) { + Glib::ustring name = (*iter)[lensfunModelLens.lens]; + listener->panelChanged(EvLensCorrLensfunLens, name); + } + } +} + + +void LensProfilePanel::onCorrModeChanged() +{ + Glib::ustring mode; + + if (corrOff->get_active()) { + useLensfunChanged = true; + lcpFileChanged = true; + + lensfunCameras->set_sensitive(false); + lensfunLenses->set_sensitive(false); + ckbUseDist->set_sensitive(false); + ckbUseVign->set_sensitive(false); + ckbUseCA->set_sensitive(false); + + mode = M("LENSPROFILE_CORRECTION_OFF"); + } else if (corrLensfunAuto->get_active()) { + useLensfunChanged = true; + lcpFileChanged = true; + useDistChanged = true; + useVignChanged = true; + + lensfunCameras->set_sensitive(false); + lensfunLenses->set_sensitive(false); + + ckbUseDist->set_sensitive(true); + ckbUseVign->set_sensitive(true); + ckbUseCA->set_sensitive(false); + + mode = M("LENSPROFILE_CORRECTION_AUTOMATCH"); + } else if (corrLensfunManual->get_active()) { + useLensfunChanged = true; + lcpFileChanged = true; + lcpFileChanged = true; + useDistChanged = true; + useVignChanged = true; + + lensfunCameras->set_sensitive(true); + lensfunLenses->set_sensitive(true); + + ckbUseDist->set_sensitive(true); + ckbUseVign->set_sensitive(true); + ckbUseCA->set_sensitive(false); + + mode = M("LENSPROFILE_CORRECTION_MANUAL"); + } else if (corrLcpFile->get_active()) { + useLensfunChanged = true; + lcpFileChanged = true; + lcpFileChanged = true; + useDistChanged = true; + useVignChanged = true; + + lensfunCameras->set_sensitive(false); + lensfunLenses->set_sensitive(false); + updateDisabled(true); + + mode = M("LENSPROFILE_CORRECTION_LCPFILE"); + } + + if (listener) { + listener->panelChanged(EvLensCorrMode, mode); + } +} diff --git a/rtgui/lensprofile.h b/rtgui/lensprofile.h index 9543721a0..34222932e 100644 --- a/rtgui/lensprofile.h +++ b/rtgui/lensprofile.h @@ -41,6 +41,42 @@ protected: bool isRaw; LensGeometry *lensgeomLcpFill; + Gtk::RadioButton::Group corrGroup; + Gtk::RadioButton *corrOff; + Gtk::RadioButton *corrLensfunAuto; + Gtk::RadioButton *corrLensfunManual; + Gtk::RadioButton *corrLcpFile; + Gtk::RadioButton *corrUnchanged; + MyComboBox *lensfunCameras; + MyComboBox *lensfunLenses; + + class LFModelCam: public Gtk::TreeModel::ColumnRecord { + public: + LFModelCam() { add(make); add(model); } + Gtk::TreeModelColumn make; + Gtk::TreeModelColumn model; + }; + + class LFModelLens: public Gtk::TreeModel::ColumnRecord { + public: + LFModelLens() { add(lens); } + Gtk::TreeModelColumn lens; + }; + + LFModelCam lensfunModelCam; + LFModelLens lensfunModelLens; + + Glib::RefPtr lensfunCameraModel; + Glib::RefPtr lensfunLensModel; + + bool useLensfunChanged; + bool lensfunAutoChanged; + bool lensfunCameraChanged; + bool lensfunLensChanged; + + void fillLensfunCameras(); + void fillLensfunLenses(); + public: LensProfilePanel (); @@ -58,6 +94,12 @@ public: { lensgeomLcpFill = foo ; }; + + void setBatchMode(bool yes); + + void onLensfunCameraChanged(); + void onLensfunLensChanged(); + void onCorrModeChanged(); }; #endif