00001
00002
00025 #include <hugin_config.h>
00026 #include <hugin_version.h>
00027 #include "panoinc_WX.h"
00028 #include "panoinc.h"
00029
00030 #include <wx/wfstream.h>
00031
00032 #include <fstream>
00033 #include <sstream>
00034 #include <vigra/error.hxx>
00035 #include <vigra_ext/MultiThreadOperations.h>
00036 #include "PT/Panorama.h"
00037 #include "PT/utils.h"
00038 #include "base_wx/huginConfig.h"
00039 #include "base_wx/MyProgressDialog.h"
00040 #include "base_wx/MyExternalCmdExecDialog.h"
00041 #include "base_wx/platform.h"
00042 #include "base_wx/wxPlatform.h"
00043
00044 #include "RunStitchPanel.h"
00045
00046 #include "hugin/config_defaults.h"
00047
00048 using namespace vigra;
00049 using namespace PT;
00050 using namespace std;
00051 using namespace hugin_utils;
00052
00053
00054
00055
00056
00057
00058 enum
00059 {
00060 ID_Quit = 1,
00061 ID_About
00062 };
00063
00064
00065 BEGIN_EVENT_TABLE(RunStitchPanel, wxPanel)
00066 EVT_END_PROCESS(-1, RunStitchPanel::OnProcessTerminate)
00067 END_EVENT_TABLE()
00068
00069 RunStitchPanel::RunStitchPanel(wxWindow * parent)
00070 : wxPanel(parent)
00071 {
00072 m_paused=false;
00073 m_overwrite=false;
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 wxBoxSizer * topsizer = new wxBoxSizer( wxVERTICAL );
00090 m_execPanel = new MyExecPanel(this);
00091
00092 #ifdef __WXMSW__
00093
00094 this->SetBackgroundColour(m_execPanel->GetBackgroundColour());
00095 #endif
00096 topsizer->Add(m_execPanel, 1, wxEXPAND, 0);
00097 SetSizer( topsizer );
00098
00099 }
00100
00101 wxString getGNUMakeCmd(const wxString &args)
00102 {
00103 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
00104 wxString cmd = MacGetPathToBundledExecutableFile(CFSTR("gnumake"));
00105 if(cmd != wxT(""))
00106 {
00107 cmd = wxQuoteString(cmd);
00108 }
00109 else
00110 {
00111 wxMessageBox(wxString::Format(_("External program %s not found in the bundle, reverting to system path"), wxT("gnumake")), _("Error"));
00112 cmd = wxT("make");
00113 }
00114 cmd += wxT(" ") + args;
00115 #elif defined __FreeBSD__
00116 wxString cmd = wxT("gmake ") + args;
00117 #elif defined __WXMSW__
00118 wxString cmdExe;
00119 if(!wxGetEnv(wxT("ComSpec"),&cmdExe))
00120 cmdExe=wxT("cmd");
00121 wxString tempDir=wxConfigBase::Get()->Read(wxT("tempDir"),wxT(""));
00122 wxString cmd = cmdExe + wxString::Format(wxT(" /C \"chcp %d >NUL && "),GetACP());
00123
00124 if(tempDir.Len()>0)
00125 {
00126 cmd=cmd + wxT("set TEMP=")+tempDir + wxT(" && set TMP=") + tempDir + wxT(" && ");
00127 };
00128 cmd = cmd + wxT("\"") + getExePath(wxTheApp->argv[0])+wxT("\\make\" ") + args + wxT("\"");
00129 #else
00130 wxString cmd = wxT("make ") + args;
00131 #endif
00132 return cmd;
00133 };
00134
00135 bool RunStitchPanel::StitchProject(wxString scriptFile, wxString outname,
00136 HuginBase::PanoramaMakefilelibExport::PTPrograms progs)
00137 {
00138 DEBUG_TRACE("");
00139 wxFileName fname(scriptFile);
00140 if ( !fname.FileExists() ) {
00141 wxLogError( _("Could not open project file:") + scriptFile);
00142 return false;
00143 }
00144
00145 wxString pathToPTO;
00146 wxFileName::SplitPath(scriptFile, &pathToPTO, NULL, NULL);
00147 pathToPTO.Append(wxFileName::GetPathSeparator());
00148
00149 ifstream prjfile((const char *)scriptFile.mb_str(HUGIN_CONV_FILENAME));
00150 if (prjfile.bad()) {
00151 wxLogError( wxString::Format(_("could not open script : %s"), scriptFile.c_str()) );
00152 return false;
00153 }
00154 PT::Panorama pano;
00155 PT::PanoramaMemento newPano;
00156 int ptoVersion = 0;
00157 if (newPano.loadPTScript(prjfile, ptoVersion, (const char *)pathToPTO.mb_str(HUGIN_CONV_FILENAME))) {
00158 pano.setMemento(newPano);
00159 HuginBase::PanoramaOptions opts = pano.getOptions();
00160 if (ptoVersion < 2) {
00161
00162
00163 wxConfig* config = new wxConfig(wxT("hugin"));
00164 wxConfigBase::Set(config);
00165 opts.enblendOptions = wxConfigBase::Get()->Read(wxT("/Enblend/Args"), wxT(HUGIN_ENBLEND_ARGS)).mb_str(wxConvLocal);
00166 opts.enfuseOptions = wxConfigBase::Get()->Read(wxT("/Enfuse/Args"), wxT(HUGIN_ENFUSE_ARGS)).mb_str(wxConvLocal);
00167
00168 }
00169 opts.remapUsingGPU = wxConfigBase::Get()->Read(wxT("/Nona/UseGPU"), HUGIN_NONA_USEGPU) == 1;
00170 pano.setOptions(opts);
00171 } else {
00172 wxLogError( wxString::Format(_("error while parsing panotools script: %s"), scriptFile.c_str()) );
00173 return false;
00174 }
00175
00176 PanoramaOptions opts = pano.getOptions();
00177 opts.outputFormat = PanoramaOptions::TIFF_m;
00178 if (opts.enblendOptions.length() == 0) {
00179
00180
00181 wxConfig* config = new wxConfig(wxT("hugin"));
00182 wxConfigBase::Set(config);
00183 opts.enblendOptions = wxConfigBase::Get()->Read(wxT("/Enblend/Args"), wxT(HUGIN_ENBLEND_ARGS)).mb_str(wxConvLocal);
00184 }
00185 pano.setOptions(opts);
00186
00187 if (! wxIsAbsolutePath(outname)) {
00188 outname = wxGetCwd() + wxFileName::GetPathSeparator() + outname;
00189 }
00190
00191 DEBUG_DEBUG("output file specified is " << (const char *)outname.mb_str(wxConvLocal));
00192
00193 wxString basename;
00194 wxString outpath;
00195 wxFileName outputPrefix(outname);
00196 outpath = outputPrefix.GetPath();
00197 basename = outputPrefix.GetFullName();
00198
00199 UIntSet activeImgs = pano.getActiveImages();
00200
00201 wxString tempDir= wxConfigBase::Get()->Read(wxT("tempDir"),wxT(""));
00202 if(!tempDir.IsEmpty())
00203 if(tempDir.Last()!=wxFileName::GetPathSeparator())
00204 tempDir.Append(wxFileName::GetPathSeparator());
00205
00206 try {
00207 PanoramaOptions opts = pano.getOptions();
00208
00209
00210
00211
00212
00213
00214 m_currentPTOfn = wxFileName::CreateTempFileName(tempDir+wxT("huginpto_"));
00215 if(m_currentPTOfn.size() == 0) {
00216 wxLogError(_("Could not create temporary file"));
00217 }
00218 DEBUG_DEBUG("tmpPTOfn file: " << (const char *)m_currentPTOfn.mb_str(wxConvLocal));
00219
00220 ofstream script(m_currentPTOfn.mb_str(HUGIN_CONV_FILENAME));
00221 PT::UIntSet all;
00222 if (pano.getNrOfImages() > 0) {
00223 fill_set(all, 0, pano.getNrOfImages()-1);
00224 }
00225 pano.printPanoramaScript(script, pano.getOptimizeVector(), pano.getOptions(), all, false, "");
00226 script.close();
00227
00228
00229 wxFile makeFile;
00230
00231 m_currentMakefn = wxFileName::CreateTempFileName(tempDir+wxT("huginmk_"), &makeFile);
00232 if(m_currentMakefn.size() == 0) {
00233 wxLogError(_("Could not create temporary file"));
00234 return false;
00235 }
00236 DEBUG_DEBUG("makefn file: " << (const char *)m_currentMakefn.mb_str(wxConvLocal));
00237 ofstream makeFileStream(m_currentMakefn.mb_str(HUGIN_CONV_FILENAME));
00238 makeFile.Close();
00239 std::string resultFn(basename.mb_str(HUGIN_CONV_FILENAME));
00240 std::string tmpPTOfnC = (const char *) m_currentPTOfn.mb_str(HUGIN_CONV_FILENAME);
00241 wxConfigBase* config=wxConfigBase::Get();
00242 std::string tmpDir((config->Read(wxT("tempDir"),wxT(""))).mb_str(HUGIN_CONV_FILENAME));
00243 bool copyMetadata=config->Read(wxT("/output/useExiftool"),1l)==1l;
00244 int nrThreads=config->Read(wxT("/output/NumberOfThreads"),0l);
00245
00246 std::vector<std::string> outputFiles;
00247 HuginBase::PanoramaMakefilelibExport::createMakefile(pano,
00248 activeImgs,
00249 tmpPTOfnC,
00250 resultFn,
00251 progs,
00252 "",
00253 outputFiles,
00254 makeFileStream,
00255 tmpDir,
00256 copyMetadata,
00257 nrThreads);
00258 makeFileStream.close();
00259
00260
00261 wxString oldCWD = wxFileName::GetCwd();
00262 wxFileName::SetCwd(outpath);
00263
00264
00265 wxString overwrittenFiles;
00266 for(size_t i=0; i < outputFiles.size(); i++) {
00267 wxString fn(outputFiles[i].c_str(), wxConvLocal);
00268 if (wxFile::Exists(fn) ) {
00269 overwrittenFiles.Append(fn + wxT(" "));
00270 }
00271 }
00272 if (!m_overwrite && overwrittenFiles.size() > 0) {
00273 int overwriteret = wxMessageBox(_("Overwrite existing images?\n\n") + overwrittenFiles, _("Overwrite existing images"), wxYES_NO | wxICON_QUESTION);
00274
00275 if (overwriteret != wxYES) {
00276 DEBUG_DEBUG("Abort, do not overwrite images!");
00277 return false;
00278 }
00279 DEBUG_DEBUG("Overwrite existing images!");
00280 }
00281
00282 #if defined __WXMSW__
00283 wxString args = wxT("-f ") + wxQuoteFilename(m_currentMakefn) + wxT(" info test all clean");
00284 #else
00285 wxString args = wxT("-j1 -f ") + wxQuoteString(m_currentMakefn) + wxT(" info test all clean");
00286 #endif
00287
00288 wxString caption = wxString::Format(_("Stitching %s"), scriptFile.c_str());
00289
00290 wxString cmd=getGNUMakeCmd(args);
00291 if (m_execPanel->ExecWithRedirect(cmd) == -1) {
00292 wxMessageBox(wxString::Format(_("Error while stitching project\n%s"), cmd.c_str()),
00293 _("Error during stitching"), wxICON_ERROR | wxOK );
00294 }
00295 wxFileName::SetCwd(oldCWD);
00296 } catch (std::exception & e) {
00297 cerr << "caught exception: " << e.what() << std::endl;
00298 wxMessageBox(wxString(e.what(), wxConvLocal),
00299 _("Error during stitching"), wxICON_ERROR | wxOK );
00300 }
00301 return true;
00302 }
00303
00304 bool RunStitchPanel::DetectProject(wxString scriptFile,
00305 HuginBase::AssistantMakefilelibExport::AssistantPrograms progs)
00306 {
00307 m_currentPTOfn=wxEmptyString;
00308 wxFileName fname(scriptFile);
00309 if ( !fname.FileExists() ) {
00310 wxLogError( _("Could not open project file:") + scriptFile);
00311 return false;
00312 }
00313
00314
00315 ifstream prjfile((const char *)scriptFile.mb_str(HUGIN_CONV_FILENAME));
00316 if (prjfile.bad())
00317 {
00318 wxLogError( wxString::Format(_("could not open script : %s"), scriptFile.c_str()));
00319 return false;
00320 }
00321 PT::Panorama pano;
00322 PT::PanoramaMemento newPano;
00323 int ptoVersion = 0;
00324 if (!newPano.loadPTScript(prjfile, ptoVersion))
00325 {
00326 wxLogError(wxString::Format(_("error while parsing panotools script: %s"), scriptFile.c_str()));
00327 return false;
00328 }
00329 pano.setMemento(newPano);
00330
00331
00332 wxConfig config(wxT("hugin"));
00333 bool runCeleste=config.Read(wxT("/Celeste/Auto"), HUGIN_CELESTE_AUTO)!=0;
00334 double celesteThreshold;
00335 config.Read(wxT("/Celeste/Threshold"), &celesteThreshold, HUGIN_CELESTE_THRESHOLD);
00336 bool celesteSmall=config.Read(wxT("/Celeste/Filter"), HUGIN_CELESTE_FILTER)!=0;
00337 bool runLinefind=config.Read(wxT("/Assistant/Linefind"), HUGIN_ASS_LINEFIND)!=0;
00338 bool runCPClean=config.Read(wxT("/Assistant/AutoCPClean"), HUGIN_ASS_AUTO_CPCLEAN)!=0;
00339 double scale;
00340 config.Read(wxT("/Assistant/panoDownsizeFactor"), &scale, HUGIN_ASS_PANO_DOWNSIZE_FACTOR);
00341 int scalei=roundi(scale*100);
00342 wxString tempDir= config.Read(wxT("tempDir"),wxT(""));
00343 if(!tempDir.IsEmpty())
00344 if(tempDir.Last()!=wxFileName::GetPathSeparator())
00345 tempDir.Append(wxFileName::GetPathSeparator());
00346
00347 try {
00348
00349 m_currentMakefn=wxFileName::CreateTempFileName(tempDir+wxT("ham"));
00350 if(m_currentMakefn.size() == 0)
00351 {
00352 wxLogError(_("Could not create temporary file"));
00353 return false;
00354 }
00355 std::ofstream makefile(m_currentMakefn.mb_str(HUGIN_CONV_FILENAME));
00356 makefile.exceptions( std::ofstream::eofbit | std::ofstream::failbit | std::ofstream::badbit );
00357 std::string scriptString(scriptFile.mb_str(HUGIN_CONV_FILENAME));
00358 HuginBase::AssistantMakefilelibExport::createMakefile(pano,progs,runLinefind,runCeleste,celesteThreshold,celesteSmall,
00359 runCPClean,scale,makefile,scriptString);
00360 makefile.close();
00361
00362
00363 wxString args = wxT("-f ") + wxQuoteFilename(m_currentMakefn) + wxT(" all");
00364 wxString cmd=getGNUMakeCmd(args);
00365 wxFileName path(scriptFile);
00366 path.MakeAbsolute();
00367 wxString oldcwd=path.GetCwd();
00368 path.SetCwd();
00369 if (m_execPanel->ExecWithRedirect(cmd) == -1)
00370 {
00371 wxMessageBox(wxString::Format(_("Error while running assistant\n%s"), cmd.c_str()),
00372 _("Error during running assistant"), wxICON_ERROR | wxOK );
00373 }
00374 wxFileName::SetCwd(oldcwd);
00375 }
00376 catch (std::exception & e)
00377 {
00378 cerr << "caught exception: " << e.what() << std::endl;
00379 wxMessageBox(wxString(e.what(), wxConvLocal),
00380 _("Error during running assistant"), wxICON_ERROR | wxOK );
00381 }
00382 return true;
00383 }
00384
00385 void RunStitchPanel::OnProcessTerminate(wxProcessEvent & event)
00386 {
00387 DEBUG_TRACE("");
00388
00389
00390
00391 #ifndef DEBUG
00392 if(!m_currentMakefn.IsEmpty())
00393 {
00394 wxRemoveFile(m_currentMakefn);
00395 };
00396 if(!m_currentPTOfn.IsEmpty())
00397 {
00398 wxRemoveFile(m_currentPTOfn);
00399 };
00400 #endif
00401
00402 if (this->GetParent()) {
00403 event.SetEventObject( this );
00404 DEBUG_TRACE("Sending wxProcess event");
00405 this->GetParent()->GetEventHandler()->ProcessEvent( event );
00406 }
00407
00408 }
00409
00410 void RunStitchPanel::CancelStitch()
00411 {
00412 DEBUG_TRACE("");
00413 m_execPanel->KillProcess();
00414 }
00415
00416 bool RunStitchPanel::IsPaused()
00417 {
00418 return m_paused;
00419 }
00420
00421 void RunStitchPanel::SetOverwrite(bool over)
00422 {
00423 m_overwrite = over;
00424 }
00425
00426 void RunStitchPanel::PauseStitch()
00427 {
00428 m_paused=true;
00429 m_execPanel->PauseProcess();
00430 }
00431
00432 void RunStitchPanel::ContinueStitch()
00433 {
00434 m_execPanel->ContinueProcess();
00435 m_paused=false;
00436 }
00437
00438 long RunStitchPanel::GetPid()
00439 {
00440 return m_execPanel->GetPid();
00441 }
00442
00443 bool RunStitchPanel::SaveLog(const wxString &filename)
00444 {
00445 return m_execPanel->SaveLog(filename);
00446 };