Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RawImport.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
11 /* This is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This software is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public
22  * License along with this software. If not, see
23  * <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #include "hugin/RawImport.h"
28 #include "panoinc.h"
29 #include "base_wx/platform.h"
31 #include "hugin/huginApp.h"
32 #include "base_wx/CommandHistory.h"
33 #include "base_wx/wxPanoCommand.h"
34 #ifdef _WIN32
35 // workaround for a conflict between exiv2 and wxWidgets/CMake built
36 #define HAVE_PID_T 1
37 #endif
38 #include <exiv2/exiv2.hpp>
39 #ifdef __WXMSW__
40 #include <wx/msw/registry.h>
41 #endif
42 
44 class RawImport
45 {
46 public:
47  RawImport(wxString ConfigExePath) { m_exe = wxConfig::Get()->Read(ConfigExePath, ""); };
49  virtual wxString GetImageExtension() { return wxString("tif"); }
51  virtual bool ProcessAdditionalParameters(wxDialog* dlg) { return true; }
53  virtual bool SupportsOverwrite() { return true; }
56  bool CheckExe(wxDialog* dlg)
57  {
58  if (m_exe.IsEmpty())
59  {
60  m_exe = GetDefaultExe();
61  };
62  const wxFileName exePath(m_exe);
63  if (exePath.IsAbsolute())
64  {
65  if (exePath.FileExists())
66  {
67  m_exe = exePath.GetFullPath();
68  return true;
69  }
70  else
71  {
72  wxMessageBox(wxString::Format(_("Executable \"%s\" not found.\nPlease specify a valid executable in preferences."), exePath.GetFullPath()),
73 #ifdef _WIN32
74  _("Hugin"),
75 #else
76  wxT(""),
77 #endif
78  wxOK | wxICON_INFORMATION, dlg);
79  return false;
80  };
81  };
82  wxPathList pathlist;
83 #ifdef __WXMSW__
84  pathlist.Add(huginApp::Get()->GetUtilsBinDir());
85 #endif
86  pathlist.AddEnvList(wxT("PATH"));
87  m_exe = pathlist.FindAbsoluteValidPath(exePath.GetFullPath());
88  if (m_exe.IsEmpty())
89  {
90  wxMessageBox(wxString::Format(_("Executable \"%s\" not found in PATH.\nPlease specify a valid executable in preferences."), exePath.GetFullPath()),
91 #ifdef _WIN32
92  _("Hugin"),
93 #else
94  wxT(""),
95 #endif
96  wxOK | wxICON_INFORMATION, dlg);
97  return false;
98  };
99  return true;
100  };
102  virtual HuginQueue::CommandQueue* GetCmdQueueForReference(const wxString& rawFilename, const wxString& imageFilename) = 0;
104  virtual bool ProcessReferenceOutput(const wxArrayString& output) = 0;
106  virtual HuginQueue::CommandQueue* GetCmdQueueForImport(const wxArrayString& rawFilenames, const wxArrayString& imageFilenames) = 0;
110  virtual void AddAdditionalPanoramaCommand(std::vector<PanoCommand::PanoCommand*>& cmds, HuginBase::Panorama* pano, const int oldImageCount, const int addedImageCount) {};
111 protected:
113  virtual wxString GetDefaultExe() { return wxEmptyString; };
114  wxString m_exe;
115 };
116 
118 class DCRawImport :public RawImport
119 {
120 public:
121  DCRawImport() : RawImport("/RawImportDialog/dcrawExe") {};
122  wxString GetImageExtension() override { return wxString("tiff"); }
123  bool ProcessAdditionalParameters(wxDialog* dlg) override
124  {
125  m_additionalParameters = XRCCTRL(*dlg, "raw_dcraw_parameter", wxTextCtrl)->GetValue().Trim(true).Trim(false);
126  return true;
127  };
128  HuginQueue::CommandQueue* GetCmdQueueForReference(const wxString& rawFilename, const wxString& imageFilename) override
129  {
131  wxString args(" -w -v -4 -T ");
132  if (!m_additionalParameters.IsEmpty())
133  {
134  args.Append(m_additionalParameters);
135  args.Append(" ");
136  };
137  args.Append(HuginQueue::wxEscapeFilename(rawFilename));
138  queue->push_back(new HuginQueue::NormalCommand(m_exe, args, wxString::Format(_("Executing: %s %s"), m_exe, args)));
139  args.Empty();
140  args.Append("-overwrite_original -tagsfromfile ");
141  args.Append(HuginQueue::wxEscapeFilename(rawFilename));
142  args.Append(" -all:all ");
143  args.Append(HuginQueue::wxEscapeFilename(imageFilename));
144  queue->push_back(new HuginQueue::OptionalCommand(HuginQueue::GetExternalProgram(wxConfig::Get(), huginApp::Get()->GetUtilsBinDir(), "exiftool"), args, wxString::Format(_("Updating EXIF data for %s"), imageFilename)));
145  return queue;
146  };
147  bool ProcessReferenceOutput(const wxArrayString& output) override
148  {
149  for (auto& s : output)
150  {
151  int pos = s.Find("multipliers");
152  if (pos >= 0)
153  {
154  m_wb = "-r " + s.Mid(pos + 12);
155  return true;
156  };
157  };
158  return false;
159  };
160  HuginQueue::CommandQueue* GetCmdQueueForImport(const wxArrayString& rawFilenames, const wxArrayString& imageFilenames) override
161  {
163  wxConfigBase* config = wxConfig::Get();
164  const wxString binDir = huginApp::Get()->GetUtilsBinDir();
165  for (size_t i = 0; i < rawFilenames.size(); ++i)
166  {
167  wxString args(m_wb);
168  args.Append(" -v -4 -T ");
169  if (!m_additionalParameters.IsEmpty())
170  {
171  args.Append(m_additionalParameters);
172  args.Append(" ");
173  };
174  args.Append(HuginQueue::wxEscapeFilename(rawFilenames[i]));
175  queue->push_back(new HuginQueue::NormalCommand(m_exe, args,wxString::Format(_("Executing: %s %s"), m_exe, args)));
176  args.Empty();
177  args.Append("-overwrite_original -tagsfromfile ");
178  args.Append(HuginQueue::wxEscapeFilename(rawFilenames[i]));
179  args.Append(" -all:all ");
180  args.Append(HuginQueue::wxEscapeFilename(imageFilenames[i]));
181  queue->push_back(new HuginQueue::OptionalCommand(HuginQueue::GetExternalProgram(config, binDir, "exiftool"), args, wxString::Format(_("Updating EXIF data for %s"), imageFilenames[i])));
182  }
183  return queue;
184  };
185  void AddAdditionalPanoramaCommand(std::vector<PanoCommand::PanoCommand*>& cmds, HuginBase::Panorama* pano, const int oldImageCount, const int addedImageCount) override
186  {
187  // set response to linear for newly added images
188  HuginBase::UIntSet imgs;
189  fill_set(imgs, oldImageCount, oldImageCount + addedImageCount - 1);
190  cmds.push_back(new PanoCommand::ChangeImageResponseTypeCmd(*pano, imgs, HuginBase::SrcPanoImage::RESPONSE_LINEAR));
191  };
192 protected:
193  virtual wxString GetDefaultExe()
194  {
195 #ifdef _WIN32
196  return "dcraw.exe";
197 #else
198  return "dcraw";
199 #endif
200  };
201 private:
202  wxString m_additionalParameters;
203  wxString m_wb;
204 };
205 
207 class RTRawImport :public RawImport
208 {
209 public:
210  RTRawImport() : RawImport("/RawImportDialog/RTExe") {};
211  bool ProcessAdditionalParameters(wxDialog* dlg) override
212  {
213  m_processingProfile = XRCCTRL(*dlg, "raw_rt_processing_profile", wxTextCtrl)->GetValue().Trim(true).Trim(false);
215  {
216  wxMessageBox(wxString::Format(_("Processing profile \"%s\" not found.\nPlease specify a valid file or leave field empty for default settings."), m_processingProfile),
217 #ifdef _WIN32
218  _("Hugin"),
219 #else
220  wxT(""),
221 #endif
222  wxOK | wxICON_INFORMATION, dlg);
223  return false;
224  }
225  return true;
226  };
227  HuginQueue::CommandQueue* GetCmdQueueForReference(const wxString& rawFilename, const wxString& imageFilename) override
228  {
230  wxString args("-O " + HuginQueue::wxEscapeFilename(imageFilename));
231  if (m_processingProfile.IsEmpty())
232  {
233  args.Append(" -d");
234  }
235  else
236  {
237  args.Append(" -p " + HuginQueue::wxEscapeFilename(m_processingProfile));
238  };
239  // apply some special settings, especially disable all crop and rotation settings
240  args.Append(" -s -p " + HuginQueue::wxEscapeFilename(
241  wxString(std::string(hugin_utils::GetDataDir() + "hugin_rt.pp3").c_str(), HUGIN_CONV_FILENAME)));
242  args.Append(" -b16 -tz -Y -c ");
243  args.Append(HuginQueue::wxEscapeFilename(rawFilename));
244  m_usedProcessingProfile = imageFilename + ".pp3";
245  queue->push_back(new HuginQueue::NormalCommand(m_exe, args, wxString::Format(_("Executing: %s %s"), m_exe, args)));
246  return queue;
247  };
248  bool ProcessReferenceOutput(const wxArrayString& output) override
249  {
250  // we need to change the WB setting in the processing profile so the white balance of the reference image
251  // is used and not the stored WB from each individual image
252  wxFileConfig config(wxEmptyString, wxEmptyString, m_usedProcessingProfile);
253  config.Write("/White Balance/Setting", "Custom");
254  config.Flush();
255  return true;
256  };
257  HuginQueue::CommandQueue* GetCmdQueueForImport(const wxArrayString& rawFilenames, const wxArrayString& imageFilenames) override
258  {
260  for (size_t i = 0; i < rawFilenames.size(); ++i)
261  {
262  wxString args("-o " + HuginQueue::wxEscapeFilename(imageFilenames[i]));
264  args.Append(" -b16 -tz -Y -c ");
265  args.Append(HuginQueue::wxEscapeFilename(rawFilenames[i]));
266  queue->push_back(new HuginQueue::NormalCommand(m_exe, args, wxString::Format(_("Executing: %s %s"), m_exe, args)));
267  }
268  return queue;
269  };
270 protected:
271  virtual wxString GetDefaultExe()
272  {
273 #ifdef __WXMSW__
274  // try reading installed version from registry
275  // works only with RT 5.5 and above
276  wxRegKey regkey(wxRegKey::HKLM, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\rawtherapee-cli.exe");
277  wxString prog;
278  if (regkey.HasValue(wxT("")) && regkey.QueryRawValue(wxT(""), prog))
279  {
280  if (wxFileName::FileExists(prog))
281  {
282  return prog;
283  };
284  }
285  else
286  {
287  // now check if installed for current user only
288  wxRegKey regkeyUser(wxRegKey::HKCU, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\rawtherapee-cli.exe");
289  wxString prog;
290  if (regkeyUser.HasValue(wxT("")) && regkeyUser.QueryRawValue(wxT(""), prog))
291  {
292  if (wxFileName::FileExists(prog))
293  {
294  return prog;
295  };
296  };
297  };
298  // nothing found in registry, return default name
299  return "rawtherapee-cli.exe";
300 #elif defined __WXMAC__
301  return "/Applications/RawTherapee.app/Contents/MacOS/rawtherapee-cli";
302 #else
303  return "rawtherapee-cli";
304 #endif
305  };
306 private:
307  wxString m_processingProfile;
309 };
310 
313 {
314 public:
315  DarkTableRawImport() : RawImport("/RawImportDialog/DarktableExe") {}
317  {
318  // destructor, clean up generated files;
319  if (!m_usedSettings.IsEmpty())
320  {
321  wxRemoveFile(m_usedSettings);
322  };
323  }
324  bool SupportsOverwrite() override { return false; }
325  HuginQueue::CommandQueue* GetCmdQueueForReference(const wxString& rawFilename, const wxString& imageFilename) override
326  {
328  wxString args(" --verbose ");
329  args.Append(HuginQueue::wxEscapeFilename(rawFilename));
330  args.Append(" ");
331 #ifdef __WXMSW__
332  // darktable has problems with Windows paths as output
333  // so change separator before
334  wxString file(imageFilename);
335  file.Replace("\\", "/", true);
336  args.Append(HuginQueue::wxEscapeFilename(file));
337 #else
338  args.Append(HuginQueue::wxEscapeFilename(imageFilename));
339 #endif
340  // switch --bpp does not work, so using this strange workaround
341  args.Append(" --core --conf plugins/imageio/format/tiff/bpp=16");
342  m_refImage = imageFilename;
343  queue->push_back(new HuginQueue::NormalCommand(m_exe, args, wxString::Format(_("Executing: %s %s"), m_exe, args)));
344  return queue;
345  };
346  bool ProcessReferenceOutput(const wxArrayString& output) override
347  {
348  // extract XMP package for converted reference image and store in temp
349 #if defined EXIV2_VERSION && EXIV2_TEST_VERSION(0,27,99)
350  Exiv2::Image::UniquePtr image;
351 #else
352  Exiv2::Image::AutoPtr image;
353 #endif
354  try
355  {
356  image = Exiv2::ImageFactory::open(std::string(m_refImage.mb_str(HUGIN_CONV_FILENAME)));
357  }
358  catch (const Exiv2::Error& e)
359  {
360  std::cerr << "Exiv2: Error reading metadata (" << e.what() << ")" << std::endl;
361  return false;
362  }
363  try
364  {
365  image->readMetadata();
366  }
367  catch (const Exiv2::Error& e)
368  {
369  std::cerr << "Caught Exiv2 exception " << e.what() << std::endl;
370  return false;
371  };
372  m_usedSettings = wxFileName::CreateTempFileName("hugdt");
373 #if defined EXIV2_VERSION && EXIV2_TEST_VERSION(0,27,99)
374  Exiv2::Image::UniquePtr image2;
375 #else
376  Exiv2::Image::AutoPtr image2;
377 #endif
378  try
379  {
380  image2 = Exiv2::ImageFactory::create(Exiv2::ImageType::xmp, std::string(m_usedSettings.mb_str(HUGIN_CONV_FILENAME)));
381  }
382  catch (const Exiv2::Error& e)
383  {
384  std::cerr << "Exiv2: Error creating temp xmp file (" << e.what() << ")" << std::endl;
385  return false;
386  }
387  image2->setXmpData(image->xmpData());
388  image2->writeMetadata();
389  return true;
390  };
391  HuginQueue::CommandQueue* GetCmdQueueForImport(const wxArrayString& rawFilenames, const wxArrayString& imageFilenames) override
392  {
394  for (size_t i = 0; i < rawFilenames.size(); ++i)
395  {
396  wxString args("--verbose ");
397  args.Append(HuginQueue::wxEscapeFilename(rawFilenames[i]));
398  args.Append(" ");
400  args.Append(" ");
401 #ifdef __WXMSW__
402  // darktable has problems with Windows paths as output
403  // so change separator before
404  wxString file(imageFilenames[i]);
405  file.Replace("\\", "/", true);
406  args.Append(HuginQueue::wxEscapeFilename(file));
407 #else
408  args.Append(HuginQueue::wxEscapeFilename(imageFilenames[i]));
409 #endif
410  // switch --bpp does not work, so using this strange workaround
411  args.Append(" --core --conf plugins/imageio/format/tiff/bpp=16");
412  queue->push_back(new HuginQueue::NormalCommand(m_exe, args, wxString::Format(_("Executing: %s %s"), m_exe, args)));
413  }
414  return queue;
415  };
416 protected:
417  virtual wxString GetDefaultExe()
418  {
419 #ifdef __WXMSW__
420  // try reading installed version from registry
421  wxRegKey regkey(wxRegKey::HKLM, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\darktable-cli.exe");
422  wxString prog;
423  if (regkey.HasValue(wxT("")) && regkey.QueryRawValue(wxT(""), prog))
424  {
425  if (wxFileName::FileExists(prog))
426  {
427  return prog;
428  }
429  }
430  else
431  {
432  // now check if installed for current user only
433  wxRegKey regkeyUser(wxRegKey::HKCU, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\darktable-cli.exe");
434  wxString prog;
435  if (regkeyUser.HasValue(wxT("")) && regkeyUser.QueryRawValue(wxT(""), prog))
436  {
437  if (wxFileName::FileExists(prog))
438  {
439  return prog;
440  };
441  };
442  };
443  // nothing found in registry, return default name
444  return "darktable-cli.exe";
445 #elif defined __WXMAC__
446  return "/Applications/darktable.app/Contents/MacOS/darktable-cli";
447 #else
448  return "darktable-cli";
449 #endif
450  };
451 private:
452  wxString m_refImage;
453  wxString m_usedSettings;
454 };
455 
456 
458 class RawImportProgress :public wxDialog
459 {
460 public:
461  RawImportProgress(wxWindow * parent, std::shared_ptr<RawImport>& converter, const wxArrayString& rawImages, const wxArrayString& images, const int refImg) :
462  wxDialog(parent, wxID_ANY, _("Import Raw Images"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
463  m_converter(converter), m_rawImages(rawImages), m_images(images), m_refImg(refImg), m_isRunning(false)
464  {
465  DEBUG_ASSERT(m_rawImages.size() > 0);
466  DEBUG_ASSERT(m_rawImages.size() == m_images.size());
467  if (m_refImg < 0)
468  {
469  m_refImg = 0;
470  };
471  if (m_refImg >= m_rawImages.size())
472  {
473  m_refImg = 0;
474  };
475  wxBoxSizer * topsizer = new wxBoxSizer(wxVERTICAL);
476  m_progressPanel = new MyExecPanel(this);
477  topsizer->Add(m_progressPanel, 1, wxEXPAND | wxALL, 2);
478 
479  wxBoxSizer* bottomsizer = new wxBoxSizer(wxHORIZONTAL);
480  m_progress = new wxGauge(this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL | wxGA_PROGRESS);
481  bottomsizer->Add(m_progress, 1, wxEXPAND | wxALL, 10);
482  m_cancelButton = new wxButton(this, wxID_CANCEL, _("Cancel"));
483  bottomsizer->Add(m_cancelButton, 0, wxALL, 10);
484  m_cancelButton->Bind(wxEVT_BUTTON, &RawImportProgress::OnCancel, this);
485  topsizer->Add(bottomsizer, 0, wxEXPAND);
486  SetSizer(topsizer);
487  RestoreFramePosition(this, "RawImportProgress");
488  Bind(EVT_QUEUE_PROGRESS, &RawImportProgress::OnProgress, this);
489  Bind(wxEVT_INIT_DIALOG, &RawImportProgress::OnInitDialog, this);
490  };
492  {
493  StoreFramePosition(this, "RawImportProgress");
494  }
495 
496 protected:
497  void OnProcessReferenceTerminate(wxProcessEvent& e)
498  {
499  if (e.GetExitCode() == 0)
500  {
501  if (!m_converter->ProcessReferenceOutput(m_progressPanel->GetLogAsArrayString()))
502  {
503  wxMessageBox(_("Could not process the output of reference image.\nFurther processed images will not have a consistent white balance."),
504 #ifdef _WIN32
505  _("Hugin"),
506 #else
507  wxT(""),
508 #endif
509  wxOK | wxICON_INFORMATION, this);
510 
511  };
512  Unbind(wxEVT_END_PROCESS, &RawImportProgress::OnProcessReferenceTerminate, this);
513  m_progress->SetValue(hugin_utils::roundi(100.0 / m_images.size()));
514  wxArrayString rawFiles(m_rawImages);
515  rawFiles.RemoveAt(m_refImg);
516  if (rawFiles.IsEmpty())
517  {
518  // copy log to clipboard if preference is set
519  if (wxConfigBase::Get()->Read(wxT("CopyLogToClipboard"), 0l) == 1l)
520  {
522  };
523  EndModal(wxID_OK);
524  }
525  else
526  {
527  wxArrayString imgFiles(m_images);
528  imgFiles.RemoveAt(m_refImg);
529  Bind(wxEVT_END_PROCESS, &RawImportProgress::OnProcessTerminate, this);
530  m_progressPanel->ExecQueue(m_converter->GetCmdQueueForImport(rawFiles, imgFiles));
531  };
532  }
533  else
534  {
535  m_isRunning = false;
536  m_cancelButton->SetLabel(_("Close"));
537  };
538  };
539  void OnProcessTerminate(wxProcessEvent& e)
540  {
541  if (e.GetExitCode() == 0)
542  {
543  // copy log to clipboard if preference is set
544  if (wxConfigBase::Get()->Read(wxT("CopyLogToClipboard"), 0l) == 1l)
545  {
547  };
548  EndModal(wxID_OK);
549  }
550  else
551  {
552  m_isRunning = false;
553  m_cancelButton->SetLabel(_("Close"));
554  };
555  };
556  void OnProgress(wxCommandEvent& event)
557  {
558  if (event.GetInt() >= 0)
559  {
560  m_progress->SetValue(hugin_utils::roundi((1 + event.GetInt() / 100.0f * (m_images.size() - 1)) * 100.0f / m_images.size()));
561  };
562  };
563  void OnCancel(wxCommandEvent & event)
564  {
565  if (m_isRunning)
566  {
568  m_isRunning = false;
569  }
570  else
571  {
572  EndModal(wxID_CANCEL);
573  };
574  };
575  void OnInitDialog(wxInitDialogEvent& e)
576  {
577  // start processing reference image
578  Bind(wxEVT_END_PROCESS, &RawImportProgress::OnProcessReferenceTerminate, this);
579  m_progressPanel->ExecQueue(m_converter->GetCmdQueueForReference(m_rawImages[m_refImg], m_images[m_refImg]));
580  }
581 
582 private:
583  std::shared_ptr<RawImport> m_converter;
584  wxArrayString m_rawImages, m_images;
585  int m_refImg;
587  wxGauge* m_progress;
588  wxButton* m_cancelButton;
590 };
591 
592 RawImportDialog::RawImportDialog(wxWindow *parent, HuginBase::Panorama* pano, std::vector<std::string>& rawFiles)
593 {
594  // load our children. some children might need special
595  // initialization. this will be done later.
596  wxXmlResource::Get()->LoadDialog(this, parent, wxT("import_raw_dialog"));
597 
598  RestoreFramePosition(this, "RawImportDialog");
599  wxConfigBase* config = wxConfig::Get();
600  // dcraw
601  wxString s = config->Read("/RawImportDialog/dcrawParameter", "");
602  XRCCTRL(*this, "raw_dcraw_parameter", wxTextCtrl)->SetValue(s);
603 
604  // RT processing profile
605  s = config->Read("/RawImportDialog/RTProcessingProfile", "");
606  wxTextCtrl* ctrl = XRCCTRL(*this, "raw_rt_processing_profile", wxTextCtrl);
607  ctrl->SetValue(s);
608  ctrl->AutoCompleteFileNames();
609  // read last used converter
610  const long converter = config->Read("/RawImportDialog/Converter", 0l);
611  switch (converter)
612  {
613  default:
614  case 0:
615  XRCCTRL(*this, "raw_rb_dcraw", wxRadioButton)->SetValue(true);
616  break;
617  case 1:
618  XRCCTRL(*this, "raw_rb_rt", wxRadioButton)->SetValue(true);
619  break;
620  case 2:
621  XRCCTRL(*this, "raw_rb_darktable", wxRadioButton)->SetValue(true);
622  break;
623  };
624  wxCommandEvent dummy;
625  OnRawConverterSelected(dummy);
626 
627  m_pano=pano;
628  for (auto& file : rawFiles)
629  {
630  m_rawImages.Add(wxString(file.c_str(), HUGIN_CONV_FILENAME));
631  };
632  Bind(wxEVT_BUTTON, &RawImportDialog::OnSelectRTProcessingProfile, this, XRCID("raw_rt_processing_profile_select"));
633  Bind(wxEVT_RADIOBUTTON, &RawImportDialog::OnRawConverterSelected, this, XRCID("raw_rb_dcraw"));
634  Bind(wxEVT_RADIOBUTTON, &RawImportDialog::OnRawConverterSelected, this, XRCID("raw_rb_rt"));
635  Bind(wxEVT_RADIOBUTTON, &RawImportDialog::OnRawConverterSelected, this, XRCID("raw_rb_darktable"));
636  Bind(wxEVT_BUTTON, &RawImportDialog::OnOk, this, wxID_OK);
637 };
638 
640 {
641  StoreFramePosition(this, "RawImportDialog");
642 }
643 
645 {
646  return m_cmd;
647 };
648 
650 {
651  wxArrayString errorReadingFile;
652  wxArrayString differentCam;
653  std::string camera;
654  for (auto& file : m_rawImages)
655  {
656  // check that all images are from the same camera
657 #if defined EXIV2_VERSION && EXIV2_TEST_VERSION(0,27,99)
658 #if defined EXV_ENABLE_BMFF && !EXIV2_TEST_VERSION(0,28,3)
659  // enable BMFF option if available, necessary for Canon CR3 files
660  // only needed for exiv2 version <0.28.3
661  // in higher version this function is deprecated
662  Exiv2::enableBMFF();
663 #endif
664  Exiv2::Image::UniquePtr image;
665 #else
666  Exiv2::Image::AutoPtr image;
667 #endif
668  try
669  {
670  image = Exiv2::ImageFactory::open(std::string(file.mb_str(HUGIN_CONV_FILENAME)));
671  }
672  catch (const Exiv2::Error& e)
673  {
674  std::cerr << "Exiv2: Error reading metadata (" << e.what() << ")" << std::endl;
675  errorReadingFile.push_back(file);
676  continue;
677  }
678 
679  try
680  {
681  image->readMetadata();
682  }
683  catch (const Exiv2::Error& e)
684  {
685  std::cerr << "Caught Exiv2 exception '" << e.what() << "' for file " << file << std::endl;
686  errorReadingFile.push_back(file);
687  };
688  Exiv2::ExifData &exifData = image->exifData();
689  if (exifData.empty())
690  {
691  errorReadingFile.push_back(file);
692  continue;
693  };
694  std::string cam;
695  auto make = Exiv2::make(exifData);
696  if (make != exifData.end() && make->count())
697  {
698  cam = make->toString();
699  };
700  auto model = Exiv2::model(exifData);
701  if (model != exifData.end() && model->count())
702  {
703  cam += "|" + model->toString();
704  };
705  if (camera.empty())
706  {
707  camera = cam;
708  }
709  else
710  {
711  if (cam != camera)
712  {
713  differentCam.push_back(file);
714  continue;
715  };
716  };
717  };
718  if (!errorReadingFile.IsEmpty())
719  {
720  wxDialog dlg;
721  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("dlg_warning_filename"));
722  dlg.SetLabel(_("Warning: Read error"));
723  XRCCTRL(dlg, "dlg_warning_text", wxStaticText)->SetLabel(_("The following files will be skipped because the metadata of these files could not read."));
724  XRCCTRL(dlg, "dlg_warning_list", wxListBox)->Append(errorReadingFile);
725  dlg.Fit();
726  dlg.CenterOnScreen();
727  dlg.ShowModal();
728  for (auto& file : errorReadingFile)
729  {
730  m_rawImages.Remove(file);
731  };
732  if (m_rawImages.IsEmpty())
733  {
734  return false;
735  };
736  };
737  if (differentCam.IsEmpty())
738  {
739  FillImageChoice();
740  return true;
741  }
742  else
743  {
744  wxDialog dlg;
745  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("dlg_warning_filename"));
746  dlg.SetLabel(_("Warning: raw images from different cameras"));
747  XRCCTRL(dlg, "dlg_warning_text", wxStaticText)->SetLabel(_("The following images were shot with different camera than the other one.\nThe raw import works only for images from the same cam."));
748  XRCCTRL(dlg, "dlg_warning_list", wxListBox)->Append(differentCam);
749  dlg.Fit();
750  dlg.CenterOnScreen();
751  dlg.ShowModal();
752  return false;
753  };
754 };
755 
756 void RawImportDialog::OnOk(wxCommandEvent & e)
757 {
758  std::shared_ptr<RawImport> rawConverter;
759  long rawConverterInt;
760  if (XRCCTRL(*this, "raw_rb_dcraw", wxRadioButton)->GetValue())
761  {
762  rawConverter = std::make_shared<DCRawImport>();
763  rawConverterInt = 0;
764  }
765  else
766  {
767  if (XRCCTRL(*this, "raw_rb_rt", wxRadioButton)->GetValue())
768  {
769  rawConverter = std::make_shared<RTRawImport>();
770  rawConverterInt = 1;
771  }
772  else
773  {
774  rawConverter = std::make_shared<DarkTableRawImport>();
775  rawConverterInt = 2;
776  };
777  };
778  // check if given program is available
779  if (!rawConverter->CheckExe(this))
780  {
781  return;
782  }
783  // check additional parameters
784  if (!rawConverter->ProcessAdditionalParameters(this))
785  {
786  return;
787  };
788  {
789  // check if image files already exists
790  m_images.clear();
791  wxArrayString existingImages;
792  for (auto& img : m_rawImages)
793  {
794  wxFileName newImage(img);
795  newImage.SetExt(rawConverter->GetImageExtension());
796  m_images.push_back(newImage.GetFullPath());
797  if (newImage.FileExists())
798  {
799  existingImages.push_back(newImage.GetFullPath());
800  };
801  };
802  if (!existingImages.IsEmpty())
803  {
804  wxDialog dlg;
805  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("dlg_warning_overwrite"));
806  XRCCTRL(dlg, "dlg_overwrite_list", wxListBox)->Append(existingImages);
807  dlg.Fit();
808  dlg.CenterOnScreen();
809  if (dlg.ShowModal() != wxID_OK)
810  {
811  return;
812  };
813  };
814  if (!rawConverter->SupportsOverwrite())
815  {
816  // raw converter does not support overwritting
817  // so delete the file explicit before
818  for (auto& img : existingImages)
819  {
820  wxRemoveFile(img);
821  };
822  };
823  };
824  RawImportProgress dlg(this, rawConverter, m_rawImages, m_images, XRCCTRL(*this, "raw_choice_wb", wxChoice)->GetSelection());
825  if (dlg.ShowModal() == wxID_OK)
826  {
827  // save settings for next call
828  wxConfigBase* config = wxConfig::Get();
829  config->Write("/RawImportDialog/Converter", rawConverterInt);
830  config->Write("/RawImportDialog/dcrawParameter", XRCCTRL(*this, "raw_dcraw_parameter", wxTextCtrl)->GetValue().Trim(true).Trim(false));
831  config->Write("/RawImportDialog/RTProcessingProfile", XRCCTRL(*this, "raw_rt_processing_profile", wxTextCtrl)->GetValue());
832  config->Flush();
833  // check if all files were generated
834  std::vector<std::string> files;
835  bool missingFiles = false;
836  for (auto& img:m_images)
837  {
838  if (wxFileName::FileExists(img))
839  {
840  files.push_back(std::string(img.mb_str(HUGIN_CONV_FILENAME)));
841  }
842  else
843  {
844  missingFiles = true;
845  };
846  };
847  if (missingFiles || files.empty())
848  {
849  wxMessageBox(_("At least one raw images was not successfully converted.\nThis image(s) will be skipped"),
850 #ifdef _WIN32
851  _("Hugin"),
852 #else
853  wxT(""),
854 #endif
855  wxOK | wxICON_INFORMATION, this);
856  };
857  if (files.empty())
858  {
859  return;
860  };
861  // now build PanoCommand and store it
862  std::vector<PanoCommand::PanoCommand*> cmds;
863  cmds.push_back(new PanoCommand::wxAddImagesCmd(*m_pano, files));
864  rawConverter->AddAdditionalPanoramaCommand(cmds, m_pano, m_pano->getNrOfImages(), files.size());
866  m_cmd->setName("import raw images");
867  // close dialog
868  EndModal(wxID_OK);
869  return;
870  };
871  EndModal(wxID_CANCEL);
872 }
873 
875 {
876  wxTextCtrl* input = XRCCTRL(*this, "raw_rt_processing_profile", wxTextCtrl);
877  wxFileDialog dlg(this, _("Select default RT processing profile"), "", input->GetValue(), _("RT processing profile|*.pp3"), wxFD_OPEN, wxDefaultPosition);
878  if (dlg.ShowModal() == wxID_OK)
879  {
880  input->SetValue(dlg.GetPath());
881  }
882 }
883 
885 {
886  enum Converter {
887  DCRAW,
888  RAWTHERAPEE,
889  DARKTABLE
890  } rawConverter;
891  if (XRCCTRL(*this, "raw_rb_dcraw", wxRadioButton)->GetValue())
892  {
893  rawConverter = Converter::DCRAW;
894  }
895  else
896  {
897  if (XRCCTRL(*this, "raw_rb_rt", wxRadioButton)->GetValue())
898  {
899  rawConverter = Converter::RAWTHERAPEE;
900  }
901  else
902  {
903  rawConverter = Converter::DARKTABLE;
904  };
905  };
906  XRCCTRL(*this, "raw_dcraw_text", wxStaticText)->Enable(rawConverter == Converter::DCRAW);
907  XRCCTRL(*this, "raw_dcraw_parameter", wxTextCtrl)->Enable(rawConverter == Converter::DCRAW);
908  XRCCTRL(*this, "raw_rt_text", wxStaticText)->Enable(rawConverter == Converter::RAWTHERAPEE);
909  XRCCTRL(*this, "raw_rt_processing_profile", wxTextCtrl)->Enable(rawConverter == Converter::RAWTHERAPEE);
910  XRCCTRL(*this, "raw_rt_processing_profile_select", wxButton)->Enable(rawConverter == Converter::RAWTHERAPEE);
911 };
912 
914 {
915  wxChoice* choice = XRCCTRL(*this, "raw_choice_wb", wxChoice);
916  for (int i=0; i<m_rawImages.size();++i)
917  {
918  const wxFileName file(m_rawImages[i]);
919  choice->Append(file.GetFullName());
920  };
921  choice->SetSelection(0);
922 };
923 
Base class for all panorama commands.
Definition: Command.h:38
void OnOk(wxCommandEvent &e)
called when dialog is finished and does the conversion
Definition: RawImport.cpp:756
normal command for queue, processing is stopped if an error occurred in program
Definition: Executor.h:37
implementation of huginApp Class
bool FileExists(const std::string &filename)
checks if file exists
Definition: utils.cpp:362
wxString GetImageExtension() override
image extension of converted files
Definition: RawImport.cpp:122
wxArrayString GetLogAsArrayString()
returns the output
special class for raw import with dcraw
Definition: RawImport.cpp:118
wxString m_usedProcessingProfile
Definition: RawImport.cpp:308
int roundi(T x)
Definition: hugin_math.h:73
virtual wxString GetImageExtension()
image extension of converted files
Definition: RawImport.cpp:49
RawImportDialog(wxWindow *parent, HuginBase::Panorama *pano, std::vector< std::string > &rawFiles)
Constructor, read from xrc ressource; restore last uses settings and position.
Definition: RawImport.cpp:592
wxArrayString m_images
Definition: RawImport.cpp:584
virtual void AddAdditionalPanoramaCommand(std::vector< PanoCommand::PanoCommand * > &cmds, HuginBase::Panorama *pano, const int oldImageCount, const int addedImageCount)
add additional PanoCommand::PanoCommand to vector if needed hint: we need to pass old and new image n...
Definition: RawImport.cpp:110
void OnProcessTerminate(wxProcessEvent &e)
Definition: RawImport.cpp:539
optional command for queue, processing of queue is always continued, also if an error occurred ...
Definition: Executor.h:53
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
special class for Darktable raw import
Definition: RawImport.cpp:312
HuginQueue::CommandQueue * GetCmdQueueForImport(const wxArrayString &rawFilenames, const wxArrayString &imageFilenames) override
return commands for processing of all other images with white balance read by RawImport::ProcessRefer...
Definition: RawImport.cpp:391
int ExecQueue(HuginQueue::CommandQueue *queue)
std::shared_ptr< RawImport > m_converter
Definition: RawImport.cpp:583
void OnSelectRTProcessingProfile(wxCommandEvent &e)
Definition: RawImport.cpp:874
virtual void setName(const std::string &newName)
sets the name for the command
Definition: Command.cpp:88
wxArrayString m_rawImages
Definition: RawImport.h:56
HuginQueue::CommandQueue * GetCmdQueueForReference(const wxString &rawFilename, const wxString &imageFilename) override
return command for processing of reference image
Definition: RawImport.cpp:227
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
include file for the hugin project
void FillImageChoice()
fill list with image names
Definition: RawImport.cpp:913
void OnCancel(wxCommandEvent &event)
Definition: RawImport.cpp:563
static huginApp * Get()
hack.. kind of a pseudo singleton...
Definition: huginApp.cpp:645
wxString m_additionalParameters
Definition: RawImport.cpp:200
virtual bool ProcessReferenceOutput(const wxArrayString &output)=0
read output of processing of reference image to read in white balance of reference image ...
bool ProcessAdditionalParameters(wxDialog *dlg) override
reads additional parameters from dialog into class
Definition: RawImport.cpp:211
PanoCommand to combine other PanoCommands.
Definition: PanoCommand.h:39
PanoCommand::PanoCommand * m_cmd
Definition: RawImport.h:58
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
void OnInitDialog(wxInitDialogEvent &e)
Definition: RawImport.cpp:575
Model for a panorama.
Definition: Panorama.h:152
std::string GetDataDir()
returns the full path to the data directory
Definition: utils.cpp:441
Definition of dialog and functions to import RAW images to project file.
virtual HuginQueue::CommandQueue * GetCmdQueueForImport(const wxArrayString &rawFilenames, const wxArrayString &imageFilenames)=0
return commands for processing of all other images with white balance read by RawImport::ProcessRefer...
MyExecPanel * m_progressPanel
Definition: RawImport.cpp:589
PanoCommand::PanoCommand * GetPanoCommand()
return PanoCommand for adding converted raw files to Panorama
Definition: RawImport.cpp:644
HuginQueue::CommandQueue * GetCmdQueueForImport(const wxArrayString &rawFilenames, const wxArrayString &imageFilenames) override
return commands for processing of all other images with white balance read by RawImport::ProcessRefer...
Definition: RawImport.cpp:160
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
HuginQueue::CommandQueue * GetCmdQueueForImport(const wxArrayString &rawFilenames, const wxArrayString &imageFilenames) override
return commands for processing of all other images with white balance read by RawImport::ProcessRefer...
Definition: RawImport.cpp:257
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Store window size and position in configfile/registry.
Definition: LensCalApp.cpp:210
dialog class for showing progress of raw import
Definition: RawImport.cpp:458
wxGauge * m_progress
Definition: RawImport.cpp:587
virtual wxString GetDefaultExe()
returns the default name of the executable
Definition: RawImport.cpp:113
wxButton * m_cancelButton
Definition: RawImport.cpp:588
RawImportProgress(wxWindow *parent, std::shared_ptr< RawImport > &converter, const wxArrayString &rawImages, const wxArrayString &images, const int refImg)
Definition: RawImport.cpp:461
base class for implementation of Raw import functions
Definition: RawImport.cpp:44
wxString m_wb
Definition: RawImport.cpp:203
bool ProcessReferenceOutput(const wxArrayString &output) override
read output of processing of reference image to read in white balance of reference image ...
Definition: RawImport.cpp:147
void OnProcessReferenceTerminate(wxProcessEvent &e)
Definition: RawImport.cpp:497
virtual wxString GetDefaultExe()
returns the default name of the executable
Definition: RawImport.cpp:193
wxwindows specific panorama commands
void RestoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Restore window size and position from configfile/registry.
Definition: LensCalApp.cpp:156
bool SupportsOverwrite() override
return true if program supports overwritting output, otherwise false
Definition: RawImport.cpp:324
class for RawTherapee raw import
Definition: RawImport.cpp:207
virtual bool ProcessAdditionalParameters(wxDialog *dlg)
reads additional parameters from dialog into class
Definition: RawImport.cpp:51
~RawImportDialog()
destructor, saves position
Definition: RawImport.cpp:639
bool ProcessAdditionalParameters(wxDialog *dlg) override
reads additional parameters from dialog into class
Definition: RawImport.cpp:123
void OnRawConverterSelected(wxCommandEvent &e)
Definition: RawImport.cpp:884
virtual wxString GetDefaultExe()
returns the default name of the executable
Definition: RawImport.cpp:417
const wxString & GetUtilsBinDir()
Definition: huginApp.h:123
bool CheckExe(wxDialog *dlg)
checks if valid executable was given in dialog either absolute path or when relative path is given ch...
Definition: RawImport.cpp:56
bool ProcessReferenceOutput(const wxArrayString &output) override
read output of processing of reference image to read in white balance of reference image ...
Definition: RawImport.cpp:346
bool ProcessReferenceOutput(const wxArrayString &output) override
read output of processing of reference image to read in white balance of reference image ...
Definition: RawImport.cpp:248
wxString m_exe
Definition: RawImport.cpp:113
wxString m_processingProfile
Definition: RawImport.cpp:305
HuginBase::Panorama * m_pano
Definition: RawImport.h:55
HuginQueue::CommandQueue * GetCmdQueueForReference(const wxString &rawFilename, const wxString &imageFilename) override
return command for processing of reference image
Definition: RawImport.cpp:325
str wxEscapeFilename(const str &arg)
special escaping routine for CommandQueues
Definition: Executor.h:79
void AddAdditionalPanoramaCommand(std::vector< PanoCommand::PanoCommand * > &cmds, HuginBase::Panorama *pano, const int oldImageCount, const int addedImageCount) override
add additional PanoCommand::PanoCommand to vector if needed hint: we need to pass old and new image n...
Definition: RawImport.cpp:185
wxArrayString m_rawImages
Definition: RawImport.cpp:584
RawImport(wxString ConfigExePath)
Definition: RawImport.cpp:47
add image(s) to a panorama
Definition: wxPanoCommand.h:50
wxArrayString m_images
Definition: RawImport.h:57
virtual HuginQueue::CommandQueue * GetCmdQueueForReference(const wxString &rawFilename, const wxString &imageFilename)=0
return command for processing of reference image
wxString m_usedSettings
Definition: RawImport.cpp:453
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
Definition: stl_utils.h:81
virtual bool SupportsOverwrite()
return true if program supports overwritting output, otherwise false
Definition: RawImport.cpp:53
void OnProgress(wxCommandEvent &event)
Definition: RawImport.cpp:556
virtual ~RawImportProgress()
Definition: RawImport.cpp:491
HuginQueue::CommandQueue * GetCmdQueueForReference(const wxString &rawFilename, const wxString &imageFilename) override
return command for processing of reference image
Definition: RawImport.cpp:128
wxString GetExternalProgram(wxConfigBase *config, const wxString &bindir, const wxString &name)
return path and name of external program, which can be overwritten by the user
Definition: Executor.cpp:148
std::vector< NormalCommand * > CommandQueue
Definition: Executor.h:61
bool CheckRawFiles()
return true, if all raw files are from the same camera
Definition: RawImport.cpp:649
void CopyLogToClipboard()
copy the content of the log window into the clipboard
virtual wxString GetDefaultExe()
returns the default name of the executable
Definition: RawImport.cpp:271