LensTools.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00010 /*  This program is free software; you can redistribute it and/or
00011  *  modify it under the terms of the GNU General Public
00012  *  License as published by the Free Software Foundation; either
00013  *  version 2 of the License, or (at your option) any later version.
00014  *
00015  *  This software is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  *  General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public
00021  *  License along with this software. If not, see
00022  *  <http://www.gnu.org/licenses/>.
00023  *
00024  */
00025 
00026 #include "panoinc_WX.h"
00027 #include <wx/msgdlg.h>
00028 #include "panoinc.h"
00029 #include "LensTools.h"
00030 #include <algorithm>
00031 #include "panodata/ImageVariableTranslate.h"
00032 #include "panodata/StandardImageVariableGroups.h"
00033 #include "base_wx/PanoCommand.h"
00034 
00035 using namespace std;
00036 
00037 void FillLensProjectionList(wxControlWithItems* list)
00038 {
00039     list->Clear();
00040     list->Append(_("Normal (rectilinear)"),(void*)HuginBase::SrcPanoImage::RECTILINEAR);
00041     list->Append(_("Panoramic (cylindrical)"),(void*)HuginBase::SrcPanoImage::PANORAMIC);
00042     list->Append(_("Circular fisheye"),(void*)HuginBase::SrcPanoImage::CIRCULAR_FISHEYE);
00043     list->Append(_("Full frame fisheye"),(void*)HuginBase::SrcPanoImage::FULL_FRAME_FISHEYE);
00044     list->Append(_("Equirectangular"),(void*)HuginBase::SrcPanoImage::EQUIRECTANGULAR);
00045     list->Append(_("Orthographic"),(void*)HuginBase::SrcPanoImage::FISHEYE_ORTHOGRAPHIC);
00046     list->Append(_("Stereographic"),(void*)HuginBase::SrcPanoImage::FISHEYE_STEREOGRAPHIC);
00047     list->Append(_("Equisolid"),(void*)HuginBase::SrcPanoImage::FISHEYE_EQUISOLID);
00048     list->Append(_("Fisheye Thoby"),(void*)HuginBase::SrcPanoImage::FISHEYE_THOBY);
00049     list->SetSelection(0);
00050 };
00051 
00052 void FillBlenderList(wxControlWithItems* list)
00053 {
00054     list->Clear();
00055     list->Append(_("enblend"), (void*)HuginBase::PanoramaOptions::ENBLEND_BLEND);
00056     list->Append(_("builtin"), (void*)HuginBase::PanoramaOptions::INTERNAL_BLEND);
00057     list->SetSelection(0);
00058 };
00059 
00060 void SelectListValue(wxControlWithItems* list, size_t newValue)
00061 {
00062     for(unsigned int i=0;i<list->GetCount();i++)
00063     {
00064         if((size_t)list->GetClientData(i)==newValue)
00065         {
00066             list->SetSelection(i);
00067             return;
00068         };
00069     };
00070     list->SetSelection(0);
00071 };
00072 
00073 size_t GetSelectedValue(wxControlWithItems* list)
00074 {
00075     return (size_t)(list->GetClientData(list->GetSelection()));
00076 };
00077 
00078 wxString getProjectionString(const HuginBase::SrcPanoImage& img)
00079 {
00080     wxString ps;
00081     switch (img.getProjection())
00082     {
00083     case HuginBase::SrcPanoImage::RECTILINEAR:          ps << _("Normal (rectilinear)"); break;
00084     case HuginBase::SrcPanoImage::PANORAMIC:            ps << _("Panoramic (cylindrical)"); break;
00085     case HuginBase::SrcPanoImage::CIRCULAR_FISHEYE:     ps << _("Circular fisheye"); break;
00086     case HuginBase::SrcPanoImage::FULL_FRAME_FISHEYE:   ps << _("Full frame fisheye"); break;
00087     case HuginBase::SrcPanoImage::EQUIRECTANGULAR:      ps << _("Equirectangular"); break;
00088     case HuginBase::SrcPanoImage::FISHEYE_ORTHOGRAPHIC: ps << _("Orthographic"); break;
00089     case HuginBase::SrcPanoImage::FISHEYE_STEREOGRAPHIC:ps << _("Stereographic"); break;
00090     case HuginBase::SrcPanoImage::FISHEYE_EQUISOLID:    ps << _("Equisolid"); break;
00091     case HuginBase::SrcPanoImage::FISHEYE_THOBY:        ps << _("Fisheye Thoby"); break;
00092     }
00093     return ps;
00094 };
00095 
00096 wxString getResponseString(const HuginBase::SrcPanoImage& img)
00097 {
00098     wxString s;
00099     switch (img.getResponseType())
00100     {
00101     case HuginBase::BaseSrcPanoImage::RESPONSE_EMOR:
00102         s = _("custom (EMoR)");
00103         break;
00104     case HuginBase::BaseSrcPanoImage::RESPONSE_LINEAR:
00105         s = _("Linear");
00106         break;
00107     };
00108     return s;
00109 };
00110 
00111 void SaveLensParameters(const wxString filename, HuginBase::Panorama* pano, unsigned int imgNr)
00112 {
00113     HuginBase::StandardImageVariableGroups variable_groups(*pano);
00114     const HuginBase::Lens & lens = variable_groups.getLensForImage(imgNr);
00115     const HuginBase::VariableMap & vars = pano->getImageVariables(imgNr);
00116     // get the variable map
00117     char * p = setlocale(LC_NUMERIC,NULL);
00118     char * old_locale = strdup(p);
00119     setlocale(LC_NUMERIC,"C");
00120     wxFileConfig cfg(wxT("hugin lens file"),wxT(""),filename);
00121     cfg.Write(wxT("Lens/image_width"), (long) lens.getImageSize().x);
00122     cfg.Write(wxT("Lens/image_height"), (long) lens.getImageSize().y);
00123     cfg.Write(wxT("Lens/type"), (long) lens.getProjection());
00124     cfg.Write(wxT("Lens/hfov"), const_map_get(vars,"v").getValue());
00125     cfg.Write(wxT("Lens/hfov_link"), const_map_get(lens.variables,"v").isLinked() ? 1:0);
00126     cfg.Write(wxT("Lens/crop"), lens.getCropFactor());
00127 
00128     // loop to save lens variables
00129     const char ** varname = HuginBase::Lens::variableNames;
00130     while (*varname)
00131     {
00132         //ignore exposure value and hfov, hfov is separately handled by the code above
00133         if (string(*varname) == "Eev" || string(*varname) == "v")
00134         {
00135             varname++;
00136             continue;
00137         }
00138         wxString key(wxT("Lens/"));
00139         key.append(wxString(*varname, wxConvLocal));
00140         cfg.Write(key, const_map_get(vars,*varname).getValue());
00141         key.append(wxT("_link"));
00142         cfg.Write(key, const_map_get(lens.variables,*varname).isLinked() ? 1:0);
00143         varname++;
00144     }
00145 
00146     const HuginBase::SrcPanoImage & image = pano->getImage(imgNr);
00147     cfg.Write(wxT("Lens/crop/enabled"), image.getCropMode()==HuginBase::SrcPanoImage::NO_CROP ? 0l : 1l);
00148     cfg.Write(wxT("Lens/crop/autoCenter"), image.getAutoCenterCrop() ? 1l : 0l);
00149     const vigra::Rect2D cropRect=image.getCropRect();
00150     cfg.Write(wxT("Lens/crop/left"), cropRect.left());
00151     cfg.Write(wxT("Lens/crop/top"), cropRect.top());
00152     cfg.Write(wxT("Lens/crop/right"), cropRect.right());
00153     cfg.Write(wxT("Lens/crop/bottom"), cropRect.bottom());
00154 
00155     if (!image.getExifMake().empty() && !image.getExifModel().empty() && image.getExifFocalLength()>0)
00156     {
00157         // write exif data to ini file
00158         cfg.Write(wxT("EXIF/CameraMake"),  wxString(image.getExifMake().c_str(), wxConvLocal));
00159         cfg.Write(wxT("EXIF/CameraModel"), wxString(image.getExifModel().c_str(), wxConvLocal));
00160         cfg.Write(wxT("EXIF/FocalLength"), image.getExifFocalLength());
00161         cfg.Write(wxT("EXIF/Aperture"), image.getExifAperture());
00162         cfg.Write(wxT("EXIF/ISO"), image.getExifISO());
00163         cfg.Write(wxT("EXIF/CropFactor"), image.getCropFactor()); 
00164         cfg.Write(wxT("EXIF/Distance"), image.getExifDistance()); 
00165     }
00166     cfg.Flush();
00167 
00168     // reset locale
00169     setlocale(LC_NUMERIC,old_locale);
00170     free(old_locale);
00171 };
00172 
00173 bool ApplyLensParameters(wxWindow * parent, HuginBase::Panorama *pano, HuginBase::UIntSet images, PanoCommand::PanoCommand*& cmd)
00174 {
00175     HuginBase::StandardImageVariableGroups variable_groups(*pano);
00176     HuginBase::Lens lens=variable_groups.getLensForImage(*images.begin());
00177     bool cropped=false;
00178     bool autoCenterCrop=false;
00179     vigra::Rect2D cropRect;
00180     if (LoadLensParametersChoose(parent, lens, cropped, autoCenterCrop, cropRect))
00181     {
00182         // Merge the lens parameters with the image variable map.
00183         HuginBase::VariableMapVector vars(images.size());
00184         size_t i=0;
00185         for(HuginBase::UIntSet::const_iterator it=images.begin();it!=images.end();++it,++i)
00186         {
00187             vars[i]=pano->getImageVariables(*it);
00188             for (HuginBase::LensVarMap::iterator it2 = lens.variables.begin(); it2 != lens.variables.end(); ++it2)
00189             {
00190                 if(it2->second.getName()=="EeV")
00191                 {
00192                     continue;
00193                 };
00194                 vars[i].find(it2->first)->second.setValue(it2->second.getValue());
00195             }
00196         };
00197 
00201         std::vector<PanoCommand::PanoCommand*> cmds;
00202         // update links
00203         std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> linkedVariables;
00204         std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> unlinkedVariables;
00205         for (HuginBase::LensVarMap::iterator it = lens.variables.begin(); it != lens.variables.end(); ++it)
00206         {
00207             if(it->second.getName()=="EeV")
00208             {
00209                 continue;
00210             };
00211 #define image_variable( name, type, default_value ) \
00212             if (HuginBase::PTOVariableConverterFor##name::checkApplicability(it->second.getName()))\
00213             {\
00214                 if(it->second.isLinked())\
00215                     linkedVariables.insert(HuginBase::ImageVariableGroup::IVE_##name);\
00216                 else\
00217                     unlinkedVariables.insert(HuginBase::ImageVariableGroup::IVE_##name);\
00218             }
00219 #include "panodata/image_variables.h"
00220 #undef image_variable
00221         }
00222         if (!linkedVariables.empty())
00223         {
00224             cmds.push_back(new PanoCommand::ChangePartImagesLinkingCmd(*pano, images, linkedVariables,
00225                 true,HuginBase::StandardImageVariableGroups::getLensVariables()));
00226         }
00227         if (!unlinkedVariables.empty())
00228         {
00229             cmds.push_back(new PanoCommand::ChangePartImagesLinkingCmd(*pano, images, unlinkedVariables,
00230                 false,HuginBase::StandardImageVariableGroups::getLensVariables()));
00231         }
00232         //update lens parameters
00233         cmds.push_back(new PanoCommand::UpdateImagesVariablesCmd(*pano, images, vars));
00234 
00235         // Set the lens projection type.
00236         cmds.push_back(new PanoCommand::ChangeImageProjectionCmd(*pano, images, (HuginBase::SrcPanoImage::Projection) lens.getProjection()));
00237         // update crop factor
00238         cmds.push_back(new PanoCommand::ChangeImageCropFactorCmd(*pano,images,lens.getCropFactor()));
00239         // update the crop rect
00240         cmds.push_back(new PanoCommand::ChangeImageAutoCenterCropCmd(*pano,images,autoCenterCrop));
00241         if(cropped)
00242         {
00243             cmds.push_back(new PanoCommand::ChangeImageCropRectCmd(*pano,images,cropRect));
00244         }
00245         else
00246         {
00247             cmds.push_back(new PanoCommand::ChangeImageCropModeCmd(*pano,images,HuginBase::BaseSrcPanoImage::NO_CROP));
00248         };
00249         cmd=new PanoCommand::CombinedPanoCommand(*pano, cmds);
00250         return true;
00251     }
00252     else
00253     {
00254         return false;
00255     };
00256 };
00257 
00258 bool LoadLensParametersChoose(wxWindow * parent, HuginBase::Lens & lens, 
00259      bool & cropped, bool & autoCenterCrop, vigra::Rect2D & cropRect)
00260 {
00261     wxString fname;
00262     wxFileDialog dlg(parent,
00263                         _("Load lens parameters"),
00264                         wxConfigBase::Get()->Read(wxT("/lensPath"),wxT("")), wxT(""),
00265                         _("Lens Project Files (*.ini)|*.ini|All files (*.*)|*.*"),
00266                         wxFD_OPEN, wxDefaultPosition);
00267     dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/lensPath"),wxT("")));
00268     if (dlg.ShowModal() == wxID_OK)
00269     {
00270         fname = dlg.GetPath();
00271         wxConfig::Get()->Write(wxT("/lensPath"), dlg.GetDirectory());  // remember for later
00272         // read with with standart C numeric format
00273         char * p = setlocale(LC_NUMERIC,NULL);
00274         char * old_locale = strdup(p);
00275         setlocale(LC_NUMERIC,"C");
00276         {
00277             wxFileConfig cfg(wxT("hugin lens file"),wxT(""),fname);
00278             long w=0;
00279             cfg.Read(wxT("Lens/image_width"), &w);
00280             long h=0;
00281             cfg.Read(wxT("Lens/image_height"), &h);
00282             if (w>0 && h>0) {
00283                 vigra::Size2D sz = lens.getImageSize();
00284                 if (w != sz.x || h != sz.y) {
00285                     cerr << "Image size: " << sz << " size in lens parameter file: " << w << "x" << h << std::endl;
00286                     int ret = wxMessageBox(_("Incompatible lens parameter file, image sizes do not match\nApply settings anyway?"), _("Error loading lens parameters"), wxICON_QUESTION |wxYES_NO);
00287                     if (ret == wxNO) {
00288                         setlocale(LC_NUMERIC,old_locale);
00289                         free(old_locale);
00290                         return false;
00291                     }
00292                 }
00293             } else {
00294                 // lens ini file didn't store the image size,
00295                 // assume everything is all right.
00296             }
00297             long integer=0;
00298             if(cfg.Read(wxT("Lens/type"), &integer))
00299             {
00300                 lens.setProjection((HuginBase::Lens::LensProjectionFormat) integer);
00301             };
00302             double d=1;
00303             if(cfg.Read(wxT("Lens/crop"), &d))
00304             {
00305                 lens.setCropFactor(d);
00306             };
00307             //special treatment for hfov, we are reading hfov and hfov_linked instead of v and v_linked
00308             d=50;
00309             if(cfg.Read(wxT("Lens/hfov"), &d))
00310             {
00311                 map_get(lens.variables,"v").setValue(d);
00312             };
00313             integer=1;
00314             if(cfg.Read(wxT("Lens/hfov_linked"), &integer))
00315             {
00316                 map_get(lens.variables,"v").setLinked(integer != 0);
00317             };
00318             DEBUG_DEBUG("read lens hfov: " << d);
00319 
00320             // loop to load lens variables
00321             const char ** varname = HuginBase::Lens::variableNames;
00322             while (*varname) {
00323                 if (string(*varname) == "Eev")
00324                 {
00325                     varname++;
00326                     continue;
00327                 }
00328                 wxString key(wxT("Lens/"));
00329                 key.append(wxString(*varname, wxConvLocal));
00330                 d = 0;
00331                 if (cfg.Read(key,&d))
00332                 {
00333                     // only set value if variabe was found in the script
00334                     map_get(lens.variables, *varname).setValue(d);
00335                     integer = 1;
00336                     key.append(wxT("_link"));
00337                     if(cfg.Read(key, &integer))
00338                     {
00339                         map_get(lens.variables, *varname).setLinked(integer != 0);
00340                     };
00341                 }
00342                 varname++;
00343             }
00344 
00345             // crop parameters
00346             long v=0;
00347             cfg.Read(wxT("Lens/crop/enabled"), &v);
00348             cropped=(v!=0);
00349             if(cropped)
00350             {
00351                 long left=0;
00352                 long top=0;
00353                 long right=0;
00354                 long bottom=0;
00355                 if(cfg.Read(wxT("Lens/crop/left"), &left) && cfg.Read(wxT("Lens/crop/top"), &top) &&
00356                     cfg.Read(wxT("Lens/crop/right"), &right) && cfg.Read(wxT("Lens/crop/bottom"), &bottom))
00357                 {
00358                     cropped=true;
00359                     cropRect=vigra::Rect2D(left,top,right,bottom);
00360                 }
00361                 else
00362                 {
00363                     cropped=false;
00364                 };
00365             };
00366             v=1;
00367             if(cfg.Read(wxT("Lens/crop/autoCenter"), &v))
00368             {
00369                 autoCenterCrop=(v!=0);
00370             };
00371         }
00372         // reset locale
00373         setlocale(LC_NUMERIC,old_locale);
00374         free(old_locale);
00375         return true;
00376     }
00377     else
00378     {
00379         return false;
00380     };
00381 };
00382 
00383 void SaveLensParametersToIni(wxWindow * parent, HuginBase::Panorama *pano, const HuginBase::UIntSet images)
00384 {
00385     if (images.size() == 1)
00386     {
00387         unsigned int imgNr = *(images.begin());
00388         wxFileDialog dlg(parent,
00389                          _("Save lens parameters file"),
00390                          wxConfigBase::Get()->Read(wxT("/lensPath"),wxT("")), wxT(""),
00391                          _("Lens Project Files (*.ini)|*.ini|All files (*)|*"),
00392                          wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
00393         dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/lensPath"),wxT("")));
00394         if (dlg.ShowModal() == wxID_OK)
00395         {
00396             wxFileName filename(dlg.GetPath());
00397             if(!filename.HasExt())
00398             {
00399                 filename.SetExt(wxT("ini"));
00400 #if wxCHECK_VERSION(3,0,0)
00401                 if (filename.Exists())
00402 #else
00403                 if (wxFile::Exists(filename.GetFullPath()))
00404 #endif
00405                 {
00406                     int d = wxMessageBox(wxString::Format(_("File %s exists. Overwrite?"), filename.GetFullPath().c_str()),
00407                         _("Save project"), wxYES_NO | wxICON_QUESTION);
00408                     if (d != wxYES) {
00409                         return;
00410                     }
00411                 }
00412             }
00413             wxConfig::Get()->Write(wxT("/lensPath"), dlg.GetDirectory());  // remember for later
00414             SaveLensParameters(filename.GetFullPath(),pano,imgNr);
00415         }
00416     }
00417     else 
00418     {
00419         wxLogError(_("Please select an image and try again"));
00420     }
00421 }
00422 
00423 bool CheckLensStacks(HuginBase::Panorama* pano, bool allowCancel)
00424 {
00425     if (pano->getNrOfImages() < 2)
00426     {
00427         return true;
00428     };
00429     const size_t nrImages = pano->getNrOfImages();
00430     bool stacksCorrectLinked = true;
00431     for (size_t i = 0; i < nrImages - 1; ++i)
00432     {
00433         const HuginBase::SrcPanoImage& image1 = pano->getImage(i);
00434         if (image1.YawisLinked())
00435         {
00436             for (size_t j = i + 1; j < nrImages && stacksCorrectLinked; ++j)
00437             {
00438                 const HuginBase::SrcPanoImage& image2 = pano->getImage(j);
00439                 if (image1.YawisLinkedWith(image2))
00440                 {
00441                     stacksCorrectLinked = stacksCorrectLinked &
00442                         image1.HFOVisLinkedWith(image2) &
00443                         image1.RadialDistortionisLinkedWith(image2) &
00444                         image1.RadialDistortionCenterShiftisLinkedWith(image2) &
00445                         image1.ShearisLinkedWith(image2);
00446                 };
00447             };
00448         };
00449     };
00450     if (stacksCorrectLinked)
00451     {
00452         return true;
00453     }
00454     else
00455     {
00456         int flags = wxICON_EXCLAMATION | wxOK;
00457         if (allowCancel)
00458         {
00459             flags = flags | wxCANCEL;
00460         };
00461         if (wxMessageBox(_("This project contains stacks with linked positions. But the lens parameters are not linked for these images.\nThis will result in unwanted results.\nPlease check and correct this before proceeding."),
00462 #ifdef _WINDOWS
00463             _("Hugin"),
00464 #else
00465             wxT(""),
00466 #endif
00467             flags)==wxOK)
00468         {
00469             return true;
00470         }
00471         else
00472         {
00473             return false;
00474         };
00475     };
00476 };
00477 

Generated on 27 Aug 2015 for Hugintrunk by  doxygen 1.4.7