LensCalFrame.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00011 /* 
00012  *  This program is free software; you can redistribute it and/or
00013  *  modify it under the terms of the GNU General Public
00014  *  License as published by the Free Software Foundation; either
00015  *  version 2 of the License, or (at your option) any later version.
00016  *
00017  *  This software is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  *  General Public License for more details.
00021  *
00022  *  You should have received a copy of the GNU General Public
00023  *  License along with this software; if not, write to the Free Software
00024  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025  *
00026  */
00027 
00028 #include "panoinc_WX.h"
00029 #include "panoinc.h"
00030 
00031 #include "base_wx/platform.h"
00032 #include "base_wx/wxPlatform.h"
00033 #include "base_wx/LensTools.h"
00034 #include "huginapp/ImageCache.h"
00035 #include "LensCalFrame.h"
00036 #include <wx/app.h>
00037 #include "LensCalApp.h"
00038 #include "hugin/config_defaults.h"
00039 #include <algorithms/optimizer/PTOptimizer.h>
00040 #include "lensdb/LensDB.h"
00041 #include "base_wx/wxLensDB.h"
00042 
00043 using namespace HuginBase;
00044 
00045 const unsigned int cps_per_line=10;
00046 
00047 #define DEFAULT_LENSCAL_SCALE 2.0
00048 #define DEFAULT_LENSCAL_THRESHOLD 4.0
00049 #define DEFAULT_RESIZE_DIMENSION 1600
00050 #define DEFAULT_MINLINELENGTH 0.3
00051 
00052 // utility functions
00053 bool str2double(wxString s, double & d)
00054 {
00055     if (!hugin_utils::stringToDouble(std::string(s.mb_str(wxConvLocal)), d)) 
00056     {
00057         return false;
00058     }
00059     return true;
00060 }
00061 
00063 bool FileDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
00064 {
00065     DEBUG_TRACE("OnDropFiles");
00066     LensCalFrame* frame=wxGetApp().GetLensCalFrame();
00067     if (!frame) 
00068         return false;
00069 
00070     // try to add as images
00071     wxArrayString files;
00072     wxArrayString invalidFiles;
00073     for (unsigned int i=0; i< filenames.GetCount(); i++)
00074     {
00075         wxFileName file(filenames[i]);
00076         if (file.GetExt().CmpNoCase(wxT("jpg")) == 0 ||
00077             file.GetExt().CmpNoCase(wxT("jpeg")) == 0 ||
00078             file.GetExt().CmpNoCase(wxT("tif")) == 0 ||
00079             file.GetExt().CmpNoCase(wxT("tiff")) == 0 ||
00080             file.GetExt().CmpNoCase(wxT("png")) == 0 ||
00081             file.GetExt().CmpNoCase(wxT("bmp")) == 0 ||
00082             file.GetExt().CmpNoCase(wxT("gif")) == 0 ||
00083             file.GetExt().CmpNoCase(wxT("pnm")) == 0 ||
00084             file.GetExt().CmpNoCase(wxT("sun")) == 0 ||
00085             file.GetExt().CmpNoCase(wxT("hdr")) == 0 ||
00086             file.GetExt().CmpNoCase(wxT("viff")) == 0 )
00087         {
00088             if(containsInvalidCharacters(file.GetFullPath()))
00089             {
00090                 invalidFiles.push_back(file.GetFullPath());
00091             }
00092             else
00093             {
00094                 files.push_back(file.GetFullPath());
00095             };
00096         }
00097     }
00098     if(invalidFiles.size()>0)
00099     {
00100         ShowFilenameWarning(frame, invalidFiles);
00101     }
00102     // we got some images to add.
00103     if (files.size() > 0)
00104     {
00105         // use a Command to ensure proper undo and updating of GUI parts
00106         frame->AddImages(files);
00107     }
00108     return true;
00109 }
00110 
00111 // event table. this frame will recieve mostly global commands.
00112 BEGIN_EVENT_TABLE(LensCalFrame, wxFrame)
00113     EVT_LISTBOX(XRCID("lenscal_images_list"), LensCalFrame::OnImageSelected)
00114     EVT_MENU(XRCID("menu_save"), LensCalFrame::OnSaveProject)
00115     EVT_MENU(XRCID("menu_quit"), LensCalFrame::OnExit)
00116     EVT_BUTTON(XRCID("lenscal_add_image"), LensCalFrame::OnAddImage)
00117     EVT_BUTTON(XRCID("lenscal_remove_image"), LensCalFrame::OnRemoveImage)
00118     EVT_BUTTON(XRCID("lenscal_find_lines"), LensCalFrame::OnFindLines)
00119     EVT_BUTTON(XRCID("lenscal_reset"), LensCalFrame::OnReset)
00120     EVT_BUTTON(XRCID("lenscal_opt"), LensCalFrame::OnOptimize)
00121     EVT_BUTTON(XRCID("lenscal_save_lens"), LensCalFrame::OnSaveLens)
00122     EVT_BUTTON(XRCID("lenscal_refresh"), LensCalFrame::OnRefresh)
00123     EVT_CHOICE(XRCID("lenscal_preview_content"), LensCalFrame::OnSelectPreviewContent)
00124     EVT_CHECKBOX(XRCID("lenscal_show_lines"), LensCalFrame::OnShowLines)
00125 END_EVENT_TABLE()
00126 
00127 LensCalFrame::LensCalFrame(wxWindow* parent)
00128 {
00129     DEBUG_TRACE("");
00130     // load our children. some children might need special
00131     // initialization. this will be done later.
00132     wxXmlResource::Get()->LoadFrame(this, parent, wxT("lenscal_frame"));
00133     DEBUG_TRACE("");
00134 
00135     // load our menu bar
00136 #ifdef __WXMAC__
00137     wxApp::s_macExitMenuItemId = XRCID("menu_quit");
00138 #endif
00139     SetMenuBar(wxXmlResource::Get()->LoadMenuBar(this, wxT("lenscal_menubar")));
00140 
00141     m_choice_projection=XRCCTRL(*this,"lenscal_proj_choice",wxChoice);
00142     FillLensProjectionList(m_choice_projection);
00143     m_images_list=XRCCTRL(*this,"lenscal_images_list",wxListBox);
00144     m_preview=XRCCTRL(*this,"lenscal_preview",LensCalImageCtrl);
00145 
00146     wxConfigBase* config = wxConfigBase::Get();
00147     config->Read(wxT("/LensCalFrame/EdgeScale"),&m_edge_scale,DEFAULT_LENSCAL_SCALE);
00148     config->Read(wxT("/LensCalFrame/EdgeThreshold"),&m_edge_threshold,DEFAULT_LENSCAL_THRESHOLD);
00149     m_resize_dimension=config->Read(wxT("/LensCalFrame/ResizeDimension"),DEFAULT_RESIZE_DIMENSION);
00150     config->Read(wxT("/LensCalFrame/MinLineLength"),&m_minlinelength,DEFAULT_MINLINELENGTH);
00151     ParametersToDisplay();
00152 
00153     bool selected;
00154     config->Read(wxT("/LensCalFrame/Optimize_a"),&selected,false);
00155     XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->SetValue(selected);
00156     config->Read(wxT("/LensCalFrame/Optimize_b"),&selected,true);
00157     XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->SetValue(selected);
00158     config->Read(wxT("/LensCalFrame/Optimize_c"),&selected,false);
00159     XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->SetValue(selected);
00160     config->Read(wxT("/LensCalFrame/Optimize_de"),&selected,false);
00161     XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->SetValue(selected);
00162 
00163     // set the minimize icon
00164 #ifdef __WXMSW__
00165     wxIcon myIcon(GetXRCPath() + wxT("data/hugin.ico"),wxBITMAP_TYPE_ICO);
00166 #else
00167     wxIcon myIcon(GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
00168 #endif
00169     SetIcon(myIcon);
00170     SetTitle(_("Hugin Lens calibration GUI"));
00171 
00172     // create a new drop handler. wxwindows deletes the automatically
00173     SetDropTarget(new FileDropTarget());
00174 
00175     // create a status bar
00176     const int fields (2);
00177     CreateStatusBar(fields);
00178     int widths[fields] = {-1, 85};
00179     SetStatusWidths( fields, &widths[0]);
00180 
00181     // Set sizing characteristics
00182     //set minumum size
00183 #if defined __WXMAC__ || defined __WXMSW__
00184     // a minimum nice looking size; smaller than this would clutter the layout.
00185     SetSizeHints(900, 675);
00186 #else
00187     // For ASUS eeePc
00188     SetSizeHints(780, 455); //set minumum size
00189 #endif
00190 
00191     // set progress display for image cache.
00192     ImageCache::getInstance().setProgressDisplay(this);
00193 #if defined __WXMSW__
00194     unsigned long long mem = HUGIN_IMGCACHE_UPPERBOUND;
00195     unsigned long mem_low = config->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND);
00196     unsigned long mem_high = config->Read(wxT("/ImageCache/UpperBoundHigh"), (long) 0);
00197     if (mem_high > 0) {
00198       mem = ((unsigned long long) mem_high << 32) + mem_low;
00199     }
00200     else {
00201       mem = mem_low;
00202     }
00203     ImageCache::getInstance().SetUpperLimit(mem);
00204 #else
00205     ImageCache::getInstance().SetUpperLimit(config->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND));
00206 #endif
00207     //disable buttons
00208     EnableButtons();
00209     XRCCTRL(*this,"lenscal_remove_image",wxButton)->Enable(false);
00210 }
00211 
00212 LensCalFrame::~LensCalFrame()
00213 {
00214     DEBUG_TRACE("dtor");
00215     m_preview->SetEmptyImage();
00216     ImageCache::getInstance().setProgressDisplay(0);
00217     delete & ImageCache::getInstance();
00218     // get the global config object
00219     wxConfigBase* config = wxConfigBase::Get();
00220     if(ReadInputs(false,true,false))
00221     {
00222         config->Write(wxT("/LensCalFrame/EdgeScale"),m_edge_scale);
00223         config->Write(wxT("/LensCalFrame/EdgeThreshold"),m_edge_threshold);
00224         config->Write(wxT("/LensCalFrame/ResizeDimension"),(int)m_resize_dimension);
00225         config->Write(wxT("/LensCalFrame/MinLineLength"),m_minlinelength);
00226     };
00227     config->Write(wxT("/LensCalFrame/Optimize_a"),XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->GetValue());
00228     config->Write(wxT("/LensCalFrame/Optimize_b"),XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->GetValue());
00229     config->Write(wxT("/LensCalFrame/Optimize_c"),XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->GetValue());
00230     config->Write(wxT("/LensCalFrame/Optimize_de"),XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->GetValue());
00231     StoreFramePosition(this, wxT("LensCalFrame"));
00232     config->Flush();
00233     //cleanup
00234     for(unsigned int i=0;i<m_images.size();i++)
00235     {
00236         delete m_images[i];
00237     };
00238     m_images.clear();
00239     LensDB::LensDB::Clean();
00240     DEBUG_TRACE("dtor end");
00241 }
00242 
00243 void LensCalFrame::ParametersToDisplay()
00244 {
00245     XRCCTRL(*this,"lenscal_scale",wxTextCtrl)->SetValue(doubleTowxString(m_edge_scale,2));
00246     XRCCTRL(*this,"lenscal_threshold",wxTextCtrl)->SetValue(doubleTowxString(m_edge_threshold,2));
00247     XRCCTRL(*this,"lenscal_resizedim",wxTextCtrl)->SetValue(wxString::Format(wxT("%d"),m_resize_dimension));
00248     XRCCTRL(*this,"lenscal_minlinelength",wxTextCtrl)->SetValue(doubleTowxString(m_minlinelength,2));
00249 };
00250 
00251 const wxString & LensCalFrame::GetXRCPath()
00252 {
00253      return wxGetApp().GetXRCPath();
00254 };
00255 
00256 void LensCalFrame::resetProgress(double max)
00257 {
00258     m_progressMax = max;
00259     m_progress = 0;
00260     m_progressMsg = wxT("");
00261 }
00262 
00263 bool LensCalFrame::increaseProgress(double delta)
00264 {
00265     m_progress += delta;
00266 
00267     // build the message:
00268     int percentage = (int) floor(m_progress/m_progressMax*100);
00269     if (percentage > 100) percentage = 100;
00270 
00271     return displayProgress();
00272 }
00273 
00274 bool LensCalFrame::increaseProgress(double delta, const std::string & msg)
00275 {
00276     m_progress += delta;
00277     m_progressMsg = wxString(msg.c_str(), wxConvLocal);
00278 
00279     return displayProgress();
00280 }
00281 
00282 
00283 void LensCalFrame::setMessage(const std::string & msg)
00284 {
00285     m_progressMsg = wxString(msg.c_str(), wxConvLocal);
00286 }
00287 
00288 bool LensCalFrame::displayProgress()
00289 {
00290     // build the message:
00291     int percentage = (int) floor(m_progress/m_progressMax*100);
00292     if (percentage > 100) percentage = 100;
00293 
00294     wxStatusBar *statbar = GetStatusBar();
00295     statbar->SetStatusText(wxString::Format(wxT("%s: %d%%"),m_progressMsg.c_str(), percentage),0);
00296 #ifdef __WXMSW__
00297     UpdateWindow(NULL);
00298 #endif
00299     return true;
00300 }
00301 
00303 void LensCalFrame::updateProgressDisplay()
00304 {
00305     wxString msg;
00306     // build the message:
00307     for (std::vector<AppBase::ProgressTask>::reverse_iterator it = tasks.rbegin();
00308                  it != tasks.rend(); ++it)
00309     {
00310         wxString cMsg;
00311         if (it->getProgress() > 0) {
00312             cMsg.Printf(wxT("%s %s [%3.0f%%]"),
00313                         wxString(it->getShortMessage().c_str(), wxConvLocal).c_str(),
00314                         wxString(it->getMessage().c_str(), wxConvLocal).c_str(),
00315                         100 * it->getProgress());
00316         } else {
00317             cMsg.Printf(wxT("%s %s"),wxString(it->getShortMessage().c_str(), wxConvLocal).c_str(),
00318                         wxString(it->getMessage().c_str(), wxConvLocal).c_str());
00319         }
00320         // append to main message
00321         if (it == tasks.rbegin()) {
00322             msg = cMsg;
00323         } else {
00324             msg.Append(wxT(" | "));
00325             msg.Append(cMsg);
00326         }
00327     }
00328     wxStatusBar *m_statbar = GetStatusBar();
00329     DEBUG_TRACE("Statusmb : " << msg.mb_str(wxConvLocal));
00330     m_statbar->SetStatusText(msg,0);
00331 
00332 #ifdef __WXMSW__
00333     UpdateWindow(NULL);
00334 #endif
00335 }
00336 
00337 void LensCalFrame::OnExit(wxCommandEvent &e)
00338 {
00339     Close();
00340 };
00341 
00342 void LensCalFrame::AddImages(wxArrayString files)
00343 {
00344     wxArrayString wrongSize;
00345     wxArrayString wrongExif;
00346     for (unsigned int i=0; i<files.GetCount(); i++)
00347     {
00348         ImageLineList* image=new ImageLineList(files[i]);
00349         //check input
00350         if(m_images.size()>0)
00351         {
00352             const HuginBase::SrcPanoImage* image0=m_images[0]->GetPanoImage();
00353             const HuginBase::SrcPanoImage* image1=image->GetPanoImage();
00354             if(image0->getSize()!=image1->getSize())
00355             {
00356                 wrongSize.push_back(files[i]);
00357                 delete image;
00358                 continue;
00359             };
00360             if(image0->hasEXIFread() && image1->hasEXIFread())
00361             {
00362                 if(image0->getExifMake()!=image1->getExifMake() ||
00363                     image0->getExifModel()!=image1->getExifModel() ||
00364                     image0->getExifFocalLength()!=image1->getExifFocalLength() ||
00365                     image0->getExifCropFactor()!=image1->getExifCropFactor())
00366                 {
00367                     //only show a warning, but continue processing
00368                     wrongExif.push_back(files[i]);
00369                 };
00370             };
00371         };
00372         m_images.push_back(image);
00373         SetStatusText(wxString::Format(_("Added %s"),image->GetFilename().c_str()));
00374         if(image->GetPanoImage()->hasEXIFread())
00375         {
00376             XRCCTRL(*this,"lenscal_focallength",wxTextCtrl)->SetValue( 
00377                 hugin_utils::doubleTowxString(image->GetPanoImage()->getExifFocalLength(),2)
00378                 );
00379             XRCCTRL(*this,"lenscal_cropfactor",wxTextCtrl)->SetValue(
00380                 hugin_utils::doubleTowxString(image->GetPanoImage()->getExifCropFactor(),2)
00381                 );
00382             SelectProjection(m_choice_projection,image->GetPanoImage()->getProjection());
00383         };
00384     }
00385     UpdateList(false);
00386     m_images_list->SetSelection(m_images_list->GetCount()-1);
00387     wxCommandEvent e;
00388     OnImageSelected(e);
00389     EnableButtons();
00390     if(wrongSize.size()>0)
00391     {
00392         wxString fileText;
00393         for(unsigned int i=0;i<wrongSize.size();i++)
00394         {
00395             wxFileName filename(wrongSize[i]);
00396             fileText.Append(filename.GetFullName());
00397             if(i<wrongSize.size()-1)
00398                 fileText.Append(wxT(", "));
00399         };
00400         wxMessageBox(wxString::Format(_("The size of the images (%s) does not match the already added image(s)."),fileText.c_str()),
00401             _("Error"),wxOK|wxICON_EXCLAMATION,this);
00402     };
00403     if(wrongExif.size()>0)
00404     {
00405         wxString fileText;
00406         for(unsigned int i=0;i<wrongExif.size();i++)
00407         {
00408             wxFileName filename(wrongExif[i]);
00409             fileText.Append(filename.GetFullName());
00410             if(i<wrongExif.size()-1)
00411                 fileText.Append(wxT(", "));
00412         };
00413         wxMessageBox(wxString::Format(_("The EXIF information of the added images (%s) is not consistent with the already added image(s).\nPlease check the image again, if you selected the correct images."),fileText.c_str()),
00414             _("Warning"),wxOK|wxICON_EXCLAMATION,this);
00415     };
00416 };
00417 
00418 void LensCalFrame::OnAddImage(wxCommandEvent &e)
00419 {
00420     wxConfigBase* config = wxConfigBase::Get();
00421     wxString path = config->Read(wxT("/actualPath"), wxT(""));
00422     wxFileDialog dlg(this,_("Add images"),
00423                      path, wxT(""),
00424                      HUGIN_WX_FILE_IMG_FILTER,
00425                      wxFD_OPEN | wxFD_MULTIPLE, wxDefaultPosition);
00426     dlg.SetDirectory(path);
00427 
00428     // remember the image extension
00429     wxString img_ext;
00430     if (config->HasEntry(wxT("lastImageType"))){
00431       img_ext = config->Read(wxT("lastImageType")).c_str();
00432     }
00433     if (img_ext == wxT("all images"))
00434       dlg.SetFilterIndex(0);
00435     else if (img_ext == wxT("jpg"))
00436       dlg.SetFilterIndex(1);
00437     else if (img_ext == wxT("tiff"))
00438       dlg.SetFilterIndex(2);
00439     else if (img_ext == wxT("png"))
00440       dlg.SetFilterIndex(3);
00441     else if (img_ext == wxT("hdr"))
00442       dlg.SetFilterIndex(4);
00443     else if (img_ext == wxT("exr"))
00444       dlg.SetFilterIndex(5);
00445     else if (img_ext == wxT("all files"))
00446       dlg.SetFilterIndex(6);
00447     DEBUG_INFO ( "Image extention: " << img_ext.mb_str(wxConvLocal) )
00448 
00449     // call the file dialog
00450     if (dlg.ShowModal() == wxID_OK)
00451     {
00452         // get the selections
00453         wxArrayString Pathnames;
00454         dlg.GetPaths(Pathnames);
00455 
00456         // save the current path to config
00457 #ifdef __WXGTK__
00458         //workaround a bug in GTK, see https://bugzilla.redhat.com/show_bug.cgi?id=849692 and http://trac.wxwidgets.org/ticket/14525
00459         config->Write(wxT("/actualPath"), wxPathOnly(Pathnames[0]));
00460 #else
00461         config->Write(wxT("/actualPath"), dlg.GetDirectory());
00462 #endif
00463 
00464         wxArrayString invalidFiles;
00465         for(unsigned int i=0;i<Pathnames.GetCount(); i++)
00466         {
00467             if(containsInvalidCharacters(Pathnames[i]))
00468             {
00469                 invalidFiles.push_back(Pathnames[i]);
00470             };
00471         };
00472         if(invalidFiles.size()>0)
00473         {
00474             ShowFilenameWarning(this, invalidFiles);
00475         }
00476         else
00477         {
00478             AddImages(Pathnames);
00479         };
00480         DEBUG_INFO ( wxString::Format(wxT("img_ext: %d"), dlg.GetFilterIndex()).mb_str(wxConvLocal) )
00481         // save the image extension
00482         switch ( dlg.GetFilterIndex() )
00483         {
00484             case 0: config->Write(wxT("lastImageType"), wxT("all images")); break;
00485             case 1: config->Write(wxT("lastImageType"), wxT("jpg")); break;
00486             case 2: config->Write(wxT("lastImageType"), wxT("tiff")); break;
00487             case 3: config->Write(wxT("lastImageType"), wxT("png")); break;
00488             case 4: config->Write(wxT("lastImageType"), wxT("hdr")); break;
00489             case 5: config->Write(wxT("lastImageType"), wxT("exr")); break;
00490             case 6: config->Write(wxT("lastImageType"), wxT("all files")); break;
00491         }
00492     }
00493     else
00494     {
00495         // nothing to open
00496         SetStatusText( _("Add Image: cancel"));
00497     }
00498     EnableButtons();
00499 };
00500 
00501 void LensCalFrame::UpdateListString(unsigned int index)
00502 {
00503     wxFileName file(m_images[index]->GetFilename());
00504     m_images_list->SetString(index,wxString::Format(_("%s (%d lines)"),file.GetFullName().c_str(),m_images[index]->GetNrOfValidLines()));
00505 };
00506 
00507 void LensCalFrame::UpdateList(bool restoreSelection)
00508 {
00509     int oldSelection=m_images_list->GetSelection();
00510     m_images_list->Clear();
00511     for(unsigned int i=0;i<m_images.size();i++)
00512     {
00513         wxFileName file(m_images[i]->GetFilename());
00514         wxString text=wxString::Format(_("%s (%d lines)"),file.GetFullName().c_str(),m_images[i]->GetNrOfValidLines());
00515         m_images_list->Append(text);
00516     };
00517     if(oldSelection!=wxNOT_FOUND && restoreSelection)
00518     {
00519         m_images_list->SetSelection(oldSelection);
00520     };
00521     wxCommandEvent e;
00522     OnImageSelected(e);
00523 };
00524 
00525 void LensCalFrame::OnRemoveImage(wxCommandEvent &e)
00526 {
00527     int selection=m_images_list->GetSelection();
00528     if(selection!=wxNOT_FOUND)
00529     {
00530         delete m_images[selection];
00531         m_images.erase(m_images.begin()+selection);
00532         ImageCache::getInstance().softFlush();
00533         UpdateList(false);
00534     }
00535     else
00536     {
00537         wxBell();
00538     };
00539     EnableButtons();
00540 };
00541 
00542 void LensCalFrame::EnableButtons()
00543 {
00544     bool enabling=m_images.size()>0;
00545     XRCCTRL(*this,"lenscal_find_lines",wxButton)->Enable(enabling);
00546     XRCCTRL(*this,"lenscal_opt",wxButton)->Enable(enabling);
00547     XRCCTRL(*this,"lenscal_save_lens",wxButton)->Enable(enabling);
00548     GetMenuBar()->Enable(XRCID("menu_save"),enabling);
00549 };
00550 
00551 bool LensCalFrame::ReadInputs(bool readFocalLength,bool readOptions,bool readLensParameter)
00552 {
00553     if(readFocalLength)
00554     {
00555         m_projection=(SrcPanoImage::Projection)GetSelectedProjection(m_choice_projection);
00556         if(!str2double(XRCCTRL(*this,"lenscal_focallength",wxTextCtrl)->GetValue(),m_focallength))
00557             return false;
00558         if(m_focallength<1)
00559             return false;
00560         if(!str2double(XRCCTRL(*this,"lenscal_cropfactor",wxTextCtrl)->GetValue(),m_cropfactor))
00561             return false;
00562         if(m_cropfactor<0.1)
00563             return false;
00564     }
00565     if(readOptions)
00566     {
00567         if(!str2double(XRCCTRL(*this,"lenscal_scale",wxTextCtrl)->GetValue(),m_edge_scale))
00568             return false;
00569         if(!str2double(XRCCTRL(*this,"lenscal_threshold",wxTextCtrl)->GetValue(),m_edge_threshold))
00570             return false;
00571         double resize_dim;
00572         if(!str2double(XRCCTRL(*this,"lenscal_resizedim",wxTextCtrl)->GetValue(),resize_dim))
00573             return false;
00574         if(resize_dim<100)
00575             return false;
00576         m_resize_dimension=(unsigned int)resize_dim;
00577         if(!str2double(XRCCTRL(*this,"lenscal_minlinelength",wxTextCtrl)->GetValue(),m_minlinelength))
00578             return false;
00579         if(m_minlinelength<=0 || m_minlinelength>1)
00580             return false;
00581     };
00582     if(readLensParameter)
00583     {
00584         if(!str2double(XRCCTRL(*this,"lenscal_a",wxTextCtrl)->GetValue(),m_a))
00585             return false;
00586         if(!str2double(XRCCTRL(*this,"lenscal_b",wxTextCtrl)->GetValue(),m_b))
00587             return false;
00588         if(!str2double(XRCCTRL(*this,"lenscal_c",wxTextCtrl)->GetValue(),m_c))
00589             return false;
00590         if(!str2double(XRCCTRL(*this,"lenscal_d",wxTextCtrl)->GetValue(),m_d))
00591             return false;
00592         if(!str2double(XRCCTRL(*this,"lenscal_e",wxTextCtrl)->GetValue(),m_e))
00593             return false;
00594     }
00595     return true;
00596 };
00597 
00598 void LensCalFrame::OnFindLines(wxCommandEvent &e)
00599 {
00600     if(!ReadInputs(true,true,false))
00601     {
00602         wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."),_("Warning"),wxOK | wxICON_INFORMATION, this);
00603         return;
00604     }
00605     m_preview->SetLens(m_projection,m_focallength,m_cropfactor);
00606     for(unsigned int i=0;i<m_images.size();i++)
00607     {
00608         std::string filename(m_images[i]->GetFilename().mb_str(HUGIN_CONV_FILENAME));
00609         ImageCache::EntryPtr img=ImageCache::getInstance().getImage(filename);
00610         double scale;
00611         SetStatusText(_("Detecting edges..."));
00612         m_images[i]->SetEdgeImage(HuginLines::detectEdges(*(img->get8BitImage()),m_edge_scale,m_edge_threshold,m_resize_dimension,scale));
00613         SetStatusText(_("Finding lines..."));
00614         m_images[i]->SetLines(HuginLines::findLines(*(m_images[i]->GetEdgeImage()),m_minlinelength,m_focallength,m_cropfactor));
00615         m_images[i]->ScaleLines(scale);
00616     };
00617     SetStatusText(_("Finished"));
00618     UpdateList(true);
00619 };
00620 
00621 void LensCalFrame::OnOptimize(wxCommandEvent &e)
00622 {
00623     if(!ReadInputs(true,false,true))
00624     {
00625         wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."),_("Warning"),wxOK | wxICON_INFORMATION, this);
00626         return;
00627     }
00628     unsigned int count=0;
00629     for(unsigned int i=0;i<m_images.size();i++)
00630         count+=m_images[i]->GetNrOfValidLines();
00631     if(count==0)
00632     {
00633         wxMessageBox(_("There are no detected lines.\nPlease run \"Find lines\" first. If there are no lines found, change the parameters."),_("Warning"),wxOK  | wxICON_INFORMATION, this);
00634         return;
00635     };
00636     Optimize();
00637 };
00638 
00639 Panorama LensCalFrame::GetPanorama()
00640 {
00641     HuginBase::Panorama pano;
00642     OptimizeVector optvec;
00643     unsigned int line_number=3; 
00644     for(unsigned int i=0;i<m_images.size();i++)
00645     {
00646         SrcPanoImage image(*(m_images[i]->GetPanoImage()));
00647         image.setProjection(m_projection);
00648         image.setExifFocalLength(m_focallength);
00649         image.setExifCropFactor(m_cropfactor);
00650         image.setVar("a",m_a);
00651         image.setVar("b",m_b);
00652         image.setVar("c",m_c);
00653         image.setVar("d",m_d);
00654         image.setVar("e",m_e);
00655         double hfov=SrcPanoImage::calcHFOV(image.getProjection(),image.getExifFocalLength(),image.getExifCropFactor(),image.getSize());
00656         image.setHFOV(hfov);
00657         pano.addImage(image);
00658         std::set<std::string> imgopt;
00659         if(i==0)
00660         {
00661             if(XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->GetValue())
00662                 imgopt.insert("a");
00663             if(XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->GetValue())
00664                 imgopt.insert("b");
00665             if(XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->GetValue())
00666                 imgopt.insert("c");
00667             if(XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->GetValue())
00668             {
00669                 imgopt.insert("d");
00670                 imgopt.insert("e");
00671             }
00672         };
00673         optvec.push_back(imgopt);
00674         //now generate control points from lines
00675         HuginLines::Lines lines=m_images[i]->GetLines();
00676         for(unsigned j=0;j<lines.size();j++)
00677         {
00678             if(lines[j].status==HuginLines::valid_line)
00679             {
00680                 HuginBase::CPVector cpv=GetControlPoints(lines[j],i,line_number,cps_per_line);
00681                 for(unsigned int k=0;k<cpv.size();k++)
00682                     pano.addCtrlPoint(cpv[k]);
00683                 line_number++;
00684             };
00685         };
00686     };
00687     //assign all images the same lens number
00688     StandardImageVariableGroups variable_groups(pano);
00689     ImageVariableGroup & lenses = variable_groups.getLenses();
00690     if(pano.getNrOfImages()>1)
00691     {
00692         for(unsigned int i=1;i<pano.getNrOfImages();i++)
00693         {
00694             SrcPanoImage img=pano.getSrcImage(i);
00695             lenses.switchParts(i,lenses.getPartNumber(0));
00696             lenses.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_ExposureValue, i);
00697             img.setExposureValue(0);
00698             lenses.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_WhiteBalanceRed, i);
00699             lenses.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_WhiteBalanceBlue, i);
00700             img.setWhiteBalanceRed(1);
00701             img.setWhiteBalanceBlue(1);
00702             pano.setSrcImage(i, img);
00703         };
00704     };
00705     //set default exposure value
00706     PanoramaOptions opts = pano.getOptions();
00707     opts.outputExposureValue = 0;
00708     opts.setProjection(HuginBase::PanoramaOptions::RECTILINEAR);
00709     pano.setOptions(opts);
00710 
00711     pano.setOptimizeVector(optvec);
00712     return pano;
00713 };
00714 
00715 void LensCalFrame::Optimize()
00716 {
00717     SetStatusText(_("Optimizing lens distortion parameters..."));
00718     Panorama pano=GetPanorama();
00719     HuginBase::PTools::optimize(pano);
00720 
00721     const SrcPanoImage img=pano.getImage(0);
00722     m_a=img.getVar("a");
00723     m_b=img.getVar("b");
00724     m_c=img.getVar("c");
00725     m_d=img.getVar("d");
00726     m_e=img.getVar("e");
00727     XRCCTRL(*this,"lenscal_a",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_a,5));
00728     XRCCTRL(*this,"lenscal_b",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_b,5));
00729     XRCCTRL(*this,"lenscal_c",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_c,5));
00730     XRCCTRL(*this,"lenscal_d",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_d,3));
00731     XRCCTRL(*this,"lenscal_e",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_e,3));
00732     m_preview->SetLensDistortions(m_a,m_b,m_c,m_d,m_e);
00733     SetStatusText(_("Finished"));
00734 };
00735 
00736 void LensCalFrame::SaveLensToIni()
00737 {
00738     wxFileDialog dlg(this,
00739                         _("Save lens parameters file"),
00740                         wxConfigBase::Get()->Read(wxT("/lensPath"),wxT("")), wxT(""),
00741                         _("Lens Project Files (*.ini)|*.ini|All files (*)|*"),
00742                         wxFD_SAVE, wxDefaultPosition);
00743     dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/lensPath"),wxT("")));
00744     if (dlg.ShowModal() == wxID_OK)
00745     {
00746         wxFileName filename(dlg.GetPath());
00747         if(!filename.HasExt())
00748             filename.SetExt(wxT("ini"));
00749         wxConfig::Get()->Write(wxT("/lensPath"), dlg.GetDirectory());  // remember for later
00750         if (filename.FileExists())
00751         {
00752             int d = wxMessageBox(wxString::Format(_("File %s exists. Overwrite?"), filename.GetFullPath().c_str()),
00753                                  _("Save project"), wxYES_NO | wxICON_QUESTION);
00754             if (d != wxYES)
00755             {
00756                 return;
00757             }
00758         }
00759         Panorama pano=GetPanorama();
00760         SaveLensParameters(filename.GetFullPath(),&pano,0);
00761     }
00762 };
00763 
00764 void LensCalFrame::OnSaveLens(wxCommandEvent &e)
00765 {
00766     if(!ReadInputs(true,false,true))
00767     {
00768         wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."),_("Warning"),wxOK | wxICON_INFORMATION, this);
00769         return;
00770     }
00771     unsigned int count=0;
00772     for(unsigned int i=0;i<m_images.size();i++)
00773         count+=m_images[i]->GetNrOfValidLines();
00774     if(count==0)
00775     {
00776         wxMessageBox(_("There are no detected lines.\nPlease run \"Find lines\" and \"Optimize\" before saving the lens data. If there are no lines found, change the parameters."),_("Warning"),wxOK  | wxICON_INFORMATION, this);
00777         return;
00778     };
00779 
00780     wxArrayString choices;
00781     choices.push_back(_("Save lens parameters to ini file"));
00782     choices.push_back(_("Save lens parameters to lensfun database"));
00783     wxSingleChoiceDialog save_dlg(this,_("Saving lens data"),_("Save lens"),choices);
00784     if(save_dlg.ShowModal()==wxID_OK)
00785     {
00786         if(save_dlg.GetSelection()==0)
00787         {
00788             SaveLensToIni();
00789         }
00790         else
00791         {
00792             Panorama pano=GetPanorama();
00793             SaveLensParameters(this,pano.getImage(0),false);
00794         };
00795     };
00796 };
00797 
00798 void LensCalFrame::OnSaveProject(wxCommandEvent &e)
00799 {
00800     if(!ReadInputs(true,false,true))
00801     {
00802         wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."),_("Warning"),wxOK | wxICON_INFORMATION, this);
00803         return;
00804     }
00805 
00806     wxFileDialog dlg(this,_("Save project file"),wxEmptyString,wxEmptyString,
00807                      _("Project files (*.pto)|*.pto|All files (*)|*"), wxFD_SAVE, wxDefaultPosition);
00808     dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")));
00809     if (dlg.ShowModal() == wxID_OK)
00810     {
00811         wxConfig::Get()->Write(wxT("/actualPath"), dlg.GetDirectory());  // remember for later
00812         wxFileName filename(dlg.GetPath());
00813         if(!filename.HasExt())
00814             filename.SetExt(wxT("pto"));
00815         if (filename.FileExists())
00816         {
00817             int d = wxMessageBox(wxString::Format(_("File %s exists. Overwrite?"), filename.GetFullPath().c_str()),
00818                                  _("Save project"), wxYES_NO | wxICON_QUESTION);
00819             if (d != wxYES)
00820             {
00821                 return;
00822             }
00823         }
00824         Panorama pano=GetPanorama();
00825         std::string path = getPathPrefix(std::string(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME)));
00826         std::ofstream script(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
00827         script.exceptions ( std::ofstream::eofbit | std::ofstream::failbit | std::ofstream::badbit );
00828         PT::UIntSet all;
00829         fill_set(all, 0, pano.getNrOfImages()-1);
00830         pano.printPanoramaScript(script, pano.getOptimizeVector(), pano.getOptions(), all, false, path);
00831         script.close();
00832     };
00833 };
00834 
00835 void LensCalFrame::OnImageSelected(wxCommandEvent &e)
00836 {
00837     bool selected=m_images_list->GetSelection()!=wxNOT_FOUND;
00838     XRCCTRL(*this,"lenscal_remove_image",wxButton)->Enable(selected);
00839     if(selected)
00840     {
00841         m_preview->SetImage(m_images[m_images_list->GetSelection()],m_images_list->GetSelection());
00842     }
00843     else
00844     {
00845         m_preview->SetEmptyImage();
00846     };
00847 };
00848 
00849 void LensCalFrame::OnSelectPreviewContent(wxCommandEvent &e)
00850 {
00851     m_preview->SetMode((LensCalImageCtrl::LensCalPreviewMode)e.GetSelection());
00852     XRCCTRL(*this,"lenscal_refresh",wxButton)->Enable(m_preview->GetMode()==LensCalImageCtrl::mode_corrected);
00853 };
00854 
00855 void LensCalFrame::OnShowLines(wxCommandEvent &e)
00856 {
00857     m_preview->SetShowLines(XRCCTRL(*this,"lenscal_show_lines",wxCheckBox)->GetValue());
00858     m_preview->Refresh(true);
00859 };
00860 
00861 void LensCalFrame::OnReset(wxCommandEvent &e)
00862 {
00863     m_edge_scale=DEFAULT_LENSCAL_SCALE;
00864     m_edge_threshold=DEFAULT_LENSCAL_THRESHOLD;
00865     m_resize_dimension=DEFAULT_RESIZE_DIMENSION;
00866     m_minlinelength=DEFAULT_MINLINELENGTH;
00867     ParametersToDisplay();
00868 };
00869 
00870 void LensCalFrame::OnRefresh(wxCommandEvent &e)
00871 {
00872     if(!ReadInputs(true,false,true))
00873     {
00874         wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."),_("Warning"),wxOK | wxICON_INFORMATION, this);
00875         return;
00876     }
00877     m_preview->SetLens(m_projection,m_focallength,m_cropfactor);
00878     m_preview->SetLensDistortions(m_a,m_b,m_c,m_d,m_e);
00879 };
00880 

Generated on 31 Oct 2014 for Hugintrunk by  doxygen 1.4.7