LensDB.cpp

Go to the documentation of this file.
00001 
00008 /*  This program is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU General Public
00010  *  License as published by the Free Software Foundation; either
00011  *  version 2 of the License, or (at your option) any later version.
00012  *
00013  *  This software is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU General Public
00019  *  License along with this software; if not, write to the Free Software
00020  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #include "LensDB.h"
00025 #include <boost/filesystem.hpp>
00026 #include <iostream>
00027 #include <hugin_utils/stl_utils.h>
00028 
00029 // minimum version for all features is 0.2.5.1, for earlierer version only a subset of the functions
00030 // is supported
00031 #define MIN_LF_VERSION  0x20501
00032 
00033 namespace HuginBase
00034 {
00035 
00036 namespace LensDB
00037 {
00038 
00039 #if BOOST_FILESYSTEM_VERSION < 3
00040 typedef boost::filesystem::basic_path<std::string, boost::filesystem::path_traits> basic_path;
00041 #define GETPATHSTRING(x) x
00042 #else
00043 typedef boost::filesystem::path basic_path;
00044 #define GETPATHSTRING(x) (x).string()
00045 #endif
00046 
00047 LensDB* LensDB::m_instance=NULL;
00048 
00049 LensDB::LensDB()
00050 {
00051     m_db=lf_db_new();
00052     if(!m_db)
00053     {
00054         m_db=NULL;
00055     }
00056     else
00057     {
00058         m_user_db_path=std::string(m_db->HomeDataDir);
00059     };
00060     m_initialized=false;
00061     m_lenses=NULL;
00062     m_newDB=NULL;
00063     m_updatedLenses=NULL;
00064     m_currentLens=NULL;
00065     m_updatedMounts=NULL;
00066     m_needLensCleanup=true;
00067 };
00068 
00069 LensDB::~LensDB()
00070 {
00071     FreeLensList();
00072     if (m_db!=NULL)
00073     {
00074         m_db->Destroy();
00075     };
00076     CleanSaveInformation();
00077 };
00078 
00079 void LensDB::FreeLensList()
00080 {
00081     if(m_lenses!=NULL)
00082     {
00083         if(!m_needLensCleanup)
00084         {
00085             delete [] m_lenses;
00086         }
00087         else
00088         {
00089             lf_free(m_lenses);
00090         };
00091     };
00092     m_lenses=NULL;
00093 };
00094 
00095 LensDB& LensDB::GetSingleton()
00096 {
00097     if(m_instance==NULL)
00098     {
00099         m_instance = new LensDB();
00100     };
00101     return *m_instance;
00102 };
00103 
00104 void LensDB::Clean()
00105 {
00106     if(m_instance!=NULL)
00107     {
00108         delete m_instance;
00109     };
00110     m_instance=NULL;
00111 };
00112 
00113 void LensDB::SetMainDBPath(std::string mainPath)
00114 {
00115     m_main_db_path=mainPath;
00116 };
00117 
00118 std::string LensDB::GetMainDBPath()
00119 {
00120     return m_main_db_path;
00121 };
00122 
00123 std::string LensDB::GetUserDBPath()
00124 {
00125     return m_user_db_path;
00126 };
00127 
00128 bool LensDB::InitDB()
00129 {
00130     if(m_initialized)
00131         return true;
00132     if(m_db!=NULL)
00133     {
00134 #if LF_VERSION < MIN_LF_VERSION
00135         // workaround a bug in lensfun, that the numeric locale is not correctly set back
00136         char * old_locale = setlocale(LC_NUMERIC,NULL);
00137         old_locale = strdup(old_locale);
00138         setlocale(LC_NUMERIC,"C");
00139 #endif
00140         if(m_main_db_path.empty())
00141         {
00142             lfError e=m_db->Load();
00143             m_initialized=true;
00144         }
00145         else
00146         {
00147             LoadFilesInDir(m_main_db_path);
00148             LoadFilesInDir(m_user_db_path);
00149             m_initialized=true;
00150         };
00151 #if LF_VERSION < MIN_LF_VERSION
00152         // workaround a bug in lensfun, that the numeric locale is not correctly set back
00153         setlocale(LC_NUMERIC,old_locale);
00154         free(old_locale);
00155 #endif
00156     };
00157     return m_initialized;
00158 };
00159 
00160 // this function is a rewrite of a lensfun function, because it can not publically accessed
00161 bool LensDB::LoadFilesInDir(std::string path)
00162 {
00163     if(m_db==NULL)
00164         return false;
00165     lfError e=LF_NO_ERROR;
00166     basic_path p(path);
00167     try
00168     {
00169         if(exists(p))
00170         {
00171             if (is_directory(p))
00172             {
00173                 typedef std::vector<basic_path> fl_vec;
00174                 fl_vec filelist;
00175                 std::copy(boost::filesystem::directory_iterator(p), boost::filesystem::directory_iterator(), std::back_inserter(filelist));
00176                 for(fl_vec::const_iterator it=filelist.begin();it!=filelist.end();it++)
00177                 {
00178                     basic_path file=*it;
00179                     if(GETPATHSTRING(file.extension())==std::string(".xml"))
00180                     {
00181                         lfError e2=m_db->Load(file.string().c_str());
00182                         if(e==LF_NO_ERROR && e2!=LF_NO_ERROR)
00183                         {
00184                             e=e2;
00185                         };
00186                     };
00187                 };
00188             }
00189         }
00190     }
00191     catch (const boost::filesystem::filesystem_error& ex)
00192     {
00193         std::cout << "Error reading lensfun db. Code: " << ex.what() << '\n';
00194     }
00195     return e==LF_NO_ERROR;
00196 };
00197 
00198 void LensDB::ReloadUserPart()
00199 {
00200     if(m_db==NULL)
00201     {
00202         return;
00203     };
00204     if(!m_initialized)
00205     {
00206         InitDB();
00207     }
00208     else
00209     {
00210         LoadFilesInDir(m_user_db_path);
00211     };
00212 };
00213 
00214 bool LensDB::GetCropFactor(std::string maker, std::string model, double &cropFactor)
00215 {
00216     InitDB();
00217     if(!m_initialized)
00218         return false;
00219     cropFactor=0;
00220     const lfCamera **cameras=m_db->FindCameras(maker.c_str(),model.c_str());
00221     if(cameras)
00222     {
00223         cropFactor=cameras[0]->CropFactor;
00224     }
00225     lf_free (cameras);
00226     return cropFactor>0;
00227 };
00228 
00229 bool LensDB::GetCameraMount(std::string maker, std::string model, std::string &mount)
00230 {
00231     InitDB();
00232     if(!m_initialized)
00233         return false;
00234     mount="";
00235     const lfCamera **cameras=m_db->FindCameras(maker.c_str(),model.c_str());
00236     if(cameras)
00237     {
00238         mount=std::string(cameras[0]->Mount);
00239     }
00240     lf_free (cameras);
00241     return !mount.empty();
00242 };
00243 
00244 bool LensDB::FindLens(std::string camMaker, std::string camModel, std::string lens)
00245 {
00246     FreeLensList();
00247     m_needLensCleanup=true;
00248     InitDB();
00249     if(!m_initialized)
00250     {
00251         return false;
00252     };
00253     if(camMaker.empty() && camModel.empty() && lens.empty())
00254     {
00255         return false;
00256     };
00257     if(lens.empty() || hugin_utils::tolower(lens)=="standard")
00258     {
00259         const lfCamera** cam=m_db->FindCameras(camMaker.c_str(),camModel.c_str());
00260         if(cam)
00261         {
00262             m_lenses=m_db->FindLenses(cam[0],NULL,"Standard");
00263             lf_free(cam);
00264         }
00265         else
00266         {
00267             return false;
00268         };
00269     }
00270     else
00271     {
00272         if(!camModel.empty())
00273         {
00274             const lfCamera** cam=m_db->FindCameras(camMaker.c_str(),camModel.c_str());
00275             if(cam)
00276             {
00277                 m_lenses=m_db->FindLenses(cam[0], NULL, lens.c_str());
00278                 lf_free(cam);
00279             }
00280             else
00281             {
00282                 m_lenses=m_db->FindLenses(NULL, NULL, lens.c_str());
00283             }
00284         }
00285         else
00286         {
00287             m_lenses=m_db->FindLenses(NULL, NULL,lens.c_str());
00288         };
00289     };
00290     if(m_lenses)
00291     {
00292         return true;
00293     }
00294     else
00295     {
00296         lf_free(m_lenses);
00297         m_lenses=NULL;
00298         return false;
00299     };
00300 };
00301 
00302 void LensDB::SetActiveLens(const lfLens* activeLens)
00303 {
00304     FreeLensList();
00305     m_needLensCleanup=false;
00306     m_lenses=new const lfLens* [1];
00307     m_lenses[0]=activeLens;
00308 };
00309 
00310 bool LensDB::CheckLensFocal(double focal)
00311 {
00312     if(m_lenses==NULL)
00313     {
00314         return false;
00315     };
00316     return focal>=m_lenses[0]->MinFocal && focal<=m_lenses[0]->MaxFocal;
00317 };
00318 
00319 bool LensDB::CheckLensAperture(double aperture)
00320 {
00321     if(m_lenses==NULL)
00322     {
00323         return false;
00324     };
00325     if(m_lenses[0]->MinAperture>0)
00326     {
00327         return aperture>=m_lenses[0]->MinAperture;
00328     }
00329     else
00330     {
00331         //no aperture found, assuming it is correct
00332         return true;
00333     };
00334 };
00335 
00336 bool LensDB::FindLenses(std::string camMaker, std::string camModel, std::string lensname, LensDBList &foundLenses, bool fuzzy)
00337 {
00338     InitDB();
00339     if(!m_initialized)
00340     {
00341         return false;
00342     };
00343     foundLenses.SetCameraModelMaker(camMaker, camModel);
00344     if(camMaker.empty() && camModel.empty() && lensname.empty())
00345     {
00346         return false;
00347     };
00348     const lfLens **lenses;
00349     int searchFlag=fuzzy ? LF_SEARCH_LOOSE : 0;
00350     if(lensname.empty() || hugin_utils::tolower(lensname)=="standard")
00351     {
00352         const lfCamera** cam=m_db->FindCameras(camMaker.c_str(),camModel.c_str());
00353         if(cam)
00354         {
00355             lenses=m_db->FindLenses(cam[0],NULL,"Standard",searchFlag);
00356             lf_free(cam);
00357         }
00358         else
00359         {
00360             return false;
00361         };
00362     }
00363     else
00364     {
00365         if(!camModel.empty())
00366         {
00367             const lfCamera** cam=m_db->FindCameras(camMaker.c_str(), camModel.c_str());
00368             if(cam)
00369             {
00370                 lenses=m_db->FindLenses(cam[0], NULL, lensname.c_str(), searchFlag);
00371                 lf_free(cam);
00372             }
00373             else
00374             {
00375                 lenses=m_db->FindLenses(NULL, NULL, lensname.c_str(), searchFlag);
00376             }
00377         }
00378         else
00379         {
00380             lenses=m_db->FindLenses(NULL, NULL, lensname.c_str(), searchFlag);
00381         };
00382     };
00383 
00384     foundLenses.SetLenses(lenses);
00385     return foundLenses.GetLensCount()>0;
00386 };
00387 
00388 bool LensDB::GetMounts(std::vector<std::string> &foundMounts)
00389 {
00390     InitDB();
00391     if(!m_initialized)
00392     {
00393         return false;
00394     };
00395     foundMounts.clear();
00396     const lfMount *const* mounts=m_db->GetMounts();
00397     if(mounts)
00398     {
00399         for(int i=0;mounts[i];i++)
00400         {
00401             foundMounts.push_back(m_db->MountName(mounts[i]->Name));
00402         }
00403     };
00404     return foundMounts.size()>0;
00405 };
00406 
00409 bool TranslateProjectionLF2Hugin(const lfLens* lens, BaseSrcPanoImage::Projection & projection)
00410 {
00411     switch(lens->Type)
00412     {
00413         case LF_RECTILINEAR:
00414             projection=BaseSrcPanoImage::RECTILINEAR;
00415             return true;
00416             break;
00417         case LF_FISHEYE:
00418             projection=BaseSrcPanoImage::FULL_FRAME_FISHEYE;
00419 #if LF_VERSION>=MIN_LF_VERSION
00420             lfLensCalibCrop cropMode;
00421             if (lens->InterpolateCrop(lens->MinFocal,cropMode))
00422             {
00423                 if(cropMode.CropMode==LF_CROP_CIRCLE)
00424                 {
00425                     projection=BaseSrcPanoImage::CIRCULAR_FISHEYE;
00426                     return true;
00427                 }
00428             };
00429 #endif
00430             return true;
00431             break;
00432         case LF_PANORAMIC:
00433             projection=BaseSrcPanoImage::PANORAMIC;
00434             return true;
00435             break;
00436         case LF_EQUIRECTANGULAR:
00437             projection=BaseSrcPanoImage::EQUIRECTANGULAR;
00438             return true;
00439             break;
00440 #if LF_VERSION>=MIN_LF_VERSION
00441             // the following projection are only defined in lensfun in 0.2.5.1 and later
00442         case LF_FISHEYE_ORTHOGRAPHIC:
00443             projection=BaseSrcPanoImage::FISHEYE_ORTHOGRAPHIC;
00444             return true;
00445             break;
00446         case LF_FISHEYE_STEREOGRAPHIC:
00447             projection=BaseSrcPanoImage::FISHEYE_STEREOGRAPHIC;
00448             return true;
00449             break;
00450         case LF_FISHEYE_EQUISOLID:
00451             projection=BaseSrcPanoImage::FISHEYE_EQUISOLID;
00452             return true;
00453             break;
00454         case LF_FISHEYE_THOBY:
00455             projection=BaseSrcPanoImage::FISHEYE_THOBY;
00456             return true;
00457             break;
00458 #endif
00459         case LF_UNKNOWN:
00460         default:
00461             return false;
00462             break;
00463     };
00464     return false;
00465 };
00466 
00469 bool TranslateProjectionHugin2LF(BaseSrcPanoImage::Projection projection, lfLens* lens)
00470 {
00471     switch(projection)
00472     {
00473         case BaseSrcPanoImage::RECTILINEAR:
00474             lens->Type=LF_RECTILINEAR;
00475             return true;
00476             break;
00477         case BaseSrcPanoImage::CIRCULAR_FISHEYE:
00478             lens->Type=LF_FISHEYE;
00479 #if LF_VERSION>=MIN_LF_VERSION
00480             lfLensCalibCrop crop;
00481             if(lens->InterpolateCrop(lens->MinFocal,crop))
00482             {
00483                 if(crop.CropMode!=LF_CROP_CIRCLE)
00484                 {
00485                     return false;
00486                 }
00487             }
00488             else
00489             {
00490                 crop.Crop[0]=0;
00491                 crop.Crop[1]=1;
00492                 crop.Crop[2]=0;
00493                 crop.Crop[3]=1;
00494                 crop.CropMode=LF_CROP_CIRCLE;
00495                 crop.Focal=lens->MinFocal;
00496                 lens->AddCalibCrop(&crop);
00497             };
00498 #endif
00499             return true;
00500             break;
00501         case BaseSrcPanoImage::FULL_FRAME_FISHEYE:
00502             lens->Type=LF_FISHEYE;
00503             return true;
00504             break;
00505         case BaseSrcPanoImage::PANORAMIC:
00506             lens->Type=LF_PANORAMIC;
00507             return true;
00508             break;
00509         case BaseSrcPanoImage::EQUIRECTANGULAR:
00510             lens->Type=LF_EQUIRECTANGULAR;
00511             return true;
00512             break;
00513 #if LF_VERSION>=MIN_LF_VERSION
00514             // the following projection are only defined in lensfun in 0.2.5.1 and later
00515         case BaseSrcPanoImage::FISHEYE_ORTHOGRAPHIC:
00516             lens->Type=LF_FISHEYE_ORTHOGRAPHIC;
00517             return true;
00518             break;
00519         case BaseSrcPanoImage::FISHEYE_STEREOGRAPHIC:
00520             lens->Type=LF_FISHEYE_STEREOGRAPHIC;
00521             return true;
00522             break;
00523         case BaseSrcPanoImage::FISHEYE_EQUISOLID:
00524             lens->Type=LF_FISHEYE_EQUISOLID;
00525             return true;
00526             break;
00527         case BaseSrcPanoImage::FISHEYE_THOBY:
00528             lens->Type=LF_FISHEYE_THOBY;
00529             return true;
00530             break;
00531 #endif
00532     };
00533     return false;
00534 };
00535 
00536 bool LensDB::GetProjection(BaseSrcPanoImage::Projection & projection)
00537 {
00538     if(m_lenses==NULL)
00539     {
00540         return false;
00541     };
00542     return TranslateProjectionLF2Hugin(m_lenses[0],projection);
00543 };
00544 
00545 bool LensDB::GetCrop(double focal,BaseSrcPanoImage::CropMode &cropMode,hugin_utils::FDiff2D &cropLeftTop,hugin_utils::FDiff2D &cropRightBottom)
00546 {
00547     if(m_lenses==NULL)
00548     {
00549         return false;
00550     };
00551 #if LF_VERSION>=MIN_LF_VERSION
00552     struct lfLensCalibCrop crop;
00553     if(m_lenses[0]->InterpolateCrop(focal,crop))
00554     {
00555         switch (crop.CropMode)
00556         {
00557             case LF_CROP_RECTANGLE:
00558                 cropMode=BaseSrcPanoImage::CROP_RECTANGLE;
00559                 break;
00560             case LF_CROP_CIRCLE:
00561                 cropMode=BaseSrcPanoImage::CROP_CIRCLE;
00562                 break;
00563             default:
00564                 cropMode=BaseSrcPanoImage::NO_CROP;
00565                 break;
00566         };
00567         if(cropMode!=BaseSrcPanoImage::NO_CROP)
00568         {
00569             cropLeftTop.x=crop.Crop[0];
00570             cropLeftTop.y=crop.Crop[2];
00571             cropRightBottom.x=crop.Crop[1];
00572             cropRightBottom.y=crop.Crop[3];
00573         };
00574         return true;
00575     }
00576     else
00577     {
00578         return false;
00579     };
00580 #else
00581     return false;
00582 #endif
00583 };
00584 
00585 bool LensDB::GetFov(double focal,double &fov)
00586 {
00587     if(m_lenses==NULL)
00588     {
00589         return false;
00590     };
00591 #if LF_VERSION>=MIN_LF_VERSION
00592     lfLensCalibFov calibFov;
00593     if(m_lenses[0]->InterpolateFov(focal,calibFov))
00594     {
00595         fov=calibFov.FieldOfView;
00596         return true;
00597     }
00598 #endif
00599     return false;
00600 };
00601 
00602 bool LensDB::GetDistortion(double focal, std::vector<double> &distortion)
00603 {
00604     distortion.clear();
00605     if(m_lenses==NULL)
00606     {
00607         return false;
00608     };
00609     lfLensCalibDistortion calibDist;
00610     if(m_lenses[0]->InterpolateDistortion(focal,calibDist))
00611     {
00612         switch(calibDist.Model)
00613         {
00614             //only a part of the distortion models are supported by Hugin
00615             //convert all into PTLens model where possible
00616             case LF_DIST_MODEL_POLY3:
00617                 distortion.push_back(0);
00618                 distortion.push_back(calibDist.Terms[0]);
00619                 distortion.push_back(0);
00620                 return true;
00621                 break;
00622             case LF_DIST_MODEL_PTLENS:
00623                 distortion.push_back(calibDist.Terms[0]);
00624                 distortion.push_back(calibDist.Terms[1]);
00625                 distortion.push_back(calibDist.Terms[2]);
00626                 return true;
00627                 break;
00628             case LF_DIST_MODEL_NONE:
00629             case LF_DIST_MODEL_POLY5:
00630             case LF_DIST_MODEL_FOV1:
00631             default:
00632                 return false;
00633                 break;
00634         };
00635     }
00636     else
00637     {
00638         return false;
00639     };
00640 };
00641 
00642 bool LensDB::GetVignetting(double focal, double aperture, double distance, std::vector<double> &vignetting)
00643 {
00644     vignetting.clear();
00645     if(m_lenses==NULL)
00646     {
00647         return false;
00648     };
00649     double checkedAperture=0;
00650     if(m_lenses[0]->MinAperture>0)
00651     {
00652         checkedAperture=aperture;
00653     };
00654     lfLensCalibVignetting calibVig;
00655     if(m_lenses[0]->InterpolateVignetting(focal,checkedAperture,distance,calibVig))
00656     {
00657         switch(calibVig.Model)
00658         {
00659             case LF_VIGNETTING_MODEL_PA:
00660                 vignetting.push_back(1.0);
00661                 vignetting.push_back(calibVig.Terms[0]);
00662                 vignetting.push_back(calibVig.Terms[1]);
00663                 vignetting.push_back(calibVig.Terms[2]);
00664                 return true;
00665                 break;
00666             case LF_VIGNETTING_MODEL_NONE:
00667             default:
00668                 return false;
00669                 break;
00670         };
00671     }
00672     else
00673     {
00674         return false;
00675     };
00676 };
00677 
00678 bool LensDB::SaveCameraCrop(std::string filename, std::string maker, std::string model, std::string mount, double cropfactor)
00679 {
00680 #if LF_VERSION < MIN_LF_VERSION
00681     // workaround a bug in lensfun, that the numeric locale is not correctly set for saving
00682     char * old_locale = setlocale(LC_NUMERIC,NULL);
00683     old_locale = strdup(old_locale);
00684     setlocale(LC_NUMERIC,"C");
00685 #endif
00686 
00687     if(m_newDB!=NULL)
00688     {
00689         CleanSaveInformation();
00690     };
00691     m_newDB=lf_db_new();
00692     if(!m_newDB)
00693     {
00694         m_newDB=NULL;
00695         return false;
00696     };
00697     // load if file exists already
00698     basic_path p(filename);
00699     if(boost::filesystem::exists(p))
00700     {
00701         if(boost::filesystem::is_regular_file(p))
00702         {
00703             m_newDB->Load(filename.c_str());
00704             //ignore errors
00705         };
00706     };
00707     // check if camera is already in db
00708     const lfCamera **oldCameras=m_newDB->FindCameras(maker.c_str(),model.c_str());
00709     bool updateCam=false;
00710     if(oldCameras)
00711     {
00712         for(size_t i=0;oldCameras[i];i++)
00713         {
00714             updateCam=true;
00715         };
00716     };
00717 
00718     //check, if we have a new mount
00719     bool newMount=false;
00720     if(!updateCam)
00721     {
00722         newMount=IsNewMount(mount);
00723     };
00724 
00725     //count, how many cameras are in the db
00726     const lfCamera *const* allCameras=m_newDB->GetCameras();
00727     size_t nrCam=0;
00728     if(allCameras)
00729     {
00730         for(size_t i=0;allCameras[i];i++)
00731         {
00732             nrCam++;
00733         };
00734     };
00735 
00736     if(!updateCam)
00737     {
00738         nrCam++;
00739     };
00740 
00741     //build the updated list
00742     //lensfun does not provide an easy way to add a new camera, so we are using this ugly workaround
00743     lfCamera** updatedCams=new lfCamera*[nrCam+1];
00744     for(size_t i=0;i<nrCam;i++)
00745     {
00746         updatedCams[i]=new lfCamera();
00747     };
00748     updatedCams[nrCam]=NULL;
00749 
00750     for(size_t i=0;allCameras[i];i++)
00751     {
00752         lf_camera_copy(updatedCams[i],allCameras[i]);
00753         if(updateCam)
00754         {
00755             if(strcmp(allCameras[i]->Maker,oldCameras[0]->Maker)==0 && 
00756                strcmp(allCameras[i]->Model,oldCameras[0]->Model)==0)
00757             {
00758                 updatedCams[i]->CropFactor=cropfactor;
00759             };
00760         };
00761     };
00762     lf_free(oldCameras);
00763     if(!updateCam)
00764     {
00765         updatedCams[nrCam-1]->SetMaker(maker.c_str());
00766         updatedCams[nrCam-1]->SetModel(model.c_str());
00767         if(mount.empty())
00768         {
00769             updatedCams[nrCam-1]->SetMount("Generic");
00770         }
00771         else
00772         {
00773             updatedCams[nrCam-1]->SetMount(mount.c_str());
00774         };
00775         updatedCams[nrCam-1]->CropFactor=cropfactor;
00776     };
00777 
00778     //finally save
00779     lfError e;
00780     if(newMount)
00781     {
00782         e=m_newDB->Save(filename.c_str(), m_updatedMounts, updatedCams, m_newDB->GetLenses());
00783     }
00784     else
00785     {
00786         e=m_newDB->Save(filename.c_str(),m_newDB->GetMounts(),updatedCams,m_newDB->GetLenses());
00787     };
00788     //cleanup
00789     if (updatedCams)
00790     {
00791         for (int i = 0; updatedCams[i]; i++)
00792         {
00793             delete updatedCams[i];
00794         };
00795     };
00796     delete []updatedCams;
00797 #if LF_VERSION < MIN_LF_VERSION
00798     setlocale(LC_NUMERIC, old_locale);
00799     free(old_locale);
00800 #endif
00801     m_newDB->Destroy();
00802     m_newDB=NULL;
00803     return e==LF_NO_ERROR;
00804 };
00805 
00806 int LensDB::BeginSaveLens(std::string filename, std::string maker, std::string lensname, std::string mount, BaseSrcPanoImage::Projection projection, double cropfactor)
00807 {
00808     if(m_newDB!=NULL)
00809     {
00810         CleanSaveInformation();
00811     };
00812     m_newDB=lf_db_new();
00813     if(!m_newDB)
00814     {
00815         m_newDB=NULL;
00816         return 1;
00817     };
00818     // load if file exists already
00819     basic_path p(filename);
00820     m_lensFilename=p.string();
00821     if(boost::filesystem::exists(p))
00822     {
00823         if(boost::filesystem::is_regular_file(p))
00824         {
00825 #if LF_VERSION < MIN_LF_VERSION
00826             char * old_locale = setlocale(LC_NUMERIC,NULL);
00827             old_locale = strdup(old_locale);
00828             setlocale(LC_NUMERIC,"C");
00829 #endif
00830             m_newDB->Load(m_lensFilename.c_str());
00831             //ignore errors
00832 #if LF_VERSION < MIN_LF_VERSION
00833             setlocale(LC_NUMERIC, old_locale);
00834             free(old_locale);
00835 #endif
00836         };
00837     };
00838 
00839     // check if lens is already in db
00840     lfCamera* cam=NULL;
00841     if(!mount.empty())
00842     {
00843         cam=new lfCamera();
00844         cam->SetMount(mount.c_str());
00845         cam->CropFactor=cropfactor;
00846     };
00847     const lfLens **oldLenses=m_newDB->FindLenses(cam,NULL,lensname.c_str());
00848     if(cam!=NULL)
00849     {
00850         delete cam;
00851     };
00852     bool updateLens=false;
00853     if(oldLenses)
00854     {
00855         for(size_t i=0;oldLenses[i];i++)
00856         {
00857             updateLens=true;
00858         };
00859     };
00860 
00861     if(updateLens)
00862     {
00863         BaseSrcPanoImage::Projection oldProjection;
00864         if(TranslateProjectionLF2Hugin(oldLenses[0],oldProjection))
00865         {
00866             if(oldProjection!=projection)
00867             {
00868                 //if projection does not match, reject to save lens
00869                 lf_free(oldLenses);
00870                 m_newDB->Destroy();
00871                 return 2;
00872             };
00873         };
00874         if(abs(oldLenses[0]->CropFactor-cropfactor)>0.05)
00875         {
00876             //if crop factor does not match, reject to save lens
00877             lf_free(oldLenses);
00878             m_newDB->Destroy();
00879             return 3;
00880         };
00881     }
00882     else
00883     {
00884         IsNewMount(mount);
00885     };
00886 
00887     //count, how many lenses are in the db
00888     const lfLens *const* allLenses=m_newDB->GetLenses();
00889     size_t nrLens=0;
00890     if(allLenses)
00891     {
00892         for(size_t i=0;allLenses[i];i++)
00893         {
00894             nrLens++;
00895         };
00896     };
00897 
00898     if(!updateLens)
00899     {
00900         nrLens++;
00901     };
00902 
00903     //build the updated list
00904     //lensfun does not provide an easy way to add a new camera, so we are using this ugly workaround
00905     m_updatedLenses=new lfLens*[nrLens+1];
00906     for(size_t i=0;i<nrLens;i++)
00907     {
00908         m_updatedLenses[i]=new lfLens();
00909     };
00910     m_updatedLenses[nrLens]=NULL;
00911 
00912     for(size_t i=0;allLenses[i];i++)
00913     {
00914         lf_lens_copy(m_updatedLenses[i],allLenses[i]);
00915         if(updateLens)
00916         {
00917             if(strcmp(m_updatedLenses[i]->Model,oldLenses[0]->Model)==0 && 
00918                strcmp(m_updatedLenses[i]->Maker,oldLenses[0]->Maker)==0)
00919             {
00920                 bool compareMounts=false;
00921                 if(oldLenses[0]->Mounts)
00922                 {
00923                     for(int j=0; oldLenses[0]->Mounts[j] && !compareMounts; j++)
00924                     {
00925                         for(int k=0; m_updatedLenses[i]->Mounts[k] && !compareMounts; k++)
00926                         {
00927                             if(strcmp(m_updatedLenses[i]->Mounts[k], oldLenses[0]->Mounts[j])==0)
00928                             {
00929                                 compareMounts=true;
00930                             };
00931                         };
00932                     };
00933                 };
00934                 if(compareMounts)
00935                 {
00936                     m_currentLens=m_updatedLenses[i];
00937                 };
00938             };
00939         };
00940     };
00941     lf_free(oldLenses);
00942     if(!updateLens)
00943     {
00944         m_currentLens=m_updatedLenses[nrLens-1];
00945         m_currentLens->SetModel(lensname.c_str());
00946         m_currentLens->SetMaker(maker.c_str());
00947         if(mount.empty())
00948         {
00949             m_currentLens->AddMount("Generic");
00950         }
00951         else
00952         {
00953             m_currentLens->AddMount(mount.c_str());
00954         };
00955         TranslateProjectionHugin2LF(projection,m_currentLens);
00956         m_currentLens->CropFactor=cropfactor;
00957         m_currentLens->GuessParameters();
00958     };
00959     m_currentLens->Check();
00960     return 0;
00961 };
00962 
00963 void LensDB::SaveHFOV(double focal, double hfov)
00964 {
00965 #if LF_VERSION>=MIN_LF_VERSION
00966     if(m_currentLens)
00967     {
00968         int index=-1;
00969         if(m_currentLens->CalibFov)
00970         {
00971             for(int i=0;m_currentLens->CalibFov[i];i++)
00972             {
00973                 if(abs(m_currentLens->CalibFov[i]->Focal-focal)<0.05)
00974                 {
00975                     index=i;
00976                     break;
00977                 };
00978             };
00979         };
00980         if(index>-1)
00981         {
00982             m_currentLens->RemoveCalibFov(index);
00983         };
00984         lfLensCalibFov lcf;
00985         lcf.Focal=focal;
00986         lcf.FieldOfView=hfov;
00987         m_currentLens->AddCalibFov(&lcf);
00988     };
00989 #endif
00990 };
00991 
00992 void LensDB::SaveCrop(double focal, BaseSrcPanoImage::CropMode cropMode, hugin_utils::FDiff2D cropLeftTop, hugin_utils::FDiff2D cropRightBottom)
00993 {
00994 #if LF_VERSION>=MIN_LF_VERSION
00995     if(m_currentLens)
00996     {
00997         //first run, we search and remove crop with focal length 0
00998         //this can happen with circular fisheye lenses
00999         int index=-1;
01000         if(m_currentLens->CalibCrop)
01001         {
01002             for(int i=0;m_currentLens->CalibCrop[i];i++)
01003             {
01004                 if(m_currentLens->CalibCrop[i]->Focal==0)
01005                 {
01006                     index=i;
01007                     break;
01008                 };
01009             };
01010         };
01011         if(index>-1)
01012         {
01013             m_currentLens->RemoveCalibCrop(index);
01014         };
01015         //now searching for existing crop setting
01016         index=-1;
01017         if(m_currentLens->CalibCrop)
01018         {
01019             for(int i=0;m_currentLens->CalibCrop[i];i++)
01020             {
01021                 if(abs(m_currentLens->CalibCrop[i]->Focal-focal)<0.05)
01022                 {
01023                     index=i;
01024                     break;
01025                 };
01026             };
01027         };
01028         if(index>-1)
01029         {
01030             m_currentLens->RemoveCalibCrop(index);
01031         };
01032         lfLensCalibCrop lcc;
01033         lcc.Focal=focal;
01034         switch(cropMode)
01035         {
01036             case BaseSrcPanoImage::CROP_CIRCLE:
01037                 lcc.CropMode=LF_CROP_CIRCLE;
01038                 break;
01039             case BaseSrcPanoImage::CROP_RECTANGLE:
01040                 lcc.CropMode=LF_CROP_RECTANGLE;
01041                 break;
01042             case BaseSrcPanoImage::NO_CROP:
01043                 return;
01044         };
01045         lcc.Crop[0]=cropLeftTop.x;
01046         lcc.Crop[1]=cropRightBottom.x;
01047         lcc.Crop[2]=cropLeftTop.y;
01048         lcc.Crop[3]=cropRightBottom.y;
01049         m_currentLens->AddCalibCrop(&lcc);
01050     };
01051 #endif
01052 };
01053 
01054 void LensDB::SaveDistortion(double focal, std::vector<double> distortion)
01055 {
01056     if(m_currentLens)
01057     {
01058         if(distortion.size()!=4)
01059         {
01060             //skip invalid distortion data
01061             return;
01062         };
01063         int index=-1;
01064         if(m_currentLens->CalibDistortion)
01065         {
01066             for(int i=0;m_currentLens->CalibDistortion[i];i++)
01067             {
01068                 if(abs(m_currentLens->CalibDistortion[i]->Focal-focal)<0.05)
01069                 {
01070                     index=i;
01071                     break;
01072                 };
01073             };
01074         };
01075         if(index>-1)
01076         {
01077             m_currentLens->RemoveCalibDistortion(index);
01078         };
01079         lfLensCalibDistortion lcd;
01080         lcd.Focal=focal;
01081         lcd.Model=LF_DIST_MODEL_PTLENS;
01082         lcd.Terms[0]=distortion[0];
01083         lcd.Terms[1]=distortion[1];
01084         lcd.Terms[2]=distortion[2];
01085         m_currentLens->AddCalibDistortion(&lcd);
01086     };
01087 };
01088 
01089 void LensDB::SaveVignetting(double focal, double aperture, double distance, std::vector<double> vignetting)
01090 {
01091     if(m_currentLens)
01092     {
01093         if(vignetting.size()!=4)
01094         {
01095             //skip invalid vignetting data
01096             return;
01097         };
01098         int index=-1;
01099         if(m_currentLens->CalibVignetting)
01100         {
01101             for(int i=0;m_currentLens->CalibVignetting[i];i++)
01102             {
01103                 if(abs(m_currentLens->CalibVignetting[i]->Focal-focal)<0.05 &&
01104                    abs(m_currentLens->CalibVignetting[i]->Aperture-aperture)<0.05 &&
01105                    abs(m_currentLens->CalibVignetting[i]->Distance-distance)<0.05)
01106                 {
01107                     index=i;
01108                     break;
01109                 };
01110             };
01111         };
01112         if(index>-1)
01113         {
01114             m_currentLens->RemoveCalibVignetting(index);
01115         };
01116         lfLensCalibVignetting lcv;
01117         lcv.Focal=focal;
01118         lcv.Aperture=aperture;
01119         lcv.Distance=distance;
01120         lcv.Model=LF_VIGNETTING_MODEL_PA;
01121         lcv.Terms[0]=vignetting[1];
01122         lcv.Terms[1]=vignetting[2];
01123         lcv.Terms[2]=vignetting[3];
01124         m_currentLens->AddCalibVignetting(&lcv);
01125     };
01126 };
01127 
01128 bool LensDB::EndSaveLens()
01129 {
01130     lfError e=LF_WRONG_FORMAT;
01131     if(m_newDB!=NULL)
01132     {
01133 #if LF_VERSION < MIN_LF_VERSION
01134         // lensfun does not set correctly the numeric locale for saving
01135         char * old_locale = setlocale(LC_NUMERIC,NULL);
01136         old_locale = strdup(old_locale);
01137         setlocale(LC_NUMERIC,"C");
01138 #endif
01139         m_currentLens->Check();
01140         if(m_updatedMounts!=NULL)
01141         {
01142             e=m_newDB->Save(m_lensFilename.c_str(),m_updatedMounts,m_newDB->GetCameras(),m_updatedLenses);
01143         }
01144         else
01145         {
01146             e=m_newDB->Save(m_lensFilename.c_str(),m_newDB->GetMounts(),m_newDB->GetCameras(),m_updatedLenses);
01147         };
01148         m_lensFilename.clear();
01149 #if LF_VERSION < MIN_LF_VERSION
01150         setlocale(LC_NUMERIC,old_locale);
01151         free(old_locale);
01152 #endif
01153         CleanSaveInformation();
01154     };
01155     return e==LF_NO_ERROR;
01156 };
01157 
01158 void LensDB::CleanSaveInformation()
01159 {
01160     CleanUpdatedMounts();
01161     if (m_updatedLenses!=NULL)
01162     {
01163         for (int i = 0; m_updatedLenses[i]; i++)
01164         {
01165             delete m_updatedLenses[i];
01166         };
01167         delete []m_updatedLenses;
01168         m_updatedLenses=NULL;
01169     };
01170     if(m_newDB!=NULL)
01171     {
01172         m_newDB->Destroy();
01173         m_newDB=NULL;
01174     };
01175 };
01176 
01177 bool LensDB::IsNewMount(std::string newMount)
01178 {
01179     CleanUpdatedMounts();
01180     //check, if mount is already in main database
01181     const lfMount* mount=m_db->FindMount(newMount.c_str());
01182     if(mount)
01183     {
01184         return false;
01185     };
01186     //check, if mount is already in new file
01187     mount=NULL;
01188     mount=m_newDB->FindMount(newMount.c_str());
01189     if(mount)
01190     {
01191         return false;
01192     };
01193     //we have a new mount
01194     const lfMount *const* allMounts=m_newDB->GetMounts();
01195     size_t nrMounts=0;
01196     if(allMounts)
01197     {
01198         for(size_t i=0;allMounts[i];i++)
01199         {
01200             nrMounts++;
01201         };
01202     };
01203     nrMounts++;
01204 
01205     //build the updated list
01206     //lensfun does not provide an easy way to add a new camera, so we are using this ugly workaround
01207     m_updatedMounts=new lfMount*[nrMounts+1];
01208     m_updatedMounts[nrMounts]=NULL;
01209 
01210     for(size_t i=0;allMounts[i];i++)
01211     {
01212         //lf_mount_copy(m_updatedMounts[i],allMounts[i]);
01213         m_updatedMounts[i]=new lfMount(*allMounts[i]);
01214     };
01215 
01216     m_updatedMounts[nrMounts-1]=new lfMount();
01217     m_updatedMounts[nrMounts-1]->SetName(newMount.c_str());
01218     m_updatedMounts[nrMounts-1]->AddCompat("Generic");
01219     return true;
01220 };
01221 
01222 void LensDB::CleanUpdatedMounts()
01223 {
01224     if (m_updatedMounts!=NULL)
01225     {
01226         for (int i = 0; m_updatedMounts[i]; i++)
01227         {
01228             delete m_updatedMounts[i];
01229         };
01230         delete []m_updatedMounts;
01231         m_updatedMounts=NULL;
01232     };
01233 };
01234 
01235 LensDBList::LensDBList()
01236 {
01237     m_lenses=NULL;
01238 };
01239 
01240 LensDBList::~LensDBList()
01241 {
01242     if(m_lenses)
01243     {
01244         lf_free(m_lenses);
01245     };
01246 };
01247 
01248 const size_t LensDBList::GetLensCount() const
01249 {
01250     return m_lensCount;
01251 };
01252 
01253 const lfLens* LensDBList::GetLens(size_t index) const
01254 {
01255     if(index<m_lensCount)
01256     {
01257         return m_lenses[index];
01258     }
01259     else
01260     {
01261         return NULL;
01262     };
01263 };
01264 
01265 void LensDBList::SetLenses(const lfLens** lenses)
01266 {
01267     if(m_lenses)
01268     {
01269         lf_free(m_lenses);
01270     };
01271     m_lenses=lenses;
01272     m_lensCount=0;
01273     if(m_lenses)
01274     {
01275         for(size_t i=0;m_lenses[i];i++)
01276         {
01277             m_lensCount++;
01278         };
01279     };
01280 };
01281 
01282 std::string LensDBList::GetLensName(size_t index) const
01283 {
01284     if(index>=m_lensCount)
01285     {
01286         return "";
01287     };
01288     std::string lensname=m_lenses[index]->Model;
01289     if(lensname=="Standard")
01290     {
01291         return m_camModel + " (" + m_camMaker + ")";
01292     }
01293     else
01294     {
01295         return lensname + " (Focal length multiplier: " + hugin_utils::doubleToString(m_lenses[index]->CropFactor,1) +")";
01296     };
01297 };
01298 
01299 void LensDBList::SetCameraModelMaker(const std::string camMaker, const std::string camModel)
01300 {
01301     m_camMaker=camMaker;
01302     m_camModel=camModel;
01303 };
01304 
01305 } //namespace LensDB
01306 } //namespace HuginBase

Generated on Sun Apr 20 01:25:40 2014 for Hugintrunk by  doxygen 1.3.9.1