1 // ***************************************************************** -*- C++ -*- 2 /* 3 * Copyright (C) 2004-2017 Andreas Huggel <ahuggel@gmx.net> 4 * 5 * This program is part of the Exiv2 distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. 20 */ 21 /* 22 File: easyaccess.cpp 23 Version: $Rev: 4719 $ 24 */ 25 // ***************************************************************************** 26 #include "rcsid_int.hpp" 27 EXIV2_RCSID("@(#) $Id: easyaccess.cpp 4719 2017-03-08 20:42:28Z robinwmills $") 28 29 // ***************************************************************************** 30 // included header files 31 #include "easyaccess.hpp" 32 33 // ***************************************************************************** 34 namespace { 35 36 using namespace Exiv2; 37 38 /*! 39 @brief Search \em ed for a Metadatum specified by the \em keys. 40 The \em keys are searched in the order of their appearance, the 41 first available Metadatum is returned. 42 43 @param ed The %Exif metadata container to search 44 @param keys Array of keys to look for 45 @param count Number of elements in the array 46 */ findMetadatum(const ExifData & ed,const char * keys[],int count)47 ExifData::const_iterator findMetadatum(const ExifData& ed, 48 const char* keys[], 49 int count) 50 { 51 for (int i = 0; i < count; ++i) { 52 ExifData::const_iterator pos = ed.findKey(ExifKey(keys[i])); 53 if (pos != ed.end()) return pos; 54 } 55 return ed.end(); 56 } // findMetadatum 57 58 } // anonymous namespace 59 60 // ***************************************************************************** 61 // class member definitions 62 namespace Exiv2 { 63 orientation(const ExifData & ed)64 ExifData::const_iterator orientation(const ExifData& ed) 65 { 66 static const char* keys[] = { 67 "Exif.Image.Orientation", 68 "Exif.Panasonic.Rotation", 69 "Exif.MinoltaCs5D.Rotation", 70 "Exif.MinoltaCs5D.Rotation2", 71 "Exif.MinoltaCs7D.Rotation", 72 "Exif.Sony1MltCsA100.Rotation", 73 "Exif.Sony1Cs.Rotation", 74 "Exif.Sony2Cs.Rotation", 75 "Exif.Sony1Cs2.Rotation", 76 "Exif.Sony2Cs2.Rotation", 77 "Exif.Sony1MltCsA100.Rotation" 78 }; 79 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 80 } 81 isoSpeed(const ExifData & ed)82 ExifData::const_iterator isoSpeed(const ExifData& ed) 83 { 84 static const char* keys[] = { 85 "Exif.Photo.ISOSpeedRatings", 86 "Exif.Image.ISOSpeedRatings", 87 "Exif.CanonSi.ISOSpeed", 88 "Exif.CanonCs.ISOSpeed", 89 "Exif.Nikon1.ISOSpeed", 90 "Exif.Nikon2.ISOSpeed", 91 "Exif.Nikon3.ISOSpeed", 92 "Exif.NikonIi.ISO", 93 "Exif.NikonIi.ISO2", 94 "Exif.MinoltaCsNew.ISOSetting", 95 "Exif.MinoltaCsOld.ISOSetting", 96 "Exif.MinoltaCs5D.ISOSpeed", 97 "Exif.MinoltaCs7D.ISOSpeed", 98 "Exif.Sony1Cs.ISOSetting", 99 "Exif.Sony2Cs.ISOSetting", 100 "Exif.Sony1Cs2.ISOSetting", 101 "Exif.Sony2Cs2.ISOSetting", 102 "Exif.Sony1MltCsA100.ISOSetting", 103 "Exif.Pentax.ISO", 104 "Exif.PentaxDng.ISO", 105 "Exif.Olympus.ISOSpeed", 106 "Exif.Samsung2.ISO", 107 "Exif.Casio.ISO", 108 "Exif.Casio2.ISO", 109 "Exif.Casio2.ISOSpeed" 110 }; 111 112 struct SensKeyNameList { 113 int count; 114 const char* keys[3]; 115 }; 116 117 // covers Exif.Phot.SensitivityType values 1-7. Note that SOS, REI and 118 // ISO do differ in their meaning. Values coming first in a list (and 119 // existing as a tag) are picked up first and used as the "ISO" value. 120 static const SensKeyNameList sensitivityKey[] = { 121 { 1, { "Exif.Photo.StandardOutputSensitivity" }}, 122 { 1, { "Exif.Photo.RecommendedExposureIndex" }}, 123 { 1, { "Exif.Photo.ISOSpeed" }}, 124 { 2, { "Exif.Photo.RecommendedExposureIndex", "Exif.Photo.StandardOutputSensitivity" }}, 125 { 2, { "Exif.Photo.ISOSpeed", "Exif.Photo.StandardOutputSensitivity" }}, 126 { 2, { "Exif.Photo.ISOSpeed", "Exif.Photo.RecommendedExposureIndex" }}, 127 { 3, { "Exif.Photo.ISOSpeed", "Exif.Photo.RecommendedExposureIndex", "Exif.Photo.StandardOutputSensitivity" }} 128 }; 129 130 static const char* sensitivityType[] = { 131 "Exif.Photo.SensitivityType" 132 }; 133 134 // Find the first ISO value which is not "0" 135 const int cnt = EXV_COUNTOF(keys); 136 ExifData::const_iterator md = ed.end(); 137 long iso_val = -1; 138 for (int idx = 0; idx < cnt; ) { 139 md = findMetadatum(ed, keys + idx, cnt - idx); 140 if (md == ed.end()) break; 141 std::ostringstream os; 142 md->write(os, &ed); 143 bool ok = false; 144 iso_val = parseLong(os.str(), ok); 145 if (ok && iso_val > 0) break; 146 while (strcmp(keys[idx++], md->key().c_str()) != 0 && idx < cnt) {} 147 md = ed.end(); 148 } 149 150 // there is either a possible ISO "overflow" or no legacy 151 // ISO tag at all. Check for SensitivityType tag and the referenced 152 // ISO value (see EXIF 2.3 Annex G) 153 long iso_tmp_val = -1; 154 while (iso_tmp_val == -1 && (iso_val == 65535 || md == ed.end())) { 155 ExifData::const_iterator md_st = ed.end(); 156 md_st = findMetadatum(ed, sensitivityType, 1); 157 // no SensitivityType? exit with existing data 158 if (md_st == ed.end()) 159 break; 160 // otherwise pick up actual value and grab value accordingly 161 std::ostringstream os; 162 md_st->write(os, &ed); 163 bool ok = false; 164 long st_val = parseLong(os.str(), ok); 165 // SensivityType out of range or cannot be parsed properly 166 if (!ok || st_val < 1 || st_val > 7) 167 break; 168 // pick up list of ISO tags, and check for at least one of 169 // them available. 170 const SensKeyNameList *sensKeys = &sensitivityKey[st_val - 1]; 171 md_st = ed.end(); 172 for (int idx = 0; idx < sensKeys->count; md_st = ed.end()) { 173 md_st = findMetadatum(ed, const_cast<const char**>(sensKeys->keys), sensKeys->count); 174 if (md_st == ed.end()) 175 break; 176 std::ostringstream os_iso; 177 md_st->write(os_iso, &ed); 178 ok = false; 179 iso_tmp_val = parseLong(os_iso.str(), ok); 180 // something wrong with the value 181 if (ok || iso_tmp_val > 0) { 182 md = md_st; 183 break; 184 } 185 while (strcmp(sensKeys->keys[idx++], md_st->key().c_str()) != 0 && idx < cnt) {} 186 } 187 break; 188 } 189 190 return md; 191 } 192 flashBias(const ExifData & ed)193 ExifData::const_iterator flashBias(const ExifData& ed) 194 { 195 static const char* keys[] = { 196 "Exif.CanonSi.FlashBias", 197 "Exif.Panasonic.FlashBias", 198 "Exif.Olympus.FlashBias", 199 "Exif.OlympusCs.FlashExposureComp", 200 "Exif.Minolta.FlashExposureComp", 201 "Exif.SonyMinolta.FlashExposureComp", 202 "Exif.Sony1.FlashExposureComp", 203 "Exif.Sony2.FlashExposureComp" 204 }; 205 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 206 } 207 exposureMode(const ExifData & ed)208 ExifData::const_iterator exposureMode(const ExifData& ed) 209 { 210 static const char* keys[] = { 211 "Exif.Photo.ExposureProgram", 212 "Exif.Image.ExposureProgram", 213 "Exif.CanonCs.ExposureProgram", 214 "Exif.MinoltaCs7D.ExposureMode", 215 "Exif.MinoltaCs5D.ExposureMode", 216 "Exif.MinoltaCsNew.ExposureMode", 217 "Exif.MinoltaCsOld.ExposureMode", 218 "Exif.Sony1MltCsA100.ExposureMode", 219 "Exif.Sony1Cs.ExposureProgram", 220 "Exif.Sony2Cs.ExposureProgram", 221 "Exif.Sigma.ExposureMode" 222 }; 223 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 224 } 225 sceneMode(const ExifData & ed)226 ExifData::const_iterator sceneMode(const ExifData& ed) 227 { 228 static const char* keys[] = { 229 "Exif.CanonCs.EasyMode", 230 "Exif.Fujifilm.PictureMode", 231 "Exif.MinoltaCsNew.SubjectProgram", 232 "Exif.MinoltaCsOld.SubjectProgram", 233 "Exif.Minolta.SceneMode", 234 "Exif.SonyMinolta.SceneMode", 235 "Exif.Sony1.SceneMode", 236 "Exif.Sony2.SceneMode", 237 "Exif.OlympusCs.SceneMode", 238 "Exif.Panasonic.ShootingMode", 239 "Exif.Panasonic.SceneMode", 240 "Exif.Pentax.PictureMode", 241 "Exif.PentaxDng.PictureMode", 242 "Exif.Photo.SceneCaptureType" 243 }; 244 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 245 } 246 macroMode(const ExifData & ed)247 ExifData::const_iterator macroMode(const ExifData& ed) 248 { 249 static const char* keys[] = { 250 "Exif.CanonCs.Macro", 251 "Exif.Fujifilm.Macro", 252 "Exif.Olympus.Macro", 253 "Exif.OlympusCs.MacroMode", 254 "Exif.Panasonic.Macro", 255 "Exif.MinoltaCsNew.MacroMode", 256 "Exif.MinoltaCsOld.MacroMode", 257 "Exif.Sony1.Macro", 258 "Exif.Sony2.Macro" 259 }; 260 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 261 } 262 imageQuality(const ExifData & ed)263 ExifData::const_iterator imageQuality(const ExifData& ed) 264 { 265 static const char* keys[] = { 266 "Exif.CanonCs.Quality", 267 "Exif.Fujifilm.Quality", 268 "Exif.Sigma.Quality", 269 "Exif.Nikon1.Quality", 270 "Exif.Nikon2.Quality", 271 "Exif.Nikon3.Quality", 272 "Exif.Olympus.Quality", 273 "Exif.OlympusCs.Quality", 274 "Exif.Panasonic.Quality", 275 "Exif.Minolta.Quality", 276 "Exif.MinoltaCsNew.Quality", 277 "Exif.MinoltaCsOld.Quality", 278 "Exif.MinoltaCs5D.Quality", 279 "Exif.MinoltaCs7D.Quality", 280 "Exif.Sony1MltCsA100.Quality", 281 "Exif.Sony1.JPEGQuality", 282 "Exif.Sony1.Quality", 283 "Exif.Sony1Cs.Quality", 284 "Exif.Sony2.JPEGQuality", 285 "Exif.Sony2.Quality", 286 "Exif.Sony2Cs.Quality", 287 "Exif.Casio.Quality", 288 "Exif.Casio2.QualityMode", 289 "Exif.Casio2.Quality" 290 }; 291 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 292 } 293 whiteBalance(const ExifData & ed)294 ExifData::const_iterator whiteBalance(const ExifData& ed) 295 { 296 static const char* keys[] = { 297 "Exif.CanonSi.WhiteBalance", 298 "Exif.Fujifilm.WhiteBalance", 299 "Exif.Sigma.WhiteBalance", 300 "Exif.Nikon1.WhiteBalance", 301 "Exif.Nikon2.WhiteBalance", 302 "Exif.Nikon3.WhiteBalance", 303 "Exif.Olympus.WhiteBalance", 304 "Exif.OlympusCs.WhiteBalance", 305 "Exif.Panasonic.WhiteBalance", 306 "Exif.MinoltaCs5D.WhiteBalance", 307 "Exif.MinoltaCs7D.WhiteBalance", 308 "Exif.MinoltaCsNew.WhiteBalance", 309 "Exif.MinoltaCsOld.WhiteBalance", 310 "Exif.Minolta.WhiteBalance", 311 "Exif.Sony1MltCsA100.WhiteBalance", 312 "Exif.SonyMinolta.WhiteBalance", 313 "Exif.Sony1.WhiteBalance", 314 "Exif.Sony2.WhiteBalance", 315 "Exif.Sony1.WhiteBalance2", 316 "Exif.Sony2.WhiteBalance2", 317 "Exif.Casio.WhiteBalance", 318 "Exif.Casio2.WhiteBalance", 319 "Exif.Casio2.WhiteBalance2", 320 "Exif.Photo.WhiteBalance" 321 }; 322 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 323 } 324 lensName(const ExifData & ed)325 ExifData::const_iterator lensName(const ExifData& ed) 326 { 327 static const char* keys[] = { 328 // Exif.Canon.LensModel only reports focal length. 329 // Try Exif.CanonCs.LensType first. 330 "Exif.CanonCs.LensType", 331 "Exif.Photo.LensModel", 332 "Exif.NikonLd1.LensIDNumber", 333 "Exif.NikonLd2.LensIDNumber", 334 "Exif.NikonLd3.LensIDNumber", 335 "Exif.Pentax.LensType", 336 "Exif.PentaxDng.LensType", 337 "Exif.Minolta.LensID", 338 "Exif.SonyMinolta.LensID", 339 "Exif.Sony1.LensID", 340 "Exif.Sony2.LensID", 341 "Exif.OlympusEq.LensType", 342 "Exif.Panasonic.LensType", 343 "Exif.Samsung2.LensType" 344 }; 345 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 346 } 347 saturation(const ExifData & ed)348 ExifData::const_iterator saturation(const ExifData& ed) 349 { 350 static const char* keys[] = { 351 "Exif.Photo.Saturation", 352 "Exif.CanonCs.Saturation", 353 "Exif.MinoltaCsNew.Saturation", 354 "Exif.MinoltaCsOld.Saturation", 355 "Exif.MinoltaCs7D.Saturation", 356 "Exif.MinoltaCs5D.Saturation", 357 "Exif.Fujifilm.Color", 358 "Exif.Nikon3.Saturation", 359 "Exif.Panasonic.Saturation", 360 "Exif.Pentax.Saturation", 361 "Exif.PentaxDng.Saturation", 362 "Exif.Sigma.Saturation", 363 "Exif.Casio.Saturation", 364 "Exif.Casio2.Saturation", 365 "Exif.Casio2.Saturation2" 366 }; 367 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 368 } 369 sharpness(const ExifData & ed)370 ExifData::const_iterator sharpness(const ExifData& ed) 371 { 372 static const char* keys[] = { 373 "Exif.Photo.Sharpness", 374 "Exif.CanonCs.Sharpness", 375 "Exif.Fujifilm.Sharpness", 376 "Exif.MinoltaCsNew.Sharpness", 377 "Exif.MinoltaCsOld.Sharpness", 378 "Exif.MinoltaCs7D.Sharpness", 379 "Exif.MinoltaCs5D.Sharpness", 380 "Exif.Olympus.SharpnessFactor", 381 "Exif.Panasonic.Sharpness", 382 "Exif.Pentax.Sharpness", 383 "Exif.PentaxDng.Sharpness", 384 "Exif.Sigma.Sharpness", 385 "Exif.Casio.Sharpness", 386 "Exif.Casio2.Sharpness", 387 "Exif.Casio2.Sharpness2" 388 }; 389 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 390 } 391 contrast(const ExifData & ed)392 ExifData::const_iterator contrast(const ExifData& ed) 393 { 394 static const char* keys[] = { 395 "Exif.Photo.Contrast", 396 "Exif.CanonCs.Contrast", 397 "Exif.Fujifilm.Tone", 398 "Exif.MinoltaCsNew.Contrast", 399 "Exif.MinoltaCsOld.Contrast", 400 "Exif.MinoltaCs7D.Contrast", 401 "Exif.MinoltaCs5D.Contrast", 402 "Exif.Olympus.Contrast", 403 "Exif.Panasonic.Contrast", 404 "Exif.Pentax.Contrast", 405 "Exif.PentaxDng.Contrast", 406 "Exif.Sigma.Contrast", 407 "Exif.Casio.Contrast", 408 "Exif.Casio2.Contrast", 409 "Exif.Casio2.Contrast2" 410 411 }; 412 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 413 } 414 sceneCaptureType(const ExifData & ed)415 ExifData::const_iterator sceneCaptureType(const ExifData& ed) 416 { 417 static const char* keys[] = { 418 "Exif.Photo.SceneCaptureType", 419 "Exif.Olympus.SpecialMode" 420 }; 421 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 422 } 423 meteringMode(const ExifData & ed)424 ExifData::const_iterator meteringMode(const ExifData& ed) 425 { 426 static const char* keys[] = { 427 "Exif.Photo.MeteringMode", 428 "Exif.Image.MeteringMode", 429 "Exif.CanonCs.MeteringMode", 430 "Exif.Sony1MltCsA100.MeteringMode" 431 }; 432 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 433 } 434 make(const ExifData & ed)435 ExifData::const_iterator make(const ExifData& ed) 436 { 437 static const char* keys[] = { 438 "Exif.Image.Make" 439 }; 440 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 441 } 442 model(const ExifData & ed)443 ExifData::const_iterator model(const ExifData& ed) 444 { 445 static const char* keys[] = { 446 "Exif.Image.Model" 447 }; 448 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 449 } 450 exposureTime(const ExifData & ed)451 ExifData::const_iterator exposureTime(const ExifData& ed) 452 { 453 static const char* keys[] = { 454 "Exif.Photo.ExposureTime", 455 "Exif.Image.ExposureTime", 456 "Exif.Samsung2.ExposureTime" 457 }; 458 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 459 } 460 fNumber(const ExifData & ed)461 ExifData::const_iterator fNumber(const ExifData& ed) 462 { 463 static const char* keys[] = { 464 "Exif.Photo.FNumber", 465 "Exif.Image.FNumber", 466 "Exif.Samsung2.FNumber" 467 }; 468 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 469 } 470 subjectDistance(const ExifData & ed)471 ExifData::const_iterator subjectDistance(const ExifData& ed) 472 { 473 static const char* keys[] = { 474 "Exif.Photo.SubjectDistance", 475 "Exif.Image.SubjectDistance", 476 "Exif.CanonSi.SubjectDistance", 477 "Exif.CanonFi.FocusDistanceUpper", 478 "Exif.CanonFi.FocusDistanceLower", 479 "Exif.MinoltaCsNew.FocusDistance", 480 "Exif.Nikon1.FocusDistance", 481 "Exif.Nikon3.FocusDistance", 482 "Exif.NikonLd2.FocusDistance", 483 "Exif.NikonLd3.FocusDistance", 484 "Exif.Olympus.FocusDistance", 485 "Exif.OlympusFi.FocusDistance", 486 "Exif.Casio.ObjectDistance", 487 "Exif.Casio2.ObjectDistance" 488 }; 489 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 490 } 491 serialNumber(const ExifData & ed)492 ExifData::const_iterator serialNumber(const ExifData& ed) 493 { 494 static const char* keys[] = { 495 "Exif.Image.CameraSerialNumber", 496 "Exif.Canon.SerialNumber", 497 "Exif.Nikon3.SerialNumber", 498 "Exif.Nikon3.SerialNO", 499 "Exif.Fujifilm.SerialNumber", 500 "Exif.Olympus.SerialNumber2", 501 "Exif.Sigma.SerialNumber" 502 }; 503 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 504 } 505 focalLength(const ExifData & ed)506 ExifData::const_iterator focalLength(const ExifData& ed) 507 { 508 static const char* keys[] = { 509 "Exif.Photo.FocalLength", 510 "Exif.Image.FocalLength", 511 "Exif.Canon.FocalLength", 512 "Exif.NikonLd2.FocalLength", 513 "Exif.NikonLd3.FocalLength", 514 "Exif.MinoltaCsNew.FocalLength", 515 "Exif.Pentax.FocalLength", 516 "Exif.PentaxDng.FocalLength", 517 "Exif.Casio2.FocalLength" 518 }; 519 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 520 } 521 afPoint(const ExifData & ed)522 ExifData::const_iterator afPoint(const ExifData& ed) 523 { 524 static const char* keys[] = { 525 "Exif.CanonPi.AFPointsUsed", 526 "Exif.CanonPi.AFPointsUsed20D", 527 "Exif.CanonSi.AFPointUsed", 528 "Exif.CanonCs.AFPoint", 529 "Exif.MinoltaCs7D.AFPoints", 530 "Exif.Nikon1.AFFocusPos", 531 "Exif.NikonAf.AFPoint", 532 "Exif.NikonAf.AFPointsInFocus", 533 "Exif.NikonAf2.AFPointsUsed", 534 "Exif.NikonAf2.PrimaryAFPoint", 535 "Exif.OlympusFi.AFPoint", 536 "Exif.Pentax.AFPoint", 537 "Exif.Pentax.AFPointInFocus", 538 "Exif.PentaxDng.AFPoint", 539 "Exif.PentaxDng.AFPointInFocus", 540 "Exif.Sony1Cs.LocalAFAreaPoint", 541 "Exif.Sony2Cs.LocalAFAreaPoint", 542 "Exif.Sony1Cs2.LocalAFAreaPoint", 543 "Exif.Sony2Cs2.LocalAFAreaPoint", 544 "Exif.Sony1MltCsA100.LocalAFAreaPoint", 545 "Exif.Casio.AFPoint", 546 "Exif.Casio2.AFPointPosition" 547 }; 548 return findMetadatum(ed, keys, EXV_COUNTOF(keys)); 549 } 550 551 } // namespace Exiv2 552