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