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