Hugin trunk 0.1
Loading...
Searching...
No Matches
GenerateSequenceDialog.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
10/* This 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 * Lesser 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
27#include "base_wx/wxPlatform.h"
28#include <wx/busyinfo.h>
29#include "panoinc.h"
30#include "base_wx/wxutils.h"
31
34{
37 if (!dir.IsOpened())
38 {
39 // could not open given directories
40 return subDirs;
41 }
42 wxString filename;
43 bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS);
44 while (cont)
45 {
46 subDirs.Add(filename);
47 cont = dir.GetNext(&filename);
48 };
49 return subDirs;
50}
51
53wxString GetNumberString(size_t x, size_t width)
54{
55 const wxString formatString = wxString::Format("%%0%dd", width);
56 return wxString::Format(formatString, x);
57}
58
60{
61 // load our children. some children might need special
62 // initialization. this will be done later.
63 wxXmlResource::Get()->LoadDialog(this,batchframe, "generate_sequence_dialog");
64
66 m_filename = ptoFilename;
68 if (IsValidPanorama())
69 {
70 this->SetLabel(wxString::Format(_("Generating sequence from %s"), m_filename.c_str()));
71 m_basepath = XRCCTRL(*this, "sequence_base_path", wxTextCtrl);
73
74 m_choiceSubDir = XRCCTRL(*this, "sequence_choice_subdirectory", wxChoice);
76 m_subDirTextCtrl = XRCCTRL(*this, "sequence_directory_name", wxTextCtrl);
77
78 m_imagesListCtrl = XRCCTRL(*this, "sequence_images_list", wxListCtrl);
79 m_imagesListCtrl->InsertColumn(0, _("Template image name"));
80 m_imagesListCtrl->InsertColumn(1, _("Sequence image name"));
84
85
86 m_originalImage = XRCCTRL(*this, "sequence_orignal_image_text", wxStaticText);
87 m_imageTemplate = XRCCTRL(*this, "sequence_image_text", wxTextCtrl);
88 m_changeImageTemplate = XRCCTRL(*this, "sequence_change_image", wxButton);
90 m_changeAllImagesTemplate = XRCCTRL(*this, "sequence_change_all_images", wxButton);
92
93 m_spinCounterP_offset = XRCCTRL(*this, "sequence_p_offset", wxSpinCtrl);
95 m_spinCounterP_step = XRCCTRL(*this, "sequence_p_step", wxSpinCtrl);
97 m_spinCounterP_end = XRCCTRL(*this, "sequence_p_end", wxSpinCtrl);
99 m_spinCounterI_offset = XRCCTRL(*this, "sequence_i_offset", wxSpinCtrl);
101 m_spinCounterI_step = XRCCTRL(*this, "sequence_i_step", wxSpinCtrl);
103 m_spinCounterI_end = XRCCTRL(*this, "sequence_i_end", wxSpinCtrl);
105 m_spinCounterX_offset = XRCCTRL(*this, "sequence_x_offset", wxSpinCtrl);
107 m_spinCounterX_step = XRCCTRL(*this, "sequence_x_step", wxSpinCtrl);
109 m_spinCounterX_end = XRCCTRL(*this, "sequence_x_end", wxSpinCtrl);
111
112 wxCommandEvent dummy;
114 // UpdateCounters();
115
116 //set parameters
117 wxConfigBase* config = wxConfigBase::Get();
118 // restore position and size
119 hugin_utils::RestoreFramePosition(this, "GenerateSequenceDialog");
120 m_imagesListCtrl->SetColumnWidth(0, config->Read("/GenerateSequenceDialog/ImageListColumn0Width", 200l));
121 m_imagesListCtrl->SetColumnWidth(1, config->Read("/GenerateSequenceDialog/ImageListColumn1Width", 200l));
122 XRCCTRL(*this, "sequence_naming", wxChoice)->SetSelection(config->Read("/GenerateSequenceDialog/NamingConvention", 0l));
123 };
124 XRCCTRL(*this, "sequence_counter_help", wxTextCtrl)->SetBackgroundColour(this->GetBackgroundColour());
125 Bind(wxEVT_BUTTON, &GenerateSequenceDialog::OnSelectBasePath, this, XRCID("sequence_select_base_path"));
126 Bind(wxEVT_BUTTON, &GenerateSequenceDialog::OnGeneratePreview, this, XRCID("sequence_generate_preview"));
127 Bind(wxEVT_BUTTON, &GenerateSequenceDialog::OnGenerateStitchingPanorama, this, XRCID("sequence_generate_stitching"));
128 Bind(wxEVT_BUTTON, &GenerateSequenceDialog::OnGenerateAssistantPanorama, this, XRCID("sequence_generate_assistant"));
129
130};
131
133{
134 wxConfigBase* config=wxConfigBase::Get();
135 hugin_utils::StoreFramePosition(this, "GenerateSequenceDialog");
136 config->Write("/GenerateSequenceDialog/ImageListColumn0Width", m_imagesListCtrl->GetColumnWidth(0));
137 config->Write("/GenerateSequenceDialog/ImageListColumn1Width", m_imagesListCtrl->GetColumnWidth(1));
138 config->Write("/GenerateSequenceDialog/NamingConvention", XRCCTRL(*this, "sequence_naming", wxChoice)->GetSelection());
139}
140
142{
143 return m_validPTO && m_pano.getNrOfImages() > 0;
144}
145
147{
148 std::ifstream prjfile((const char*)m_filename.mb_str(HUGIN_CONV_FILENAME));
149 if (prjfile.good())
150 {
152 int ptoVersion = 0;
153 if (newPano.loadPTScript(prjfile, ptoVersion, ""))
154 {
155 m_pano.setMemento(newPano);
156 m_validPTO = true;
157 for (size_t i = 0; i < m_pano.getNrOfImages(); ++i)
158 {
159 const wxString imageFilename(wxString(m_pano.getImage(i).getFilename().c_str(), HUGIN_CONV_FILENAME));
160 m_orignalFilenames.Add(imageFilename);
161 m_mappedFilenames.Add(imageFilename);
162 };
163 };
164 };
165}
166
168{
169 long selItem = -1;
170 if (m_imagesListCtrl->GetSelectedItemCount() > 0)
171 {
172 // remember selected item
174 };
175 m_imagesListCtrl->DeleteAllItems();
177 for (size_t i = 0; i < m_orignalFilenames.size(); ++i)
178 {
179 const size_t index = m_imagesListCtrl->GetItemCount();
180 m_imagesListCtrl->InsertItem(index, m_orignalFilenames[i]);
181 m_imagesListCtrl->SetItem(index, 1, m_mappedFilenames[i]);
182 };
183 // restore selected item
184 if (selItem != -1)
185 {
187 };
188}
189
191{
192 wxDirDialog dlg(this, _("Specify a directory to search for projects in"),
194 if (dlg.ShowModal() == wxID_OK)
195 {
196 m_basepath->SetValue(dlg.GetPath());
198 };
199}
200
202{
203 // show text ctrl only when "use name template" use selected
204 m_subDirTextCtrl->Enable(m_choiceSubDir->GetSelection() == 2);
205 if (m_choiceSubDir->GetSelection() != 2)
206 {
207 // clear input wxTextCtrl if not used
208 m_subDirTextCtrl->Clear();
209 };
210 if (m_choiceSubDir->GetSelection() == 1)
211 {
212 // get list of all sub-directories
214 m_subDirCount = subDirs.size();
215 }
216 else
217 {
218 m_subDirCount = 0;
219 };
221}
222
224{
225 if (m_imagesListCtrl->GetSelectedItemCount() > 0)
226 {
227 // enable all controls
228 // if one image is selected in list control
229 m_imageTemplate->Enable(true);
230 m_changeImageTemplate->Enable(true);
231 m_changeAllImagesTemplate->Enable(true);
232 // set text
233 long item = -1;
237 }
238 else
239 {
240 // no item selected, disable all related ctrl
241 m_imageTemplate->Enable(false);
242 m_changeImageTemplate->Enable(false);
243 m_changeAllImagesTemplate->Enable(false);
244 }
245}
246
248{
249 if (m_imagesListCtrl->GetSelectedItemCount() > 0)
250 {
251 // find selected item
252 long item = -1;
254 // now update value
257 }
258 else
259 {
260 wxBell();
261 };
262}
263
265{
266 for (size_t i = 0; i < m_mappedFilenames.size(); ++i)
267 {
268 // update values
269 m_mappedFilenames[i] = m_imageTemplate->GetValue();
270 };
272}
273
278
280{
281 // update %p counter
282 size_t pano_count;
283 if (m_choiceSubDir->GetSelection() == 1)
284 {
285 // iterate all sub-directories selected
286 m_spinCounterP_end->Enable(false);
288 if (pano_count > 0)
289 {
290 m_spinCounterP_end->SetValue(m_spinCounterP_offset->GetValue() + m_spinCounterI_step->GetValue() * (pano_count - 1));
291 }
292 else
293 {
294 m_spinCounterP_end->SetValue(m_spinCounterP_offset->GetValue());
295 };
296 }
297 else
298 {
299 m_spinCounterP_end->Enable(true);
300 m_spinCounterP_end->SetRange(m_spinCounterP_offset->GetValue(), m_spinCounterP_end->GetMax());
301 if (m_spinCounterP_end->GetValue() < m_spinCounterP_offset->GetValue())
302 {
303 m_spinCounterP_end->SetValue(m_spinCounterP_offset->GetValue());
304 };
305 pano_count = (m_spinCounterP_end->GetValue() - m_spinCounterP_offset->GetValue()) / m_spinCounterP_step->GetValue() + 1;
306 };
307 // update end value for image counter
308 m_spinCounterI_end->Enable(false);
309 m_spinCounterI_end->SetValue(m_spinCounterI_offset->GetValue() + m_spinCounterI_step->GetValue() * (m_pano.getNrOfImages() - 1));
310 // update end value for x counter
311 m_spinCounterX_end->Enable(false);
312 m_spinCounterX_end->SetValue(m_spinCounterX_offset->GetValue() + m_spinCounterX_step->GetValue() * (m_pano.getNrOfImages() * pano_count - 1));
313}
314
316{
317 // read all counter values
318 // first update all counters if necessary
320 const size_t pano_offset = m_spinCounterP_offset->GetValue();
321 const size_t pano_step = m_spinCounterP_step->GetValue();
322 const size_t pano_end = m_spinCounterP_end->GetValue();
323 const size_t pano_width = XRCCTRL(*this, "sequence_p_width", wxSpinCtrl)->GetValue();
324 const size_t img_offset = m_spinCounterI_offset->GetValue();
325 const size_t img_step = m_spinCounterI_step->GetValue();
326 const size_t img_width = XRCCTRL(*this, "sequence_i_width", wxSpinCtrl)->GetValue();
327 const size_t x_offset = m_spinCounterX_offset->GetValue();
328 const size_t x_step = m_spinCounterX_step->GetValue();
329 const size_t x_width = XRCCTRL(*this, "sequence_x_width", wxSpinCtrl)->GetValue();
330 const size_t pano_count = (pano_end - pano_offset) / pano_step + 1;
331 const size_t img_count = m_pano.getNrOfImages();
332 // generate list of all sub-directories
333 if (m_choiceSubDir->GetSelection() == 1)
334 {
336 if (panoSubDirs.IsEmpty())
337 {
338 wxBell();
339 return;
340 };
341 }
342 else
343 {
345 panoSubDirs.resize(pano_count);
346 if (!panoNameTemplate.IsEmpty())
347 {
348 size_t panoCounter = pano_offset;
349 for (size_t i = 0; i < pano_count; ++i, panoCounter += pano_step)
350 {
352 // replace placeholder
353 panoSubDirs[i].Replace("%p", GetNumberString(panoCounter, pano_width), true);
354 };
355 };
356 };
357 // now iterate all panoramas and generate file list
358 size_t panoCounter = pano_offset;
359 size_t xCounter = x_offset;
360 for (size_t i = 0; i < pano_count; ++i, panoCounter += pano_step)
361 {
363 currentPath.SetPath(m_basepath->GetValue());
364 if (!panoSubDirs[i].IsEmpty())
365 {
366 currentPath.AppendDir(panoSubDirs[i]);
367 };
368 size_t imgCounter = img_offset;
370 for (size_t j = 0; j < m_pano.getNrOfImages(); ++j, imgCounter += img_step, xCounter += x_step)
371 {
372 // replace all counter variables
374 // replace all placeholders
375 file.Replace("%p", GetNumberString(panoCounter, pano_width), true);
376 file.Replace("%i", GetNumberString(imgCounter, img_width), true);
377 file.Replace("%x", GetNumberString(xCounter, x_width), true);
378 wxFileName fileName(file);
379 fileName.MakeAbsolute(currentPath.GetPath());
380 panoFileList.Add(fileName.GetFullPath());
381 }
382 fileList.push_back(panoFileList);
383 };
384}
385
387{
391 .Parent(this)
392 .Text(_("Generating preview list. Please wait..."))
393 .Icon(GetIcon())
394 );
395 // generate a preview of all images in text form
397 std::vector<wxArrayString> fileList;
399 wxTextCtrl* preview = XRCCTRL(*this, "sequence_preview", wxTextCtrl);
400 preview->Clear();
402#ifdef __WXMSW__
403 const wxString linebreak("\r\n");
404#else
405 const wxString linebreak("\n");
406#endif
407 if (fileList.empty())
408 {
409 text.Append(_("No matching sub-directories found."));
410 }
411 else
412 {
413 // iterate above all panoramas
414 for (size_t i = 0; i < fileList.size(); ++i)
415 {
416 text.Append(wxString::Format(_("Panorama %d"), i));
417 text.Append(linebreak);
418 if (!subDirList[i].IsEmpty())
419 {
420 text.Append(wxString::Format(_("Sub-directory: %s"), subDirList[i].c_str()));
421 text.Append(linebreak);
422 };
423 // iterate above all files in current pano
424 bool missingFiles = false;
425 for (size_t j = 0; j < m_pano.getNrOfImages(); ++j)
426 {
427 text.Append("\t");
428 text.Append(fileList[i][j]);
429 if (!wxFileName::FileExists(fileList[i][j]))
430 {
431 missingFiles = true;
432 text.Append(" <-- ");
433 text.Append(_("File not found"));
434 };
435 text.Append(linebreak);
436 };
437 if (missingFiles)
438 {
439 text.Append("\t");
440 text.Append(_("This panorama will be skipped becaused of missing files."));
441 text.Append(linebreak);
442 };
443 };
444 };
445 preview->SetValue(text);
446}
447
452{
453 // check image sizes, and correct parameters if required.
455 for (unsigned int i = 0; i < newPano.getNrOfImages(); i++)
456 {
457 // check if image size is correct
460
461 // just keep the file name
462 newSrcImg.setFilename(oldSrcImg.getFilename());
463 if (oldSrcImg.getSize() != newSrcImg.getSize())
464 {
465 // adjust size properly.
466 newSrcImg.resize(oldSrcImg.getSize(), &vars[i]);
467 }
468 newPano.setSrcImage(i, newSrcImg);
469 }
470 // now update all possible linked variables
471 for (unsigned int i = 0; i < newPano.getNrOfImages(); ++i)
472 {
473 if (!vars[i].empty())
474 {
475 newPano.updateVariables(i, vars[i]);
476 };
477 };
478 // remove all control points, they are only valid for the original template
480}
481
485{
486 wxString mask;
487 projectFile.SetPath(basePath);
488 projectFile.SetExt("pto");
489 if (!projectFile.IsDirWritable())
490 {
491 return false;
492 };
493 switch (index)
494 {
495 case 0:
496 // panoramaXX.pto
497 mask = wxString::Format("panorama%d", currentIndex);
498 break;
499 case 1:
500 // First file - last file.pto
501 {
502 const wxFileName f1(wxString(pano.getImage(0).getFilename().c_str(), HUGIN_CONV_FILENAME));
503 const wxFileName f2(wxString(pano.getImage(pano.getNrOfImages() - 1).getFilename().c_str(), HUGIN_CONV_FILENAME));
504 mask = f1.GetName() + "-" + f2.GetName();
505 }
506 break;
507 case 2:
508 // Foldername.pto
509 {
511 if (folders.GetCount() == 0)
512 {
513 return false;
514 }
515 mask = folders.Last();
516 }
517 break;
518 case 3:
519 // Template from preferences
520 {
522 mask = newProject.GetName();
523 projectFile.SetName(mask);
524 };
525 break;
526 default:
527 mask = wxString::Format("panorama%d", currentIndex);
528 };
529
530 projectFile.SetName(mask);
531 if (projectFile.FileExists())
532 {
533 unsigned int i = 1;
534 mask = mask.Append("_%d");
535 projectFile.SetName(wxString::Format(mask, i));
536 while (projectFile.FileExists())
537 {
538 i++;
539 projectFile.SetName(wxString::Format(mask, i));
540 //security fall through
541 if (i > 1000)
542 {
543 return false;
544 };
545 };
546 };
547 return true;
548}
549
551{
555 .Parent(this)
556 .Text(_("Generating panorama files. Please wait..."))
557 .Icon(GetIcon())
558 );
560 std::vector<wxArrayString> fileList;
562 if (fileList.empty())
563 {
564 hugin_utils::HuginMessageBox(_("No matching sub-directories found."), _("PTBatcherGUI"), wxOK | wxICON_EXCLAMATION, this);
565 }
566 else
567 {
568 const wxString basePath = m_basepath->GetValue();
570
571 for (size_t i = 0; i < fileList.size(); ++i)
572 {
573 // check that all files exists
574 bool missingFiles = false;
575 for (size_t j = 0; j < m_pano.getNrOfImages(); ++j)
576 {
577 if (!wxFileName::FileExists(fileList[i][j]))
578 {
579 missingFiles = true;
580 break;
581 };
582 };
583 if (!missingFiles)
584 {
585 // now build the new panorama object
586 HuginBase::Panorama newPano;
587 bool allFilesReadable = true;
588 for (size_t j = 0; j < m_pano.getNrOfImages(); ++j)
589 {
591 image.setFilename(std::string(fileList[i][j].mb_str(HUGIN_CONV_FILENAME)));
592 if (!image.checkImageSizeKnown())
593 {
594 allFilesReadable = false;
595 break;
596 };
597 newPano.addImage(image);
598 };
600 {
603 // write to disc
605 if (!GetNewProjectFilename(XRCCTRL(*this, "sequence_naming", wxChoice)->GetSelection(), newGeneratedPano, basePath, projectFile, i))
606 {
607 break;
608 };
609 const std::string scriptString(projectFile.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
611 // all done, remember pto file name
612 ptoFileList.Add(projectFile.GetFullPath());
613 };
614 };
615 };
616 // all done, now add the pto files to queue
617 if (!ptoFileList.IsEmpty())
618 {
620 };
622 };
623}
624
629
wxArrayString GetAllSubDirectories(const wxString baseDir)
return a list of all sub-directories
bool GetNewProjectFilename(long index, const HuginBase::Panorama &pano, const wxString basePath, wxFileName &projectFile, unsigned int currentIndex)
generate filename from given settings and panorama append a number if file already exists
void ApplyTemplate(const HuginBase::Panorama &pano, HuginBase::Panorama &newPano)
copy the image files from pano to newPano -> this corresponds to apply the template newPano to pano t...
wxString GetNumberString(size_t x, size_t width)
return given number as string with given number of digits
Definition of GenerateSequenceDialog class.
void AddArrayToList(const wxArrayString &fileList, Project::Target target)
~GenerateSequenceDialog()
destructor, saves size and position
void FillImagesList()
fill the images list with current values
void ReadPTOFile()
read pto template from file
void OnUpdateCounters(wxSpinEvent &e)
update all spin controls with current numbers
void OnImageListSelected(wxListEvent &e)
image in list ctrl selected
void OnGenerateAssistantPanorama(wxCommandEvent &e)
generate assistant sequence button
void OnUpdateAllImagesTemplate(wxCommandEvent &e)
update images filename template for all images
void OnGeneratePreview(wxCommandEvent &e)
generate preview
void GenerateFileList(wxArrayString &panoSubDirs, std::vector< wxArrayString > &fileList)
generate a list of all panorama and images in panoramas
void OnGenerateStitchingPanorama(wxCommandEvent &e)
generate stitching sequence button
void DoGeneratePanorama(const Project::Target target)
generates all panoramas and add them to the batch queue with given queue target
void OnSelectBasePath(wxCommandEvent &e)
show select directory dialog
void OnUpdateImageTemplate(wxCommandEvent &e)
update image filename template on selected image
void OnSelectSubDir(wxCommandEvent &e)
select which sub-directory should be used
bool IsValidPanorama() const
return true if given template is a valid pto file, if not the dialog should not be used
void UpdateCounters()
update all counters, enable/disable end value and calculate end values
GenerateSequenceDialog(BatchFrame *batchframe, wxString xrcPrefix, wxString ptoFilename)
Constructor, read from xrc ressource; restore last uses settings, size and position.
Memento class for a Panorama object.
Definition Panorama.h:50
bool loadPTScript(std::istream &i, int &ptoVersion, const std::string &prefix="")
load a Hugin file
Model for a panorama.
Definition Panorama.h:153
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition Panorama.h:211
void setMemento(const PanoramaMemento &memento)
set the internal state
void setCtrlPoints(const CPVector &points)
set all control points (Ippei: Is this supposed to be 'add' method?)
Definition Panorama.cpp:449
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image
Definition Panorama.cpp:319
void setSrcImage(unsigned int nr, const SrcPanoImage &img)
set input image parameters
virtual void updateVariables(const VariableMapVector &vars)
Set the variables.
Definition Panorama.cpp:171
Panorama duplicate() const
duplicate the panorama
std::size_t getNrOfImages() const
number of images.
Definition Panorama.h:205
All variables of a source image.
bool checkImageSizeKnown()
check if the image size is known, if try to load the information from the file
void resize(const vigra::Size2D &size, VariableMap *potentialLinkedVars)
"resize" image, adjusts all distortion coefficients for usage with a source image of size size potent...
#define HUGIN_CONV_FILENAME
Definition platform.h:40
wxString getDefaultProjectName(const HuginBase::Panorama &pano, const wxString filenameTemplate)
gets the default project name, as defined in the preferences
#define DEBUG_ASSERT(cond)
Definition utils.h:80
std::vector< VariableMap > VariableMapVector
std::vector< ControlPoint > CPVector
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
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition utils.cpp:184
void RestoreFramePosition(wxTopLevelWindow *frame, const wxString &basename, const bool ignoreMaximize)
Definition wxutils.cpp:67
include file for the hugin project
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.