RunStitchPanel.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
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 // Implementation of stitch window
00056 
00057 // event ID's for RunStitchPanel
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     wxMenu *menuFile = new wxMenu;
00076 
00077     menuFile->AppendSeparator();
00078     menuFile->Append( ID_Quit, _("E&xit") );
00079 
00080     wxMenu *menuHelp = new wxMenu;
00081     menuHelp->Append( ID_About, _("&About...") );
00082 
00083     wxMenuBar *menuBar = new wxMenuBar;
00084     menuBar->Append( menuFile, _("&File") );
00085     menuBar->Append( menuHelp, _("&Help") );
00086     SetMenuBar( menuBar );
00087     */
00088 
00089     wxBoxSizer * topsizer = new wxBoxSizer( wxVERTICAL );
00090     m_execPanel = new MyExecPanel(this);
00091 
00092 #ifdef __WXMSW__
00093     // wxFrame does have a strange background color on Windows, copy color from a child widget
00094     this->SetBackgroundColour(m_execPanel->GetBackgroundColour());
00095 #endif
00096     topsizer->Add(m_execPanel, 1, wxEXPAND, 0);
00097     SetSizer( topsizer );
00098 //    topsizer->SetSizeHints( this );   // set size hints to honour minimum size
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     //explicit set temp path for make, e. g. in case user name contains an ampersand
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             // no options stored in file, use default arguments in config
00162                         
00163                         wxConfig* config = new wxConfig(wxT("hugin"));  //needed for PTBatcher console application
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     // get options and correct for correct makefile
00176     PanoramaOptions opts = pano.getOptions();
00177     opts.outputFormat = PanoramaOptions::TIFF_m;
00178     if (opts.enblendOptions.length() == 0) {
00179         // no options stored in file, use default arguments in config file
00180 
00181                 wxConfig* config = new wxConfig(wxT("hugin"));  //needed for PTBatcher console application
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     // make sure we got an absolute path
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     // stitch only active images
00199     UIntSet activeImgs = pano.getActiveImages();
00200     //get temp dir from preferences
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                 //preview image generation
00209                 /*opts.setHeight(150);
00210                 opts.setWidth(300);
00211                 opts.setROI(vigra::Rect2D(vigra::Size2D(300,150)));
00212                 pano.setOptions(opts);*/
00213         // copy pto file to temporary file
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         // copy is not enough, need to adjust image path names...
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         // produce suitable makefile
00228 
00229         wxFile makeFile;
00230         //TODO: change to implementatin with config->Read(wxT("tempDir"),wxT(""))
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         // cd to output directory, if one is given.
00261         wxString oldCWD = wxFileName::GetCwd();
00262         wxFileName::SetCwd(outpath);
00263         // check output directories.
00264         //std::vector<std::string> overwrittenFiles;
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             // TODO: change button label ok to overwrite
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     //read project file
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     //read settings
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         //generate makefile
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         //execute makefile
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         //if(!m_paused)
00389         //{
00390                 // delete temporary files
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                 // notify parent of exit
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 };

Generated on Wed Jul 16 01:25:30 2014 for Hugintrunk by  doxygen 1.3.9.1