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

Generated on 3 May 2016 for Hugintrunk by  doxygen 1.4.7