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