File indexing completed on 2025-01-19 03:55:58
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2006-02-23 0007 * Description : item metadata interface - photo info helpers. 0008 * 0009 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0011 * SPDX-FileCopyrightText: 2011 by Leif Huhn <leif at dkstat dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "dmetadata.h" 0018 0019 // C++ includes 0020 0021 #include <cmath> 0022 0023 // Qt includes 0024 0025 #include <QLocale> 0026 0027 // Local includes 0028 0029 #include "metaenginesettings.h" 0030 #include "digikam_version.h" 0031 #include "digikam_globals.h" 0032 #include "digikam_debug.h" 0033 0034 namespace Digikam 0035 { 0036 0037 PhotoInfoContainer DMetadata::getPhotographInformation() const 0038 { 0039 PhotoInfoContainer photoInfo; 0040 0041 if (hasExif() || hasXmp()) 0042 { 0043 photoInfo.dateTime = getItemDateTime(); 0044 0045 // ----------------------------------------------------------------------------------- 0046 0047 photoInfo.make = getExifTagString("Exif.Image.Make"); 0048 0049 if (photoInfo.make.isEmpty()) 0050 { 0051 photoInfo.make = getXmpTagString("Xmp.tiff.Make"); 0052 } 0053 0054 if (photoInfo.make.isEmpty()) 0055 { 0056 photoInfo.make = getExifTagString("Exif.PanasonicRaw.Make"); 0057 } 0058 0059 // ----------------------------------------------------------------------------------- 0060 0061 photoInfo.model = getExifTagString("Exif.Image.Model"); 0062 0063 if (photoInfo.model.isEmpty()) 0064 { 0065 photoInfo.model = getXmpTagString("Xmp.tiff.Model"); 0066 } 0067 0068 if (photoInfo.model.isEmpty()) 0069 { 0070 photoInfo.model = getExifTagString("Exif.PanasonicRaw.Model"); 0071 } 0072 0073 // ----------------------------------------------------------------------------------- 0074 0075 photoInfo.lens = getLensDescription(); 0076 0077 // ----------------------------------------------------------------------------------- 0078 0079 photoInfo.aperture = getExifTagString("Exif.Photo.FNumber"); 0080 0081 if (photoInfo.aperture.isEmpty()) 0082 { 0083 photoInfo.aperture = getExifTagString("Exif.Image.FNumber"); 0084 } 0085 0086 if (photoInfo.aperture.isEmpty()) 0087 { 0088 photoInfo.aperture = getExifTagString("Exif.Photo.ApertureValue"); 0089 } 0090 0091 if (photoInfo.aperture.isEmpty()) 0092 { 0093 photoInfo.aperture = getXmpTagString("Xmp.exif.FNumber"); 0094 } 0095 0096 if (photoInfo.aperture.isEmpty()) 0097 { 0098 photoInfo.aperture = getXmpTagString("Xmp.exif.ApertureValue"); 0099 } 0100 0101 // ----------------------------------------------------------------------------------- 0102 0103 photoInfo.exposureTime = getExifTagString("Exif.Photo.ExposureTime"); 0104 0105 if (photoInfo.exposureTime.isEmpty()) 0106 { 0107 photoInfo.exposureTime = getExifTagString("Exif.Image.ExposureTime"); 0108 } 0109 0110 if (photoInfo.exposureTime.isEmpty()) 0111 { 0112 photoInfo.exposureTime = getExifTagString("Exif.Photo.ShutterSpeedValue"); 0113 } 0114 0115 if (photoInfo.exposureTime.isEmpty()) 0116 { 0117 photoInfo.exposureTime = getXmpTagString("Xmp.exif.ExposureTime"); 0118 } 0119 0120 if (photoInfo.exposureTime.isEmpty()) 0121 { 0122 photoInfo.exposureTime = getXmpTagString("Xmp.exif.ShutterSpeedValue"); 0123 } 0124 0125 // ----------------------------------------------------------------------------------- 0126 0127 photoInfo.exposureMode = getExifTagString("Exif.Photo.ExposureMode"); 0128 0129 if (photoInfo.exposureMode.isEmpty()) 0130 { 0131 photoInfo.exposureMode = getXmpTagString("Xmp.exif.ExposureMode"); 0132 } 0133 0134 if (photoInfo.exposureMode.isEmpty()) 0135 { 0136 photoInfo.exposureMode = getExifTagString("Exif.CanonCs.MeteringMode"); 0137 } 0138 0139 // ----------------------------------------------------------------------------------- 0140 0141 photoInfo.exposureProgram = getExifTagString("Exif.Photo.ExposureProgram"); 0142 0143 if (photoInfo.exposureProgram.isEmpty()) 0144 { 0145 photoInfo.exposureProgram = getXmpTagString("Xmp.exif.ExposureProgram"); 0146 } 0147 0148 if (photoInfo.exposureProgram.isEmpty()) 0149 { 0150 photoInfo.exposureProgram = getExifTagString("Exif.CanonCs.ExposureProgram"); 0151 } 0152 0153 // ----------------------------------------------------------------------------------- 0154 0155 photoInfo.focalLength = getExifTagString("Exif.Photo.FocalLength"); 0156 0157 if (photoInfo.focalLength.isEmpty()) 0158 { 0159 photoInfo.focalLength = getXmpTagString("Exif.Image.FocalLength"); 0160 } 0161 0162 if (photoInfo.focalLength.isEmpty()) 0163 { 0164 photoInfo.focalLength = getXmpTagString("Xmp.exif.FocalLength"); 0165 } 0166 0167 if (photoInfo.focalLength.isEmpty()) 0168 { 0169 photoInfo.focalLength = getExifTagString("Exif.Canon.FocalLength"); 0170 } 0171 0172 // ----------------------------------------------------------------------------------- 0173 0174 photoInfo.focalLength35mm = getExifTagString("Exif.Photo.FocalLengthIn35mmFilm"); 0175 0176 if (photoInfo.focalLength35mm.isEmpty()) 0177 { 0178 photoInfo.focalLength35mm = getXmpTagString("Xmp.exif.FocalLengthIn35mmFilm"); 0179 } 0180 0181 // ----------------------------------------------------------------------------------- 0182 0183 QStringList ISOSpeedTags; 0184 0185 ISOSpeedTags << QLatin1String("Exif.Photo.ISOSpeedRatings"); 0186 ISOSpeedTags << QLatin1String("Exif.Photo.ExposureIndex"); 0187 ISOSpeedTags << QLatin1String("Exif.Image.ISOSpeedRatings"); 0188 ISOSpeedTags << QLatin1String("Xmp.exif.ISOSpeedRatings"); 0189 ISOSpeedTags << QLatin1String("Xmp.exif.ExposureIndex"); 0190 ISOSpeedTags << QLatin1String("Exif.CanonSi.ISOSpeed"); 0191 ISOSpeedTags << QLatin1String("Exif.CanonCs.ISOSpeed"); 0192 ISOSpeedTags << QLatin1String("Exif.Nikon1.ISOSpeed"); 0193 ISOSpeedTags << QLatin1String("Exif.Nikon2.ISOSpeed"); 0194 ISOSpeedTags << QLatin1String("Exif.Nikon3.ISOSpeed"); 0195 ISOSpeedTags << QLatin1String("Exif.NikonIi.ISO"); 0196 ISOSpeedTags << QLatin1String("Exif.NikonIi.ISO2"); 0197 ISOSpeedTags << QLatin1String("Exif.MinoltaCsNew.ISOSetting"); 0198 ISOSpeedTags << QLatin1String("Exif.MinoltaCsOld.ISOSetting"); 0199 ISOSpeedTags << QLatin1String("Exif.MinoltaCs5D.ISOSpeed"); 0200 ISOSpeedTags << QLatin1String("Exif.MinoltaCs7D.ISOSpeed"); 0201 ISOSpeedTags << QLatin1String("Exif.Sony1Cs.ISOSetting"); 0202 ISOSpeedTags << QLatin1String("Exif.Sony2Cs.ISOSetting"); 0203 ISOSpeedTags << QLatin1String("Exif.Sony1Cs2.ISOSetting"); 0204 ISOSpeedTags << QLatin1String("Exif.Sony2Cs2.ISOSetting"); 0205 ISOSpeedTags << QLatin1String("Exif.Sony1MltCsA100.ISOSetting"); 0206 ISOSpeedTags << QLatin1String("Exif.PanasonicRaw.ISOSpeed"); 0207 ISOSpeedTags << QLatin1String("Exif.Pentax.ISO"); 0208 ISOSpeedTags << QLatin1String("Exif.Olympus.ISOSpeed"); 0209 ISOSpeedTags << QLatin1String("Exif.Samsung2.ISO"); 0210 0211 photoInfo.sensitivity = getExifTagStringFromTagsList(ISOSpeedTags); 0212 0213 // ----------------------------------------------------------------------------------- 0214 0215 photoInfo.flash = getExifTagString("Exif.Photo.Flash"); 0216 0217 if (photoInfo.flash.isEmpty()) 0218 { 0219 photoInfo.flash = getXmpTagString("Xmp.exif.Flash/exif:Mode"); 0220 } 0221 0222 if (photoInfo.flash.isEmpty()) 0223 { 0224 photoInfo.flash = getExifTagString("Exif.CanonCs.FlashActivity"); 0225 } 0226 0227 // ----------------------------------------------------------------------------------- 0228 0229 photoInfo.whiteBalance = getExifTagString("Exif.Photo.WhiteBalance"); 0230 0231 if (photoInfo.whiteBalance.isEmpty()) 0232 { 0233 photoInfo.whiteBalance = getXmpTagString("Xmp.exif.WhiteBalance"); 0234 } 0235 0236 // ----------------------------------------------------------------------------------- 0237 0238 double l, L, a; 0239 photoInfo.hasCoordinates = getGPSInfo(a, l, L); 0240 } 0241 0242 return photoInfo; 0243 } 0244 0245 QString DMetadata::getLensDescription() const 0246 { 0247 QString lens; 0248 QStringList lensExifTags; 0249 0250 // In first, try to get Lens information from Makernotes. 0251 0252 lensExifTags.append(QLatin1String("Exif.CanonCs.LensType")); ///< Canon Cameras Makernote. 0253 lensExifTags.append(QLatin1String("Exif.CanonCs.Lens")); ///< Canon Cameras Makernote. 0254 lensExifTags.append(QLatin1String("Exif.Canon.0x0095")); ///< Alternative Canon Cameras Makernote. 0255 lensExifTags.append(QLatin1String("Exif.NikonLd1.LensIDNumber")); ///< Nikon Cameras Makernote. 0256 lensExifTags.append(QLatin1String("Exif.NikonLd2.LensIDNumber")); ///< Nikon Cameras Makernote. 0257 lensExifTags.append(QLatin1String("Exif.NikonLd3.LensIDNumber")); ///< Nikon Cameras Makernote. 0258 lensExifTags.append(QLatin1String("Exif.Minolta.LensID")); ///< Minolta Cameras Makernote. 0259 lensExifTags.append(QLatin1String("Exif.Sony1.LensID")); ///< Sony Cameras Makernote. 0260 lensExifTags.append(QLatin1String("Exif.Sony2.LensID")); ///< Sony Cameras Makernote. 0261 lensExifTags.append(QLatin1String("Exif.SonyMinolta.LensID")); ///< Sony Cameras Makernote. 0262 lensExifTags.append(QLatin1String("Exif.Pentax.LensType")); ///< Pentax Cameras Makernote. 0263 lensExifTags.append(QLatin1String("Exif.PentaxDng.LensType")); ///< Pentax Cameras Makernote. 0264 lensExifTags.append(QLatin1String("Exif.Panasonic.0x0051")); ///< Panasonic Cameras Makernote. 0265 lensExifTags.append(QLatin1String("Exif.Panasonic.0x0310")); ///< Panasonic Cameras Makernote. 0266 lensExifTags.append(QLatin1String("Exif.Sigma.LensRange")); ///< Sigma Cameras Makernote. 0267 lensExifTags.append(QLatin1String("Exif.Samsung2.LensType")); ///< Samsung Cameras Makernote. 0268 lensExifTags.append(QLatin1String("Exif.Photo.0xFDEA")); ///< Non-standard Exif tag set by Camera Raw. 0269 lensExifTags.append(QLatin1String("Exif.OlympusEq.LensModel")); ///< Olympus Cameras Makernote. 0270 lensExifTags.append(QLatin1String("Exif.OlympusEq.LensType")); ///< Olympus Cameras Makernote. 0271 0272 // Try Exif.Photo.LensModel for Sony and Canon first. 0273 0274 QString make = getExifTagString("Exif.Image.Make"); 0275 QString lensModel = QLatin1String("Exif.Photo.LensModel"); 0276 0277 if (make.contains(QLatin1String("SONY"), Qt::CaseInsensitive)) 0278 { 0279 lensExifTags.prepend(lensModel); 0280 } 0281 else if (make.contains(QLatin1String("CANON"), Qt::CaseInsensitive)) 0282 { 0283 QString canonLt = QLatin1String("Exif.CanonCs.LensType"); 0284 QString canonCs = getExifTagString(canonLt.toLatin1().constData()); 0285 QString exifMod = getExifTagString(lensModel.toLatin1().constData()); 0286 0287 if ((exifMod == QLatin1String("RF70-200mm F2.8 L IS USM")) && 0288 (canonCs == QLatin1String("Canon RF 70-200mm F4L IS USM"))) 0289 { 0290 return QLatin1String("Canon RF 70-200mm F2.8L IS USM"); 0291 } 0292 else 0293 { 0294 lensExifTags.prepend(lensModel); 0295 } 0296 } 0297 else 0298 { 0299 lensExifTags.append(lensModel); 0300 } 0301 0302 // TODO : add Fuji camera Makernotes. 0303 0304 // ------------------------------------------------------------------- 0305 // Try to get Lens Data information from Exif. 0306 0307 for (QStringList::const_iterator it = lensExifTags.constBegin() ; it != lensExifTags.constEnd() ; ++it) 0308 { 0309 lens = getExifTagString((*it).toLatin1().constData()); 0310 0311 // To prevent undecoded tag values from Exiv2 as "(65535)" 0312 // or the value "----" from Exif.Photo.LensModel 0313 0314 if (!lens.isEmpty() && 0315 (lens != QLatin1String("----")) && 0316 (lens != QLatin1String("65535")) && 0317 !(lens.startsWith(QLatin1Char('(')) && 0318 lens.endsWith(QLatin1Char(')')) 0319 ) 0320 ) 0321 { 0322 return lens; 0323 } 0324 } 0325 0326 // ------------------------------------------------------------------- 0327 // Try to get Lens Data information from XMP. 0328 // XMP aux tags. 0329 0330 lens = getXmpTagString("Xmp.aux.Lens"); 0331 0332 if (lens.isEmpty()) 0333 { 0334 // XMP M$ tags (Lens Maker + Lens Model). 0335 0336 lens = getXmpTagString("Xmp.MicrosoftPhoto.LensManufacturer"); 0337 0338 if (!lens.isEmpty()) 0339 { 0340 lens.append(QLatin1Char(' ')); 0341 } 0342 0343 lens.append(getXmpTagString("Xmp.MicrosoftPhoto.LensModel")); 0344 } 0345 0346 return lens; 0347 } 0348 0349 QString DMetadata::getCameraSerialNumber() const 0350 { 0351 QString sn = getExifTagString("Exif.Image.CameraSerialNumber"); 0352 0353 if (sn.isEmpty()) 0354 { 0355 sn = getExifTagString("Exif.Canon.SerialNumber"); 0356 } 0357 0358 if (sn.isEmpty()) 0359 { 0360 sn = getExifTagString("Exif.Fujifilm.SerialNumber"); 0361 } 0362 0363 if (sn.isEmpty()) 0364 { 0365 sn = getExifTagString("Exif.Nikon3.SerialNumber"); 0366 } 0367 0368 if (sn.isEmpty()) 0369 { 0370 sn = getExifTagString("Exif.Nikon3.SerialNO"); 0371 } 0372 0373 if (sn.isEmpty()) 0374 { 0375 sn = getExifTagString("Exif.OlympusEq.SerialNumber"); 0376 } 0377 0378 if (sn.isEmpty()) 0379 { 0380 sn = getExifTagString("Exif.Olympus.SerialNumber2"); 0381 } 0382 0383 if (sn.isEmpty()) 0384 { 0385 sn = getExifTagString("Exif.OlympusEq.InternalSerialNumber"); 0386 } 0387 0388 if (sn.isEmpty()) 0389 { 0390 sn = getExifTagString("Exif.Panasonic.InternalSerialNumber"); 0391 } 0392 0393 if (sn.isEmpty()) 0394 { 0395 sn = getExifTagString("Exif.Sigma.SerialNumber"); 0396 } 0397 0398 if (sn.isEmpty()) 0399 { 0400 sn = getExifTagString("Exif.Sigma.SerialNumber"); 0401 } 0402 0403 if (sn.isEmpty()) 0404 { 0405 sn = getExifTagString("Exif.Sigma.SerialNumber"); 0406 } 0407 0408 if (sn.isEmpty()) 0409 { 0410 sn = getExifTagString("Exif.Pentax.SerialNumber"); 0411 } 0412 0413 if (sn.isEmpty()) 0414 { 0415 sn = getXmpTagString("Xmp.exifEX.BodySerialNumber"); 0416 } 0417 0418 if (sn.isEmpty()) 0419 { 0420 sn = getXmpTagString("Xmp.aux.SerialNumber"); 0421 } 0422 0423 if (sn.isEmpty()) 0424 { 0425 sn = getXmpTagString("Xmp.MicrosoftPhoto.CameraSerialNumber"); 0426 } 0427 0428 return sn; 0429 } 0430 0431 double DMetadata::apexApertureToFNumber(double aperture) 0432 { 0433 // convert from APEX. See Exif spec, Annex C. 0434 0435 if (aperture == 0.0) 0436 { 0437 return 1; 0438 } 0439 else if (aperture == 1.0) 0440 { 0441 return 1.4; 0442 } 0443 else if (aperture == 2.0) 0444 { 0445 return 2; 0446 } 0447 else if (aperture == 3.0) 0448 { 0449 return 2.8; 0450 } 0451 else if (aperture == 4.0) 0452 { 0453 return 4; 0454 } 0455 else if (aperture == 5.0) 0456 { 0457 return 5.6; 0458 } 0459 else if (aperture == 6.0) 0460 { 0461 return 8; 0462 } 0463 else if (aperture == 7.0) 0464 { 0465 return 11; 0466 } 0467 else if (aperture == 8.0) 0468 { 0469 return 16; 0470 } 0471 else if (aperture == 9.0) 0472 { 0473 return 22; 0474 } 0475 else if (aperture == 10.0) 0476 { 0477 return 32; 0478 } 0479 0480 return exp(log(2) * aperture / 2.0); 0481 } 0482 0483 double DMetadata::apexShutterSpeedToExposureTime(double shutterSpeed) 0484 { 0485 // convert from APEX. See Exif spec, Annex C. 0486 0487 if (shutterSpeed == -5.0) 0488 { 0489 return 30; 0490 } 0491 else if (shutterSpeed == -4.0) 0492 { 0493 return 15; 0494 } 0495 else if (shutterSpeed == -3.0) 0496 { 0497 return 8; 0498 } 0499 else if (shutterSpeed == -2.0) 0500 { 0501 return 4; 0502 } 0503 else if (shutterSpeed == -1.0) 0504 { 0505 return 2; 0506 } 0507 else if (shutterSpeed == 0.0) 0508 { 0509 return 1; 0510 } 0511 else if (shutterSpeed == 1.0) 0512 { 0513 return 0.5; 0514 } 0515 else if (shutterSpeed == 2.0) 0516 { 0517 return 0.25; 0518 } 0519 else if (shutterSpeed == 3.0) 0520 { 0521 return 0.125; 0522 } 0523 else if (shutterSpeed == 4.0) 0524 { 0525 return 1.0 / 15.0; 0526 } 0527 else if (shutterSpeed == 5.0) 0528 { 0529 return 1.0 / 30.0; 0530 } 0531 else if (shutterSpeed == 6.0) 0532 { 0533 return 1.0 / 60.0; 0534 } 0535 else if (shutterSpeed == 7.0) 0536 { 0537 return 0.008; // 1/125 0538 } 0539 else if (shutterSpeed == 8.0) 0540 { 0541 return 0.004; // 1/250 0542 } 0543 else if (shutterSpeed == 9.0) 0544 { 0545 return 0.002; // 1/500 0546 } 0547 else if (shutterSpeed == 10.0) 0548 { 0549 return 0.001; // 1/1000 0550 } 0551 else if (shutterSpeed == 11.0) 0552 { 0553 return 0.0005; // 1/2000 0554 } 0555 // supplemental rules 0556 else if (shutterSpeed == 12.0) 0557 { 0558 return 0.00025; // 1/4000 0559 } 0560 else if (shutterSpeed == 13.0) 0561 { 0562 return 0.000125; // 1/8000 0563 } 0564 0565 return exp( - log(2) * shutterSpeed); 0566 } 0567 0568 } // namespace Digikam