Hugin trunk 0.1
Loading...
Searching...
No Matches
StackerPanel.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
10/* This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This software is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public
21 * License along with this software. If not, see
22 * <http://www.gnu.org/licenses/>.
23 *
24 */
25
26#include "StackerPanel.h"
27#include <wx/stdpaths.h>
28#include <wx/propgrid/advprops.h>
29#include "base_wx/platform.h"
30#include "base_wx/wxPlatform.h"
32#include "base_wx/Executor.h"
33#include <wx/fileconf.h>
34#include <wx/wfstream.h>
35#include <wx/sstream.h>
36#include <wx/filepicker.h>
37#include <wx/dir.h>
38#include "hugin_utils/utils.h"
40#include "base_wx/LensTools.h"
41#include "base_wx/wxutils.h"
42#include "CreateBrightImgDlg.h"
43
45class SelectDirectoryFileDialog :public wxDialog
46{
47public:
50 {
51 wxXmlResource::Get()->LoadDialog(this, parent, "select_dir_dialog");
52 m_dirPicker = XRCCTRL(*this, "select_dir_picker", wxDirPickerCtrl);
53 wxConfigBase* config = wxConfigBase::Get();
54 wxString path = config->Read("/actualPath", "");
55 if (!path.IsEmpty())
56 {
57 m_dirPicker->SetPath(path);
58 }
59 m_recursiveCheck = XRCCTRL(*this, "select_dir_recursive", wxCheckBox);
60 if (config->HasEntry("/ToolboxFrame/Stacker/AddDirRecursive"))
61 {
62 m_recursiveCheck->SetValue(config->ReadBool("/ToolboxFrame/Stacker/AddDirRecursive", false));
63 };
64 m_filenameCtrl = XRCCTRL(*this, "select_dir_filename", wxTextCtrl);
65 if (config->HasEntry("/ToolboxFrame/Stacker/AddDirFilenames"))
66 {
67 m_filenameCtrl->SetValue(config->Read("/ToolboxFrame/Stacker/AddDirFilenames", "*"));
68 };
69 m_filetypeChoice = XRCCTRL(*this, "select_dir_filetype", wxChoice);
71 if (config->HasEntry("/ToolboxFrame/Stacker/AddDirFileType"))
72 {
73 m_filetypeChoice->SetSelection(config->ReadLong("/ToolboxFrame/Stacker/AddDirFileType", 0l));
74 };
76 hugin_utils::RestoreFramePosition(this, "ToolboxFrame/Stacker/AddDirDialog");
77 }
78 // return list which matches the given criterium
80 {
81 return m_filenames;
82 }
83protected:
84 void OnOk(wxCommandEvent& e)
85 {
86 // save positions and settings
87 wxConfigBase* config = wxConfigBase::Get();
88 config->Write("/actualPath", m_dirPicker->GetPath());
89 config->Write("/ToolboxFrame/Stacker/AddDirRecursive", m_recursiveCheck->GetValue());
90 config->Write("/ToolboxFrame/Stacker/AddDirFilenames", m_filenameCtrl->GetValue());
91 config->Write("/ToolboxFrame/Stacker/AddDirFileType", m_filetypeChoice->GetSelection());
92 hugin_utils::StoreFramePosition(this, "ToolboxFrame/Stacker/AddDirDialog");
93 // now try to find all images
94 wxString filename = m_filenameCtrl->GetValue();
95 if (filename.IsEmpty())
96 {
97 filename = "*";
98 };
99 m_filenames.Clear();
101 if (m_recursiveCheck->GetValue())
102 {
104 };
106 for (auto& currExt : ext)
107 {
109 currFilename.Replace("*", filename, true);
110 wxDir::GetAllFiles(m_dirPicker->GetPath(), &m_filenames, currFilename, flags);
111 };
112 hugin_utils::HuginMessageBox(wxString::Format("Found %zu images", m_filenames.size()), _("Hugin_toolbox"), wxOK | wxICON_INFORMATION, this);
113 if (!m_filenames.IsEmpty())
114 {
116 };
117 }
118private:
120 {
122 size_t i = 0;
123 while (i < fileTypes.size())
124 {
125 if (i + 1 >= fileTypes.size())
126 {
127 break;
128 };
129 m_filetypeChoice->AppendString(fileTypes[i]);
130 ++i;
132 ++i;
133 };
134 m_filetypeChoice->SetSelection(0);
135 }
138 wxTextCtrl* m_filenameCtrl;
142};
143
145class StackerDropTarget : public wxFileDropTarget
146{
147public:
148 StackerDropTarget(StackerPanel* parent) : wxFileDropTarget()
149 {
151 }
152
154 {
155 // try to add as images
156 wxArrayString files;
157 for (unsigned int i = 0; i < filenames.GetCount(); i++)
158 {
159 wxFileName file(filenames[i]);
160 if (file.GetExt().CmpNoCase("jpg") == 0 ||
161 file.GetExt().CmpNoCase("jpeg") == 0 ||
162 file.GetExt().CmpNoCase("tif") == 0 ||
163 file.GetExt().CmpNoCase("tiff") == 0 ||
164 file.GetExt().CmpNoCase("png") == 0 ||
165 file.GetExt().CmpNoCase("bmp") == 0 ||
166 file.GetExt().CmpNoCase("gif") == 0 ||
167 file.GetExt().CmpNoCase("pnm") == 0 ||
168 file.GetExt().CmpNoCase("sun") == 0 ||
169 file.GetExt().CmpNoCase("hdr") == 0 ||
170 file.GetExt().CmpNoCase("viff") == 0)
171 {
172 files.push_back(file.GetFullPath());
173 };
174 };
175 // we got some images to add.
176 if (!files.empty())
177 {
178 for (auto& f : files)
179 {
181 };
182 };
183 return true;
184 }
185private:
187};
188
189// destructor, save settings
191{
192 wxConfigBase* config = wxConfigBase::Get();
193 config->Write("/ToolboxFrame/Stacker/Splitter", XRCCTRL(*this, "stacker_splitter", wxSplitterWindow)->GetSashPosition());
194
195 config->Write("/ToolboxFrame/Stacker/Mode", m_modeChoice->GetSelection());
196 config->Write("/ToolboxFrame/Stacker/WinsorTrim", m_winsorTrim->GetValue());
197 config->Write("/ToolboxFrame/Stacker/Sigma", m_sigma->GetValue());
198 config->Write("/ToolboxFrame/Stacker/SigmaIter", m_sigmaMaxIter->GetValue());
199 for (int j = 0; j < m_fileListCtrl->GetColumnCount(); j++)
200 {
201 config->Write(wxString::Format("/ToolboxFrame/Stacker/FileListColumnWidth%d", j), m_fileListCtrl->GetColumnWidth(j));
202 };
203 config->Write("/ToolboxFrame/Stacker/FileListSortColumn", m_sortCol);
204 config->Write("/ToolboxFrame/Stacker/FileListSortAscending", m_sortAscending);
205
206 config->Flush();
208}
209
211{
212 if (!wxPanel::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, "panel"))
213 {
214 return false;
215 }
216 // create preview window
217 m_preview = new PreviewWindow();
218 m_preview->Create(this);
219
221 // load from xrc file and attach unknown controls
222 wxXmlResource::Get()->LoadPanel(this, "stacker_panel");
223 wxXmlResource::Get()->AttachUnknownControl("stacker_preview_window", m_preview, this);
224 // add to sizer
225 wxPanel* mainPanel = XRCCTRL(*this, "stacker_panel", wxPanel);
227 topsizer->Add(mainPanel, wxSizerFlags(1).Expand());
228 // create columns in wxListCtrl
229 m_fileListCtrl = XRCCTRL(*this, "stacker_files", wxListCtrl);
230 m_fileListCtrl->InsertColumn(0, _("Filename"), wxLIST_FORMAT_LEFT, 200);
231 m_fileListCtrl->InsertColumn(1, _("Width"), wxLIST_FORMAT_LEFT, 50);
232 m_fileListCtrl->InsertColumn(2, _("Height"), wxLIST_FORMAT_LEFT, 50);
233 m_fileListCtrl->InsertColumn(3, _("Path"), wxLIST_FORMAT_LEFT, 200);
234 m_fileListCtrl->EnableCheckBoxes(true);
236 // store some controls for easier access
237 m_modeChoice = XRCCTRL(*this, "stacker_mode_choice", wxChoice);
238 m_winsorTrim = XRCCTRL(*this, "stacker_winsor_trim_spinctrl", wxSpinCtrlDouble);
239 m_sigma = XRCCTRL(*this, "stacker_sigma_spinctrl", wxSpinCtrlDouble);
240 m_sigmaMaxIter = XRCCTRL(*this, "stacker_sigma_iterations_spinctrl", wxSpinCtrl);
241
243
244 wxConfigBase* config = wxConfigBase::Get();
245 // restore splitter position
246 if (config->HasEntry("/ToolboxFrame/Stacker/Splitter"))
247 {
248 XRCCTRL(*this, "stacker_splitter", wxSplitterWindow)->SetSashPosition(config->ReadLong("/ToolboxFrame/Stacker/Splitter", 300));
249 }
250 m_modeChoice->SetSelection(config->ReadLong("/ToolboxFrame/Stacker/Mode", 0));
251 m_winsorTrim->SetValue(config->ReadDouble("/ToolboxFrame/Stacker/WinsorTrim", 0.2));
252 m_sigma->SetValue(config->ReadDouble("/ToolboxFrame/Stacker/Sigma", 2));
253 m_sigmaMaxIter->SetValue(config->ReadLong("/ToolboxFrame/Stacker/SigmaIter", 5));
254 //get saved width of list ctrl column width
255 for (int j = 0; j < m_fileListCtrl->GetColumnCount(); j++)
256 {
257 // -1 is auto
258 int width = config->Read(wxString::Format("/ToolboxFrame/Stacker/FileListColumnWidth%d", j), -1);
259 if (width != -1)
260 {
261 m_fileListCtrl->SetColumnWidth(j, width);
262 };
263 };
264 m_sortCol = config->Read("/ToolboxFrame/Stacker/FileListSortColumn", -1);
265 m_sortAscending = config->Read("/ToolboxFrame/Stacker/FileListSortAscending", 1) == 1 ? true : false;
266 if (m_sortCol != -1)
267 {
268 m_fileListCtrl->ShowSortIndicator(m_sortCol, m_sortAscending);
269 };
270
271 // bind event handler
272 Bind(wxEVT_BUTTON, &StackerPanel::OnAddFiles, this, XRCID("stacker_add_file"));
273 Bind(wxEVT_BUTTON, &StackerPanel::OnAddDirectory, this, XRCID("stacker_add_files_dir"));
274 Bind(wxEVT_BUTTON, &StackerPanel::OnRemoveFile, this, XRCID("stacker_remove_file"));
281 Bind(wxEVT_CHOICE, &StackerPanel::OnModeChanged, this, XRCID("stacker_mode_choice"));
282 Bind(wxEVT_BUTTON, &StackerPanel::OnGeneratePreview, this, XRCID("stacker_preview"));
283 Bind(wxEVT_BUTTON, &StackerPanel::OnGenerateOutput, this, XRCID("stacker_output"));
284 Bind(wxEVT_CHOICE, &StackerPanel::OnZoom, this, XRCID("stacker_choice_zoom"));
285
287 EnableOutputButtons(false);
288 wxCommandEvent e;
289 OnModeChanged(e);
290 return true;
291}
292
293void StackerPanel::AddFile(const wxString& filename)
294{
295 wxFileName fullFilename(filename);
296 // add image dimensions
297 vigra::ImageImportInfo info(fullFilename.GetFullPath().c_str());
298 vigra::Size2D imageSize = info.getCanvasSize();
299 if (imageSize.area() == 0)
300 {
301 imageSize = info.size();
302 };
303 // add to array
304 m_files.push_back(FileInfo(fullFilename.GetFullPath(), fullFilename.GetFullName(), fullFilename.GetPath(), imageSize.width(), imageSize.height()));
305 AddFileInfo(m_files.back());
307}
308
309void StackerPanel::OnAddFiles(wxCommandEvent& e)
310{
311 wxConfigBase* config = wxConfigBase::Get();
312 wxString path = config->Read("/actualPath", "");
313 wxFileDialog dlg(this, _("Add images"), path, wxEmptyString,
315 dlg.SetDirectory(path);
316
317 // remember the image extension
319 if (config->HasEntry("lastImageType"))
320 {
321 img_ext = config->Read("lastImageType").c_str();
322 }
323 if (img_ext == "all images")
324 dlg.SetFilterIndex(0);
325 else if (img_ext == "jpg")
326 dlg.SetFilterIndex(1);
327 else if (img_ext == "tiff")
328 dlg.SetFilterIndex(2);
329 else if (img_ext == "png")
330 dlg.SetFilterIndex(3);
331 else if (img_ext == "hdr")
332 dlg.SetFilterIndex(4);
333 else if (img_ext == "exr")
334 dlg.SetFilterIndex(5);
335 else if (img_ext == "all files")
336 dlg.SetFilterIndex(6);
337
338 // call the file dialog
339 if (dlg.ShowModal() == wxID_OK)
340 {
341 // get the selections
343 dlg.GetPaths(Pathnames);
344 // save the current path to config
345 config->Write("/actualPath", dlg.GetDirectory());
346 // save the image extension
347 switch (dlg.GetFilterIndex())
348 {
349 case 0: config->Write("lastImageType", "all images"); break;
350 case 1: config->Write("lastImageType", "jpg"); break;
351 case 2: config->Write("lastImageType", "tiff"); break;
352 case 3: config->Write("lastImageType", "png"); break;
353 case 4: config->Write("lastImageType", "hdr"); break;
354 case 5: config->Write("lastImageType", "exr"); break;
355 case 6: config->Write("lastImageType", "all files"); break;
356 };
357 m_fileListCtrl->Freeze();
358 for (auto& f : Pathnames)
359 {
360 AddFile(f);
361 };
362 SortList();
363 m_fileListCtrl->Thaw();
364 }
365}
366
367void StackerPanel::OnAddDirectory(wxCommandEvent& e)
368{
370 if (dlg.ShowModal() == wxID_OK)
371 {
372 const wxArrayString filenames = dlg.GetFilenames();
374 m_fileListCtrl->Freeze();
375 for (auto& f : filenames)
376 {
377 AddFile(f);
378 };
379 SortList();
380 m_fileListCtrl->Thaw();
381 };
382}
383
384void StackerPanel::OnRemoveFile(wxCommandEvent& e)
385{
387 if (m_fileListCtrl->GetSelectedItemCount() >= 1)
388 {
389 for (int i = 0; i < m_fileListCtrl->GetItemCount(); ++i)
390 {
392 {
393 selected.insert(m_fileListCtrl->GetItemData(i));
394 };
395 };
396 };
397 if (!selected.empty())
398 {
399 // remove selected file from internal file list
400 for (auto it = selected.rbegin(); it != selected.rend(); ++it)
401 {
402 m_files.erase(m_files.begin() + (*it));
403 };
404 // now refill list again
405 m_fileListCtrl->DeleteAllItems();
406 FillFileList();
409 }
410 else
411 {
412 wxBell();
413 };
414}
415
417{
418 // ctrl + a, select all files
419 if (e.GetKeyCode() == 1 && e.CmdDown())
420 {
421 // select all
422 for (int i = 0; i < m_fileListCtrl->GetItemCount(); i++)
423 {
425 };
426 };
427 // insert key, add file
428 if ((e.GetKeyCode() == WXK_INSERT || e.GetKeyCode() == WXK_NUMPAD_INSERT) && !e.HasAnyModifiers())
429 {
430 wxCommandEvent e(wxEVT_BUTTON, XRCID("stacker_add_file"));
431 this->GetEventHandler()->AddPendingEvent(e);
432 };
433 // delete key, delete selected file
434 if ((e.GetKeyCode() == WXK_DELETE || e.GetKeyCode() == WXK_NUMPAD_DELETE) && !e.HasAnyModifiers())
435 {
436 if (m_fileListCtrl->GetSelectedItemCount() > 0)
437 {
438 wxCommandEvent e(wxEVT_BUTTON, XRCID("stacker_remove_file"));
439 this->GetEventHandler()->AddPendingEvent(e);
440 }
441 else
442 {
443 wxBell();
444 };
445 };
446 e.Skip();
447}
448
450{
451 // enable/disable button according to selected files
453}
454
456{
457 const long index = m_fileListCtrl->GetItemData(e.GetItem());
458 m_files[index].isChecked = m_fileListCtrl->IsItemChecked(e.GetItem());
460}
461
463{
464 const int newCol = e.GetColumn();
465 if (m_sortCol == newCol)
466 {
468 }
469 else
470 {
472 m_sortAscending = true;
473 };
474 m_fileListCtrl->ShowSortIndicator(m_sortCol, m_sortAscending);
475 SortList();
476 Refresh();
477}
478
479void StackerPanel::OnModeChanged(wxCommandEvent& e)
480{
481 const int mode = m_modeChoice->GetSelection();
482 // hide controls which are not necessary for current mode
483 XRCCTRL(*this, "stacker_winsor_trim_label", wxStaticText)->Show(mode == 2);
484 m_winsorTrim->Show(mode == 2);
485 XRCCTRL(*this, "stacker_sigma_label", wxStaticText)->Show(mode == 3);
486 m_sigma->Show(mode == 3);
487 XRCCTRL(*this, "stacker_sigma_iterations_label", wxStaticText)->Show(mode == 3);
488 m_sigmaMaxIter->Show(mode == 3);
489 m_modeChoice->GetParent()->Layout();
490}
491
492void StackerPanel::OnGeneratePreview(wxCommandEvent& e)
493{
494 // create temp file name, set extension to tif
495 m_outputFilenames.resize(2);
496 wxFileName tempfile(wxFileName::CreateTempFileName(HuginQueue::GetConfigTempDir(wxConfig::Get()) + "he"));
497 m_outputFilenames[1] = tempfile.GetFullPath();
498 tempfile.SetExt("tif");
499 m_outputFilenames[0] = tempfile.GetFullPath();
500 m_cleanupOutput = true;
501 // get command line and execute
503}
504
517
519{
521 if (!cmd.IsEmpty())
522 {
523 EnableOutputButtons(false);
527 queue->push_back(new HuginQueue::NormalCommand(HuginQueue::GetInternalProgram(exePath, "hugin_stacker"), cmd, _("Stacking images") + " (" + cmd + ")"));
528 // get first image
529 long index = -1;
530 for (long i = 0; i < m_fileListCtrl->GetItemCount(); ++i)
531 {
532 if (m_fileListCtrl->IsItemChecked(i))
533 {
534 index = m_fileListCtrl->GetItemData(i);
535 break;
536 };
537 };
538 wxString exiftoolArgs(" -overwrite_original -tagsfromfile " + HuginQueue::wxEscapeFilename(m_files[index].fullFilename));
539 exiftoolArgs.Append(" -all:all --thumbnail --thumbnailimage --xposition --yposition --imagefullwidth --imagefullheight ");
541 queue->push_back(new HuginQueue::OptionalCommand(HuginQueue::GetExternalProgram(wxConfig::Get(), exePath, "exiftool"), exiftoolArgs, _("Updating EXIF")));
542 m_logWindow->ExecQueue(queue);
543 };
544}
545
546void StackerPanel::OnGenerateOutput(wxCommandEvent& e)
547{
548 if (m_files.empty())
549 {
550 wxBell();
551 return;
552 };
553 wxConfigBase* config = wxConfigBase::Get();
554 wxString path = config->Read("/actualPath", "");
556 dlg.SetDirectory(path);
557
558 // remember the image extension
560 if (config->HasEntry("lastImageType"))
561 {
562 img_ext = config->Read("lastImageType").c_str();
563 }
564 if (img_ext == "jpg")
565 {
566 dlg.SetFilterIndex(0);
567 }
568 else
569 {
570 if (img_ext == "tiff")
571 {
572 dlg.SetFilterIndex(1);
573 }
574 else
575 {
576 if (img_ext == "png")
577 {
578 dlg.SetFilterIndex(2);
579 };
580 };
581 };
582 wxFileName outputfilename(m_files[0].fullFilename);
583 outputfilename.SetName(outputfilename.GetName() + "_stacked");
584 dlg.SetFilename(outputfilename.GetFullPath());
585 // call the file dialog
586 if (dlg.ShowModal() == wxID_OK)
587 {
588 m_outputFilenames.resize(1);
589 m_outputFilenames[0] = dlg.GetPath();
590 // save the current path to config
591 config->Write("/actualPath", dlg.GetDirectory());
592 // save the image extension
593 switch (dlg.GetFilterIndex())
594 {
595 case 0:
596 config->Write("lastImageType", "jpg");
597 break;
598 case 1:
599 config->Write("lastImageType", "tiff");
600 break;
601 case 2:
602 config->Write("lastImageType", "png");
603 break;
604 };
605 m_cleanupOutput = false;
607 };
608}
609
610void StackerPanel::OnZoom(wxCommandEvent& e)
611{
612 double factor;
613 switch (e.GetSelection())
614 {
615 case 0:
616 factor = 1;
617 break;
618 case 1:
619 // fit to window
620 factor = 0;
621 break;
622 case 2:
623 factor = 2;
624 break;
625 case 3:
626 factor = 1.5;
627 break;
628 case 4:
629 factor = 0.75;
630 break;
631 case 5:
632 factor = 0.5;
633 break;
634 case 6:
635 factor = 0.25;
636 break;
637 default:
638 DEBUG_ERROR("unknown scale factor");
639 factor = 1;
640 }
641 m_preview->setScale(factor);
642}
643
644void StackerPanel::OnProcessFinished(wxCommandEvent& e)
645{
647 if (output.FileExists() && output.GetSize()>0)
648 {
649 m_preview->setImage(output.GetFullPath());
650 };
652 if (m_cleanupOutput && output.FileExists())
653 {
654 // cleanup up preview files
655 for (const auto& f : m_outputFilenames)
656 {
657 wxRemoveFile(f);
658 };
659 };
661}
662
664{
666 switch (XRCCTRL(*this, "stacker_mode_choice", wxChoice)->GetSelection())
667 {
668 case 0:
669 // mean or average
670 commandline.Append(" --mode=mean ");
671 break;
672 case 1:
673 // Median
674 commandline.Append(" --mode=median ");
675 break;
676 case 2:
677 // Winsor trimmed mean
678 commandline.Append(" --mode=winsor ");
679 commandline.Append("--winsor-trim=" + wxString::FromCDouble(m_winsorTrim->GetValue()) + " ");
680 break;
681 case 3:
682 // Sigma clipped mean
683 commandline.Append(" --mode=sigma ");
684 commandline.Append("--max-sigma=" + wxString::FromCDouble(m_sigma->GetValue()) + wxString::Format(" --max-iterations=%d ", m_sigmaMaxIter->GetValue()));
685 break;
686 case 4:
687 //Minimum
688 commandline.Append(" --mode=minimum ");
689 break;
690 case 5:
691 //Maximum
692 commandline.Append(" --mode=maximum ");
693 break;
694 }
695 return commandline;
696}
697
699{
701 // add options from control
702 commandline.Append(" ");
704 // now build image list
706 for (int i = 0; i < m_fileListCtrl->GetItemCount(); ++i)
707 {
708 if (m_fileListCtrl->IsItemChecked(i))
709 {
710 selectedFiles.push_back(m_fileListCtrl->GetItemData(i));
711 };
712 };
713 if (selectedFiles.IsEmpty())
714 {
715 hugin_utils::HuginMessageBox(_("Please activate at least one file."), _("Hugin_toolbox"), wxOK | wxOK_DEFAULT | wxICON_WARNING, this);
716 return wxEmptyString;
717 }
718 if (selectedFiles.size() > 5)
719 {
720 // for more than 5 files use response file
721 // first create a temp file
722 wxString tempFilename = wxFileName::CreateTempFileName(HuginQueue::GetConfigTempDir(wxConfig::Get()) + "hsfl");
724 textfile.Open();
725 if (textfile.IsOpened())
726 {
727 m_tempFiles.push_back(tempFilename);
728 // write filenames to response file
729 for (int i = 0; i < selectedFiles.size(); ++i)
730 {
731 textfile.AddLine(m_files[selectedFiles[i]].fullFilename);
732 };
733 // write file and do some checking for erros
735 {
736 textfile.Close();
737 // add response file to command line
738 commandline.Append(" @ ");
740 return commandline;
741 }
742 else
743 {
744 textfile.Close();
745 hugin_utils::HuginMessageBox(wxString::Format(_("Could not write to temporary file (%s)."), tempFilename), _("Hugin_toolbox"), wxOK | wxOK_DEFAULT | wxICON_WARNING, this);
746 return wxEmptyString;
747
748 };
749 }
750 else
751 {
752 hugin_utils::HuginMessageBox(wxString::Format(_("Could not write to temporary file (%s)."), tempFilename), _("Hugin_toolbox"), wxOK | wxOK_DEFAULT | wxICON_WARNING, this);
753 return wxEmptyString;
754 };
755 }
756 else
757 {
758 // use filename direct on command line, if there are only up to 5 files
759 for (int i = 0; i < selectedFiles.size(); ++i)
760 {
761 commandline.Append(" ");
763 }
764 return commandline;
765 };
766}
767
769{
770 // enable/disable button according to selected files
771 XRCCTRL(*this, "stacker_remove_file", wxButton)->Enable(m_fileListCtrl->GetSelectedItemCount() >= 1);
772}
773
775{
776 // count checked items
777 long count = 0;
778 for (int i = 0; i < m_fileListCtrl->GetItemCount(); ++i)
779 {
780 if (m_fileListCtrl->IsItemChecked(i))
781 {
782 ++count;
783 };
784 };
785 return count;
786}
787
789{
790 XRCCTRL(*this, "stacker_preview", wxButton)->Enable(enable);
791 XRCCTRL(*this, "stacker_output", wxButton)->Enable(enable);
792}
793
795{
796 for (const auto& f : m_tempFiles)
797 {
798 wxRemoveFile(f);
799 };
800 m_tempFiles.clear();
801}
802
804{
805 m_fileListCtrl->Freeze();
806 for (auto& info : m_files)
807 {
808 AddFileInfo(info);
809 };
810 SortList();
811 m_fileListCtrl->Thaw();
812}
813
815{
816 const long index = m_fileListCtrl->InsertItem(m_fileListCtrl->GetItemCount(), info.name);
817 // store index as client data for sorting
818 m_fileListCtrl->SetItemData(index, index);
819 // add image dimensions
820 m_fileListCtrl->SetItem(index, 1, wxString::Format("%zu", info.width));
821 m_fileListCtrl->SetItem(index, 2, wxString::Format("%zu", info.height));
822 m_fileListCtrl->SetItem(index, 3, info.path);
823 // set checkbox
824 m_fileListCtrl->CheckItem(index, info.isChecked);
825}
826
827#define SORTASCENDING(functionName, var) \
828int wxCALLBACK functionName(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)\
829{\
830 StackerPanel::FileInfoVector* data = (StackerPanel::FileInfoVector*)(sortData);\
831 if (data->at(item1).var > data->at(item2).var)\
832 return 1;\
833 if (data->at(item1).var < data->at(item2).var)\
834 return -1;\
835 return 0;\
836}
837
838#define SORTDESCENDING(functionName, var) \
839int wxCALLBACK functionName(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)\
840{\
841 StackerPanel::FileInfoVector* data = (StackerPanel::FileInfoVector*)(sortData); \
842 if (data->at(item1).var < data->at(item2).var)\
843 return 1; \
844 if (data->at(item1).var > data->at(item2).var)\
845 return -1; \
846 return 0; \
847}
848
857
858#undef SORTASCENDING
859#undef SORTDESCENDING
860
862{
863 if (m_sortCol > -1)
864 {
865 switch (m_sortCol)
866 {
867 case 0: // filename
868 if (m_sortAscending)
869 {
871 }
872 else
873 {
875 };
876 break;
877 case 1: // image width
878 if (m_sortAscending)
879 {
881 }
882 else
883 {
885 };
886 break;
887 case 2: // image height
888 if (m_sortAscending)
889 {
891 }
892 else
893 {
895 };
896 break;
897 case 3: // path
898 if (m_sortAscending)
899 {
901 }
902 else
903 {
905 };
906 break;
907 };
908 };
909}
910
911IMPLEMENT_DYNAMIC_CLASS(StackerPanel, wxPanel)
Definition of dialog class to create brighter/darker versions of the image.
basic classes and function for queuing commands in wxWidgets
some helper classes for graphes
#define SORTDESCENDING(functionName, var)
#define SORTASCENDING(functionName, var)
declaration of panel for stacker GUI
normal command for queue, processing is stopped if an error occurred in program
Definition Executor.h:38
optional command for queue, processing of queue is always continued, also if an error occurred
Definition Executor.h:54
int ExecQueue(HuginQueue::CommandQueue *queue)
void AddString(const wxString &s)
display the string in the panel
int ExecWithRedirect(wxString command)
void ClearOutput()
clear the output
preview window
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name="panel")
create the control
void setImage(const wxString &filename)
set the current image and mask list, this loads also the image from cache
void setScale(double factor)
set the scaling factor f.
dialog for selection of directory and file name/type
wxArrayString GetFilenames()
wxDirPickerCtrl * m_dirPicker
SelectDirectoryFileDialog(wxWindow *parent)
Constructor, read from xrc ressource; restore last uses settings, size and position.
void OnOk(wxCommandEvent &e)
wxArrayString m_filetypeExtensions
file drag and drop handler method
bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
StackerPanel * m_stackerPanel
StackerDropTarget(StackerPanel *parent)
panel for stacker GUI
void OnRemoveFile(wxCommandEvent &e)
void SortList()
sort filename list
PreviewWindow * m_preview
long GetCheckedItemCount() const
return the number of check images
void OnZoom(wxCommandEvent &e)
void AddFileInfo(const FileInfo &info)
void CleanUpTempFiles()
delete all temporary files, to be called mainly at end
void OnAddDirectory(wxCommandEvent &e)
wxSpinCtrlDouble * m_winsorTrim
void OnFileColumnHeaderClick(wxListEvent &e)
void OnProcessFinished(wxCommandEvent &e)
call at the end of the enfuse command, to load result back and enable buttons again
void OnFileCheckStateChanged(wxListEvent &e)
void ExecuteStackerExiftool()
build the command line and execute enfuse and exiftool afterwards
wxListCtrl * m_fileListCtrl
wxSpinCtrl * m_sigmaMaxIter
void EnableOutputButtons(bool enable)
enable/disable output buttons
void OnFileListChar(wxKeyEvent &e)
bool Create(wxWindow *parent, MyExecPanel *logPanel)
creates the control and populates all controls with their settings
wxChoice * m_modeChoice
FileInfoVector m_files
void OnModeChanged(wxCommandEvent &e)
void FillFileList()
fill the list from internal file list
void AddFile(const wxString &filename)
adds the given file to the list
wxArrayString m_outputFilenames
void EnableFileButtons()
enable/disable the file(s) remove and create buttons depending on selection of wxListCtrl
MyExecPanel * m_logWindow
void ExecuteStacker()
build the command line and execute enfuse command
void OnGenerateOutput(wxCommandEvent &e)
wxString GetStackerOptions()
build string with all stacker options from values in wxPropertyGrid this are the mainly the fusion op...
void OnGeneratePreview(wxCommandEvent &e)
~StackerPanel()
destructor, save state and settings
wxArrayString m_tempFiles
void OnAddFiles(wxCommandEvent &e)
event handler
wxString GetStackerCommandLine()
get the full commandline for enfuse without program, but with files and output options,...
void OnFileSelectionChanged(wxCommandEvent &e)
wxSpinCtrlDouble * m_sigma
static uint16_t flags
implementation of huginApp Class
#define DEBUG_ERROR(msg)
Definition utils.h:76
std::set< unsigned int > UIntSet
str wxEscapeFilename(const str &arg)
special escaping routine for CommandQueues
Definition Executor.h:79
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
wxString GetInternalProgram(const wxString &bindir, const wxString &name)
return path and name of external program, which comes bundled with Hugin
Definition Executor.cpp:129
const wxString GetConfigTempDir(const wxConfigBase *config)
return the temp dir from the preferences, ensure that it ends with path separator
Definition Executor.cpp:302
str wxQuoteFilename(const str &arg)
Quote a filename, so that it is surrounded by "".
Definition wxPlatform.h:82
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition wxutils.cpp:176
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename, const bool ignoreMaximize)
Definition wxutils.cpp:106
void RestoreFramePosition(wxTopLevelWindow *frame, const wxString &basename, const bool ignoreMaximize)
Definition wxutils.cpp:67
wxString GetFileDialogImageFilters()
return filter for image files, needed by file open dialog it contains all image format vigra can read...
Definition platform.cpp:70
wxString GetMainImageFilters()
return a filter for the main image files (JPG/TIFF/PNG) only
Definition platform.cpp:81
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41
platform/compiler specific stuff.