57
57
// *****************************************************************************
60
// Print version string from an intermediate string
61
std::ostream& printVersion(std::ostream& os, const std::string& str);
64
// *****************************************************************************
58
65
// class member definitions
61
IfdInfo::IfdInfo(IfdId ifdId, const char* name, const char* item)
62
: ifdId_(ifdId), name_(name), item_(item)
66
// Todo: Allow to register new IfdInfo entries from elsewhere (the makernotes)
68
IfdInfo::Item::Item(const std::string& item)
73
bool IfdInfo::operator==(IfdId ifdId) const
75
return ifdId_ == ifdId;
78
bool IfdInfo::operator==(Item item) const
80
return std::string(item_) == item.i_;
67
83
// Important: IFD item must be unique!
68
84
const IfdInfo ExifTags::ifdInfo_[] = {
69
IfdInfo(ifdIdNotSet, "(Unknown IFD)", "(Unknown item)"),
70
IfdInfo(ifd0Id, "IFD0", "Image"),
71
IfdInfo(exifIfdId, "Exif", "Photo"), // just to avoid 'Exif.Exif.*' keys
72
IfdInfo(gpsIfdId, "GPSInfo", "GPSInfo"),
73
IfdInfo(iopIfdId, "Iop", "Iop"),
74
IfdInfo(ifd1Id, "IFD1", "Thumbnail"),
75
IfdInfo(canonIfdId, "Makernote", "Canon"),
76
IfdInfo(canonCsIfdId, "Makernote", "CanonCs"),
77
IfdInfo(canonSiIfdId, "Makernote", "CanonSi"),
78
IfdInfo(canonCfIfdId, "Makernote", "CanonCf"),
79
IfdInfo(canonPiIfdId, "Makernote", "CanonPi"),
80
IfdInfo(canonPaIfdId, "Makernote", "CanonPa"),
81
IfdInfo(fujiIfdId, "Makernote", "Fujifilm"),
82
IfdInfo(minoltaIfdId, "Makernote", "Minolta"),
83
IfdInfo(minoltaCs5DIfdId, "Makernote", "MinoltaCs5D"),
84
IfdInfo(minoltaCs7DIfdId, "Makernote", "MinoltaCs7D"),
85
IfdInfo(minoltaCsOldIfdId, "Makernote", "MinoltaCsOld"),
86
IfdInfo(minoltaCsNewIfdId, "Makernote", "MinoltaCsNew"),
87
IfdInfo(nikon1IfdId, "Makernote", "Nikon1"),
88
IfdInfo(nikon2IfdId, "Makernote", "Nikon2"),
89
IfdInfo(nikon3IfdId, "Makernote", "Nikon3"),
90
IfdInfo(olympusIfdId, "Makernote", "Olympus"),
91
IfdInfo(panasonicIfdId, "Makernote", "Panasonic"),
92
IfdInfo(sigmaIfdId, "Makernote", "Sigma"),
93
IfdInfo(sonyIfdId, "Makernote", "Sony"),
94
IfdInfo(lastIfdId, "(Last IFD info)", "(Last IFD item)")
85
{ ifdIdNotSet, "(Unknown IFD)", "(Unknown item)", 0 },
86
{ ifd0Id, "IFD0", "Image", ExifTags::ifdTagList },
87
{ exifIfdId, "Exif", "Photo", ExifTags::exifTagList }, // just to avoid 'Exif.Exif.*' keys
88
{ gpsIfdId, "GPSInfo", "GPSInfo", ExifTags::gpsTagList },
89
{ iopIfdId, "Iop", "Iop", ExifTags::iopTagList },
90
{ ifd1Id, "IFD1", "Thumbnail", ExifTags::ifdTagList },
91
{ canonIfdId, "Makernote", "Canon", CanonMakerNote::tagList },
92
{ canonCsIfdId, "Makernote", "CanonCs", CanonMakerNote::tagListCs },
93
{ canonSiIfdId, "Makernote", "CanonSi", CanonMakerNote::tagListSi },
94
{ canonCfIfdId, "Makernote", "CanonCf", CanonMakerNote::tagListCf },
95
{ canonPiIfdId, "Makernote", "CanonPi", CanonMakerNote::tagListPi },
96
{ canonPaIfdId, "Makernote", "CanonPa", CanonMakerNote::tagListPa },
97
{ fujiIfdId, "Makernote", "Fujifilm", FujiMakerNote::tagList },
98
{ minoltaIfdId, "Makernote", "Minolta", MinoltaMakerNote::tagList },
99
{ minoltaCs5DIfdId, "Makernote", "MinoltaCs5D", MinoltaMakerNote::tagListCs5D },
100
{ minoltaCs7DIfdId, "Makernote", "MinoltaCs7D", MinoltaMakerNote::tagListCs7D },
101
{ minoltaCsOldIfdId, "Makernote", "MinoltaCsOld", MinoltaMakerNote::tagListCsStd },
102
{ minoltaCsNewIfdId, "Makernote", "MinoltaCsNew", MinoltaMakerNote::tagListCsStd },
103
{ nikon1IfdId, "Makernote", "Nikon1", Nikon1MakerNote::tagList },
104
{ nikon2IfdId, "Makernote", "Nikon2", Nikon2MakerNote::tagList },
105
{ nikon3IfdId, "Makernote", "Nikon3", Nikon3MakerNote::tagList },
106
{ olympusIfdId, "Makernote", "Olympus", OlympusMakerNote::tagList },
107
{ panasonicIfdId, "Makernote", "Panasonic", PanasonicMakerNote::tagList },
108
{ pentaxIfdId, "Makernote", "Pentax", PentaxMakerNote::tagList },
109
{ sigmaIfdId, "Makernote", "Sigma", SigmaMakerNote::tagList },
110
{ sonyIfdId, "Makernote", "Sony", SonyMakerNote::tagList },
111
{ lastIfdId, "(Last IFD info)", "(Last IFD item)", 0 }
97
SectionInfo::SectionInfo(
102
: sectionId_(sectionId), name_(name), desc_(desc)
106
114
const SectionInfo ExifTags::sectionInfo_[] = {
107
SectionInfo(sectionIdNotSet, "(UnknownSection)", N_("Unknown section")),
108
SectionInfo(imgStruct, "ImageStructure", N_("Image data structure")),
109
SectionInfo(recOffset, "RecordingOffset", N_("Recording offset")),
110
SectionInfo(imgCharacter, "ImageCharacteristics", N_("Image data characteristics")),
111
SectionInfo(otherTags, "OtherTags", N_("Other data")),
112
SectionInfo(exifFormat, "ExifFormat", N_("Exif data structure")),
113
SectionInfo(exifVersion, "ExifVersion", N_("Exif version")),
114
SectionInfo(imgConfig, "ImageConfig", N_("Image configuration")),
115
SectionInfo(userInfo, "UserInfo", N_("User information")),
116
SectionInfo(relatedFile, "RelatedFile", N_("Related file")),
117
SectionInfo(dateTime, "DateTime", N_("Date and time")),
118
SectionInfo(captureCond, "CaptureConditions", N_("Picture taking conditions")),
119
SectionInfo(gpsTags, "GPS", N_("GPS information")),
120
SectionInfo(iopTags, "Interoperability", N_("Interoperability information")),
121
SectionInfo(makerTags, "Makernote", N_("Vendor specific information")),
122
SectionInfo(lastSectionId, "(LastSection)", N_("Last section"))
115
{ sectionIdNotSet, "(UnknownSection)", N_("Unknown section") },
116
{ imgStruct, "ImageStructure", N_("Image data structure") },
117
{ recOffset, "RecordingOffset", N_("Recording offset") },
118
{ imgCharacter, "ImageCharacteristics", N_("Image data characteristics") },
119
{ otherTags, "OtherTags", N_("Other data") },
120
{ exifFormat, "ExifFormat", N_("Exif data structure") },
121
{ exifVersion, "ExifVersion", N_("Exif version") },
122
{ imgConfig, "ImageConfig", N_("Image configuration") },
123
{ userInfo, "UserInfo", N_("User information") },
124
{ relatedFile, "RelatedFile", N_("Related file") },
125
{ dateTime, "DateTime", N_("Date and time") },
126
{ captureCond, "CaptureConditions", N_("Picture taking conditions") },
127
{ gpsTags, "GPS", N_("GPS information") },
128
{ iopTags, "Interoperability", N_("Interoperability information") },
129
{ makerTags, "Makernote", N_("Vendor specific information") },
130
{ lastSectionId, "(LastSection)", N_("Last section") }
125
133
TagInfo::TagInfo(
565
583
{ 0x01, N_("Fired") },
566
584
{ 0x05, N_("Fired, strobe return light not detected") },
567
585
{ 0x07, N_("Fired, strobe return light detected") },
586
{ 0x08, N_("Yes, did not fire") },
568
587
{ 0x09, N_("Yes, compulsory") },
569
588
{ 0x0d, N_("Yes, compulsory, return light not detected") },
570
589
{ 0x0f, N_("Yes, compulsory, return light detected") },
571
590
{ 0x10, N_("No, compulsory") },
591
{ 0x14, N_("No, did not fire, return not detected") },
572
592
{ 0x18, N_("No, auto") },
573
593
{ 0x19, N_("Yes, auto") },
574
594
{ 0x1d, N_("Yes, auto, return light not detected") },
575
595
{ 0x1f, N_("Yes, auto, return light detected") },
576
596
{ 0x20, N_("No flash function") },
597
{ 0x20, N_("No, no flash function") },
577
598
{ 0x41, N_("Yes, red-eye reduction") },
578
599
{ 0x45, N_("Yes, red-eye reduction, return light not detected") },
579
600
{ 0x47, N_("Yes, red-eye reduction, return light detected") },
580
601
{ 0x49, N_("Yes, compulsory, red-eye reduction") },
581
602
{ 0x4d, N_("Yes, compulsory, red-eye reduction, return light not detected") },
582
603
{ 0x4f, N_("Yes, compulsory, red-eye reduction, return light detected") },
604
{ 0x50, N_("No, red-eye reduction") },
605
{ 0x58, N_("No, auto, red-eye reduction") },
583
606
{ 0x59, N_("Yes, auto, red-eye reduction") },
584
607
{ 0x5d, N_("Yes, auto, red-eye reduction, return light not detected") },
585
608
{ 0x5f, N_("Yes, auto, red-eye reduction, return light detected") }
911
927
N_("This tag indicates the type of scene that was shot. It can "
912
928
"also be used to record the mode in which the image was "
913
929
"shot. Note that this differs from the <SceneType> tag."),
914
exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifSceneCaptureType)),
930
exifIfdId, captureCond, unsignedShort, print0xa406),
915
931
TagInfo(0xa407, "GainControl", N_("Gain Control"),
916
932
N_("This tag indicates the degree of overall image gain adjustment."),
917
exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifGainControl)),
933
exifIfdId, captureCond, unsignedShort, print0xa407),
918
934
TagInfo(0xa408, "Contrast", N_("Contrast"),
919
935
N_("This tag indicates the direction of contrast processing "
920
936
"applied by the camera when the image was shot."),
921
exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifContrast)),
937
exifIfdId, captureCond, unsignedShort, printNormalSoftHard),
922
938
TagInfo(0xa409, "Saturation", N_("Saturation"),
923
939
N_("This tag indicates the direction of saturation processing "
924
940
"applied by the camera when the image was shot."),
925
exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifSaturation)),
941
exifIfdId, captureCond, unsignedShort, print0xa409),
926
942
TagInfo(0xa40a, "Sharpness", N_("Sharpness"),
927
943
N_("This tag indicates the direction of sharpness processing "
928
944
"applied by the camera when the image was shot."),
929
exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifSharpness)),
945
exifIfdId, captureCond, unsignedShort, printNormalSoftHard),
930
946
TagInfo(0xa40b, "DeviceSettingDescription", N_("Device Setting Description"),
931
947
N_("This tag indicates information on the picture-taking "
932
948
"conditions of a particular camera model. The tag is used "
1175
1222
N_("Unknown tag"),
1176
1223
ifdIdNotSet, sectionIdNotSet, asciiString, printValue);
1178
// Tag lookup lists with tag names, desc and where they (preferably) belong to;
1179
// this is an array with pointers to one list per IFD. The IfdId is used as the
1180
// index into the array.
1181
const TagInfo* ExifTags::tagInfos_[] = {
1183
ifdTagInfo, exifTagInfo, gpsTagInfo, iopTagInfo, ifdTagInfo,
1187
// Lookup list for registered makernote tag info tables
1188
const TagInfo* ExifTags::makerTagInfos_[];
1190
// All makernote ifd ids, in the same order as the tag infos in makerTagInfos_
1191
IfdId ExifTags::makerIfdIds_[];
1193
void ExifTags::registerBaseTagInfo(IfdId ifdId)
1195
registerMakerTagInfo(ifdId, ifdTagInfo);
1198
void ExifTags::registerMakerTagInfo(IfdId ifdId, const TagInfo* tagInfo)
1201
for (; i < MAX_MAKER_TAG_INFOS; ++i) {
1202
if (makerIfdIds_[i] == 0) {
1203
makerIfdIds_[i] = ifdId;
1204
makerTagInfos_[i] = tagInfo;
1208
if (i == MAX_MAKER_TAG_INFOS) throw Error(16);
1209
} // ExifTags::registerMakerTagInfo
1211
int ExifTags::tagInfoIdx(uint16_t tag, IfdId ifdId)
1213
const TagInfo* tagInfo = tagInfos_[ifdId];
1214
if (tagInfo == 0) return -1;
1216
for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
1217
if (tagInfo[idx].tag_ == tag) return idx;
1220
} // ExifTags::tagInfoIdx
1222
const TagInfo* ExifTags::makerTagInfo(uint16_t tag, IfdId ifdId)
1225
for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
1226
if (i == MAX_MAKER_TAG_INFOS) return 0;
1228
for (int k = 0; makerTagInfos_[i][k].tag_ != 0xffff; ++k) {
1229
if (makerTagInfos_[i][k].tag_ == tag) return &makerTagInfos_[i][k];
1233
} // ExifTags::makerTagInfo
1235
const TagInfo* ExifTags::makerTagInfo(const std::string& tagName,
1239
for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
1240
if (i == MAX_MAKER_TAG_INFOS) return 0;
1242
for (int k = 0; makerTagInfos_[i][k].tag_ != 0xffff; ++k) {
1243
if (makerTagInfos_[i][k].name_ == tagName) {
1244
return &makerTagInfos_[i][k];
1249
} // ExifTags::makerTagInfo
1225
const TagInfo* ExifTags::tagList(IfdId ifdId)
1227
const IfdInfo* ii = find(ifdInfo_, ifdId);
1228
if (ii == 0 || ii->tagList_ == 0) return 0;
1229
return ii->tagList_();
1230
} // ExifTags::tagList
1232
const TagInfo* ExifTags::tagInfo(uint16_t tag, IfdId ifdId)
1234
const TagInfo* ti = tagList(ifdId);
1235
if (ti == 0) return 0;
1236
for (int idx = 0; ti[idx].tag_ != 0xffff; ++idx) {
1237
if (ti[idx].tag_ == tag) return &ti[idx];
1240
} // ExifTags::tagInfo
1242
const TagInfo* ExifTags::tagInfo(const std::string& tagName, IfdId ifdId)
1244
const TagInfo* ti = tagList(ifdId);
1245
if (ti == 0) return 0;
1246
for (int idx = 0; ti[idx].tag_ != 0xffff; ++idx) {
1247
if (std::string(ti[idx].name_) == tagName) return &ti[idx];
1250
} // ExifTags::tagInfo
1251
1252
bool ExifTags::isMakerIfd(IfdId ifdId)
1254
for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
1255
return i != MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != IfdId(0);
1255
const IfdInfo* ii = find(ifdInfo_, ifdId);
1256
if (ii != 0 && std::string(ii->name_) == "Makernote") {
1260
} // ExifTags::isMakerIfd
1258
1262
std::string ExifTags::tagName(uint16_t tag, IfdId ifdId)
1260
if (isExifIfd(ifdId)) {
1261
int idx = tagInfoIdx(tag, ifdId);
1262
if (idx != -1) return tagInfos_[ifdId][idx].name_;
1264
if (isMakerIfd(ifdId)) {
1265
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1266
if (tagInfo != 0) return tagInfo->name_;
1264
const TagInfo* ti = tagInfo(tag, ifdId);
1265
if (ti != 0) return ti->name_;
1268
1266
std::ostringstream os;
1269
1267
os << "0x" << std::setw(4) << std::setfill('0') << std::right
1270
1268
<< std::hex << tag;
1279
1277
const char* ExifTags::tagLabel(uint16_t tag, IfdId ifdId)
1281
if (isExifIfd(ifdId)) {
1282
int idx = tagInfoIdx(tag, ifdId);
1283
if (idx == -1) return _(unknownTag.title_);
1284
return _(tagInfos_[ifdId][idx].title_);
1286
if (isMakerIfd(ifdId)) {
1287
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1288
if (tagInfo != 0) return _(tagInfo->title_);
1279
const TagInfo* ti = tagInfo(tag, ifdId);
1280
if (ti == 0) return "";
1281
return _(ti->title_);
1291
1282
} // ExifTags::tagLabel
1293
1284
const char* ExifTags::tagDesc(uint16_t tag, IfdId ifdId)
1295
if (isExifIfd(ifdId)) {
1296
int idx = tagInfoIdx(tag, ifdId);
1297
if (idx == -1) return _(unknownTag.desc_);
1298
return _(tagInfos_[ifdId][idx].desc_);
1300
if (isMakerIfd(ifdId)) {
1301
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1302
if (tagInfo != 0) return _(tagInfo->desc_);
1286
const TagInfo* ti = tagInfo(tag, ifdId);
1287
if (ti == 0) return "";
1288
return _(ti->desc_);
1305
1289
} // ExifTags::tagDesc
1307
const char* ExifTags::sectionName(uint16_t tag, IfdId ifdId)
1309
if (isExifIfd(ifdId)) {
1310
int idx = tagInfoIdx(tag, ifdId);
1311
if (idx == -1) return sectionInfo_[unknownTag.sectionId_].name_;
1312
const TagInfo* tagInfo = tagInfos_[ifdId];
1313
return sectionInfo_[tagInfo[idx].sectionId_].name_;
1315
if (isMakerIfd(ifdId)) {
1316
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1317
if (tagInfo != 0) return sectionInfo_[tagInfo->sectionId_].name_;
1320
} // ExifTags::sectionName
1322
const char* ExifTags::sectionDesc(uint16_t tag, IfdId ifdId)
1324
if (isExifIfd(ifdId)) {
1325
int idx = tagInfoIdx(tag, ifdId);
1326
if (idx == -1) return _(sectionInfo_[unknownTag.sectionId_].desc_);
1327
const TagInfo* tagInfo = tagInfos_[ifdId];
1328
return _(sectionInfo_[tagInfo[idx].sectionId_].desc_);
1330
if (isMakerIfd(ifdId)) {
1331
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1332
if (tagInfo != 0) return _(sectionInfo_[tagInfo->sectionId_].desc_);
1335
} // ExifTags::sectionDesc
1291
TypeId ExifTags::tagType(uint16_t tag, IfdId ifdId)
1293
const TagInfo* ti = tagInfo(tag, ifdId);
1294
if (ti == 0) return unknownTag.typeId_;
1296
} // ExifTags::tagType
1337
1298
uint16_t ExifTags::tag(const std::string& tagName, IfdId ifdId)
1339
uint16_t tag = 0xffff;
1340
if (isExifIfd(ifdId)) {
1341
const TagInfo* tagInfo = tagInfos_[ifdId];
1344
for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
1345
if (tagInfo[idx].name_ == tagName) break;
1347
tag = tagInfo[idx].tag_;
1350
if (isMakerIfd(ifdId)) {
1351
const TagInfo* tagInfo = makerTagInfo(tagName, ifdId);
1352
if (tagInfo != 0) tag = tagInfo->tag_;
1354
if (tag == 0xffff) {
1355
if (!isHex(tagName, 4, "0x")) throw Error(7, tagName, ifdId);
1356
std::istringstream is(tagName);
1357
is >> std::hex >> tag;
1300
const TagInfo* ti = tagInfo(tagName, ifdId);
1301
if (ti != 0) return ti->tag_;
1302
if (!isHex(tagName, 4, "0x")) throw Error(7, tagName, ifdId);
1303
std::istringstream is(tagName);
1305
is >> std::hex >> tag;
1360
1307
} // ExifTags::tag
1362
1309
IfdId ExifTags::ifdIdByIfdItem(const std::string& ifdItem)
1365
for (i = int(lastIfdId) - 1; i > 0; --i) {
1366
if (ifdInfo_[i].item_ == ifdItem) break;
1311
IfdId ifdId = ifdIdNotSet;
1312
const IfdInfo* ii = find(ifdInfo_, IfdInfo::Item(ifdItem));
1313
if (ii != 0) ifdId = ii->ifdId_;
1317
const char* ExifTags::sectionName(uint16_t tag, IfdId ifdId)
1319
const TagInfo* ti = tagInfo(tag, ifdId);
1320
if (ti == 0) return sectionInfo_[unknownTag.sectionId_].name_;
1321
return sectionInfo_[ti->sectionId_].name_;
1322
} // ExifTags::sectionName
1324
const char* ExifTags::sectionDesc(uint16_t tag, IfdId ifdId)
1326
const TagInfo* ti = tagInfo(tag, ifdId);
1327
if (ti == 0) return _(sectionInfo_[unknownTag.sectionId_].desc_);
1328
return _(sectionInfo_[ti->sectionId_].desc_);
1329
} // ExifTags::sectionDesc
1371
1331
const char* ExifTags::ifdName(IfdId ifdId)
1373
return ifdInfo_[ifdId].name_;
1333
const IfdInfo* ii = find(ifdInfo_, ifdId);
1334
if (ii == 0) return ifdInfo_[0].name_;
1336
} // ExifTags::ifdName
1376
1338
const char* ExifTags::ifdItem(IfdId ifdId)
1378
return ifdInfo_[ifdId].item_;
1340
const IfdInfo* ii = find(ifdInfo_, ifdId);
1341
if (ii == 0) return ifdInfo_[0].item_;
1343
} // ExifTags::ifdItem
1381
1345
const char* ExifTags::sectionName(SectionId sectionId)
1383
1347
return sectionInfo_[sectionId].name_;
1348
} // ExifTags::sectionName
1386
1350
SectionId ExifTags::sectionId(const std::string& sectionName)