Exiv2Helper.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00011 /*
00012  *  This is free software; you can redistribute it and/or
00013  *  modify it under the terms of the GNU General Public
00014  *  License as published by the Free Software Foundation; either
00015  *  version 2 of the License, or (at your option) any later version.
00016  *
00017  *  This software is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  *  Lesser General Public License for more details.
00021  *
00022  *  You should have received a copy of the GNU General Public
00023  *  License along with this software. If not, see
00024  *  <http://www.gnu.org/licenses/>.
00025  *
00026  */
00027 
00028 #include "Exiv2Helper.h"
00029 #include "hugin_math/hugin_math.h"
00030 #include "hugin_utils/utils.h"  
00031 #include "exiv2/easyaccess.hpp"
00032 
00033 namespace HuginBase
00034 {
00035     namespace Exiv2Helper
00036     {
00037 
00038         bool _getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, long & value)
00039         {
00040             Exiv2::ExifData::iterator itr = exifData.findKey(Exiv2::ExifKey(keyName));
00041             if (itr != exifData.end() && itr->count())
00042             {
00043                 value = itr->toLong();
00044                 return true;
00045             }
00046             else
00047             {
00048                 return false;
00049             };
00050         };
00051 
00052         bool _getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, float & value)
00053         {
00054             Exiv2::ExifData::iterator itr = exifData.findKey(Exiv2::ExifKey(keyName));
00055             if (itr != exifData.end() && itr->count())
00056             {
00057                 value = itr->toFloat();
00058                 return true;
00059             }
00060             else
00061             {
00062                 return false;
00063             };
00064         };
00065 
00066         bool _getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, std::string & value)
00067         {
00068             Exiv2::ExifData::iterator itr = exifData.findKey(Exiv2::ExifKey(keyName));
00069             if (itr != exifData.end() && itr->count())
00070             {
00071                 value = itr->toString();
00072                 return true;
00073             }
00074             else
00075             {
00076                 return false;
00077             };
00078         }
00079 
00080         bool _getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, std::vector<float> & values)
00081         {
00082             values.clear();
00083             Exiv2::ExifData::iterator itr = exifData.findKey(Exiv2::ExifKey(keyName));
00084             if (itr != exifData.end() && itr->count())
00085             {
00086                 for(long i=0; i<itr->count(); i++)
00087                 {
00088                     values.push_back(itr->toFloat(i));
00089                 };
00090                 return true;
00091             }
00092             else
00093             {
00094                 return false;
00095             }
00096         }
00097 
00098         bool _getExiv2Value(Exiv2::ExifData& exifData, uint16_t tagID, std::string groupName, std::string & value)
00099         {
00100             Exiv2::ExifData::iterator itr = exifData.findKey(Exiv2::ExifKey(tagID, groupName));
00101             if (itr != exifData.end() && itr->count())
00102             {
00103                 value = itr->toString();
00104                 return true;
00105             }
00106             else
00107             {
00108                 return false;
00109             };
00110         };
00111 
00112         bool _getExiv2Value(Exiv2::ExifData& exifData, uint16_t tagID, std::string groupName, double & value)
00113         {
00114             Exiv2::ExifData::iterator itr = exifData.findKey(Exiv2::ExifKey(tagID, groupName));
00115             if (itr != exifData.end() && itr->count())
00116             {
00117                 value = itr->toFloat();
00118                 return true;
00119             }
00120             else
00121             {
00122                 return false;
00123             }
00124         }
00125 
00126         const double getExiv2ValueDouble(Exiv2::ExifData& exifData, Exiv2::ExifData::const_iterator it)
00127         {
00128             if(it!=exifData.end() && it->count())
00129             {
00130                 return it->toFloat();
00131             }
00132             return 0;
00133         };
00134 
00135         const double getExiv2ValueDouble(Exiv2::ExifData& exifData, std::string keyName)
00136         {
00137             float d;
00138             if(_getExiv2Value(exifData, keyName, d))
00139             {
00140                 return d;
00141             }
00142             return 0;
00143         };
00144 
00145         const std::string getExiv2ValueString(Exiv2::ExifData& exifData,Exiv2::ExifData::const_iterator it)
00146         {
00147             if(it!=exifData.end() && it->count())
00148             {
00149                 return hugin_utils::StrTrim(it->toString());
00150             };
00151             return std::string("");
00152         };
00153 
00154         const std::string getExiv2ValueString(Exiv2::ExifData& exifData, std::string keyName)
00155         {
00156             std::string s;
00157             if(_getExiv2Value(exifData, keyName, s))
00158             {
00159                 return hugin_utils::StrTrim(s);
00160             }
00161             return std::string("");
00162         };
00163 
00164         const long getExiv2ValueLong(Exiv2::ExifData& exifData, Exiv2::ExifData::const_iterator it)
00165         {
00166             if(it!=exifData.end() && it->count())
00167             {
00168                 return it->toLong();
00169             }
00170             return 0;
00171         };
00172 
00173         const long getExiv2ValueLong(Exiv2::ExifData& exifData, std::string keyName)
00174         {
00175             long l;
00176             if(_getExiv2Value(exifData, keyName, l))
00177             {
00178                 return l;
00179             }
00180             return 0;
00181         };
00182         
00183         //for diagnostic
00184         void PrintTag(Exiv2::ExifData::iterator itr)
00185         {
00186             std::cout << itr->value() << " (" << itr->typeName() << ", size: " << itr->count() << ")" << std::endl;
00187             if(itr->count()>1)
00188             {
00189                 std::cout << "[";
00190                 for(long i=0; i<itr->count(); i++)
00191                 {
00192                     std::cout << itr->toFloat(i) << ",";
00193                 }
00194                 std::cout << "]" << std::endl;
00195             };
00196         };
00197 
00198         bool readRedBlueBalance(Exiv2::ExifData &exifData, double & redBalance, double & blueBalance)
00199         {
00200             redBalance=1.0;
00201             blueBalance=1.0;
00202             //Panasonic makernotes (also some Leica cams)
00203             float val1=0, val2=0, val3=0;
00204             std::vector<float> values;
00205             if(_getExiv2Value(exifData, "Exif.Panasonic.WBRedLevel", val1) &&
00206                _getExiv2Value(exifData, "Exif.Panasonic.WBGreenLevel", val2) &&
00207                _getExiv2Value(exifData, "Exif.Panasonic.WBBlueLevel", val3))
00208             {
00209                 if(val1!=0 && val2!=0 && val3!=0)
00210                 {
00211                     redBalance=val1 / val2;;
00212                     blueBalance=val3 / val2;
00213                     return true;
00214                 }
00215                 else
00216                 {
00217                     return false;
00218                 };
00219             };
00220             // Pentax makernotes
00221             if (_getExiv2Value(exifData, "Exif.Pentax.RedBalance", val1) &&
00222                 _getExiv2Value(exifData, "Exif.Pentax.BlueBalance", val2))
00223             {
00224                 if(val1!=0 && val2!=0)
00225                 {
00226                     redBalance=val1 / 8192.0;
00227                     blueBalance=val2 / 8192.0;
00228                     return true;
00229                 }
00230                 else
00231                 {
00232                     return false;
00233                 };
00234             };
00235 #if EXIV2_TEST_VERSION(0,23,0)
00236             if (_getExiv2Value(exifData, "Exif.PentaxDng.RedBalance", val1) &&
00237                 _getExiv2Value(exifData, "Exif.PentaxDng.BlueBalance", val2))
00238             {
00239                 if(val1!=0 && val2!=0)
00240                 {
00241                     redBalance=val1 / 256.0;
00242                     blueBalance=val2 / 256.0;
00243                     return true;
00244                 }
00245                 else
00246                 {
00247                     return false;
00248                 };
00249             };
00250 #endif
00251             //Olympus makernotes
00252             if (_getExiv2Value(exifData, "Exif.Olympus.RedBalance", val1) &&
00253                 _getExiv2Value(exifData, "Exif.Olympus.BlueBalance", val2))
00254             {
00255                 if(val1!=0 && val2!=0)
00256                 {
00257                     redBalance=val1 / 256.0;
00258                     blueBalance=val2 / 256.0;
00259                     return true;
00260                 }
00261                 else
00262                 {
00263                     return false;
00264                 };
00265             };
00266             if(_getExiv2Value(exifData, "Exif.OlympusIp.WB_RBLevels", values))
00267             {
00268                 if(values.size()>=2)
00269                 {
00270                     if(values[0]!=0 && values[1]!=0)
00271                     {
00272                         redBalance=values[0]/256.0;
00273                         blueBalance=values[1]/256.0;
00274                         return true;
00275                     }
00276                     else
00277                     {
00278                         return false;
00279                     };
00280                 }
00281                 else
00282                 {
00283                     return false;
00284                 };
00285             };
00286             // Nikon makernotes
00287             if(_getExiv2Value(exifData, "Exif.Nikon3.WB_RBLevels", values))
00288             {
00289                 if(values.size()>=2)
00290                 {
00291                     if(values[0]!=0 && values[1]!=0)
00292                     {
00293                         redBalance=values[0];
00294                         blueBalance=values[1];
00295                         return true;
00296                     }
00297                     else
00298                     {
00299                         return false;
00300                     };
00301                 }
00302                 else
00303                 {
00304                     return false;
00305                 };
00306             };
00307             if(_getExiv2Value(exifData, "Exif.NikonCb1.WB_RBGGLevels", values))
00308             {
00309                 if(values.size()==4)
00310                 {
00311                     if(values[0]!=0 && values[1]!=0 && values[2]!=0 && values[3]!=0)
00312                     {
00313                         redBalance=values[0] / values[2];
00314                         blueBalance=values[1] / values[2];
00315                         return true;
00316                     }
00317                     else
00318                     {
00319                         return false;
00320                     };
00321                 }
00322                 else
00323                 {
00324                     return false;
00325                 };
00326             };
00327             if(_getExiv2Value(exifData, "Exif.NikonCb2.WB_RGGBLevels", values))
00328             {
00329                 if(values.size()==4)
00330                 {
00331                     if(values[0]!=0 && values[1]!=0 && values[2]!=0 && values[3]!=0)
00332                     {
00333                         redBalance=values[0] / values[1];
00334                         blueBalance=values[3] / values[1];
00335                         return true;
00336                     }
00337                     else
00338                     {
00339                         return false;
00340                     };
00341                 }
00342                 else
00343                 {
00344                     return false;
00345                 };
00346             };
00347             if(_getExiv2Value(exifData, "Exif.NikonCb2a.WB_RGGBLevels", values))
00348             {
00349                 if(values.size()==4)
00350                 {
00351                     if(values[0]!=0 && values[1]!=0 && values[2]!=0 && values[3]!=0)
00352                     {
00353                         redBalance=values[0] / values[1];
00354                         blueBalance=values[3] / values[1];
00355                         return true;
00356                     }
00357                     else
00358                     {
00359                         return false;
00360                     };
00361                 }
00362                 else
00363                 {
00364                     return false;
00365                 };
00366             };
00367             if(_getExiv2Value(exifData, "Exif.NikonCb2b.WB_RGGBLevels", values))
00368             {
00369                 if(values.size()==4)
00370                 {
00371                     if(values[0]!=0 && values[1]!=0 && values[2]!=0 && values[3]!=0)
00372                     {
00373                         redBalance=values[0] / values[1];
00374                         blueBalance=values[3] / values[1];
00375                         return true;
00376                     }
00377                     else
00378                     {
00379                         return false;
00380                     };
00381                 }
00382                 else
00383                 {
00384                     return false;
00385                 };
00386             };
00387             if(_getExiv2Value(exifData, "Exif.NikonCb3.WB_RGBGLevels", values))
00388             {
00389                 if(values.size()==4)
00390                 {
00391                     if(values[0]!=0 && values[1]!=0 && values[2]!=0 && values[3]!=0)
00392                     {
00393                         redBalance=values[0] / values[1];
00394                         blueBalance=values[2] / values[3];
00395                         return true;
00396                     }
00397                     else
00398                     {
00399                         return false;
00400                     };
00401                 }
00402                 else
00403                 {
00404                     return false;
00405                 };
00406             };
00407 
00408             return false;
00409         };
00410 
00411         const double getCropFactor(Exiv2::ExifData &exifData, long width, long height)
00412         {
00413             double cropFactor=0;
00414             // some cameras do not provide Exif.Image.ImageWidth / Length
00415             // notably some Olympus
00416             long eWidth = 0;
00417             _getExiv2Value(exifData,"Exif.Image.ImageWidth",eWidth);
00418 
00419             long eLength = 0;
00420             _getExiv2Value(exifData,"Exif.Image.ImageLength",eLength);
00421 
00422             double sensorPixelWidth = 0;
00423             double sensorPixelHeight = 0;
00424             if (eWidth > 0 && eLength > 0)
00425             {
00426                 sensorPixelHeight = (double)eLength;
00427                 sensorPixelWidth = (double)eWidth;
00428             }
00429             else
00430             {
00431                 // No EXIF information, use number of pixels in image
00432                 sensorPixelWidth = width;
00433                 sensorPixelHeight = height;
00434             }
00435 
00436             // force landscape sensor orientation
00437             if (sensorPixelWidth < sensorPixelHeight )
00438             {
00439                 double t = sensorPixelWidth;
00440                 sensorPixelWidth = sensorPixelHeight;
00441                 sensorPixelHeight = t;
00442             }
00443 
00444             DEBUG_DEBUG("sensorPixelWidth: " << sensorPixelWidth);
00445             DEBUG_DEBUG("sensorPixelHeight: " << sensorPixelHeight);
00446 
00447             // some cameras do not provide Exif.Photo.FocalPlaneResolutionUnit
00448             // notably some Olympus
00449 
00450             long exifResolutionUnits = 0;
00451             _getExiv2Value(exifData,"Exif.Photo.FocalPlaneResolutionUnit",exifResolutionUnits);
00452 
00453             float resolutionUnits= 0;
00454             switch (exifResolutionUnits)
00455             {
00456                 case 3: resolutionUnits = 10.0f; break;  //centimeter
00457                 case 4: resolutionUnits = 1.0f; break;   //millimeter
00458                 case 5: resolutionUnits = .001f; break;  //micrometer
00459                 default: resolutionUnits = 25.4f; break; //inches
00460             }
00461 
00462             DEBUG_DEBUG("Resolution Units: " << resolutionUnits);
00463 
00464             // some cameras do not provide Exif.Photo.FocalPlaneXResolution and
00465             // Exif.Photo.FocalPlaneYResolution, notably some Olympus
00466             float fplaneXresolution = 0;
00467             _getExiv2Value(exifData,"Exif.Photo.FocalPlaneXResolution",fplaneXresolution);
00468 
00469             float fplaneYresolution = 0;
00470             _getExiv2Value(exifData,"Exif.Photo.FocalPlaneYResolution",fplaneYresolution);
00471 
00472             float CCDWidth = 0;
00473             if (fplaneXresolution != 0)
00474             {
00475                 CCDWidth = (float)(sensorPixelWidth / ( fplaneXresolution / resolutionUnits));
00476             }
00477 
00478             float CCDHeight = 0;
00479             if (fplaneYresolution != 0)
00480             {
00481                 CCDHeight = (float)(sensorPixelHeight / ( fplaneYresolution / resolutionUnits));
00482             }
00483 
00484             DEBUG_DEBUG("CCDHeight:" << CCDHeight);
00485             DEBUG_DEBUG("CCDWidth: " << CCDWidth);
00486 
00487             // calc sensor dimensions if not set and 35mm focal length is available
00488             hugin_utils::FDiff2D sensorSize;
00489             if (CCDHeight > 0 && CCDWidth > 0)
00490             {
00491                 // read sensor size directly.
00492                 sensorSize.x = CCDWidth;
00493                 sensorSize.y = CCDHeight;
00494                 std::string exifModel;
00495                 if(_getExiv2Value(exifData, "Exif.Image.Model", exifModel))
00496                 {
00497                     if (exifModel == "Canon EOS 20D")
00498                     {
00499                         // special case for buggy 20D camera
00500                         sensorSize.x = 22.5;
00501                         sensorSize.y = 15;
00502                     }
00503                 };
00504                 // check if sensor size ratio and image size fit together
00505                 double rsensor = (double)sensorSize.x / sensorSize.y;
00506                 double rimg = (double) width / height;
00507                 if ( (rsensor > 1 && rimg < 1) || (rsensor < 1 && rimg > 1) )
00508                 {
00509                     // image and sensor ratio do not match
00510                     // swap sensor sizes
00511                     float t;
00512                     t = sensorSize.y;
00513                     sensorSize.y = sensorSize.x;
00514                     sensorSize.x = t;
00515                 }
00516 
00517                 DEBUG_DEBUG("sensorSize.y: " << sensorSize.y);
00518                 DEBUG_DEBUG("sensorSize.x: " << sensorSize.x);
00519 
00520                 cropFactor = sqrt(36.0*36.0+24.0*24.0) /
00521                     sqrt(sensorSize.x*sensorSize.x + sensorSize.y*sensorSize.y);
00522                 // FIXME: HACK guard against invalid image focal plane definition in EXIF metadata with arbitrarly chosen limits for the crop factor ( 1/100 < crop < 100)
00523                 if (cropFactor < 0.1 || cropFactor > 100)
00524                 {
00525                     cropFactor = 0;
00526                 }
00527             }
00528             else
00529             {
00530                 // alternative way to calculate the crop factor for Olympus cameras
00531 
00532                 // Windows debug stuff
00533                 // left in as example on how to get "console output"
00534                 // written to a log file    
00535                 // freopen ("oly.log","a",stdout);
00536                 // fprintf (stdout,"Starting Alternative crop determination\n");
00537         
00538                 float olyFPD = 0;
00539                 _getExiv2Value(exifData,"Exif.Olympus.FocalPlaneDiagonal",olyFPD);
00540                 if (olyFPD > 0.0)
00541                 {
00542                     // Windows debug stuff
00543                     // fprintf(stdout,"Oly_FPD:");
00544                     // fprintf(stdout,"%f",olyFPD);
00545                     cropFactor = sqrt(36.0*36.0+24.0*24.0) / olyFPD;
00546                 }
00547                 else
00548                 {
00549                     // for newer Olympus cameras the FocalPlaneDiagonal tag was moved into
00550                     // equipment (sub?)-directory, so check also there
00551                     _getExiv2Value(exifData,"Exif.OlympusEq.FocalPlaneDiagonal",olyFPD);
00552                     if (olyFPD > 0.0)
00553                     {
00554                         cropFactor = sqrt(36.0*36.0+24.0*24.0) / olyFPD;
00555                     };
00556                 };
00557             };
00558             return cropFactor;
00559         };
00560 
00561         const std::string getLensName(Exiv2::ExifData &exifData)
00562         {
00563             std::string lensName;
00564             // first we are reading LensModel in Exif section, this is only available
00565             // with EXIF >= 2.3
00566 #if EXIV2_TEST_VERSION(0,22,0)
00567             //the string "Exif.Photo.LensModel" is only defined in exiv2 0.22.0 and above
00568             if(_getExiv2Value(exifData, "Exif.Photo.LensModel", lensName))
00569 #else
00570             if(_getExiv2Value(exifData, 0xa434, "Photo", lensName))
00571 #endif
00572             {
00573                 if(lensName.length()>0)
00574                 {
00575                     return lensName;
00576                 };
00577             }
00578             else
00579             {
00580                 //no lens in Exif found, now look in makernotes
00581                 Exiv2::ExifData::const_iterator itr2 = Exiv2::lensName(exifData);
00582                 if (itr2!=exifData.end() && itr2->count())
00583                 {
00584                     //we are using prettyPrint function to get string of lens name
00585                     //it2->toString returns for many cameras only an ID number
00586                     lensName=itr2->print(&exifData);
00587                     //check returned lens name
00588                     if(lensName.length()>0)
00589                     {
00590                         //for Canon it can contain (65535) or (0) for unknown lenses
00591                         //for Pentax it can contain Unknown (0xHEX)
00592                         if(lensName.compare(0, 1, "(")!=0 && lensName.compare(0, 7, "Unknown")!=0)
00593                         {
00594                             return lensName;
00595                         }
00596                     };
00597                 };
00598             };
00599             return std::string("");
00600         };
00601 
00602     }; //namespace Exiv2Helper
00603 }; //namespace HuginBase

Generated on 26 Apr 2018 for Hugintrunk by  doxygen 1.4.7