1 /*
2 * This file is part of RawTherapee.
3 *
4 * Copyright (c) 2012 Oliver Duis <oduis@oliverduis.de>
5 *
6 * RawTherapee is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * RawTherapee is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include <glibmm.h>
20 #include <iostream>
21 #include "lensprofile.h"
22 #include "guiutils.h"
23 #include "../rtengine/lcp.h"
24 #include <sstream>
25 #include "rtimage.h"
26 #include "../rtengine/rtlensfun.h"
27 #include <map>
28 #include <set>
29 #include "../rtengine/lensexif.h"
30 #include "eventmapper.h"
31 #ifdef EXIF
32 # undef EXIF
33 #endif
34
35 using namespace rtengine;
36 using namespace rtengine::procparams;
37
LensProfilePanel()38 LensProfilePanel::LensProfilePanel() :
39 FoldableToolPanel(this, "lensprof", M("TP_LENSPROFILE_LABEL"), false, true, true),
40 lcModeChanged(false),
41 lcpFileChanged(false),
42 useDistChanged(false),
43 useVignChanged(false),
44 useCAChanged(false),
45 useLensfunChanged(false),
46 lensfunAutoChanged(false),
47 lensfunCameraChanged(false),
48 lensfunLensChanged(false),
49 allowFocusDep(true),
50 isRaw(true),
51 metadata(nullptr),
52 modesGrid(Gtk::manage(new Gtk::Grid())),
53 distGrid(Gtk::manage((new Gtk::Grid()))),
54 corrExif(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_EXIF"))))),
55 corrLensfunAutoRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_AUTOMATCH"))))),
56 corrLensfunManualRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_MANUAL"))))),
57 corrLcpFileRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_LCPFILE"))))),
58 corrLcpFileChooser(Gtk::manage((new MyFileChooserButton(M("TP_LENSPROFILE_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)))),
59 lensfunCamerasLbl(Gtk::manage((new Gtk::Label(M("EXIFFILTER_CAMERA"))))),
60 lensfunCameras(Gtk::manage((new MyComboBox()))),
61 lensfunLensesLbl(Gtk::manage((new Gtk::Label(M("EXIFFILTER_LENS"))))),
62 lensfunLenses(Gtk::manage((new MyComboBox()))),
63 warning(Gtk::manage(new RTImage("warning.png"))),
64 ckbUseDist(Gtk::manage((new Gtk::CheckButton(M("TP_LENSPROFILE_USE_GEOMETRIC"))))),
65 ckbUseVign(Gtk::manage((new Gtk::CheckButton(M("TP_LENSPROFILE_USE_VIGNETTING"))))),
66 ckbUseCA(Gtk::manage((new Gtk::CheckButton(M("TP_LENSPROFILE_USE_CA")))))
67 {
68 EvToolEnabled.set_action(DARKFRAME); // might need to redo vignetting
69 EvToolReset.set_action(DARKFRAME);
70
71 if (!lf) {
72 lf = new LFDbHelper();
73 }
74
75 // Main containers:
76
77 Gtk::Frame *nodesFrame = Gtk::manage(new Gtk::Frame(M("TP_LENSPROFILE_MODE_HEADER")));
78
79 modesGrid->get_style_context()->add_class("grid-spacing");
80 setExpandAlignProperties(modesGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
81
82 Gtk::Frame *distFrame = Gtk::manage(new Gtk::Frame(M("TP_LENSPROFILE_USE_HEADER")));
83
84 distGrid->get_style_context()->add_class("grid-spacing");
85 setExpandAlignProperties(distGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
86
87 // Mode choice widgets:
88
89 setExpandAlignProperties(corrLcpFileChooser, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
90
91 // Manually-selected profile widgets:
92
93 setExpandAlignProperties(lensfunCamerasLbl, false, false, Gtk::ALIGN_END, Gtk::ALIGN_CENTER);
94
95 lensfunCameras->set_model(lf->lensfunCameraModel);
96 lensfunCameras->pack_start(lf->lensfunModelCam.model);
97 lensfunCameras->setPreferredWidth(50, 120);
98 setExpandAlignProperties(lensfunCameras, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
99
100 Gtk::CellRendererText* const camerasCellRenderer = static_cast<Gtk::CellRendererText*>(lensfunCameras->get_first_cell());
101 camerasCellRenderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
102 camerasCellRenderer->property_ellipsize_set() = true;
103
104 setExpandAlignProperties(lensfunLensesLbl, false, false, Gtk::ALIGN_END, Gtk::ALIGN_CENTER);
105
106 lensfunLenses->set_model(lf->lensfunLensModel);
107 lensfunLenses->pack_start(lf->lensfunModelLens.prettylens);
108 lensfunLenses->setPreferredWidth(50, 120);
109 setExpandAlignProperties(lensfunLenses, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
110
111 Gtk::CellRendererText* const lensesCellRenderer = static_cast<Gtk::CellRendererText*>(lensfunLenses->get_first_cell());
112 lensesCellRenderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
113 lensesCellRenderer->property_ellipsize_set() = true;
114
115 warning->set_tooltip_text(M("TP_LENSPROFILE_LENS_WARNING"));
116 warning->hide();
117
118 // LCP file filter config:
119
120 const Glib::RefPtr<Gtk::FileFilter> filterLCP = Gtk::FileFilter::create();
121 filterLCP->set_name(M("FILECHOOSER_FILTER_LCP"));
122 filterLCP->add_pattern("*.lcp");
123 filterLCP->add_pattern("*.LCP");
124 corrLcpFileChooser->add_filter(filterLCP);
125
126 const Glib::ustring defDir = LCPStore::getInstance()->getDefaultCommonDirectory();
127
128 if (!defDir.empty()) {
129 #ifdef WIN32
130 corrLcpFileChooser->set_show_hidden(true); // ProgramData is hidden on Windows
131 #endif
132 corrLcpFileChooser->set_current_folder(defDir);
133 } else if (!options.lastLensProfileDir.empty()) {
134 corrLcpFileChooser->set_current_folder(options.lastLensProfileDir);
135 }
136
137 bindCurrentFolder(*corrLcpFileChooser, options.lastLensProfileDir);
138
139 // Choice of properties to correct, applicable to all modes:
140
141 // Populate modes grid:
142
143 modesGrid->attach(*corrExif, 0, 0, 3, 1);
144 modesGrid->attach(*corrLensfunAutoRB, 0, 1, 3, 1);
145 modesGrid->attach(*corrLensfunManualRB, 0, 2, 3, 1);
146
147 modesGrid->attach(*lensfunCamerasLbl, 0, 3, 1, 1);
148 modesGrid->attach(*lensfunCameras, 1, 3, 1, 1);
149 modesGrid->attach(*lensfunLensesLbl, 0, 4, 1, 1);
150 modesGrid->attach(*lensfunLenses, 1, 4, 1, 1);
151 modesGrid->attach(*warning, 2, 3, 1, 2);
152
153 modesGrid->attach(*corrLcpFileRB, 0, 5, 1, 1);
154 modesGrid->attach(*corrLcpFileChooser, 1, 5, 1, 1);
155
156 #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 20
157 modesGrid->set_row_spacing(2);
158 modesGrid->set_column_spacing(4);
159 #endif
160
161 // Populate distortions grid:
162
163 distGrid->attach(*ckbUseDist, 0, 0, 1, 1);
164 distGrid->attach(*ckbUseVign, 0, 1, 1, 1);
165 distGrid->attach(*ckbUseCA, 0, 2, 1, 1);
166
167 // Attach grids:
168 nodesFrame->add(*modesGrid);
169 distFrame->add(*distGrid);
170
171 pack_start(*nodesFrame, Gtk::PACK_EXPAND_WIDGET);
172 pack_start(*distFrame, Gtk::PACK_EXPAND_WIDGET);
173
174 // Signals:
175
176 conLCPFile = corrLcpFileChooser->signal_file_set().connect(sigc::mem_fun(*this, &LensProfilePanel::onLCPFileChanged));
177 conUseDist = ckbUseDist->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onUseDistChanged));
178 ckbUseVign->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onUseVignChanged));
179 ckbUseCA->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onUseCAChanged));
180
181 lensfunCameras->signal_changed().connect(sigc::mem_fun(*this, &LensProfilePanel::onLensfunCameraChanged));
182 lensfunLenses->signal_changed().connect(sigc::mem_fun(*this, &LensProfilePanel::onLensfunLensChanged));
183 corrExif->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrExif));
184 corrLensfunAutoRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrLensfunAutoRB));
185 corrLensfunManualRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrLensfunManualRB));
186 corrLcpFileRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrLcpFileRB));
187 }
188
read(const rtengine::procparams::ProcParams * pp)189 void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp)
190 {
191 disableListener();
192 conUseDist.block(true);
193
194 setEnabled(true);
195
196 switch (pp->lensProf.lcMode) {
197 case procparams::LensProfParams::LcMode::LCP: {
198 corrLcpFileRB->set_active(true);
199 break;
200 }
201
202 case procparams::LensProfParams::LcMode::LENSFUNAUTOMATCH: {
203 corrLensfunAutoRB->set_active(true);
204 break;
205 }
206
207 case procparams::LensProfParams::LcMode::LENSFUNMANUAL: {
208 corrLensfunManualRB->set_active(true);
209 break;
210 }
211
212 case procparams::LensProfParams::LcMode::EXIF: {
213 if (metadata) {
214 if (rtengine::ExifLensCorrection::ok(metadata)) {
215 corrExif->set_active(true);
216 corrExif->set_sensitive(true);
217 ckbUseCA->set_sensitive(true);
218 } else {
219 corrExif->set_sensitive(false);
220 corrLensfunAutoRB->set_active(true);
221 }
222 } else {
223 corrExif->set_sensitive(false);
224 setEnabled(false);
225 }
226 break;
227 }
228
229 case procparams::LensProfParams::LcMode::NONE: {
230 setEnabled(false);
231 break;
232 }
233 }
234
235 if (pp->lensProf.lcpFile.empty()) {
236 const Glib::ustring lastFolder = corrLcpFileChooser->get_current_folder();
237 corrLcpFileChooser->set_current_folder(lastFolder);
238 corrLcpFileChooser->unselect_all();
239 bindCurrentFolder(*corrLcpFileChooser, options.lastLensProfileDir);
240 updateDisabled();
241 } else if (LCPStore::getInstance()->isValidLCPFileName(pp->lensProf.lcpFile)) {
242 corrLcpFileChooser->set_filename(pp->lensProf.lcpFile);
243
244 if (corrLcpFileRB->get_active()) {
245 updateDisabled();
246 }
247 } else {
248 corrLcpFileChooser->unselect_filename(corrLcpFileChooser->get_filename());
249 updateDisabled();
250 }
251
252 setManualParamsVisibility(corrLensfunAutoRB->get_active() || corrLensfunManualRB->get_active());
253
254 const LFDatabase* const db = LFDatabase::getInstance();
255 LFCamera c;
256
257 if (pp->lensProf.lfAutoMatch()) {
258 if (metadata) {
259 c = db->findCamera(metadata->getMake(), metadata->getModel());
260 setLensfunCamera(c.getMake(), c.getModel());
261 }
262 } else if (pp->lensProf.lfManual()) {
263 setLensfunCamera(pp->lensProf.lfCameraMake, pp->lensProf.lfCameraModel);
264 }
265
266 if (pp->lensProf.lfAutoMatch()) {
267 if (metadata) {
268 const LFLens l = db->findLens(c, metadata->getLens());
269 setLensfunLens(l.getLens());
270 }
271 } else if (pp->lensProf.lfManual()) {
272 setLensfunLens(pp->lensProf.lfLens);
273 }
274
275
276 ckbUseDist->set_active(pp->lensProf.useDist);
277 ckbUseVign->set_active(pp->lensProf.useVign);
278 ckbUseCA->set_active(pp->lensProf.useCA);
279
280 lcModeChanged = lcpFileChanged = useDistChanged = useVignChanged = useCAChanged = false;
281 useLensfunChanged = lensfunAutoChanged = lensfunCameraChanged = lensfunLensChanged = false;
282
283 updateLensfunWarning();
284 enableListener();
285 conUseDist.block(false);
286 }
287
write(rtengine::procparams::ProcParams * pp)288 void LensProfilePanel::write(rtengine::procparams::ProcParams* pp)
289 {
290 if (!getEnabled()) {
291 pp->lensProf.lcMode = procparams::LensProfParams::LcMode::NONE;
292 } else if (corrLcpFileRB->get_active()) {
293 pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LCP;
294 }
295 else if (corrLensfunManualRB->get_active()) {
296 pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LENSFUNMANUAL;
297 }
298 else if (corrLensfunAutoRB->get_active()) {
299 pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LENSFUNAUTOMATCH;
300 }
301 else if (corrExif->get_active()) {
302 pp->lensProf.lcMode = procparams::LensProfParams::LcMode::EXIF;
303 }
304
305 if (LCPStore::getInstance()->isValidLCPFileName(corrLcpFileChooser->get_filename())) {
306 pp->lensProf.lcpFile = corrLcpFileChooser->get_filename();
307 } else {
308 pp->lensProf.lcpFile = "";
309 }
310
311 pp->lensProf.useDist = ckbUseDist->get_active();
312 pp->lensProf.useVign = ckbUseVign->get_active();
313 pp->lensProf.useCA = ckbUseCA->get_active();
314
315 const auto itc = lensfunCameras->get_active();
316
317 if (itc && !corrLensfunAutoRB->get_active()) {
318 pp->lensProf.lfCameraMake = (*itc)[lf->lensfunModelCam.make];
319 pp->lensProf.lfCameraModel = (*itc)[lf->lensfunModelCam.model];
320 } else {
321 pp->lensProf.lfCameraMake = "";
322 pp->lensProf.lfCameraModel = "";
323 }
324
325 const auto itl = lensfunLenses->get_active();
326
327 if (itl && !corrLensfunAutoRB->get_active()) {
328 pp->lensProf.lfLens = (*itl)[lf->lensfunModelLens.lens];
329 } else {
330 pp->lensProf.lfLens = "";
331 }
332 }
333
setRawMeta(bool raw,const rtengine::FramesMetaData * pMeta)334 void LensProfilePanel::setRawMeta(bool raw, const rtengine::FramesMetaData* pMeta)
335 {
336 disableListener();
337 // if ((!raw || pMeta->getFocusDist() <= 0)) {
338
339 // // CA is very focus layer dependent, otherwise it might even worsen things
340 // allowFocusDep = false;
341 // ckbUseCA->set_active(false);
342 // ckbUseCA->set_sensitive(false);
343 // }
344
345 isRaw = raw;
346 metadata = pMeta;
347
348 if (metadata) {
349 if (!rtengine::ExifLensCorrection::ok(metadata)) {
350 corrExif->set_sensitive(false);
351 } else {
352 ckbUseCA->set_sensitive(true);
353 }
354 } else {
355 corrExif->set_sensitive(false);
356 }
357 enableListener();
358 }
359
onLCPFileChanged()360 void LensProfilePanel::onLCPFileChanged()
361 {
362 lcpFileChanged = true;
363 const bool valid = LCPStore::getInstance()->isValidLCPFileName(corrLcpFileChooser->get_filename());
364 updateDisabled();
365
366 if (listener) {
367 if (valid) {
368 disableListener();
369 corrLcpFileRB->set_active(true);
370 enableListener();
371 }
372
373 listener->panelChanged(EvLCPFile, Glib::path_get_basename(corrLcpFileChooser->get_filename()));
374 }
375 }
376
onUseDistChanged()377 void LensProfilePanel::onUseDistChanged()
378 {
379 useDistChanged = true;
380 if (ckbUseDist->get_inconsistent()) {
381 ckbUseDist->set_inconsistent(false);
382 ckbUseDist->set_active(false);
383 }
384
385 if (listener) {
386 listener->panelChanged(EvLCPUseDist, ckbUseDist->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
387 }
388 }
389
onUseVignChanged()390 void LensProfilePanel::onUseVignChanged()
391 {
392 useVignChanged = true;
393 if (ckbUseVign->get_inconsistent()) {
394 ckbUseVign->set_inconsistent(false);
395 ckbUseVign->set_active(false);
396 }
397
398 if (listener) {
399 listener->panelChanged(EvLCPUseVign, ckbUseVign->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
400 }
401 }
402
onUseCAChanged()403 void LensProfilePanel::onUseCAChanged()
404 {
405 useCAChanged = true;
406 if (ckbUseCA->get_inconsistent()) {
407 ckbUseCA->set_inconsistent(false);
408 ckbUseCA->set_active(false);
409 }
410
411 if (listener) {
412 listener->panelChanged(EvLCPUseCA, ckbUseCA->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
413 }
414 }
415
416
onLensfunCameraChanged()417 void LensProfilePanel::onLensfunCameraChanged()
418 {
419 const auto iter = lensfunCameras->get_active();
420
421 if (iter) {
422 lensfunCameraChanged = true;
423
424 if (listener) {
425 disableListener();
426 corrLensfunManualRB->set_active(true);
427 enableListener();
428
429 const Glib::ustring name = (*iter)[lf->lensfunModelCam.model];
430 listener->panelChanged(EvLensCorrLensfunCamera, name);
431 }
432 }
433
434 updateLensfunWarning();
435 }
436
onLensfunLensChanged()437 void LensProfilePanel::onLensfunLensChanged()
438 {
439 const auto iter = lensfunLenses->get_active();
440
441 if (iter) {
442 lensfunLensChanged = true;
443
444 if (listener) {
445 disableListener();
446 corrLensfunManualRB->set_active(true);
447 enableListener();
448
449 const Glib::ustring name = (*iter)[lf->lensfunModelLens.prettylens];
450 listener->panelChanged(EvLensCorrLensfunLens, name);
451 }
452 }
453
454 updateLensfunWarning();
455 }
456
onCorrModeChanged(const Gtk::RadioButton * rbChanged)457 void LensProfilePanel::onCorrModeChanged(const Gtk::RadioButton* rbChanged)
458 {
459 if (rbChanged->get_active()) {
460 Glib::ustring mode;
461 if (rbChanged == corrLensfunAutoRB) {
462 lcModeChanged = true;
463 useLensfunChanged = true;
464 lensfunAutoChanged = true;
465 lensfunCameraChanged = true;
466 lensfunLensChanged = true;
467 lcpFileChanged = false;
468
469 const bool disabled = disableListener();
470 if (metadata) {
471 const LFDatabase* const db = LFDatabase::getInstance();
472 const LFCamera c = db->findCamera(metadata->getMake(), metadata->getModel());
473 const LFLens l = db->findLens(c, metadata->getLens());
474 setLensfunCamera(c.getMake(), c.getModel());
475 setLensfunLens(l.getLens());
476 }
477 if (disabled) {
478 enableListener();
479 }
480
481 mode = M("TP_LENSPROFILE_CORRECTION_AUTOMATCH");
482
483 } else if (rbChanged == corrLensfunManualRB) {
484 lcModeChanged = true;
485 useLensfunChanged = true;
486 lensfunAutoChanged = true;
487 lensfunCameraChanged = true;
488 lensfunLensChanged = true;
489 lcpFileChanged = false;
490
491 mode = M("TP_LENSPROFILE_CORRECTION_MANUAL");
492
493 } else if (rbChanged == corrLcpFileRB || rbChanged == corrExif) {
494 lcModeChanged = true;
495 useLensfunChanged = true;
496 lensfunAutoChanged = true;
497 lcpFileChanged = true;
498
499
500 mode = M("TP_LENSPROFILE_CORRECTION_LCPFILE");
501 }
502
503 updateLensfunWarning();
504 updateDisabled();
505
506 if (rbChanged == corrLensfunManualRB || (rbChanged == corrLensfunAutoRB)) {
507 setManualParamsVisibility(true);
508 } else {
509 setManualParamsVisibility(false);
510 }
511
512 if (listener) {
513 listener->panelChanged(EvLensCorrMode, mode);
514 }
515 }
516 }
517
518 //-----------------------------------------------------------------------------
519 // LFDbHelper
520 //-----------------------------------------------------------------------------
521
LFDbHelper()522 LensProfilePanel::LFDbHelper::LFDbHelper()
523 {
524 lensfunCameraModel = Gtk::TreeStore::create(lensfunModelCam);
525 lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens);
526
527 #ifdef _OPENMP
528 #pragma omp parallel sections if (!options.rtSettings.verbose)
529 #endif
530 {
531 #ifdef _OPENMP
532 #pragma omp section
533 #endif
534 {
535 fillLensfunCameras();
536 }
537 #ifdef _OPENMP
538 #pragma omp section
539 #endif
540 {
541 fillLensfunLenses();
542 }
543 }
544 }
545
fillLensfunCameras()546 void LensProfilePanel::LFDbHelper::fillLensfunCameras()
547 {
548 if (options.rtSettings.verbose) {
549 std::cout << "LENSFUN, scanning cameras:" << std::endl;
550 }
551
552 std::map<Glib::ustring, std::set<Glib::ustring>> camnames;
553 const auto camlist = LFDatabase::getInstance()->getCameras();
554
555 for (const auto& c : camlist) {
556 camnames[c.getMake()].insert(c.getModel());
557
558 if (options.rtSettings.verbose) {
559 std::cout << " found: " << c.getDisplayString().c_str() << std::endl;
560 }
561 }
562
563 for (const auto& p : camnames) {
564 Gtk::TreeModel::Row row = *(lensfunCameraModel->append());
565 row[lensfunModelCam.make] = p.first;
566 row[lensfunModelCam.model] = p.first;
567
568 for (const auto& c : p.second) {
569 Gtk::TreeModel::Row child = *(lensfunCameraModel->append(row.children()));
570 child[lensfunModelCam.make] = p.first;
571 child[lensfunModelCam.model] = c;
572 }
573 }
574 }
575
fillLensfunLenses()576 void LensProfilePanel::LFDbHelper::fillLensfunLenses()
577 {
578 if (options.rtSettings.verbose) {
579 std::cout << "LENSFUN, scanning lenses:" << std::endl;
580 }
581
582 std::map<Glib::ustring, std::set<Glib::ustring>> lenses;
583 const auto lenslist = LFDatabase::getInstance()->getLenses();
584
585 for (const auto& l : lenslist) {
586 const auto& name = l.getLens();
587 const auto& make = l.getMake();
588 lenses[make].insert(name);
589
590 if (options.rtSettings.verbose) {
591 std::cout << " found: " << l.getDisplayString().c_str() << std::endl;
592 }
593 }
594
595 for (const auto& p : lenses) {
596 Gtk::TreeModel::Row row = *(lensfunLensModel->append());
597 row[lensfunModelLens.lens] = p.first;
598 row[lensfunModelLens.prettylens] = p.first;
599
600 for (auto &c : p.second) {
601 Gtk::TreeModel::Row child = *(lensfunLensModel->append(row.children()));
602 child[lensfunModelLens.lens] = c;
603
604 if (c.find(p.first, p.first.size() + 1) == p.first.size() + 1) {
605 child[lensfunModelLens.prettylens] = c.substr(p.first.size() + 1);
606 } else {
607 child[lensfunModelLens.prettylens] = c;
608 }
609 }
610 }
611 }
612
updateDisabled()613 void LensProfilePanel::updateDisabled()
614 {
615 ckbUseDist->set_sensitive(true);
616 ckbUseVign->set_sensitive(true);
617 ckbUseCA->set_sensitive(true);
618
619 ckbUseVign->set_sensitive(isRaw);
620 // ckbUseCA->set_sensitive(allowFocusDep || corrExif->get_active());
621 }
622
setLensfunCamera(const Glib::ustring & make,const Glib::ustring & model)623 bool LensProfilePanel::setLensfunCamera(const Glib::ustring& make, const Glib::ustring& model)
624 {
625 if (!make.empty() && !model.empty()) {
626 const auto camera_it = lensfunCameras->get_active();
627
628 if (camera_it && (*camera_it)[lf->lensfunModelCam.make] == make && (*camera_it)[lf->lensfunModelCam.model] == model) {
629 return true;
630 }
631
632 // search for the active row
633 for (const auto& row : lf->lensfunCameraModel->children()) {
634 if (row[lf->lensfunModelCam.make] == make) {
635 const auto& c = row.children();
636
637 for (auto model_it = c.begin(), end = c.end(); model_it != end; ++model_it) {
638 const auto& childrow = *model_it;
639
640 if (childrow[lf->lensfunModelCam.model] == model) {
641 lensfunCameras->set_active(model_it);
642 return true;
643 }
644 }
645
646 break;
647 }
648 }
649 }
650
651 lensfunCameras->set_active(-1);
652 return false;
653 }
654
setLensfunLens(const Glib::ustring & lens)655 bool LensProfilePanel::setLensfunLens(const Glib::ustring& lens)
656 {
657 if (!lens.empty()) {
658 const auto lens_it = lensfunLenses->get_active();
659
660 if (lens_it && (*lens_it)[lf->lensfunModelLens.lens] == lens) {
661 return true;
662 }
663
664 bool first_maker_found = false;
665
666 for (const auto& row : lf->lensfunLensModel->children()) {
667 if (lens.find(row[lf->lensfunModelLens.lens]) == 0) {
668 const auto& c = row.children();
669
670 for (auto model_it = c.begin(), end = c.end(); model_it != end; ++model_it) {
671 const auto& childrow = *model_it;
672
673 if (childrow[lf->lensfunModelLens.lens] == lens) {
674 lensfunLenses->set_active(model_it);
675 return true;
676 }
677 }
678
679 // we do not break immediately here, because there might be multiple makers
680 // sharing the same prefix (e.g. "Leica" and "Leica Camera AG").
681 // therefore, we break below when the lens doesn't match any of them
682 first_maker_found = true;
683 } else if (first_maker_found) {
684 break;
685 }
686 }
687 }
688
689 lensfunLenses->set_active(-1);
690 return false;
691 }
692
checkLensfunCanCorrect(bool automatch)693 bool LensProfilePanel::checkLensfunCanCorrect(bool automatch)
694 {
695 if (!metadata) {
696 return false;
697 }
698
699 rtengine::procparams::ProcParams lpp;
700 write(&lpp);
701 const std::unique_ptr<LFModifier> mod(LFDatabase::getInstance()->findModifier(lpp.lensProf, metadata, 100, 100, lpp.coarse, -1));
702 return static_cast<bool>(mod);
703 }
704
setManualParamsVisibility(bool setVisible)705 void LensProfilePanel::setManualParamsVisibility(bool setVisible)
706 {
707 if (setVisible) {
708 lensfunCamerasLbl->show();
709 lensfunCameras->show();
710 lensfunLensesLbl->show();
711 lensfunLenses->show();
712 updateLensfunWarning();
713 } else {
714 lensfunCamerasLbl->hide();
715 lensfunCameras->hide();
716 lensfunLensesLbl->hide();
717 lensfunLenses->hide();
718 warning->hide();
719 }
720 }
721
updateLensfunWarning()722 void LensProfilePanel::updateLensfunWarning()
723 {
724 warning->hide();
725
726 ckbUseVign->set_sensitive(isRaw);
727 ckbUseDist->set_sensitive(true);
728 ckbUseCA->set_sensitive(true);
729
730 if (corrLensfunManualRB->get_active() || corrLensfunAutoRB->get_active()) {
731 const LFDatabase* const db = LFDatabase::getInstance();
732
733 const auto itc = lensfunCameras->get_active();
734
735 if (!itc) {
736 return;
737 }
738
739 const LFCamera c = db->findCamera((*itc)[lf->lensfunModelCam.make], (*itc)[lf->lensfunModelCam.model]);
740 const auto itl = lensfunLenses->get_active();
741
742 if (!itl) {
743 return;
744 }
745
746 const LFLens l = db->findLens(LFCamera(), (*itl)[lf->lensfunModelLens.lens]);
747 const float lenscrop = l.getCropFactor();
748 const float camcrop = c.getCropFactor();
749
750 if (lenscrop <= 0 || camcrop <= 0 || lenscrop / camcrop >= 1.01f) {
751 warning->show();
752 }
753
754 ckbUseVign->set_sensitive(l.hasVignettingCorrection());
755 ckbUseDist->set_sensitive(l.hasDistortionCorrection());
756 ckbUseCA->set_sensitive(l.hasCACorrection()); // && allowFocusDep);
757
758 if (!isRaw || !l.hasVignettingCorrection()) {
759 ckbUseVign->set_active(false);
760 }
761
762 if (!l.hasDistortionCorrection()) {
763 ckbUseDist->set_active(false);
764 }
765
766 if (!l.hasCACorrection()) {
767 ckbUseCA->set_active(false);
768 }
769 }
770 }
771
772 LensProfilePanel::LFDbHelper* LensProfilePanel::lf(nullptr);
773
774
setDefaults(const ProcParams * def)775 void LensProfilePanel::setDefaults(const ProcParams *def)
776 {
777 initial_params = def->lensProf;
778 }
779
780
toolReset(bool to_initial)781 void LensProfilePanel::toolReset(bool to_initial)
782 {
783 ProcParams pp;
784 if (to_initial) {
785 pp.lensProf = initial_params;
786 }
787 read(&pp);
788 if (listener && !getEnabled()) {
789 listener->panelChanged(EvToolReset, M("GENERAL_RESET"));
790 }
791 }
792