@ -25,6 +25,7 @@
*/
// *****************************************************************************
// included header files
# include "error.hpp"
# include "types.hpp"
# include "makernote_int.hpp"
# include "canonmn_int.hpp"
@ -34,6 +35,7 @@
# include "i18n.h" // NLS support.
// + standard includes
# include <regex>
# include <string>
# include <sstream>
# include <iomanip>
@ -54,18 +56,8 @@ namespace Exiv2 {
{ 1 , N_ ( " On " ) }
} ;
//! Special treatment pretty-print function for non-unique lens ids.
std : : ostream & printCsLensByFocalLengthAndMaxAperture ( std : : ostream & os ,
const Value & value ,
const ExifData * metadata ) ;
//! Special treatment pretty-print function for non-unique lens ids.
std : : ostream & printCsLensByFocalLength ( std : : ostream & os ,
const Value & value ,
const ExifData * metadata ) ;
//! Special treatment pretty-print function for non-unique lens ids.
std : : ostream & printCsLensByFocalLengthTC ( std : : ostream & os ,
const Value & value ,
const ExifData * metadata ) ;
std : : ostream & printCsLensTypeByMetadata ( std : : ostream & os , const Value & value , const ExifData * metadata ) ;
//! Special treatment pretty-print function for non-unique lens ids.
std : : ostream & printCsLensFFFF ( std : : ostream & os ,
const Value & value ,
@ -1972,10 +1964,9 @@ namespace Exiv2 {
{ 368 , " Sigma 150-600mm f/5-6.3 DG OS HSM | S " } , // 6
{ 368 , " Sigma 85mm f/1.4 DG HSM | A " } , // 7
{ 368 , " Sigma 105mm f/1.4 DG HSM " } , // 8
{ 368 , " Sigma 14-24mm f/2.8 DG HSM " } , // 9
{ 368 , " Sigma 70mm f/2.8 DG Macro " } , // 10
{ 368 , " Sigma 18-35mm f/1.8 DC HSM | A " } , // 11
{ 368 , " Sigma 35mm f/1.4 DG HSM | A " } , // 12
{ 368 , " Sigma 70mm f/2.8 DG Macro " } , // 9
{ 368 , " Sigma 18-35mm f/1.8 DC HSM | A " } , // 10
{ 368 , " Sigma 35mm f/1.4 DG HSM | A " } , // 11
{ 488 , " Canon EF-S 15-85mm f/3.5-5.6 IS USM " } ,
{ 489 , " Canon EF 70-300mm f/4-5.6L IS USM " } ,
{ 490 , " Canon EF 8-15mm f/4L Fisheye USM " } ,
@ -2078,70 +2069,6 @@ namespace Exiv2 {
{ 65535 , " n/a " }
} ;
//! A lens id and a pretty-print function for special treatment of the id.
struct LensIdFct {
long id_ ; //!< Lens id
PrintFct fct_ ; //!< Pretty-print function
//! Comparison operator for find template
bool operator = = ( long id ) const { return id_ = = id ; }
} ;
//! List of lens ids which require special treatment with the medicine
const LensIdFct lensIdFct [ ] = {
{ 4 , printCsLensByFocalLength } , // not tested
{ 6 , printCsLensByFocalLength } ,
{ 8 , printCsLensByFocalLength } ,
{ 9 , printCsLensByFocalLength } ,
{ 10 , printCsLensByFocalLengthAndMaxAperture } , // works partly
{ 22 , printCsLensByFocalLength } ,
{ 26 , printCsLensByFocalLengthAndMaxAperture } , // works partly
{ 28 , printCsLensByFocalLength } ,
{ 31 , printCsLensByFocalLength } ,
{ 32 , printCsLensByFocalLength } ,
{ 33 , printCsLensByFocalLengthAndMaxAperture } , // works partly
{ 37 , printCsLensByFocalLength } ,
{ 42 , printCsLensByFocalLength } ,
{ 47 , printCsLensByFocalLength } , // not tested
{ 131 , printCsLensByFocalLength } ,
{ 136 , printCsLensByFocalLength } ,
{ 137 , printCsLensByFocalLength } , // not tested
{ 143 , printCsLensByFocalLength } ,
{ 150 , printCsLensByFocalLength } ,
{ 152 , printCsLensByFocalLength } ,
{ 153 , printCsLensByFocalLength } ,
{ 154 , printCsLensByFocalLength } , // not tested
{ 155 , printCsLensByFocalLength } ,
{ 156 , printCsLensByFocalLengthAndMaxAperture } ,
{ 160 , printCsLensByFocalLength } ,
{ 161 , printCsLensByFocalLength } ,
{ 168 , printCsLensByFocalLength } ,
{ 169 , printCsLensByFocalLengthAndMaxAperture } ,
{ 172 , printCsLensByFocalLengthTC } , // not tested
{ 173 , printCsLensByFocalLengthTC } , // works partly
{ 174 , printCsLensByFocalLength } , // not tested
{ 197 , printCsLensByFocalLength } ,
{ 180 , printCsLensByFocalLength } ,
{ 181 , printCsLensByFocalLengthTC } , // not tested
{ 182 , printCsLensByFocalLengthTC } , // not tested
{ 183 , printCsLensByFocalLength } , // not tested
{ 198 , printCsLensByFocalLength } , // not tested
{ 213 , printCsLensByFocalLength } , // not tested
{ 234 , printCsLensByFocalLength } , // not tested
{ 248 , printCsLensByFocalLength } , // not tested
{ 250 , printCsLensByFocalLength } , // not tested
{ 254 , printCsLensByFocalLength } ,
{ 255 , printCsLensByFocalLength } , // not tested
{ 368 , printCsLensByFocalLengthAndMaxAperture } ,
{ 491 , printCsLensByFocalLength } ,
{ 493 , printCsLensByFocalLength } , // not tested
{ 624 , printCsLensByFocalLengthTC } ,
{ 747 , printCsLensByFocalLength } , // not tested
{ 4143 , printCsLensByFocalLength } , // not tested
{ 4154 , printCsLensByFocalLength } , // not tested
{ 61182 , printCsLensByFocalLength } ,
{ 0xffff , printCsLensFFFF }
} ;
//! FlashActivity, tag 0x001c
constexpr TagDetails canonCsFlashActivity [ ] = {
{ 0 , N_ ( " Did not fire " ) } ,
@ -2805,152 +2732,97 @@ namespace Exiv2 {
return EXV_PRINT_TAG ( canonCsLensType ) ( os , value , metadata ) ;
}
//! Helper structure
struct LensTypeAndFocalLengthAndMaxAperture {
long lensType_ ; //!< Lens type
float focalLengthMin_ ; //!< Mininum focal length
float focalLengthMax_ ; //!< Maximum focal length
std : : string focalLength_ ; //!< Focal length as a string
std : : string maxAperture_ ; //!< Aperture
} ;
//! Compare tag details with a lens entry
bool operator = = ( const TagDetails & td , const LensTypeAndFocalLengthAndMaxAperture & ltfl ) {
return ( td . val_ = = ltfl . lensType_
& & std : : string ( td . label_ ) . find ( ltfl . focalLength_ ) ! = std : : string : : npos
& & std : : string ( td . label_ ) . find ( ltfl . maxAperture_ ) ! = std : : string : : npos ) ;
}
//! extractLensFocalLength from metadata
void extractLensFocalLength ( LensTypeAndFocalLengthAndMaxAperture & ltfl ,
const ExifData * metadata )
std : : ostream & printCsLensTypeByMetadata ( std : : ostream & os , const Value & value , const ExifData * metadata )
{
ExifKey key ( " Exif.CanonCs.Lens " ) ;
auto pos = metadata - > findKey ( key ) ;
ltfl . focalLengthMin_ = 0.0F ;
ltfl . focalLengthMax_ = 0.0F ;
if ( pos ! = metadata - > end ( ) ) {
const Value & value = pos - > value ( ) ;
if ( value . count ( ) > = 3
& & value . typeId ( ) = = unsignedShort ) {
float fu = value . toFloat ( 2 ) ;
if ( fu ! = 0.0F ) {
ltfl . focalLengthMin_ = value . toLong ( 1 ) / fu ;
ltfl . focalLengthMax_ = value . toLong ( 0 ) / fu ;
}
}
}
}
//! convertFocalLength to a human readable string
void convertFocalLength ( LensTypeAndFocalLengthAndMaxAperture & ltfl , float divisor )
{
std : : ostringstream oss ;
oss < < std : : fixed < < std : : setprecision ( 0 ) ;
if ( ltfl . focalLengthMin_ = = ltfl . focalLengthMax_ ) {
oss < < " " < < ( ltfl . focalLengthMin_ / divisor ) < < " mm " ;
} else {
oss < < " " < < ( ltfl . focalLengthMin_ / divisor ) < < " - " < < ( ltfl . focalLengthMax_ / divisor ) < < " mm " ;
}
ltfl . focalLength_ = oss . str ( ) ;
}
//! printCsLensByFocalLengthAndMaxAperture to human readable string
std : : ostream & printCsLensByFocalLengthAndMaxAperture ( std : : ostream & os ,
const Value & value ,
const ExifData * metadata )
{
if ( ! metadata | | value . typeId ( ) ! = unsignedShort
| | value . count ( ) = = 0 ) return os < < value ;
LensTypeAndFocalLengthAndMaxAperture ltfl ;
ltfl . lensType_ = value . toLong ( ) ;
extractLensFocalLength ( ltfl , metadata ) ;
if ( ltfl . focalLengthMax_ = = 0.0F )
if ( ! metadata | | value . typeId ( ) ! = unsignedShort | | value . count ( ) = = 0 )
return os < < value ;
convertFocalLength ( ltfl , 1.0F ) ;
ExifKey key ( " Exif.CanonCs.MaxAperture " ) ;
auto pos = metadata - > findKey ( key ) ;
if ( pos ! = metadata - > end ( )
& & pos - > value ( ) . count ( ) = = 1
& & pos - > value ( ) . typeId ( ) = = unsignedShort ) {
auto const lensType = value . toLong ( ) ;
long val = static_cast < int16_t > ( pos - > value ( ) . toLong ( 0 ) ) ;
if ( val > 0 )
{
std : : ostringstream oss ;
oss < < std : : setprecision ( 2 ) ;
oss < < fnumber ( canonEv ( val ) ) ;
ltfl . maxAperture_ = oss . str ( ) ;
}
if ( lensType = = 0xffff ) {
return printCsLensFFFF ( os , value , metadata ) ;
}
if ( ltfl . maxAperture_ . empty ( ) ) return os < < value ;
const TagDetails * td = find ( canonCsLensType , ltfl ) ;
if ( ! td ) return os < < value ;
return os < < td - > label_ ;
}
//! printCsLensByFocalLength to human readable string
std : : ostream & printCsLensByFocalLength ( std : : ostream & os ,
const Value & value ,
const ExifData * metadata )
{
if ( ! metadata | | value . typeId ( ) ! = unsignedShort
| | value . count ( ) = = 0 ) return os < < value ;
LensTypeAndFocalLengthAndMaxAperture ltfl ;
ltfl . lensType_ = value . toLong ( ) ;
// get the values we need from the metadata container
ExifKey lensKey ( " Exif.CanonCs.Lens " ) ;
auto pos = metadata - > findKey ( lensKey ) ;
// catch possible error cases
if ( pos = = metadata - > end ( ) or pos - > value ( ) . count ( ) < 3 or pos - > value ( ) . typeId ( ) ! = unsignedShort or
pos - > value ( ) . toFloat ( 2 ) = = 0.0F ) {
os < < " Unknown Lens ( " < < lensType < < " ) " ;
}
extractLensFocalLength ( ltfl , metadata ) ;
if ( ltfl . focalLengthMax_ = = 0.0F )
return os < < value ;
convertFocalLength ( ltfl , 1.0F ) ;
int const exifFlMin = pos - > value ( ) . toLong ( 1 ) / pos - > value ( ) . toFloat ( 2 ) ;
int const exifFlMax = pos - > value ( ) . toLong ( 0 ) / pos - > value ( ) . toFloat ( 2 ) ;
if ( ltfl . focalLength_ . empty ( ) ) return os < < value ;
ExifKey aperKey ( " Exif.CanonCs.MaxAperture " ) ;
pos = metadata - > findKey ( aperKey ) ;
if ( pos = = metadata - > end ( ) or pos - > value ( ) . count ( ) ! = 1 or pos - > value ( ) . typeId ( ) ! = unsignedShort ) {
os < < " Unknown Lens ( " < < lensType < < " ) " ;
}
const TagDetails * td = find ( canonCsLensType , ltfl ) ;
if ( ! td ) return os < < value ;
return os < < td - > label_ ;
}
auto exifAperMax = fnumber ( canonEv ( static_cast < int16_t > ( pos - > value ( ) . toLong ( 0 ) ) ) ) ;
// regex to extract short and tele focal length, max aperture at short and tele position
// and the teleconverter factor from the lens label
std : : regex const lens_regex (
// anything at the start
" .*? "
// maybe min focal length and hyphen, surely max focal length e.g.: 24-70mm
" (?:([0-9]+)-)?([0-9]+)mm "
// anything in-between
" .*? "
// maybe short focal length max aperture and hyphen, surely at least single max aperture e.g.: f/4.5-5.6
// short and tele indicate apertures at the short (focal_length_min) and tele (focal_length_max)
// position of the lens
" (?:(?:f \\ /)|T)(?:([0-9]+(?: \\ .[0-9]+)?)-)?([0-9]+(?: \\ .[0-9])?) "
// check if there is a teleconverter pattern e.g. + 1.4x
" (?:.*? \\ +.*?([0-9.]+)x)? "
) ;
bool unmatched = true ;
// we loop over all our lenses to print out all matching lenses
// if we have multiple possibilities, they are concatenated by "*OR*"
for ( auto const & lens : canonCsLensType ) {
if ( lens . val_ ! = lensType ) {
continue ;
}
//! printCsLensByFocalLengthTC to human readable string
std : : ostream & printCsLensByFocalLengthTC ( std : : ostream & os ,
const Value & value ,
const ExifData * metadata )
{
if ( ! metadata | | value . typeId ( ) ! = unsignedShort
| | value . count ( ) = = 0 ) return os < < value ;
std : : cmatch base_match ;
if ( not std : : regex_search ( lens . label_ , base_match , lens_regex ) ) {
// this should never happen, as it would indicate the lens is specified incorrectly
// in the CanonCsLensType array
throw Error ( kerErrorMessage , std : : string ( " Lens regex didn't match for: " ) + std : : string ( lens . label_ ) ) ;
}
LensTypeAndFocalLengthAndMaxAperture ltfl ;
ltfl . lensType_ = value . toLong ( ) ;
auto tc = base_match [ 5 ] . length ( ) > 0 ? std : : stof ( base_match [ 5 ] . str ( ) ) : 1.f ;
extractLensFocalLength ( ltfl , metadata ) ;
int flMax = std : : stoi ( base_match [ 2 ] . str ( ) ) * tc ;
int flMin = base_match [ 1 ] . length ( ) > 0 ? std : : stoi ( base_match [ 1 ] . str ( ) ) * tc : flMax ;
if ( ltfl . focalLengthMax_ = = 0.0 ) return os < < value ;
auto aperMaxTele = std : : stof ( base_match [ 4 ] . str ( ) ) * tc ;
auto aperMaxShort = base_match [ 3 ] . length ( ) > 0 ? std : : stof ( base_match [ 3 ] . str ( ) ) * tc : aperMaxTele ;
const TagDetails * td ;
const double factors [ ] = { 1.0 , 1.4 , 2.0 } ;
for ( const double & factor : factors )
{
convertFocalLength ( ltfl , factor ) ;
if ( flMin ! = exifFlMin or flMax ! = exifFlMax or exifAperMax < ( aperMaxShort - .1 ) or
exifAperMax > ( aperMaxTele + .1 ) ) {
continue ;
}
std : : ostringstream oss ;
oss < < std : : setprecision ( 2 ) ;
oss < < factor < < " x " ;
if ( unmatched ) {
unmatched = false ;
os < < lens . label_ ;
continue ;
}
ltfl . maxAperture_ = oss . str ( ) ;
td = find ( canonCsLensType , ltfl ) ;
if ( td ) break ;
os < < " *OR* " < < lens . label_ ;
}
ltfl . maxAperture_ = " " ;
td = find ( canonCsLensType , ltfl ) ;
if ( td ) break ;
// if the entire for loop left us with unmatched==false
// we weren't able to find a single matching lens :(
if ( unmatched ) {
os < < " Unknown Lens ( " < < lensType < < " ) " ;
}
if ( ! td ) return os < < value ;
return os < < td - > label_ ;
return os ;
}
//! printCsLensType by searching the config file if necessary
@ -2968,14 +2840,9 @@ namespace Exiv2 {
return os < < Internal : : readExiv2Config ( section , value . toString ( ) , undefined ) ;
}
const LensIdFct * lif = find ( lensIdFct , value . toLong ( ) ) ;
if ( ! lif ) {
return EXV_PRINT_TAG ( canonCsLensType ) ( os , value , metadata ) ;
}
if ( metadata & & lif - > fct_ ) {
return lif - > fct_ ( os , value , metadata ) ;
}
return os < < value ;
// try our best to determine the lens based on metadata
// sometimes the result will be a set of multiple choices
return printCsLensTypeByMetadata ( os , value , metadata ) ;
}
std : : ostream & CanonMakerNote : : printCsLens ( std : : ostream & os ,