Hugin trunk 0.1
Loading...
Searching...
No Matches
EnfusePanel.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 "EnfusePanel.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 "hugin_utils/utils.h"
38#include "base_wx/LensTools.h"
39#include "base_wx/wxutils.h"
41#include "CreateBrightImgDlg.h"
42#include "ToolboxApp.h"
43
45class EnfuseDropTarget : public wxFileDropTarget
46{
47public:
48 EnfuseDropTarget(EnfusePanel* parent) : wxFileDropTarget()
49 {
51 }
52
54 {
55 // try to add as images
56 wxArrayString files;
57 for (unsigned int i = 0; i < filenames.GetCount(); i++)
58 {
59 wxFileName file(filenames[i]);
60 if (file.GetExt().CmpNoCase("jpg") == 0 ||
61 file.GetExt().CmpNoCase("jpeg") == 0 ||
62 file.GetExt().CmpNoCase("tif") == 0 ||
63 file.GetExt().CmpNoCase("tiff") == 0 ||
64 file.GetExt().CmpNoCase("png") == 0 ||
65 file.GetExt().CmpNoCase("bmp") == 0 ||
66 file.GetExt().CmpNoCase("gif") == 0 ||
67 file.GetExt().CmpNoCase("pnm") == 0 ||
68 file.GetExt().CmpNoCase("sun") == 0 ||
69 file.GetExt().CmpNoCase("hdr") == 0 ||
70 file.GetExt().CmpNoCase("viff") == 0)
71 {
72 files.push_back(file.GetFullPath());
73 };
74 };
75 // we got some images to add.
76 if (!files.empty())
77 {
78 for (auto& f : files)
79 {
81 };
82 };
83 return true;
84 }
85private:
87};
88
89// load wxPropertyGrid settings from string
91{
93 for (size_t i = 0; i < properties.size(); ++i)
94 {
96 if (prop.size() == 3)
97 {
98 if (prop[1] == "double")
99 {
100 double doubleVal;
101 if (prop[2].ToCDouble(&doubleVal))
102 {
103 grid->SetPropertyValue(prop[0], doubleVal);
104 };
105 }
106 else
107 {
108 if (prop[1] == "long")
109 {
110 long longVal;
111 if (prop[2].ToLong(&longVal))
112 {
113 grid->SetPropertyValue(prop[0], longVal);
114 }
115 }
116 else
117 {
118 if (prop[1] == "bool")
119 {
120 if (prop[2] == "true")
121 {
122 grid->SetPropertyValue(prop[0], true);
123 }
124 else
125 {
126 grid->SetPropertyValue(prop[0], false);
127 };
128 }
129 else
130 {
131 // unknown type, currently not implemented
132 };
133 };
134 };
135 };
136 };
137}
138
139// save wxPropertyGrid settings into a string
141{
144 for (it = grid->GetIterator(); !it.AtEnd(); it++)
145 {
146 const wxPGProperty* p = *it;
147 if (p->IsCategory())
148 {
149 // skip categories
150 continue;
151 }
152 if (!output.IsEmpty())
153 {
154 output.Append("|");
155 };
156 const wxString type = p->GetValueType();
157 output.Append(p->GetName() + ":");
158 if (type == "double")
159 {
160 output.Append("double:" + wxString::FromCDouble(p->GetValue().GetDouble()));
161 }
162 else
163 {
164 if (type == "long")
165 {
166 output.Append("long:" + wxString::FromCDouble(p->GetValue().GetLong()));
167 }
168 else
169 {
170 if (type == "bool")
171 {
172 if (p->GetValue().GetBool())
173 {
174 output.Append("bool:true");
175 }
176 else
177 {
178 output.Append("bool:false");
179 };
180 }
181 else
182 {
183 // this should not happen
184 output.Append(type);
185 };
186 };
187 };
188 };
189 return output;
190}
191
192// destructor, save settings
194{
195 wxConfigBase* config = wxConfigBase::Get();
196 config->Write("/ToolboxFrame/Enfuse/Splitter", XRCCTRL(*this, "enfuse_splitter", wxSplitterWindow)->GetSashPosition());
197 config->Write("/ToolboxFrame/Enfuse/LastSettings", GetPropertyGridContent(m_enfuseOptions));
198 //save width of list ctrl column width
199 for (int j = 0; j < m_fileListCtrl->GetColumnCount(); j++)
200 {
201 config->Write(wxString::Format("/ToolboxFrame/Enfuse/FileListColumnWidth%d", j), m_fileListCtrl->GetColumnWidth(j));
202 };
203 config->Write("/ToolboxFrame/Enfuse/NotebookSelection", m_enfuse_preview_notebook->GetSelection());
204 config->Flush();
206}
207
209{
210 if (!wxPanel::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, "panel"))
211 {
212 return false;
213 }
214 // populate wxPropertyGrid with all options
217 // create preview window
218 m_preview = new PreviewWindow();
219 m_preview->Create(this);
220
222 // load from xrc file and attach unknown controls
223 wxXmlResource::Get()->LoadPanel(this, "enfuse_panel");
224 wxXmlResource::Get()->AttachUnknownControl("enfuse_properties", m_enfuseOptions->GetGrid(), this);
225 wxXmlResource::Get()->AttachUnknownControl("enfuse_preview_window", m_preview, this);
226 // add to sizer
227 wxPanel* mainPanel = XRCCTRL(*this, "enfuse_panel", wxPanel);
229 topsizer->Add(mainPanel, wxSizerFlags(1).Expand());
230 // create columns in wxListCtrl
231 m_fileListCtrl = XRCCTRL(*this, "enfuse_files", wxListCtrl);
232 m_fileListCtrl->InsertColumn(0, _("Filename"), wxLIST_FORMAT_LEFT, 200);
233 m_fileListCtrl->InsertColumn(1, _("Aperture"), wxLIST_FORMAT_LEFT, 50);
234 m_fileListCtrl->InsertColumn(2, _("Shutter Speed"), wxLIST_FORMAT_LEFT, 50);
235 m_fileListCtrl->InsertColumn(3, _("ISO"), wxLIST_FORMAT_LEFT, 50);
236 m_fileListCtrl->EnableCheckBoxes(true);
237 m_previewSelectedImage = XRCCTRL(*this, "enfuse_selected_image", wxStaticBitmap);
238 m_enfuse_preview_notebook = XRCCTRL(*this, "enfuse_option_preview_notebook", wxNotebook);
241
242 wxConfigBase* config = wxConfigBase::Get();
243 // restore splitter position
244 if (config->HasEntry("/ToolboxFrame/Enfuse/Splitter"))
245 {
246 XRCCTRL(*this, "enfuse_splitter", wxSplitterWindow)->SetSashPosition(config->ReadLong("/ToolboxFrame/Enfuse/Splitter", 300));
247 }
248 const wxString enfuseOptionsString=config->Read("/ToolboxFrame/Enfuse/LastSettings");
249 if (!enfuseOptionsString.IsEmpty())
250 {
252 };
253 //get saved width of list ctrl column width
254 for (int j = 0; j < m_fileListCtrl->GetColumnCount(); j++)
255 {
256 // -1 is auto
257 int width = config->Read(wxString::Format("/ToolboxFrame/Enfuse/FileListColumnWidth%d", j), -1);
258 if (width != -1)
259 {
260 m_fileListCtrl->SetColumnWidth(j, width);
261 };
262 };
263 m_enfuse_preview_notebook->SetSelection(config->ReadLong("/ToolboxFrame/Enfuse/NotebookSelection", 0l));
264 // bind event handler
265 Bind(wxEVT_BUTTON, &EnfusePanel::OnAddFiles, this, XRCID("enfuse_add_file"));
266 Bind(wxEVT_BUTTON, &EnfusePanel::OnRemoveFile, this, XRCID("enfuse_remove_file"));
267 Bind(wxEVT_BUTTON, &EnfusePanel::OnCreateFile, this, XRCID("enfuse_create_file"));
273 Bind(wxEVT_BUTTON, &EnfusePanel::OnLoadSetting, this, XRCID("enfuse_load_setting"));
274 Bind(wxEVT_BUTTON, &EnfusePanel::OnSaveSetting, this, XRCID("enfuse_save_setting"));
275 Bind(wxEVT_BUTTON, &EnfusePanel::OnResetSetting, this, XRCID("enfuse_reset_setting"));
276 Bind(wxEVT_BUTTON, &EnfusePanel::OnGeneratePreview, this, XRCID("enfuse_preview"));
277 Bind(wxEVT_BUTTON, &EnfusePanel::OnGenerateOutput, this, XRCID("enfuse_enfuse"));
278 Bind(wxEVT_CHOICE, &EnfusePanel::OnZoom, this, XRCID("enfuse_choice_zoom"));
279
281 EnableOutputButtons(false);
282 return true;
283}
284
285void EnfusePanel::AddFile(const wxString& filename)
286{
287 // add filename
288 m_files.push_back(filename);
289 // add to wxListCtrl
290 wxFileName fullFilename(filename);
291 long index = m_fileListCtrl->InsertItem(m_fileListCtrl->GetItemCount(), fullFilename.GetFullName());
292 // set checkbox
293 m_fileListCtrl->CheckItem(index, true);
294 // read exif
295 {
297 srcImage.setFilename(std::string(fullFilename.GetFullPath().mb_str(HUGIN_CONV_FILENAME)));
298 if (srcImage.readEXIF())
299 {
300 m_fileListCtrl->SetItem(index, 1, FormatString::GetAperture(&srcImage));
301 m_fileListCtrl->SetItem(index, 2, FormatString::GetExposureTime(&srcImage));
302 m_fileListCtrl->SetItem(index, 3, FormatString::GetIso(&srcImage));
303 };
304 };
306}
307
308void EnfusePanel::OnAddFiles(wxCommandEvent& e)
309{
310 wxConfigBase* config = wxConfigBase::Get();
311 wxString path = config->Read("/actualPath", "");
312 wxFileDialog dlg(this, _("Add images"), path, wxEmptyString,
314 dlg.SetDirectory(path);
315
316 // remember the image extension
318 if (config->HasEntry("lastImageType"))
319 {
320 img_ext = config->Read("lastImageType").c_str();
321 }
322 if (img_ext == "all images")
323 dlg.SetFilterIndex(0);
324 else if (img_ext == "jpg")
325 dlg.SetFilterIndex(1);
326 else if (img_ext == "tiff")
327 dlg.SetFilterIndex(2);
328 else if (img_ext == "png")
329 dlg.SetFilterIndex(3);
330 else if (img_ext == "hdr")
331 dlg.SetFilterIndex(4);
332 else if (img_ext == "exr")
333 dlg.SetFilterIndex(5);
334 else if (img_ext == "all files")
335 dlg.SetFilterIndex(6);
336
337 // call the file dialog
338 if (dlg.ShowModal() == wxID_OK)
339 {
340 // get the selections
342 dlg.GetPaths(Pathnames);
343 // save the current path to config
344 config->Write("/actualPath", dlg.GetDirectory());
345 // save the image extension
346 switch (dlg.GetFilterIndex())
347 {
348 case 0: config->Write("lastImageType", "all images"); break;
349 case 1: config->Write("lastImageType", "jpg"); break;
350 case 2: config->Write("lastImageType", "tiff"); break;
351 case 3: config->Write("lastImageType", "png"); break;
352 case 4: config->Write("lastImageType", "hdr"); break;
353 case 5: config->Write("lastImageType", "exr"); break;
354 case 6: config->Write("lastImageType", "all files"); break;
355 }
356 for (auto& f : Pathnames)
357 {
358 AddFile(f);
359 }
360 }
361}
362
363void EnfusePanel::OnRemoveFile(wxCommandEvent& e)
364{
366 if (m_fileListCtrl->GetSelectedItemCount() >= 1)
367 {
368 for (int i = 0; i < m_fileListCtrl->GetItemCount(); ++i)
369 {
371 {
372 selected.insert(i);
373 };
374 };
375 };
376 if (!selected.empty())
377 {
378 // remove selected file from wxListBox and internal file list
379 for (auto i = selected.rbegin(); i != selected.rend(); ++i)
380 {
381 if (*i >= 0 && *i < m_files.size())
382 {
383 m_fileListCtrl->DeleteItem(*i);
384 m_files.RemoveAt(*i, 1);
385 };
386 };
389 }
390 else
391 {
392 wxBell();
393 };
394}
395
396void EnfusePanel::OnCreateFile(wxCommandEvent& e)
397{
398 if (m_fileListCtrl->GetSelectedItemCount() == 1)
399 {
400 // single image selected
401 long index = m_fileListCtrl->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
402 if (index != -1)
403 {
406 if (dlg.SetImage(std::string(m_files[index].mb_str(HUGIN_CONV_FILENAME)), errorMsg))
407 {
408 if (dlg.ShowModal() == wxID_OK)
409 {
410 // get all new files
411 wxArrayString newFiles = dlg.GetTempFiles();
412 // wait a little bit before reading the files back
413 // wxMilliSleep(1000);
414 for (const auto& f : newFiles)
415 {
416 // add to list of temp files for cleanup at end
417 m_tempFiles.Add(f);
418 // add to list
419 AddFile(f);
420 };
421 };
422 }
423 else
424 {
425 hugin_utils::HuginMessageBox(errorMsg, _("Hugin toolbox"), wxOK | wxICON_QUESTION, this);
426 };
427 };
428 }
429 else
430 {
431 wxBell();
432 };
433}
434
436{
437 // ctrl + a, select all files
438 if (e.GetKeyCode() == 1 && e.CmdDown())
439 {
440 // select all
441 for (int i = 0; i < m_fileListCtrl->GetItemCount(); i++)
442 {
444 };
445 };
446 // insert key, add file
447 if ((e.GetKeyCode() == WXK_INSERT || e.GetKeyCode() == WXK_NUMPAD_INSERT) && !e.HasAnyModifiers())
448 {
449 wxCommandEvent e(wxEVT_BUTTON);
450 e.SetId(XRCID("enfuse_add_file"));
451 this->GetEventHandler()->AddPendingEvent(e);
452 };
453 // delete key, delete selected file
454 if ((e.GetKeyCode() == WXK_DELETE || e.GetKeyCode() == WXK_NUMPAD_DELETE) && !e.HasAnyModifiers())
455 {
456 if (m_fileListCtrl->GetSelectedItemCount() > 0)
457 {
458 wxCommandEvent e(wxEVT_BUTTON);
459 e.SetId(XRCID("enfuse_remove_file"));
460 this->GetEventHandler()->AddPendingEvent(e);
461 }
462 else
463 {
464 wxBell();
465 };
466 };
467 e.Skip();
468}
469
471{
472 // enable/disable button according to selected files
474 if (m_fileListCtrl->GetSelectedItemCount() == 1)
475 {
476 const long index = m_fileListCtrl->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
477 if (index >= 0 && index < m_files.size())
478 {
479 m_selectedImage = std::string(m_files[index].mb_str(HUGIN_CONV_FILENAME));
480 ImageCache::EntryPtr cacheEntry = ImageCache::getInstance().getSmallImageIfAvailable(m_selectedImage);
481 if(cacheEntry.get())
482 {
483 // image is already in cache, display it directly
485 wxGetApp().GetToolboxFrame()->HasMonitorProfile(), wxGetApp().GetToolboxFrame()->GetMonitorProfile());
486 m_imgRequest = ImageCache::RequestPtr();
487 m_selectedImage = std::string();
488 }
489 else
490 {
491 // load the image in the background.
493 m_imgRequest->ready.push_back(
494 std::bind(&EnfusePanel::OnImageLoaded, this, std::placeholders::_1, std::placeholders::_2)
495 );
496 }
497 }
498 }
499 else
500 {
501 m_selectedImage = std::string();
502 }
503}
504
506{
507 // check we are still displaying this image
508 if (m_selectedImage == filename)
509 {
511 wxGetApp().GetToolboxFrame()->HasMonitorProfile(), wxGetApp().GetToolboxFrame()->GetMonitorProfile());
512 }
513}
514
519
522{
523 "[Enfuse_Settings]\n"
524 "Exposure fusion=exposureWeight:double:1|saturationWeight:double:0|contrastWeight:double:0|entropyWeight:double:0|hardMask:bool:false|levels:long:0|blendColorspace:long:0|wrapMode:long:0|exposureOptimum:double:0.5|exposureWidth:double:0.2|contrastEdgeScale:double:0|contrastMinCurvature:double:0|contrastWindowSize:long:5|entropyLowerCutoff:double:0|entropyUpperCutoff:double:100|entropyWindowSize:long:3|exposureLowerCutoff:double:0|exposureUpperCutoff:double:100|exposureWeightFunction:long:0|grayProjector:long:1\n"
525 "Focus stacking=exposureWeight:double:0|saturationWeight:double:0|contrastWeight:double:1|entropyWeight:double:0|hardMask:bool:true|levels:long:0|blendColorspace:long:0|wrapMode:long:0|exposureOptimum:double:0.5|exposureWidth:double:0.2|contrastEdgeScale:double:0|contrastMinCurvature:double:0|contrastWindowSize:long:5|entropyLowerCutoff:double:0|entropyUpperCutoff:double:100|entropyWindowSize:long:3|exposureLowerCutoff:double:0|exposureUpperCutoff:double:100|exposureWeightFunction:long:0|grayProjector:long:1\n"
526};
527
529{
530 wxInputStream* iniStream{ nullptr };
531 if (wxFileExists(filename))
532 {
533 iniStream = new wxFileInputStream(filename);
534 if (!iniStream->IsOk())
535 {
536 delete iniStream;
537 iniStream = nullptr;
538 }
539 };
540 if (iniStream == nullptr)
541 {
543 };
544 // now read from stream
546 delete iniStream;
547 return iniFile;
548}
549
550void EnfusePanel::OnLoadSetting(wxCommandEvent& e)
551{
553 wxFileConfig* iniFile = ReadIni(iniFilename.GetFullPath());
554 // read known settings from file
555 iniFile->SetPath("Enfuse_Settings");
559 long indexKey;
560 bool hasKeys = iniFile->GetFirstEntry(key, indexKey);
561 while (hasKeys)
562 {
563 knownNames.push_back(key);
564 knownSettings.push_back(iniFile->Read(key));
565 hasKeys = iniFile->GetNextEntry(key, indexKey);
566 };
567 int selection=wxGetSingleChoiceIndex(_("Select the Enfuse setting, which should be loaded."), _("Hugin toolbox"), knownNames, 0, this);
568 if (selection != -1)
569 {
571 };
572 delete iniFile;
573}
574
575void EnfusePanel::OnSaveSetting(wxCommandEvent& e)
576{
578 wxFileConfig* iniFile = ReadIni(iniFilename.GetFullPath());
579 // read known settings from file
580 iniFile->SetPath("Enfuse_Settings");
583 long indexKey;
584 bool hasKeys = iniFile->GetFirstEntry(key, indexKey);
585 while (hasKeys)
586 {
587 knownNames.push_back(key);
588 hasKeys = iniFile->GetNextEntry(key, indexKey);
589 };
590 wxString name;
591 while (true)
592 {
593 name = wxGetTextFromUser(_("Enter name of Enfuse setting"), "Enfuse settings", name, this);
594 if (name.IsEmpty())
595 {
596 // empty name or cancel
597 delete iniFile;
598 return;
599 };
600 // remove the '=' character from name, it is used as separator in ini file
601 name.Replace("=", "", true);
602 if (knownNames.Index(name) != wxNOT_FOUND)
603 {
604 if (hugin_utils::HuginMessageBox(wxString::Format(_("Enfuse setting with name \"%s\" is already existing.\nShould it be overwritten?"), name),
605 _("Hugin toolbox"), wxYES_NO | wxICON_QUESTION, this) == wxYES)
606 {
607 break;
608 };
609 }
610 else
611 {
612 break;
613 };
614 };
615 // finally write settings
617 // finally write to disc
619 bool success = true;
620 if (iniStream.IsOk())
621 {
622 success = iniFile->Save(iniStream);
623 };
624 if (!success)
625 {
626 hugin_utils::HuginMessageBox(wxString::Format(_("Could not save ini file \"%s\"."), iniFilename.GetFullPath()), _("Hugin toolbox"), wxOK | wxICON_ERROR, this);
627 };
628 delete iniFile;
629}
630
631void EnfusePanel::OnResetSetting(wxCommandEvent& e)
632{
633 // reset all settings to default values
634 m_enfuseOptions->SetPropertyValue("exposureWeight", 1.0);
635 m_enfuseOptions->SetPropertyValue("saturationWeight", 0.0);
636 m_enfuseOptions->SetPropertyValue("contrastWeight", 0.0);
637 m_enfuseOptions->SetPropertyValue("entropyWeight", 0.0);
638 m_enfuseOptions->SetPropertyValue("hardMask", false);
639 m_enfuseOptions->SetPropertyValue("levels", 0);
640 m_enfuseOptions->SetPropertyValue("blendColorspace", 0);
641 m_enfuseOptions->SetPropertyValue("wrapMode", 0);
642 m_enfuseOptions->SetPropertyValue("exposureOptimum", 0.5);
643 m_enfuseOptions->SetPropertyValue("exposureWidth", 0.2);
644 m_enfuseOptions->SetPropertyValue("contrastEdgeScale", 0.0);
645 m_enfuseOptions->SetPropertyValue("contrastMinCurvature", 0.0);
646 m_enfuseOptions->SetPropertyValue("contrastWindowSize", 5);
647 m_enfuseOptions->SetPropertyValue("entropyLowerCutoff", 0.0);
648 m_enfuseOptions->SetPropertyValue("entropyUpperCutoff", 100.0);
649 m_enfuseOptions->SetPropertyValue("entropyWindowSize", 3);
650 m_enfuseOptions->SetPropertyValue("exposureLowerCutoff", 0.0);
651 m_enfuseOptions->SetPropertyValue("exposureUpperCutoff", 100.0);
652 m_enfuseOptions->SetPropertyValue("exposureWeightFunction", 0);
653 m_enfuseOptions->SetPropertyValue("grayProjector", 1);
654}
655
656void EnfusePanel::OnGeneratePreview(wxCommandEvent& e)
657{
658 // create temp file name, set extension to tif
659 m_outputFilenames.resize(2);
660 wxFileName tempfile(wxFileName::CreateTempFileName(HuginQueue::GetConfigTempDir(wxConfig::Get()) + "he"));
661 m_outputFilenames[1] = tempfile.GetFullPath();
662 tempfile.SetExt("tif");
663 m_outputFilenames[0] = tempfile.GetFullPath();
664 m_cleanupOutput = true;
665 // get command line and execute
667}
668
681
683{
685 if (!cmd.IsEmpty())
686 {
687 EnableOutputButtons(false);
691 queue->push_back(new HuginQueue::NormalCommand(HuginQueue::GetExternalProgram(wxConfig::Get(), exePath, "enfuse"), cmd, _("Merging images") + " (" + cmd + ")"));
692 // get first image
693 long index = -1;
694 for (long i = 0; i < m_fileListCtrl->GetItemCount(); ++i)
695 {
696 if (m_fileListCtrl->IsItemChecked(i))
697 {
698 index = i;
699 break;
700 };
701 };
702 wxString exiftoolArgs(" -overwrite_original -tagsfromfile " + HuginQueue::wxEscapeFilename(m_files[index]));
703 exiftoolArgs.Append(" -all:all --thumbnail --thumbnailimage --xposition --yposition --imagefullwidth --imagefullheight ");
705 queue->push_back(new HuginQueue::OptionalCommand(HuginQueue::GetExternalProgram(wxConfig::Get(), exePath, "exiftool"), exiftoolArgs, _("Updating EXIF")));
706 m_logWindow->ExecQueue(queue);
707 };
708}
709
710void EnfusePanel::OnGenerateOutput(wxCommandEvent& e)
711{
712 if (m_files.IsEmpty())
713 {
714 wxBell();
715 return;
716 };
717 wxConfigBase* config = wxConfigBase::Get();
718 wxString path = config->Read("/actualPath", "");
720 dlg.SetDirectory(path);
721
722 // remember the image extension
724 if (config->HasEntry("lastImageType"))
725 {
726 img_ext = config->Read("lastImageType").c_str();
727 }
728 if (img_ext == "jpg")
729 {
730 dlg.SetFilterIndex(0);
731 }
732 else
733 {
734 if (img_ext == "tiff")
735 {
736 dlg.SetFilterIndex(1);
737 }
738 else
739 {
740 if (img_ext == "png")
741 {
742 dlg.SetFilterIndex(2);
743 };
744 };
745 };
747 outputfilename.SetName(outputfilename.GetName() + "_stacked");
748 dlg.SetFilename(outputfilename.GetFullPath());
749 // call the file dialog
750 if (dlg.ShowModal() == wxID_OK)
751 {
752 m_outputFilenames.resize(1);
753 m_outputFilenames[0] = dlg.GetPath();
754 // save the current path to config
755 config->Write("/actualPath", dlg.GetDirectory());
756 // save the image extension
757 switch (dlg.GetFilterIndex())
758 {
759 case 0:
760 config->Write("lastImageType", "jpg");
761 break;
762 case 1:
763 config->Write("lastImageType", "tiff");
764 break;
765 case 2:
766 config->Write("lastImageType", "png");
767 break;
768 };
769 m_cleanupOutput = false;
771 };
772}
773
774void EnfusePanel::OnZoom(wxCommandEvent& e)
775{
776 double factor;
777 switch (e.GetSelection())
778 {
779 case 0:
780 factor = 1;
781 break;
782 case 1:
783 // fit to window
784 factor = 0;
785 break;
786 case 2:
787 factor = 2;
788 break;
789 case 3:
790 factor = 1.5;
791 break;
792 case 4:
793 factor = 0.75;
794 break;
795 case 5:
796 factor = 0.5;
797 break;
798 case 6:
799 factor = 0.25;
800 break;
801 default:
802 DEBUG_ERROR("unknown scale factor");
803 factor = 1;
804 }
805 m_preview->setScale(factor);
806}
807
808void EnfusePanel::OnProcessFinished(wxCommandEvent& e)
809{
811 if (output.FileExists() && output.GetSize()>0)
812 {
813 m_preview->setImage(output.GetFullPath());
814 };
816 if (m_cleanupOutput && output.FileExists())
817 {
818 // cleanup up preview files
819 for (const auto& f : m_outputFilenames)
820 {
821 wxRemoveFile(f);
822 };
823 };
824}
825
827{
828 // all weight options, with spin control
829 wxPGProperty* prop = m_enfuseOptions->Append(new wxFloatProperty("Exposure weight", "exposureWeight", 1));
830 prop->SetEditor(wxPGEditor_SpinCtrl);
831 prop->SetAttribute(wxPG_ATTR_MIN, 0);
832 prop->SetAttribute(wxPG_ATTR_MAX, 1);
833 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.05);
834 prop = m_enfuseOptions->Append(new wxFloatProperty("Saturation weight", "saturationWeight", 0));
835 prop->SetEditor(wxPGEditor_SpinCtrl);
836 prop->SetAttribute(wxPG_ATTR_MIN, 0);
837 prop->SetAttribute(wxPG_ATTR_MAX, 1);
838 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.05);
839 prop = m_enfuseOptions->Append(new wxFloatProperty("Contrast weight", "contrastWeight", 0));
840 prop->SetEditor(wxPGEditor_SpinCtrl);
841 prop->SetAttribute(wxPG_ATTR_MIN, 0);
842 prop->SetAttribute(wxPG_ATTR_MAX, 1);
843 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.05);
844 prop = m_enfuseOptions->Append(new wxFloatProperty("Entropy weight", "entropyWeight", 0));
845 prop->SetEditor(wxPGEditor_SpinCtrl);
846 prop->SetAttribute(wxPG_ATTR_MIN, 0);
847 prop->SetAttribute(wxPG_ATTR_MAX, 1);
848 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.05);
849 // hard / soft mask
850 m_enfuseOptions->Append(new wxBoolProperty("Hard mask", "hardMask", false));
851 // general options
852 prop = m_enfuseOptions->Append(new wxPropertyCategory(_("General"), "general"));
853 prop = m_enfuseOptions->Append(new wxIntProperty("Levels", "levels", 0));
854 prop->SetEditor(wxPGEditor_SpinCtrl);
855 prop->SetAttribute(wxPG_ATTR_MIN, -29);
856 prop->SetAttribute(wxPG_ATTR_MAX, 29);
857 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 1);
859 blendColorspaces.Add("Auto");
860 blendColorspaces.Add("Identity (RGB)");
861 blendColorspaces.Add("CIELab");
862 blendColorspaces.Add("CIELuv");
863 blendColorspaces.Add("CIECAM02");
864 m_enfuseOptions->Append(new wxEnumProperty("Blend colorspace", "blendColorspace", blendColorspaces));
866 wrapMode.Add("None");
867 wrapMode.Add("Horizontal");
868 wrapMode.Add("Vertical");
869 wrapMode.Add("Both");
870 m_enfuseOptions->Append(new wxEnumProperty("Wrap mode", "wrapMode", wrapMode));
871 m_enfuseOptions->Collapse("general");
872 m_enfuseOptions->Append(new wxPropertyCategory(_("Fusions options"), "fusionOptions"));
873 prop = m_enfuseOptions->Append(new wxFloatProperty("Exposure optimum", "exposureOptimum", 0.5));
874 prop->SetEditor(wxPGEditor_SpinCtrl);
875 prop->SetAttribute(wxPG_ATTR_MIN, 0);
876 prop->SetAttribute(wxPG_ATTR_MAX, 1);
877 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.05);
878 prop = m_enfuseOptions->Append(new wxFloatProperty("Exposure width", "exposureWidth", 0.2));
879 prop->SetEditor(wxPGEditor_SpinCtrl);
880 prop->SetAttribute(wxPG_ATTR_MIN, 0);
881 prop->SetAttribute(wxPG_ATTR_MAX, 1);
882 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.05);
883 prop = m_enfuseOptions->Append(new wxFloatProperty("Contrast edge scale", "contrastEdgeScale", 0));
884 prop->SetEditor(wxPGEditor_SpinCtrl);
885 prop->SetAttribute(wxPG_ATTR_MIN, 0);
886 prop->SetAttribute(wxPG_ATTR_MAX, 5);
887 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.1);
888 prop = m_enfuseOptions->Append(new wxFloatProperty("Contrast min curvature", "contrastMinCurvature", 0));
889 prop->SetEditor(wxPGEditor_SpinCtrl);
890 prop->SetAttribute(wxPG_ATTR_MIN, 0);
891 prop->SetAttribute(wxPG_ATTR_MAX, 50);
892 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.5);
893 prop = m_enfuseOptions->Append(new wxIntProperty("Contrast window size", "contrastWindowSize", 5));
894 prop->SetEditor(wxPGEditor_SpinCtrl);
895 prop->SetAttribute(wxPG_ATTR_MIN, 3);
896 prop->SetAttribute(wxPG_ATTR_MAX, 30);
897 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 1);
898 prop = m_enfuseOptions->Append(new wxFloatProperty("Entropy lower cutoff", "entropyLowerCutoff", 0));
899 prop->SetEditor(wxPGEditor_SpinCtrl);
900 prop->SetAttribute(wxPG_ATTR_MIN, 0);
901 prop->SetAttribute(wxPG_ATTR_MAX, 100);
902 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.5);
903 prop = m_enfuseOptions->Append(new wxFloatProperty("Entropy higher cutoff", "entropyUpperCutoff", 100));
904 prop->SetEditor(wxPGEditor_SpinCtrl);
905 prop->SetAttribute(wxPG_ATTR_MIN, 0);
906 prop->SetAttribute(wxPG_ATTR_MAX, 100);
907 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.5);
908 prop = m_enfuseOptions->Append(new wxIntProperty("Entropy window size", "entropyWindowSize", 3));
909 prop->SetEditor(wxPGEditor_SpinCtrl);
910 prop->SetAttribute(wxPG_ATTR_MIN, 3);
911 prop->SetAttribute(wxPG_ATTR_MAX, 7);
912 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 1);
913 prop = m_enfuseOptions->Append(new wxFloatProperty("Expoure lower cutoff", "exposureLowerCutoff", 0));
914 prop->SetEditor(wxPGEditor_SpinCtrl);
915 prop->SetAttribute(wxPG_ATTR_MIN, 0);
916 prop->SetAttribute(wxPG_ATTR_MAX, 100);
917 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.5);
918 prop = m_enfuseOptions->Append(new wxFloatProperty("Exposure higher cutoff", "exposureUpperCutoff", 100));
919 prop->SetEditor(wxPGEditor_SpinCtrl);
920 prop->SetAttribute(wxPG_ATTR_MIN, 0);
921 prop->SetAttribute(wxPG_ATTR_MAX, 100);
922 prop->SetAttribute(wxPG_ATTR_SPINCTRL_STEP, 0.5);
924 exposureWeightFunction.Add("Gaussian");
925 exposureWeightFunction.Add("Lorentzian");
926 exposureWeightFunction.Add("Half-sine");
927 exposureWeightFunction.Add("Full-sine");
928 exposureWeightFunction.Add("Bi-square");
929 m_enfuseOptions->Append(new wxEnumProperty("Exposure weight function", "exposureWeightFunction", exposureWeightFunction));
931 grayProjector.Add("anti-value"); // index 0
932 grayProjector.Add("Average"); // index 1
933 grayProjector.Add("L-channel from Lab (gamma=1)"); // index 2
934 grayProjector.Add("L-channel from Lab (gamma corrected)"); // index 3
935 grayProjector.Add("Lightness"); // index 4
936 grayProjector.Add("Luminance"); // index 5
937 grayProjector.Add("Value from HSV"); // index 6
938 // missing: channelMixel
939 prop = m_enfuseOptions->Append(new wxEnumProperty("Gray projector", "grayProjector", grayProjector));
940 m_enfuseOptions->SetPropertyValue("grayProjector", 1);
941 // if you add new options also update GetEnfuseOptions() and OnResetSetting(..)
942}
943
945{
946 wxString commandline("--verbose ");
947 double doubleValue=m_enfuseOptions->GetPropertyValueAsDouble("exposureWeight");
948 if (doubleValue != 1)
949 {
950 commandline.Append(" --exposure-weight=" + wxString::FromCDouble(doubleValue));
951 };
952 doubleValue = m_enfuseOptions->GetPropertyValueAsDouble("saturationWeight");
953 if (doubleValue != 0)
954 {
955 commandline.Append(" --saturation-weight=" + wxString::FromCDouble(doubleValue));
956 };
957 doubleValue = m_enfuseOptions->GetPropertyValueAsDouble("contrastWeight");
958 if (doubleValue != 0)
959 {
960 commandline.Append(" --contrast-weight=" + wxString::FromCDouble(doubleValue));
961 };
962 doubleValue = m_enfuseOptions->GetPropertyValueAsDouble("entropyWeight");
963 if (doubleValue != 0)
964 {
965 commandline.Append(" --entropy-weight=" + wxString::FromCDouble(doubleValue));
966 };
967 bool boolVal = m_enfuseOptions->GetPropertyValueAsBool("hardMask");
968 if (boolVal)
969 {
970 commandline.Append(" --hard-mask");
971 };
972 int intValue = m_enfuseOptions->GetPropertyValueAsInt("levels");
973 if (intValue != 0)
974 {
975 commandline.Append(wxString::Format(" --level=%d", intValue));
976 };
977 intValue = m_enfuseOptions->GetPropertyValueAsInt("blendColorspace");
978 switch (intValue)
979 {
980 case 1:
981 commandline.Append(" --blend-colorspace=identity");
982 break;
983 case 2:
984 commandline.Append(" --blend-colorspace=cielab");
985 break;
986 case 3:
987 commandline.Append(" --blend-colorspace=cieluv");
988 break;
989 case 4:
990 commandline.Append(" --blend-colorspace=ciecam");
991 break;
992 default:
993 case 0:
994 // do nothing
995 break;
996 };
997 intValue = m_enfuseOptions->GetPropertyValueAsInt("wrapMode");
998 switch (intValue)
999 {
1000 case 1:
1001 commandline.Append(" --wrap=horizontal");
1002 break;
1003 case 2:
1004 commandline.Append(" --wrap=vertical");
1005 break;
1006 case 3:
1007 commandline.Append(" --wrap=both ");
1008 break;
1009 case 0:
1010 default:
1011 break;
1012 };
1013 doubleValue = m_enfuseOptions->GetPropertyValueAsDouble("exposureOptimum");
1014 if (doubleValue != 0.5)
1015 {
1016 commandline.Append(" --exposure-optimum=" + wxString::FromCDouble(doubleValue));
1017 };
1018 doubleValue = m_enfuseOptions->GetPropertyValueAsDouble("exposureWidth");
1019 if (doubleValue != 0.2)
1020 {
1021 commandline.Append(" --exposure-width=" + wxString::FromCDouble(doubleValue));
1022 };
1023 doubleValue = m_enfuseOptions->GetPropertyValueAsDouble("contrastEdgeScale");
1024 if (doubleValue != 0)
1025 {
1026 commandline.Append(" --contrast-edge-scale=" + wxString::FromCDouble(doubleValue));
1027 };
1028 doubleValue = m_enfuseOptions->GetPropertyValueAsDouble("contrastMinCurvature");
1029 if (doubleValue != 0)
1030 {
1031 commandline.Append(" --contrast-min-curvature=" + wxString::FromCDouble(doubleValue) + "%");
1032 };
1033 intValue = m_enfuseOptions->GetPropertyValueAsInt("contrastWindowSize");
1034 if (intValue != 5)
1035 {
1036 commandline.Append(wxString::Format(" --contrast-window-size=%d", intValue));
1037 };
1038 // entropy cutoff
1039 doubleValue = m_enfuseOptions->GetPropertyValueAsDouble("entropyLowerCutoff");
1040 double doubleValue2 = m_enfuseOptions->GetPropertyValueAsDouble("entropyUpperCutoff");
1041 if (doubleValue > 0 || doubleValue2 < 100)
1042 {
1043 commandline.Append(" --entropy-cutoff=" + wxString::FromCDouble(doubleValue) + "%");
1044 if (doubleValue2 < 100)
1045 {
1046 commandline.Append(":" + wxString::FromCDouble(doubleValue2) + "%");
1047 };
1048 };
1049 intValue = m_enfuseOptions->GetPropertyValueAsInt("entropyWindowSize");
1050 if (intValue != 3)
1051 {
1052 commandline.Append(wxString::Format(" --entropy-window-size=%d", intValue));
1053 };
1054 // exposure cutoff
1055 doubleValue = m_enfuseOptions->GetPropertyValueAsDouble("exposureLowerCutoff");
1056 doubleValue2 = m_enfuseOptions->GetPropertyValueAsDouble("exposureUpperCutoff");
1057 if (doubleValue > 0 || doubleValue2 < 100)
1058 {
1059 commandline.Append(" --exposure-cutoff=" + wxString::FromCDouble(doubleValue) + "%");
1060 if (doubleValue2 < 100)
1061 {
1062 commandline.Append(":" + wxString::FromCDouble(doubleValue2) + "%");
1063 };
1064 };
1065 // exposure weight function
1066 intValue = m_enfuseOptions->GetPropertyValueAsInt("exposureWeightFunction");
1067 switch (intValue)
1068 {
1069 case 1:
1070 commandline.Append(" --exposure-weight-function=lorentz");
1071 break;
1072 case 2:
1073 commandline.Append(" --exposure-weight-function=halfsine");
1074 break;
1075 case 3:
1076 commandline.Append(" --exposure-weight-function=fullsine");
1077 break;
1078 case 4:
1079 commandline.Append(" --exposure-weight-function=bisquare");
1080 break;
1081 case 0:
1082 default:
1083 break;
1084 };
1085 // gray projector
1086 intValue = m_enfuseOptions->GetPropertyValueAsInt("grayProjector");
1087 switch (intValue)
1088 {
1089 case 0:
1090 commandline.Append(" --gray-projector=anti-value");
1091 break;
1092 case 2:
1093 commandline.Append(" --gray-projector=al-star");
1094 break;
1095 case 3:
1096 commandline.Append(" --gray-projector=pl-star");
1097 break;
1098 case 4:
1099 commandline.Append(" --gray-projector=lightness");
1100 break;
1101 case 5:
1102 commandline.Append(" --gray-projector=luminance");
1103 break;
1104 case 6:
1105 commandline.Append(" --gray-projector=value");
1106 break;
1107 case 1:
1108 default:
1109 break;
1110 };
1111 return commandline;
1112}
1113
1115{
1117 // add options from control
1118 commandline.Append(" ");
1119 commandline.Append(GetEnfuseOptions());
1120 // now build image list
1122 for (int i = 0; i < m_fileListCtrl->GetItemCount(); ++i)
1123 {
1124 if (m_fileListCtrl->IsItemChecked(i))
1125 {
1126 selectedFiles.push_back(i);
1127 };
1128 };
1129 if (selectedFiles.IsEmpty())
1130 {
1131 hugin_utils::HuginMessageBox(_("Please activate at least one file."), _("Hugin_toolbox"), wxOK | wxOK_DEFAULT | wxICON_WARNING, this);
1132 return wxEmptyString;
1133 }
1134 for (int i = 0; i < selectedFiles.size(); ++i)
1135 {
1136 commandline.Append(" ");
1138 }
1139 return commandline;
1140}
1141
1143{
1144 // enable/disable button according to selected files
1145 XRCCTRL(*this, "enfuse_remove_file", wxButton)->Enable(m_fileListCtrl->GetSelectedItemCount() >= 1);
1146 XRCCTRL(*this, "enfuse_create_file", wxButton)->Enable(m_fileListCtrl->GetSelectedItemCount() == 1);
1147}
1148
1150{
1151 // count checked items
1152 long count = 0;
1153 for (int i = 0; i < m_fileListCtrl->GetItemCount(); ++i)
1154 {
1155 if (m_fileListCtrl->IsItemChecked(i))
1156 {
1157 ++count;
1158 };
1159 };
1160 return count;
1161}
1162
1164{
1165 XRCCTRL(*this, "enfuse_preview", wxButton)->Enable(enable);
1166 XRCCTRL(*this, "enfuse_enfuse", wxButton)->Enable(enable);
1167
1168}
1169
1171{
1172 for (const auto& f : m_tempFiles)
1173 {
1174 wxRemoveFile(f);
1175 };
1176}
1177
1178IMPLEMENT_DYNAMIC_CLASS(EnfusePanel, wxPanel)
Definition of dialog class to create brighter/darker versions of the image.
wxString GetPropertyGridContent(const wxPropertyGrid *grid)
wxFileConfig * ReadIni(const wxString &filename)
static const wxString defaultIni
default ini, if no one exists load this one
void SetPropertyGridContent(wxPropertyGrid *grid, const wxString values)
declaration of panel for enfuse GUI
basic classes and function for queuing commands in wxWidgets
some helper classes for graphes
Dialog for create brighter and/or darker versions of an image.
file drag and drop handler method
EnfusePanel * m_enfusePanel
EnfuseDropTarget(EnfusePanel *parent)
bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
panel for enfuse GUI
Definition EnfusePanel.h:39
void PopulateEnfuseOptions()
fill the PropertyGrid with all enfuse options
PreviewWindow * m_preview
Definition EnfusePanel.h:92
bool Create(wxWindow *parent, MyExecPanel *logPanel)
creates the control and populates all controls with their settings
void OnZoom(wxCommandEvent &e)
wxPropertyGrid * m_enfuseOptions
Definition EnfusePanel.h:90
void OnCreateFile(wxCommandEvent &e)
HuginBase::ImageCache::RequestPtr m_imgRequest
Definition EnfusePanel.h:96
void AddFile(const wxString &filename)
adds the given file to the list
void OnAddFiles(wxCommandEvent &e)
event handler
void OnProcessFinished(wxCommandEvent &e)
call at the end of the enfuse command, to load result back and enable buttons again
void OnFileListChar(wxKeyEvent &e)
void OnRemoveFile(wxCommandEvent &e)
void OnGenerateOutput(wxCommandEvent &e)
void OnImageLoaded(HuginBase::ImageCache::EntryPtr entry, std::string filename)
called when is image is fully loaded to display image in wxStaticBitmap
void CleanUpTempFiles()
delete all temporary files, to be called mainly at end
std::string m_selectedImage
Definition EnfusePanel.h:97
void EnableOutputButtons(bool enable)
enable/disable output buttons
void ExecuteEnfuseExiftool()
build the command line and execute enfuse and exiftool afterwards
long GetCheckedItemCount() const
return the number of check images
void OnGeneratePreview(wxCommandEvent &e)
~EnfusePanel()
destructor, save state and settings
wxString GetEnfuseOptions()
build string with all enfuse options from values in wxPropertyGrid this are the mainly the fusion opt...
MyExecPanel * m_logWindow
Definition EnfusePanel.h:94
void OnFileCheckStateChanged(wxCommandEvent &e)
wxString GetEnfuseCommandLine()
get the full commandline for enfuse without program, but with files and output options,...
wxStaticBitmap * m_previewSelectedImage
Definition EnfusePanel.h:95
wxArrayString m_tempFiles
Definition EnfusePanel.h:99
wxArrayString m_outputFilenames
Definition EnfusePanel.h:98
void OnLoadSetting(wxCommandEvent &e)
wxListCtrl * m_fileListCtrl
Definition EnfusePanel.h:89
wxArrayString m_files
Definition EnfusePanel.h:91
void ExecuteEnfuse()
build the command line and execute enfuse command
void OnSaveSetting(wxCommandEvent &e)
wxNotebook * m_enfuse_preview_notebook
Definition EnfusePanel.h:93
void EnableFileButtons()
enable/disable the file(s) remove and create buttons depending on selection of wxListCtrl
bool m_cleanupOutput
void OnResetSetting(wxCommandEvent &e)
void OnFileSelectionChanged(wxCommandEvent &e)
static ImageCache & getInstance()
get the global ImageCache object
RequestPtr requestAsyncSmallImage(const std::string &filename)
Request a small image be loaded.
std::shared_ptr< Entry > EntryPtr
a shared pointer to the entry
Definition ImageCache.h:112
All variables of a source image.
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.
implementation of huginApp Class
#define HUGIN_CONV_FILENAME
Definition platform.h:40
#define DEBUG_ERROR(msg)
Definition utils.h:76
wxString GetIso(const HuginBase::SrcPanoImage *img)
returns formatted iso value
wxString GetExposureTime(const HuginBase::SrcPanoImage *img)
returns formatted exposure time
wxString GetAperture(const HuginBase::SrcPanoImage *img)
returns formatted aperture value
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
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
std::string GetUserAppDataDir()
returns the directory for user specific Hugin settings, e.g.
Definition utils.cpp:497
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
void GeneratePreviewSelectedFile(wxStaticBitmap *control, ImageCache::EntryPtr cacheEntry, const bool hasMonitorProfile, const cmsHPROFILE &monitorProfile)
load given image from image cache and display in wxStaticBitmap control
platform/compiler specific stuff.