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

Generated on 8 Feb 2016 for Hugintrunk by  doxygen 1.4.7