Index: src/easyaccess.cpp =================================================================== --- src/easyaccess.cpp (revision 4428) +++ src/easyaccess.cpp (working copy) @@ -112,21 +112,85 @@ "Exif.Casio2.ISOSpeed" }; + struct SensKeyNameList { + int count; + const char* keys[3]; + }; + + // covers Exif.Phot.SensitivityType values 1-7. Note that SOS, REI and + // ISO do differ in their meaning. Values coming first in a list (and + // existing as a tag) are picked up first and used as the "ISO" value. + static const SensKeyNameList sensitivityKey[] = { + { 1, { "Exif.Photo.StandardOutputSensitivity" }}, + { 1, { "Exif.Photo.RecommendedExposureIndex" }}, + { 1, { "Exif.Photo.ISOSpeed" }}, + { 2, { "Exif.Photo.RecommendedExposureIndex", "Exif.Photo.StandardOutputSensitivity" }}, + { 2, { "Exif.Photo.ISOSpeed", "Exif.Photo.StandardOutputSensitivity" }}, + { 2, { "Exif.Photo.ISOSpeed", "Exif.Photo.RecommendedExposureIndex" }}, + { 3, { "Exif.Photo.ISOSpeed", "Exif.Photo.RecommendedExposureIndex", "Exif.Photo.StandardOutputSensitivity" }} + }; + + static const char* sensitivityType[] = { + "Exif.Photo.SensitivityType" + }; + // Find the first ISO value which is not "0" const int cnt = EXV_COUNTOF(keys); ExifData::const_iterator md = ed.end(); + long iso_val = -1; for (int idx = 0; idx < cnt; ) { md = findMetadatum(ed, keys + idx, cnt - idx); if (md == ed.end()) break; std::ostringstream os; md->write(os, &ed); bool ok = false; - long v = parseLong(os.str(), ok); - if (ok && v != 0) break; + iso_val = parseLong(os.str(), ok); + if (ok && iso_val > 0) break; while (strcmp(keys[idx++], md->key().c_str()) != 0 && idx < cnt) {} md = ed.end(); } + // there is either a possible ISO "overflow" or no legacy + // ISO tag at all. Check for SensitivityType tag and the referenced + // ISO value (see EXIF 2.3 Annex G) + long iso_tmp_val = -1; + while (iso_tmp_val == -1 && (iso_val == 65535 || md == ed.end())) { + ExifData::const_iterator md_st = ed.end(); + md_st = findMetadatum(ed, sensitivityType, 1); + // no SensitivityType? exit with existing data + if (md_st == ed.end()) + break; + // otherwise pick up actual value and grab value accordingly + const char *st_key = 0; // nullptr + std::ostringstream os; + md_st->write(os, &ed); + bool ok = false; + long st_val = parseLong(os.str(), ok); + // SensivityType out of range or cannot be parsed properly + if (!ok || st_val < 1 || st_val > 7) + break; + // pick up list of ISO tags, and check for at least one of + // them available. + const SensKeyNameList *sensKeys = &sensitivityKey[st_val - 1]; + md_st = ed.end(); + for (int idx = 0; idx < sensKeys->count; md_st = ed.end()) { + md_st = findMetadatum(ed, const_cast(sensKeys->keys), sensKeys->count); + if (md_st == ed.end()) + break; + std::ostringstream os_iso; + md_st->write(os_iso, &ed); + ok = false; + iso_tmp_val = parseLong(os_iso.str(), ok); + // something wrong with the value + if (ok || iso_tmp_val > 0) { + md = md_st; + break; + } + while (strcmp(sensKeys->keys[idx++], md_st->key().c_str()) != 0 && idx < cnt) {} + } + break; + } + return md; } @@ -266,7 +330,7 @@ { static const char* keys[] = { // Exif.Canon.LensModel only reports focal length. - // Try Exif.CanonCs.LensType first. + // Try Exif.CanonCs.LensType first. "Exif.CanonCs.LensType", "Exif.Photo.LensModel", "Exif.NikonLd1.LensIDNumber", Index: test/Makefile =================================================================== --- test/Makefile (revision 4428) +++ test/Makefile (working copy) @@ -78,7 +78,8 @@ write-test.sh \ write2-test.sh \ xmpparser-test.sh \ - conversions.sh + conversions.sh \ + iso65k-test.sh # video tests TESTV = video-test.sh