27 #include <wx/stdpaths.h>
28 #include <wx/propgrid/advprops.h>
33 #include <wx/fileconf.h>
34 #include <wx/wfstream.h>
35 #include <wx/sstream.h>
36 #include <wx/filepicker.h>
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",
"");
60 if (config->HasEntry(
"/ToolboxFrame/Stacker/AddDirRecursive"))
62 m_recursiveCheck->SetValue(config->ReadBool(
"/ToolboxFrame/Stacker/AddDirRecursive",
false));
64 m_filenameCtrl = XRCCTRL(*
this,
"select_dir_filename", wxTextCtrl);
65 if (config->HasEntry(
"/ToolboxFrame/Stacker/AddDirFilenames"))
67 m_filenameCtrl->SetValue(config->Read(
"/ToolboxFrame/Stacker/AddDirFilenames",
"*"));
71 if (config->HasEntry(
"/ToolboxFrame/Stacker/AddDirFileType"))
73 m_filetypeChoice->SetSelection(config->ReadLong(
"/ToolboxFrame/Stacker/AddDirFileType", 0l));
84 void OnOk(wxCommandEvent& e)
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());
95 if (filename.IsEmpty())
100 int flags = wxDIR_FILES | wxDIR_HIDDEN | wxDIR_NO_FOLLOW;
103 flags = flags | wxDIR_DIRS;
106 for (
auto& currExt : ext)
108 wxString currFilename(currExt);
109 currFilename.Replace(
"*", filename,
true);
123 while (i < fileTypes.size())
125 if (i + 1 >= fileTypes.size())
153 bool OnDropFiles(wxCoord x, wxCoord y,
const wxArrayString& filenames)
157 for (
unsigned int i = 0; i < filenames.GetCount(); i++)
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)
172 files.push_back(file.GetFullPath());
178 for (
auto& f : files)
192 wxConfigBase* config = wxConfigBase::Get();
193 config->Write(
"/ToolboxFrame/Stacker/Splitter", XRCCTRL(*
this,
"stacker_splitter", wxSplitterWindow)->GetSashPosition());
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());
201 config->Write(wxString::Format(
"/ToolboxFrame/Stacker/FileListColumnWidth%d", j),
m_fileListCtrl->GetColumnWidth(j));
203 config->Write(
"/ToolboxFrame/Stacker/FileListSortColumn",
m_sortCol);
204 config->Write(
"/ToolboxFrame/Stacker/FileListSortAscending",
m_sortAscending);
212 if (!wxPanel::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL,
"panel"))
222 wxXmlResource::Get()->LoadPanel(
this,
"stacker_panel");
223 wxXmlResource::Get()->AttachUnknownControl(
"stacker_preview_window",
m_preview,
this);
225 wxPanel* mainPanel = XRCCTRL(*
this,
"stacker_panel", wxPanel);
226 wxBoxSizer* topsizer =
new wxBoxSizer(wxVERTICAL);
227 topsizer->Add(mainPanel, wxSizerFlags(1).Expand());
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);
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);
244 wxConfigBase* config = wxConfigBase::Get();
246 if (config->HasEntry(
"/ToolboxFrame/Stacker/Splitter"))
248 XRCCTRL(*
this,
"stacker_splitter", wxSplitterWindow)->SetSashPosition(config->ReadLong(
"/ToolboxFrame/Stacker/Splitter", 300));
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));
258 int width = config->Read(wxString::Format(
"/ToolboxFrame/Stacker/FileListColumnWidth%d", j), -1);
264 m_sortCol = config->Read(
"/ToolboxFrame/Stacker/FileListSortColumn", -1);
265 m_sortAscending = config->Read(
"/ToolboxFrame/Stacker/FileListSortAscending", 1) == 1 ?
true :
false;
295 wxFileName fullFilename(filename);
297 vigra::ImageImportInfo
info(fullFilename.GetFullPath().c_str());
298 vigra::Size2D imageSize =
info.getCanvasSize();
299 if (imageSize.area() == 0)
301 imageSize =
info.size();
304 m_files.push_back(
FileInfo(fullFilename.GetFullPath(), fullFilename.GetFullName(), fullFilename.GetPath(), imageSize.width(), imageSize.height()));
311 wxConfigBase* config = wxConfigBase::Get();
312 wxString path = config->Read(
"/actualPath",
"");
313 wxFileDialog dlg(
this, _(
"Add images"), path, wxEmptyString,
315 dlg.SetDirectory(path);
319 if (config->HasEntry(
"lastImageType"))
321 img_ext = config->Read(
"lastImageType").c_str();
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);
339 if (dlg.ShowModal() == wxID_OK)
342 wxArrayString Pathnames;
343 dlg.GetPaths(Pathnames);
345 config->Write(
"/actualPath", dlg.GetDirectory());
347 switch (dlg.GetFilterIndex())
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;
358 for (
auto& f : Pathnames)
370 if (dlg.ShowModal() == wxID_OK)
375 for (
auto& f : filenames)
391 if (
m_fileListCtrl->GetItemState(i, wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
397 if (!selected.empty())
400 for (
auto it = selected.rbegin(); it != selected.rend(); ++it)
419 if (e.GetKeyCode() == 1 && e.CmdDown())
424 m_fileListCtrl->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
428 if ((e.GetKeyCode() == WXK_INSERT || e.GetKeyCode() == WXK_NUMPAD_INSERT) && !e.HasAnyModifiers())
430 wxCommandEvent e(wxEVT_BUTTON, XRCID(
"stacker_add_file"));
431 this->GetEventHandler()->AddPendingEvent(e);
434 if ((e.GetKeyCode() == WXK_DELETE || e.GetKeyCode() == WXK_NUMPAD_DELETE) && !e.HasAnyModifiers())
438 wxCommandEvent e(wxEVT_BUTTON, XRCID(
"stacker_remove_file"));
439 this->GetEventHandler()->AddPendingEvent(e);
464 const int newCol = e.GetColumn();
483 XRCCTRL(*
this,
"stacker_winsor_trim_label", wxStaticText)->Show(mode == 2);
485 XRCCTRL(*
this,
"stacker_sigma_label", wxStaticText)->Show(mode == 3);
487 XRCCTRL(*
this,
"stacker_sigma_iterations_label", wxStaticText)->Show(mode == 3);
498 tempfile.SetExt(
"tif");
526 wxString exePath = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
539 exiftoolArgs.Append(
" -all:all --thumbnail --thumbnailimage --xposition --yposition --imagefullwidth --imagefullheight ");
553 wxConfigBase* config = wxConfigBase::Get();
554 wxString path = config->Read(
"/actualPath",
"");
555 wxFileDialog dlg(
this, _(
"Save output"), path, wxEmptyString,
GetMainImageFilters(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
556 dlg.SetDirectory(path);
560 if (config->HasEntry(
"lastImageType"))
562 img_ext = config->Read(
"lastImageType").c_str();
564 if (img_ext ==
"jpg")
566 dlg.SetFilterIndex(0);
570 if (img_ext ==
"tiff")
572 dlg.SetFilterIndex(1);
576 if (img_ext ==
"png")
578 dlg.SetFilterIndex(2);
582 wxFileName outputfilename(
m_files[0].fullFilename);
583 outputfilename.SetName(outputfilename.GetName() +
"_stacked");
584 dlg.SetFilename(outputfilename.GetFullPath());
586 if (dlg.ShowModal() == wxID_OK)
591 config->Write(
"/actualPath", dlg.GetDirectory());
593 switch (dlg.GetFilterIndex())
596 config->Write(
"lastImageType",
"jpg");
599 config->Write(
"lastImageType",
"tiff");
602 config->Write(
"lastImageType",
"png");
613 switch (e.GetSelection())
647 if (output.FileExists() && output.GetSize()>0)
665 wxString commandline;
666 switch (XRCCTRL(*
this,
"stacker_mode_choice", wxChoice)->GetSelection())
670 commandline.Append(
" --mode=mean ");
674 commandline.Append(
" --mode=median ");
678 commandline.Append(
" --mode=winsor ");
679 commandline.Append(
"--winsor-trim=" + wxString::FromCDouble(
m_winsorTrim->GetValue()) +
" ");
683 commandline.Append(
" --mode=sigma ");
684 commandline.Append(
"--max-sigma=" + wxString::FromCDouble(
m_sigma->GetValue()) + wxString::Format(
" --max-iterations=%d ",
m_sigmaMaxIter->GetValue()));
688 commandline.Append(
" --mode=minimum ");
692 commandline.Append(
" --mode=maximum ");
702 commandline.Append(
" ");
705 wxArrayInt selectedFiles;
713 if (selectedFiles.IsEmpty())
716 return wxEmptyString;
718 if (selectedFiles.size() > 5)
723 wxTextFile textfile(tempFilename);
725 if (textfile.IsOpened())
729 for (
int i = 0; i < selectedFiles.size(); ++i)
731 textfile.AddLine(
m_files[selectedFiles[i]].fullFilename);
734 if (textfile.Write(wxTextFileType_None, wxConvLocal))
738 commandline.Append(
" @ ");
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;
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;
759 for (
int i = 0; i < selectedFiles.size(); ++i)
761 commandline.Append(
" ");
771 XRCCTRL(*
this,
"stacker_remove_file", wxButton)->Enable(
m_fileListCtrl->GetSelectedItemCount() >= 1);
790 XRCCTRL(*
this,
"stacker_preview", wxButton)->Enable(enable);
791 XRCCTRL(*
this,
"stacker_output", wxButton)->Enable(enable);
827 #define SORTASCENDING(functionName, var) \
828 int wxCALLBACK functionName(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)\
830 StackerPanel::FileInfoVector* data = (StackerPanel::FileInfoVector*)(sortData);\
831 if (data->at(item1).var > data->at(item2).var)\
833 if (data->at(item1).var < data->at(item2).var)\
838 #define SORTDESCENDING(functionName, var) \
839 int wxCALLBACK functionName(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)\
841 StackerPanel::FileInfoVector* data = (StackerPanel::FileInfoVector*)(sortData); \
842 if (data->at(item1).var < data->at(item2).var)\
844 if (data->at(item1).var > data->at(item2).var)\
859 #undef SORTDESCENDING
int ExecWithRedirect(wxString command)
wxTextCtrl * m_filenameCtrl
normal command for queue, processing is stopped if an error occurred in program
wxCheckBox * m_recursiveCheck
const wxString GetConfigTempDir(const wxConfigBase *config)
return the temp dir from the preferences, ensure that it ends with path separator ...
declaration of panel for stacker GUI
void OnModeChanged(wxCommandEvent &e)
void RestoreFramePosition(wxTopLevelWindow *frame, const wxString &basename, const bool ignoreMaximize)
void OnFileSelectionChanged(wxCommandEvent &e)
StackerDropTarget(StackerPanel *parent)
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename, const bool ignoreMaximize)
void OnProcessFinished(wxCommandEvent &e)
call at the end of the enfuse command, to load result back and enable buttons again ...
void AddFile(const wxString &filename)
adds the given file to the list
void OnGeneratePreview(wxCommandEvent &e)
optional command for queue, processing of queue is always continued, also if an error occurred ...
void EnableOutputButtons(bool enable)
enable/disable output buttons
wxSpinCtrlDouble * m_sigma
void OnFileListChar(wxKeyEvent &e)
int ExecQueue(HuginQueue::CommandQueue *queue)
void ClearOutput()
clear the output
wxString GetInternalProgram(const wxString &bindir, const wxString &name)
return path and name of external program, which comes bundled with Hugin
#define SORTASCENDING(functionName, var)
file drag and drop handler method
StackerPanel * m_stackerPanel
wxArrayString m_filenames
wxArrayString m_filetypeExtensions
void OnOk(wxCommandEvent &e)
void ExecuteStacker()
build the command line and execute enfuse command
bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
basic classes and function for queuing commands in wxWidgets
void OnAddFiles(wxCommandEvent &e)
event handler
std::set< unsigned int > UIntSet
PreviewWindow * m_preview
void EnableFileButtons()
enable/disable the file(s) remove and create buttons depending on selection of wxListCtrl ...
void setImage(const wxString &filename)
set the current image and mask list, this loads also the image from cache
wxChoice * m_filetypeChoice
wxString GetStackerCommandLine()
get the full commandline for enfuse without program, but with files and output options, the output filename is read from m_outputFilename
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
wxString GetStackerOptions()
build string with all stacker options from values in wxPropertyGrid this are the mainly the fusion op...
bool Create(wxWindow *parent, MyExecPanel *logPanel)
creates the control and populates all controls with their settings
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
Definition of dialog class to create brighter/darker versions of the image.
wxListCtrl * m_fileListCtrl
void AddString(const wxString &s)
display the string in the panel
#define SORTDESCENDING(functionName, var)
~StackerPanel()
destructor, save state and settings
void OnGenerateOutput(wxCommandEvent &e)
wxSpinCtrlDouble * m_winsorTrim
long GetCheckedItemCount() const
return the number of check images
wxArrayString m_tempFiles
void OnFileCheckStateChanged(wxListEvent &e)
void setScale(double factor)
set the scaling factor f.
void FillFileList()
fill the list from internal file list
str wxEscapeFilename(const str &arg)
special escaping routine for CommandQueues
void OnRemoveFile(wxCommandEvent &e)
MyExecPanel * m_logWindow
static void info(const char *fmt,...)
void SortList()
sort filename list
wxSpinCtrl * m_sigmaMaxIter
wxArrayString GetFilenames()
void OnFileColumnHeaderClick(wxListEvent &e)
void OnAddDirectory(wxCommandEvent &e)
str wxQuoteFilename(const str &arg)
Quote a filename, so that it is surrounded by "".
void FillFileTypeChoice()
void OnZoom(wxCommandEvent &e)
dialog for selection of directory and file name/type
void AddFileInfo(const FileInfo &info)
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
wxString GetExternalProgram(wxConfigBase *config, const wxString &bindir, const wxString &name)
return path and name of external program, which can be overwritten by the user
wxDirPickerCtrl * m_dirPicker
void ExecuteStackerExiftool()
build the command line and execute enfuse and exiftool afterwards
std::vector< NormalCommand * > CommandQueue
SelectDirectoryFileDialog(wxWindow *parent)
Constructor, read from xrc ressource; restore last uses settings, size and position.
wxArrayString m_outputFilenames
void CleanUpTempFiles()
delete all temporary files, to be called mainly at end