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 #ifdef __WXMSW__
487  // wxFrame does have a strange background color on Windows..
488  this->SetBackgroundColour(m_progressPanel->GetBackgroundColour());
489 #endif
490  SetSizer(topsizer);
491  RestoreFramePosition(this, "RawImportProgress");
492  Bind(EVT_QUEUE_PROGRESS, &RawImportProgress::OnProgress, this);
493  Bind(wxEVT_INIT_DIALOG, &RawImportProgress::OnInitDialog, this);
494  };
496  {
497  StoreFramePosition(this, "RawImportProgress");
498  }
499 
500 protected:
501  void OnProcessReferenceTerminate(wxProcessEvent& e)
502  {
503  if (e.GetExitCode() == 0)
504  {
505  if (!m_converter->ProcessReferenceOutput(m_progressPanel->GetLogAsArrayString()))
506  {
507  wxMessageBox(_("Could not process the output of reference image.\nFurther processed images will not have a consistent white balance."),
508 #ifdef _WIN32
509  _("Hugin"),
510 #else
511  wxT(""),
512 #endif
513  wxOK | wxICON_INFORMATION, this);
514 
515  };
516  Unbind(wxEVT_END_PROCESS, &RawImportProgress::OnProcessReferenceTerminate, this);
517  m_progress->SetValue(hugin_utils::roundi(100.0 / m_images.size()));
518  wxArrayString rawFiles(m_rawImages);
519  rawFiles.RemoveAt(m_refImg);
520  if (rawFiles.IsEmpty())
521  {
522  // copy log to clipboard if preference is set
523  if (wxConfigBase::Get()->Read(wxT("CopyLogToClipboard"), 0l) == 1l)
524  {
526  };
527  EndModal(wxID_OK);
528  }
529  else
530  {
531  wxArrayString imgFiles(m_images);
532  imgFiles.RemoveAt(m_refImg);
533  Bind(wxEVT_END_PROCESS, &RawImportProgress::OnProcessTerminate, this);
534  m_progressPanel->ExecQueue(m_converter->GetCmdQueueForImport(rawFiles, imgFiles));
535  };
536  }
537  else
538  {
539  m_isRunning = false;
540  m_cancelButton->SetLabel(_("Close"));
541  };
542  };
543  void OnProcessTerminate(wxProcessEvent& e)
544  {
545  if (e.GetExitCode() == 0)
546  {
547  // copy log to clipboard if preference is set
548  if (wxConfigBase::Get()->Read(wxT("CopyLogToClipboard"), 0l) == 1l)
549  {
551  };
552  EndModal(wxID_OK);
553  }
554  else
555  {
556  m_isRunning = false;
557  m_cancelButton->SetLabel(_("Close"));
558  };
559  };
560  void OnProgress(wxCommandEvent& event)
561  {
562  if (event.GetInt() >= 0)
563  {
564  m_progress->SetValue(hugin_utils::roundi((1 + event.GetInt() / 100.0f * (m_images.size() - 1)) * 100.0f / m_images.size()));
565  };
566  };
567  void OnCancel(wxCommandEvent & event)
568  {
569  if (m_isRunning)
570  {
572  m_isRunning = false;
573  }
574  else
575  {
576  EndModal(wxID_CANCEL);
577  };
578  };
579  void OnInitDialog(wxInitDialogEvent& e)
580  {
581  // start processing reference image
582  Bind(wxEVT_END_PROCESS, &RawImportProgress::OnProcessReferenceTerminate, this);
583  m_progressPanel->ExecQueue(m_converter->GetCmdQueueForReference(m_rawImages[m_refImg], m_images[m_refImg]));
584  }
585 
586 private:
587  std::shared_ptr<RawImport> m_converter;
588  wxArrayString m_rawImages, m_images;
589  int m_refImg;
591  wxGauge* m_progress;
592  wxButton* m_cancelButton;
594 };
595 
596 RawImportDialog::RawImportDialog(wxWindow *parent, HuginBase::Panorama* pano, std::vector<std::string>& rawFiles)
597 {
598  // load our children. some children might need special
599  // initialization. this will be done later.
600  wxXmlResource::Get()->LoadDialog(this, parent, wxT("import_raw_dialog"));
601 
602 #ifdef __WXMSW__
603  wxIconBundle myIcons(huginApp::Get()->GetXRCPath() + wxT("data/hugin.ico"),wxBITMAP_TYPE_ICO);
604  SetIcons(myIcons);
605 #else
606  wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
607  SetIcon(myIcon);
608 #endif
609 
610  RestoreFramePosition(this, "RawImportDialog");
611  wxConfigBase* config = wxConfig::Get();
612  // dcraw
613  wxString s = config->Read("/RawImportDialog/dcrawParameter", "");
614  XRCCTRL(*this, "raw_dcraw_parameter", wxTextCtrl)->SetValue(s);
615 
616  // RT processing profile
617  s = config->Read("/RawImportDialog/RTProcessingProfile", "");
618  wxTextCtrl* ctrl = XRCCTRL(*this, "raw_rt_processing_profile", wxTextCtrl);
619  ctrl->SetValue(s);
620  ctrl->AutoCompleteFileNames();
621  // read last used converter
622  const long converter = config->Read("/RawImportDialog/Converter", 0l);
623  switch (converter)
624  {
625  default:
626  case 0:
627  XRCCTRL(*this, "raw_rb_dcraw", wxRadioButton)->SetValue(true);
628  break;
629  case 1:
630  XRCCTRL(*this, "raw_rb_rt", wxRadioButton)->SetValue(true);
631  break;
632  case 2:
633  XRCCTRL(*this, "raw_rb_darktable", wxRadioButton)->SetValue(true);
634  break;
635  };
636  wxCommandEvent dummy;
637  OnRawConverterSelected(dummy);
638 
639  m_pano=pano;
640  for (auto& file : rawFiles)
641  {
642  m_rawImages.Add(wxString(file.c_str(), HUGIN_CONV_FILENAME));
643  };
644  Bind(wxEVT_BUTTON, &RawImportDialog::OnSelectRTProcessingProfile, this, XRCID("raw_rt_processing_profile_select"));
645  Bind(wxEVT_RADIOBUTTON, &RawImportDialog::OnRawConverterSelected, this, XRCID("raw_rb_dcraw"));
646  Bind(wxEVT_RADIOBUTTON, &RawImportDialog::OnRawConverterSelected, this, XRCID("raw_rb_rt"));
647  Bind(wxEVT_RADIOBUTTON, &RawImportDialog::OnRawConverterSelected, this, XRCID("raw_rb_darktable"));
648  Bind(wxEVT_BUTTON, &RawImportDialog::OnOk, this, wxID_OK);
649 };
650 
652 {
653  StoreFramePosition(this, "RawImportDialog");
654 }
655 
657 {
658  return m_cmd;
659 };
660 
662 {
663  wxArrayString errorReadingFile;
664  wxArrayString differentCam;
665  std::string camera;
666  for (auto& file : m_rawImages)
667  {
668  // check that all images are from the same camera
669 #if defined EXIV2_VERSION && EXIV2_TEST_VERSION(0,27,99)
670 #if defined EXV_ENABLE_BMFF && !EXIV2_TEST_VERSION(0,28,3)
671  // enable BMFF option if available, necessary for Canon CR3 files
672  // only needed for exiv2 version <0.28.3
673  // in higher version this function is deprecated
674  Exiv2::enableBMFF();
675 #endif
676  Exiv2::Image::UniquePtr image;
677 #else
678  Exiv2::Image::AutoPtr image;
679 #endif
680  try
681  {
682  image = Exiv2::ImageFactory::open(std::string(file.mb_str(HUGIN_CONV_FILENAME)));
683  }
684  catch (const Exiv2::Error& e)
685  {
686  std::cerr << "Exiv2: Error reading metadata (" << e.what() << ")" << std::endl;
687  errorReadingFile.push_back(file);
688  continue;
689  }
690 
691  try
692  {
693  image->readMetadata();
694  }
695  catch (const Exiv2::Error& e)
696  {
697  std::cerr << "Caught Exiv2 exception '" << e.what() << "' for file " << file << std::endl;
698  errorReadingFile.push_back(file);
699  };
700  Exiv2::ExifData &exifData = image->exifData();
701  if (exifData.empty())
702  {
703  errorReadingFile.push_back(file);
704  continue;
705  };
706  std::string cam;
707  auto make = Exiv2::make(exifData);
708  if (make != exifData.end() && make->count())
709  {
710  cam = make->toString();
711  };
712  auto model = Exiv2::model(exifData);
713  if (model != exifData.end() && model->count())
714  {
715  cam += "|" + model->toString();
716  };
717  if (camera.empty())
718  {
719  camera = cam;
720  }
721  else
722  {
723  if (cam != camera)
724  {
725  differentCam.push_back(file);
726  continue;
727  };
728  };
729  };
730  if (!errorReadingFile.IsEmpty())
731  {
732  wxDialog dlg;
733  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("dlg_warning_filename"));
734  dlg.SetLabel(_("Warning: Read error"));
735  XRCCTRL(dlg, "dlg_warning_text", wxStaticText)->SetLabel(_("The following files will be skipped because the metadata of these files could not read."));
736  XRCCTRL(dlg, "dlg_warning_list", wxListBox)->Append(errorReadingFile);
737  dlg.Fit();
738  dlg.CenterOnScreen();
739  dlg.ShowModal();
740  for (auto& file : errorReadingFile)
741  {
742  m_rawImages.Remove(file);
743  };
744  if (m_rawImages.IsEmpty())
745  {
746  return false;
747  };
748  };
749  if (differentCam.IsEmpty())
750  {
751  FillImageChoice();
752  return true;
753  }
754  else
755  {
756  wxDialog dlg;
757  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("dlg_warning_filename"));
758  dlg.SetLabel(_("Warning: raw images from different cameras"));
759  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."));
760  XRCCTRL(dlg, "dlg_warning_list", wxListBox)->Append(differentCam);
761  dlg.Fit();
762  dlg.CenterOnScreen();
763  dlg.ShowModal();
764  return false;
765  };
766 };
767 
768 void RawImportDialog::OnOk(wxCommandEvent & e)
769 {
770  std::shared_ptr<RawImport> rawConverter;
771  long rawConverterInt;
772  if (XRCCTRL(*this, "raw_rb_dcraw", wxRadioButton)->GetValue())
773  {
774  rawConverter = std::make_shared<DCRawImport>();
775  rawConverterInt = 0;
776  }
777  else
778  {
779  if (XRCCTRL(*this, "raw_rb_rt", wxRadioButton)->GetValue())
780  {
781  rawConverter = std::make_shared<RTRawImport>();
782  rawConverterInt = 1;
783  }
784  else
785  {
786  rawConverter = std::make_shared<DarkTableRawImport>();
787  rawConverterInt = 2;
788  };
789  };
790  // check if given program is available
791  if (!rawConverter->CheckExe(this))
792  {
793  return;
794  }
795  // check additional parameters
796  if (!rawConverter->ProcessAdditionalParameters(this))
797  {
798  return;
799  };
800  {
801  // check if image files already exists
802  m_images.clear();
803  wxArrayString existingImages;
804  for (auto& img : m_rawImages)
805  {
806  wxFileName newImage(img);
807  newImage.SetExt(rawConverter->GetImageExtension());
808  m_images.push_back(newImage.GetFullPath());
809  if (newImage.FileExists())
810  {
811  existingImages.push_back(newImage.GetFullPath());
812  };
813  };
814  if (!existingImages.IsEmpty())
815  {
816  wxDialog dlg;
817  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("dlg_warning_overwrite"));
818  XRCCTRL(dlg, "dlg_overwrite_list", wxListBox)->Append(existingImages);
819  dlg.Fit();
820  dlg.CenterOnScreen();
821  if (dlg.ShowModal() != wxID_OK)
822  {
823  return;
824  };
825  };
826  if (!rawConverter->SupportsOverwrite())
827  {
828  // raw converter does not support overwritting
829  // so delete the file explicit before
830  for (auto& img : existingImages)
831  {
832  wxRemoveFile(img);
833  };
834  };
835  };
836  RawImportProgress dlg(this, rawConverter, m_rawImages, m_images, XRCCTRL(*this, "raw_choice_wb", wxChoice)->GetSelection());
837  if (dlg.ShowModal() == wxID_OK)
838  {
839  // save settings for next call
840  wxConfigBase* config = wxConfig::Get();
841  config->Write("/RawImportDialog/Converter", rawConverterInt);
842  config->Write("/RawImportDialog/dcrawParameter", XRCCTRL(*this, "raw_dcraw_parameter", wxTextCtrl)->GetValue().Trim(true).Trim(false));
843  config->Write("/RawImportDialog/RTProcessingProfile", XRCCTRL(*this, "raw_rt_processing_profile", wxTextCtrl)->GetValue());
844  config->Flush();
845  // check if all files were generated
846  std::vector<std::string> files;
847  bool missingFiles = false;
848  for (auto& img:m_images)
849  {
850  if (wxFileName::FileExists(img))
851  {
852  files.push_back(std::string(img.mb_str(HUGIN_CONV_FILENAME)));
853  }
854  else
855  {
856  missingFiles = true;
857  };
858  };
859  if (missingFiles || files.empty())
860  {
861  wxMessageBox(_("At least one raw images was not successfully converted.\nThis image(s) will be skipped"),
862 #ifdef _WIN32
863  _("Hugin"),
864 #else
865  wxT(""),
866 #endif
867  wxOK | wxICON_INFORMATION, this);
868  };
869  if (files.empty())
870  {
871  return;
872  };
873  // now build PanoCommand and store it
874  std::vector<PanoCommand::PanoCommand*> cmds;
875  cmds.push_back(new PanoCommand::wxAddImagesCmd(*m_pano, files));
876  rawConverter->AddAdditionalPanoramaCommand(cmds, m_pano, m_pano->getNrOfImages(), files.size());
878  m_cmd->setName("import raw images");
879  // close dialog
880  EndModal(wxID_OK);
881  return;
882  };
883  EndModal(wxID_CANCEL);
884 }
885 
887 {
888  wxTextCtrl* input = XRCCTRL(*this, "raw_rt_processing_profile", wxTextCtrl);
889  wxFileDialog dlg(this, _("Select default RT processing profile"), "", input->GetValue(), _("RT processing profile|*.pp3"), wxFD_OPEN, wxDefaultPosition);
890  if (dlg.ShowModal() == wxID_OK)
891  {
892  input->SetValue(dlg.GetPath());
893  }
894 }
895 
897 {
898  enum Converter {
899  DCRAW,
900  RAWTHERAPEE,
901  DARKTABLE
902  } rawConverter;
903  if (XRCCTRL(*this, "raw_rb_dcraw", wxRadioButton)->GetValue())
904  {
905  rawConverter = Converter::DCRAW;
906  }
907  else
908  {
909  if (XRCCTRL(*this, "raw_rb_rt", wxRadioButton)->GetValue())
910  {
911  rawConverter = Converter::RAWTHERAPEE;
912  }
913  else
914  {
915  rawConverter = Converter::DARKTABLE;
916  };
917  };
918  XRCCTRL(*this, "raw_dcraw_text", wxStaticText)->Enable(rawConverter == Converter::DCRAW);
919  XRCCTRL(*this, "raw_dcraw_parameter", wxTextCtrl)->Enable(rawConverter == Converter::DCRAW);
920  XRCCTRL(*this, "raw_rt_text", wxStaticText)->Enable(rawConverter == Converter::RAWTHERAPEE);
921  XRCCTRL(*this, "raw_rt_processing_profile", wxTextCtrl)->Enable(rawConverter == Converter::RAWTHERAPEE);
922  XRCCTRL(*this, "raw_rt_processing_profile_select", wxButton)->Enable(rawConverter == Converter::RAWTHERAPEE);
923 };
924 
926 {
927  wxChoice* choice = XRCCTRL(*this, "raw_choice_wb", wxChoice);
928  for (int i=0; i<m_rawImages.size();++i)
929  {
930  const wxFileName file(m_rawImages[i]);
931  choice->Append(file.GetFullName());
932  };
933  choice->SetSelection(0);
934 };
935 
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:768
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:596
wxArrayString m_images
Definition: RawImport.cpp:588
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:543
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:587
void OnSelectRTProcessingProfile(wxCommandEvent &e)
Definition: RawImport.cpp:886
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:925
void OnCancel(wxCommandEvent &event)
Definition: RawImport.cpp:567
static huginApp * Get()
hack.. kind of a pseudo singleton...
Definition: huginApp.cpp:641
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:579
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:593
PanoCommand::PanoCommand * GetPanoCommand()
return PanoCommand for adding converted raw files to Panorama
Definition: RawImport.cpp:656
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:212
dialog class for showing progress of raw import
Definition: RawImport.cpp:458
wxGauge * m_progress
Definition: RawImport.cpp:591
virtual wxString GetDefaultExe()
returns the default name of the executable
Definition: RawImport.cpp:113
wxButton * m_cancelButton
Definition: RawImport.cpp:592
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:501
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:158
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:651
bool ProcessAdditionalParameters(wxDialog *dlg) override
reads additional parameters from dialog into class
Definition: RawImport.cpp:123
void OnRawConverterSelected(wxCommandEvent &e)
Definition: RawImport.cpp:896
virtual wxString GetDefaultExe()
returns the default name of the executable
Definition: RawImport.cpp:417
const wxString & GetUtilsBinDir()
Definition: huginApp.h:141
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:588
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:560
virtual ~RawImportProgress()
Definition: RawImport.cpp:495
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:661
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