1
// ***************************************************************** -*- C++ -*-
3
* Copyright (C) 2004, 2005 Andreas Huggel <ahuggel@gmx.net>
5
* This program is part of the Exiv2 distribution.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
25
History: 15-Jan-04, ahu: created
26
21-Jan-05, ahu: added MakerNote TagInfo registry and related code
28
// *****************************************************************************
30
EXIV2_RCSID("@(#) $Id: tags.cpp 596 2005-06-26 11:04:27Z ahuggel $");
32
// *****************************************************************************
33
// included header files
39
#include "makernote.hpp"
40
#include "mn.hpp" // To ensure that all makernotes are registered
49
// *****************************************************************************
50
// class member definitions
53
IfdInfo::IfdInfo(IfdId ifdId, const char* name, const char* item)
54
: ifdId_(ifdId), name_(name), item_(item)
58
// Todo: Allow to register new IfdInfo entries from elsewhere (the makernotes)
59
// Important: IFD item must be unique!
60
const IfdInfo ExifTags::ifdInfo_[] = {
61
IfdInfo(ifdIdNotSet, "(Unknown IFD)", "(Unknown item)"),
62
IfdInfo(ifd0Id, "IFD0", "Image"),
63
IfdInfo(exifIfdId, "Exif", "Photo"), // just to avoid 'Exif.Exif.*' keys
64
IfdInfo(gpsIfdId, "GPSInfo", "GPSInfo"),
65
IfdInfo(iopIfdId, "Iop", "Iop"),
66
IfdInfo(ifd1Id, "IFD1", "Thumbnail"),
67
IfdInfo(canonIfdId, "Makernote", "Canon"),
68
IfdInfo(canonCs1IfdId, "Makernote", "CanonCs1"),
69
IfdInfo(canonCs2IfdId, "Makernote", "CanonCs2"),
70
IfdInfo(canonCfIfdId, "Makernote", "CanonCf"),
71
IfdInfo(fujiIfdId, "Makernote", "Fujifilm"),
72
IfdInfo(nikon1IfdId, "Makernote", "Nikon1"),
73
IfdInfo(nikon2IfdId, "Makernote", "Nikon2"),
74
IfdInfo(nikon3IfdId, "Makernote", "Nikon3"),
75
IfdInfo(olympusIfdId, "Makernote", "Olympus"),
76
IfdInfo(panasonicIfdId, "Makernote", "Panasonic"),
77
IfdInfo(sigmaIfdId, "Makernote", "Sigma"),
78
IfdInfo(sonyIfdId, "Makernote", "Sony"),
79
IfdInfo(lastIfdId, "(Last IFD info)", "(Last IFD item)")
82
SectionInfo::SectionInfo(
87
: sectionId_(sectionId), name_(name), desc_(desc)
91
const SectionInfo ExifTags::sectionInfo_[] = {
92
SectionInfo(sectionIdNotSet, "(UnknownSection)", "Unknown section"),
93
SectionInfo(imgStruct, "ImageStructure", "Image data structure"),
94
SectionInfo(recOffset, "RecordingOffset", "Recording offset"),
95
SectionInfo(imgCharacter, "ImageCharacteristics", "Image data characteristics"),
96
SectionInfo(otherTags, "OtherTags", "Other data"),
97
SectionInfo(exifFormat, "ExifFormat", "Exif data structure"),
98
SectionInfo(exifVersion, "ExifVersion", "Exif Version"),
99
SectionInfo(imgConfig, "ImageConfig", "Image configuration"),
100
SectionInfo(userInfo, "UserInfo", "User information"),
101
SectionInfo(relatedFile, "RelatedFile", "Related file"),
102
SectionInfo(dateTime, "DateTime", "Date and time"),
103
SectionInfo(captureCond, "CaptureConditions", "Picture taking conditions"),
104
SectionInfo(gpsTags, "GPS", "GPS information"),
105
SectionInfo(iopTags, "Interoperability", "Interoperability information"),
106
SectionInfo(makerTags, "Makernote", "Vendor specific information"),
107
SectionInfo(lastSectionId, "(LastSection)", "Last section")
119
: tag_(tag), name_(name), desc_(desc), ifdId_(ifdId),
120
sectionId_(sectionId), typeId_(typeId), printFct_(printFct)
124
// Base IFD Tags (IFD0 and IFD1)
125
static const TagInfo ifdTagInfo[] = {
126
TagInfo(0x0100, "ImageWidth", "Image width", ifd0Id, imgStruct, unsignedLong, printValue),
127
TagInfo(0x0101, "ImageLength", "Image height", ifd0Id, imgStruct, unsignedLong, printValue),
128
TagInfo(0x0102, "BitsPerSample", "Number of bits per component", ifd0Id, imgStruct, unsignedShort, printValue),
129
TagInfo(0x0103, "Compression", "Compression scheme", ifd0Id, imgStruct, unsignedShort, print0x0103),
130
TagInfo(0x0106, "PhotometricInterpretation", "Pixel composition", ifd0Id, imgStruct, unsignedShort, print0x0106),
131
TagInfo(0x010e, "ImageDescription", "Image title", ifd0Id, otherTags, asciiString, printValue),
132
TagInfo(0x010f, "Make", "Manufacturer of image input equipment", ifd0Id, otherTags, asciiString, printValue),
133
TagInfo(0x0110, "Model", "Model of image input equipment", ifd0Id, otherTags, asciiString, printValue),
134
TagInfo(0x0111, "StripOffsets", "Image data location", ifd0Id, recOffset, unsignedLong, printValue),
135
TagInfo(0x0112, "Orientation", "Orientation of image", ifd0Id, imgStruct, unsignedShort, print0x0112),
136
TagInfo(0x0115, "SamplesPerPixel", "Number of components", ifd0Id, imgStruct, unsignedShort, printValue),
137
TagInfo(0x0116, "RowsPerStrip", "Number of rows per strip", ifd0Id, recOffset, unsignedLong, printValue),
138
TagInfo(0x0117, "StripByteCounts", "Bytes per compressed strip", ifd0Id, recOffset, unsignedLong, printValue),
139
TagInfo(0x011a, "XResolution", "Image resolution in width direction", ifd0Id, imgStruct, unsignedRational, printLong),
140
TagInfo(0x011b, "YResolution", "Image resolution in height direction", ifd0Id, imgStruct, unsignedRational, printLong),
141
TagInfo(0x011c, "PlanarConfiguration", "Image data arrangement", ifd0Id, imgStruct, unsignedShort, printValue),
142
TagInfo(0x0128, "ResolutionUnit", "Unit of X and Y resolution", ifd0Id, imgStruct, unsignedShort, printUnit),
143
TagInfo(0x012d, "TransferFunction", "Transfer function", ifd0Id, imgCharacter, unsignedShort, printValue),
144
TagInfo(0x0131, "Software", "Software used", ifd0Id, otherTags, asciiString, printValue),
145
TagInfo(0x0132, "DateTime", "File change date and time", ifd0Id, otherTags, asciiString, printValue),
146
TagInfo(0x013b, "Artist", "Person who created the image", ifd0Id, otherTags, asciiString, printValue),
147
TagInfo(0x013e, "WhitePoint", "White point chromaticity", ifd0Id, imgCharacter, unsignedRational, printValue),
148
TagInfo(0x013f, "PrimaryChromaticities", "Chromaticities of primaries", ifd0Id, imgCharacter, unsignedRational, printValue),
149
TagInfo(0x0201, "JPEGInterchangeFormat", "Offset to JPEG SOI", ifd0Id, recOffset, unsignedLong, printValue),
150
TagInfo(0x0202, "JPEGInterchangeFormatLength", "Bytes of JPEG data", ifd0Id, recOffset, unsignedLong, printValue),
151
TagInfo(0x0211, "YCbCrCoefficients", "Color space transformation matrix coefficients", ifd0Id, imgCharacter, unsignedRational, printValue),
152
TagInfo(0x0212, "YCbCrSubSampling", "Subsampling ratio of Y to C", ifd0Id, imgStruct, unsignedShort, printValue),
153
TagInfo(0x0213, "YCbCrPositioning", "Y and C positioning", ifd0Id, imgStruct, unsignedShort, print0x0213),
154
TagInfo(0x0214, "ReferenceBlackWhite", "Pair of black and white reference values", ifd0Id, imgCharacter, unsignedRational, printValue),
155
TagInfo(0x8298, "Copyright", "Copyright holder", ifd0Id, otherTags, asciiString, print0x8298),
156
TagInfo(0x8769, "ExifTag", "Exif IFD Pointer", ifd0Id, exifFormat, unsignedLong, printValue),
157
TagInfo(0x8825, "GPSTag", "GPSInfo IFD Pointer", ifd0Id, exifFormat, unsignedLong, printValue),
158
// End of list marker
159
TagInfo(0xffff, "(UnknownIfdTag)", "Unknown IFD tag", ifdIdNotSet, sectionIdNotSet, invalidTypeId, printValue)
163
static const TagInfo exifTagInfo[] = {
164
TagInfo(0x829a, "ExposureTime", "Exposure time", exifIfdId, captureCond, unsignedRational, print0x829a),
165
TagInfo(0x829d, "FNumber", "F number", exifIfdId, captureCond, unsignedRational, print0x829d),
166
TagInfo(0x8822, "ExposureProgram", "Exposure program", exifIfdId, captureCond, unsignedShort, print0x8822),
167
TagInfo(0x8824, "SpectralSensitivity", "Spectral sensitivity", exifIfdId, captureCond, asciiString, printValue),
168
TagInfo(0x8827, "ISOSpeedRatings", "ISO speed ratings", exifIfdId, captureCond, unsignedShort, print0x8827),
169
TagInfo(0x8828, "OECF", "Optoelectric coefficient", exifIfdId, captureCond, undefined, printValue),
170
TagInfo(0x9000, "ExifVersion", "Exif Version", exifIfdId, exifVersion, undefined, printValue),
171
TagInfo(0x9003, "DateTimeOriginal", "Date and time original image was generated", exifIfdId, dateTime, asciiString, printValue),
172
TagInfo(0x9004, "DateTimeDigitized", "Date and time image was made digital data", exifIfdId, dateTime, asciiString, printValue),
173
TagInfo(0x9101, "ComponentsConfiguration", "Meaning of each component", exifIfdId, imgConfig, undefined, print0x9101),
174
TagInfo(0x9102, "CompressedBitsPerPixel", "Image compression mode", exifIfdId, imgConfig, unsignedRational, printFloat),
175
TagInfo(0x9201, "ShutterSpeedValue", "Shutter speed", exifIfdId, captureCond, signedRational, printFloat),
176
TagInfo(0x9202, "ApertureValue", "Aperture", exifIfdId, captureCond, unsignedRational, printFloat),
177
TagInfo(0x9203, "BrightnessValue", "Brightness", exifIfdId, captureCond, signedRational, printFloat),
178
TagInfo(0x9204, "ExposureBiasValue", "Exposure bias", exifIfdId, captureCond, signedRational, print0x9204),
179
TagInfo(0x9205, "MaxApertureValue", "Maximum lens aperture", exifIfdId, captureCond, unsignedRational, printFloat),
180
TagInfo(0x9206, "SubjectDistance", "Subject distance", exifIfdId, captureCond, unsignedRational, print0x9206),
181
TagInfo(0x9207, "MeteringMode", "Metering mode", exifIfdId, captureCond, unsignedShort, print0x9207),
182
TagInfo(0x9208, "LightSource", "Light source", exifIfdId, captureCond, unsignedShort, print0x9208),
183
TagInfo(0x9209, "Flash", "Flash", exifIfdId, captureCond, unsignedShort, print0x9209),
184
TagInfo(0x920a, "FocalLength", "Lens focal length", exifIfdId, captureCond, unsignedRational, print0x920a),
185
TagInfo(0x9214, "SubjectArea", "Subject area", exifIfdId, captureCond, unsignedShort, printValue),
186
TagInfo(0x927c, "MakerNote", "Manufacturer notes", exifIfdId, userInfo, undefined, printValue),
187
TagInfo(0x9286, "UserComment", "User comments", exifIfdId, userInfo, comment, print0x9286),
188
TagInfo(0x9290, "SubSecTime", "DateTime subseconds", exifIfdId, dateTime, asciiString, printValue),
189
TagInfo(0x9291, "SubSecTimeOriginal", "DateTimeOriginal subseconds", exifIfdId, dateTime, asciiString, printValue),
190
TagInfo(0x9292, "SubSecTimeDigitized", "DateTimeDigitized subseconds", exifIfdId, dateTime, asciiString, printValue),
191
TagInfo(0xa000, "FlashpixVersion", "Supported Flashpix version", exifIfdId, exifVersion, undefined, printValue),
192
TagInfo(0xa001, "ColorSpace", "Color space information", exifIfdId, imgCharacter, unsignedShort, print0xa001),
193
TagInfo(0xa002, "PixelXDimension", "Valid image width", exifIfdId, imgConfig, unsignedLong, printValue),
194
TagInfo(0xa003, "PixelYDimension", "Valid image height", exifIfdId, imgConfig, unsignedLong, printValue),
195
TagInfo(0xa004, "RelatedSoundFile", "Related audio file", exifIfdId, relatedFile, asciiString, printValue),
196
TagInfo(0xa005, "InteroperabilityTag", "Interoperability IFD Pointer", exifIfdId, exifFormat, unsignedLong, printValue),
197
TagInfo(0xa20b, "FlashEnergy", "Flash energy", exifIfdId, captureCond, unsignedRational, printValue),
198
TagInfo(0xa20c, "SpatialFrequencyResponse", "Spatial frequency response", exifIfdId, captureCond, undefined, printValue),
199
TagInfo(0xa20e, "FocalPlaneXResolution", "Focal plane X resolution", exifIfdId, captureCond, unsignedRational, printFloat),
200
TagInfo(0xa20f, "FocalPlaneYResolution", "Focal plane Y resolution", exifIfdId, captureCond, unsignedRational, printFloat),
201
TagInfo(0xa210, "FocalPlaneResolutionUnit", "Focal plane resolution unit", exifIfdId, captureCond, unsignedShort, printUnit),
202
TagInfo(0xa214, "SubjectLocation", "Subject location", exifIfdId, captureCond, unsignedShort, printValue),
203
TagInfo(0xa215, "ExposureIndex", "Exposure index", exifIfdId, captureCond, unsignedRational, printValue),
204
TagInfo(0xa217, "SensingMethod", "Sensing method", exifIfdId, captureCond, unsignedShort, print0xa217),
205
TagInfo(0xa300, "FileSource", "File source", exifIfdId, captureCond, undefined, print0xa300),
206
TagInfo(0xa301, "SceneType", "Scene type", exifIfdId, captureCond, undefined, print0xa301),
207
TagInfo(0xa302, "CFAPattern", "CFA pattern", exifIfdId, captureCond, undefined, printValue),
208
TagInfo(0xa401, "CustomRendered", "Custom image processing", exifIfdId, captureCond, unsignedShort, printValue),
209
TagInfo(0xa402, "ExposureMode", "Exposure mode", exifIfdId, captureCond, unsignedShort, print0xa402),
210
TagInfo(0xa403, "WhiteBalance", "White balance", exifIfdId, captureCond, unsignedShort, print0xa403),
211
TagInfo(0xa404, "DigitalZoomRatio", "Digital zoom ratio", exifIfdId, captureCond, unsignedRational, print0xa404),
212
TagInfo(0xa405, "FocalLengthIn35mmFilm", "Focal length in 35 mm film", exifIfdId, captureCond, unsignedShort, print0xa405),
213
TagInfo(0xa406, "SceneCaptureType", "Scene capture type", exifIfdId, captureCond, unsignedShort, print0xa406),
214
TagInfo(0xa407, "GainControl", "Gain control", exifIfdId, captureCond, unsignedRational, print0xa407),
215
TagInfo(0xa408, "Contrast", "Contrast", exifIfdId, captureCond, unsignedShort, print0xa408),
216
TagInfo(0xa409, "Saturation", "Saturation", exifIfdId, captureCond, unsignedShort, print0xa409),
217
TagInfo(0xa40a, "Sharpness", "Sharpness", exifIfdId, captureCond, unsignedShort, print0xa40a),
218
TagInfo(0xa40b, "DeviceSettingDescription", "Device settings description", exifIfdId, captureCond, undefined, printValue),
219
TagInfo(0xa40c, "SubjectDistanceRange", "Subject distance range", exifIfdId, captureCond, unsignedShort, print0xa40c),
220
TagInfo(0xa420, "ImageUniqueID", "Unique image ID", exifIfdId, otherTags, asciiString, printValue),
221
// End of list marker
222
TagInfo(0xffff, "(UnknownExifTag)", "Unknown Exif tag", ifdIdNotSet, sectionIdNotSet, invalidTypeId, printValue)
226
static const TagInfo gpsTagInfo[] = {
227
TagInfo(0x0000, "GPSVersionID", "GPS tag version", gpsIfdId, gpsTags, unsignedByte, printValue),
228
TagInfo(0x0001, "GPSLatitudeRef", "North or South Latitude", gpsIfdId, gpsTags, asciiString, printValue),
229
TagInfo(0x0002, "GPSLatitude", "Latitude", gpsIfdId, gpsTags, unsignedRational, printValue),
230
TagInfo(0x0003, "GPSLongitudeRef", "East or West Longitude", gpsIfdId, gpsTags, asciiString, printValue),
231
TagInfo(0x0004, "GPSLongitude", "Longitude", gpsIfdId, gpsTags, unsignedRational, printValue),
232
TagInfo(0x0005, "GPSAltitudeRef", "Altitude reference", gpsIfdId, gpsTags, unsignedByte, printValue),
233
TagInfo(0x0006, "GPSAltitude", "Altitude", gpsIfdId, gpsTags, unsignedRational, printValue),
234
TagInfo(0x0007, "GPSTimeStamp", "GPS time (atomic clock)", gpsIfdId, gpsTags, unsignedRational, printValue),
235
TagInfo(0x0008, "GPSSatellites", "GPS satellites used for measurement", gpsIfdId, gpsTags, asciiString, printValue),
236
TagInfo(0x0009, "GPSStatus", "GPS receiver status", gpsIfdId, gpsTags, asciiString, printValue),
237
TagInfo(0x000a, "GPSMeasureMode", "GPS measurement mode", gpsIfdId, gpsTags, asciiString, printValue),
238
TagInfo(0x000b, "GPSDOP", "Measurement precision", gpsIfdId, gpsTags, unsignedRational, printValue),
239
TagInfo(0x000c, "GPSSpeedRef", "Speed unit", gpsIfdId, gpsTags, asciiString, printValue),
240
TagInfo(0x000d, "GPSSpeed", "Speed of GPS receiver", gpsIfdId, gpsTags, unsignedRational, printValue),
241
TagInfo(0x000e, "GPSTrackRef", "Reference for direction of movement", gpsIfdId, gpsTags, asciiString, printValue),
242
TagInfo(0x000f, "GPSTrack", "Direction of movement", gpsIfdId, gpsTags, unsignedRational, printValue),
243
TagInfo(0x0010, "GPSImgDirectionRef", "Reference for direction of image", gpsIfdId, gpsTags, asciiString, printValue),
244
TagInfo(0x0011, "GPSImgDirection", "Direction of image", gpsIfdId, gpsTags, unsignedRational, printValue),
245
TagInfo(0x0012, "GPSMapDatum", "Geodetic survey data used", gpsIfdId, gpsTags, asciiString, printValue),
246
TagInfo(0x0013, "GPSDestLatitudeRef", "Reference for latitude of destination", gpsIfdId, gpsTags, asciiString, printValue),
247
TagInfo(0x0014, "GPSDestLatitude", "Latitude of destination", gpsIfdId, gpsTags, unsignedRational, printValue),
248
TagInfo(0x0015, "GPSDestLongitudeRef", "Reference for longitude of destination", gpsIfdId, gpsTags, asciiString, printValue),
249
TagInfo(0x0016, "GPSDestLongitude", "Longitude of destination", gpsIfdId, gpsTags, unsignedRational, printValue),
250
TagInfo(0x0017, "GPSDestBearingRef", "Reference for bearing of destination", gpsIfdId, gpsTags, asciiString, printValue),
251
TagInfo(0x0018, "GPSDestBearing", "Bearing of destination", gpsIfdId, gpsTags, unsignedRational, printValue),
252
TagInfo(0x0019, "GPSDestDistanceRef", "Reference for distance to destination", gpsIfdId, gpsTags, asciiString, printValue),
253
TagInfo(0x001a, "GPSDestDistance", "Distance to destination", gpsIfdId, gpsTags, unsignedRational, printValue),
254
TagInfo(0x001b, "GPSProcessingMethod", "Name of GPS processing method", gpsIfdId, gpsTags, undefined, printValue),
255
TagInfo(0x001c, "GPSAreaInformation", "Name of GPS area", gpsIfdId, gpsTags, undefined, printValue),
256
TagInfo(0x001d, "GPSDateStamp", "GPS date", gpsIfdId, gpsTags, asciiString, printValue),
257
TagInfo(0x001e, "GPSDifferential", "GPS differential correction", gpsIfdId, gpsTags, unsignedShort, printValue),
258
// End of list marker
259
TagInfo(0xffff, "(UnknownGpsTag)", "Unknown GPSInfo tag", ifdIdNotSet, sectionIdNotSet, invalidTypeId, printValue)
262
// Exif Interoperability IFD Tags
263
static const TagInfo iopTagInfo[] = {
264
TagInfo(0x0001, "InteroperabilityIndex", "Interoperability Identification", iopIfdId, iopTags, asciiString, printValue),
265
TagInfo(0x0002, "InteroperabilityVersion", "Interoperability version", iopIfdId, iopTags, undefined, printValue),
266
TagInfo(0x1000, "RelatedImageFileFormat", "File format of image file", iopIfdId, iopTags, asciiString, printValue),
267
TagInfo(0x1001, "RelatedImageWidth", "Image width", iopIfdId, iopTags, unsignedLong, printValue),
268
TagInfo(0x1002, "RelatedImageLength", "Image height", iopIfdId, iopTags, unsignedLong, printValue),
269
// End of list marker
270
TagInfo(0xffff, "(UnknownIopTag)", "Unknown Exif Interoperability tag", ifdIdNotSet, sectionIdNotSet, invalidTypeId, printValue)
274
static const TagInfo unknownTag(0xffff, "Unknown tag", "Unknown tag", ifdIdNotSet, sectionIdNotSet, asciiString, printValue);
276
std::ostream& TagTranslator::print(std::ostream& os, const Value& value) const
278
if (!pTagDetails_) return os << value;
280
long l = value.toLong();
282
long e = pTagDetails_[0].val_;
284
for (; pTagDetails_[i].val_ != l && pTagDetails_[i].val_ != e; ++i) {}
285
if (pTagDetails_[i].val_ == l) {
286
os << pTagDetails_[i].label_;
289
os << "(" << l << ")";
292
} // TagTranslator::print
294
// Tag lookup lists with tag names, desc and where they (preferably) belong to;
295
// this is an array with pointers to one list per IFD. The IfdId is used as the
296
// index into the array.
297
const TagInfo* ExifTags::tagInfos_[] = {
299
ifdTagInfo, exifTagInfo, gpsTagInfo, iopTagInfo, ifdTagInfo,
303
// Lookup list for registered makernote tag info tables
304
const TagInfo* ExifTags::makerTagInfos_[];
306
// All makernote ifd ids, in the same order as the tag infos in makerTagInfos_
307
IfdId ExifTags::makerIfdIds_[];
309
void ExifTags::registerBaseTagInfo(IfdId ifdId)
311
registerMakerTagInfo(ifdId, ifdTagInfo);
314
void ExifTags::registerMakerTagInfo(IfdId ifdId, const TagInfo* tagInfo)
317
for (; i < MAX_MAKER_TAG_INFOS; ++i) {
318
if (makerIfdIds_[i] == 0) {
319
makerIfdIds_[i] = ifdId;
320
makerTagInfos_[i] = tagInfo;
324
if (i == MAX_MAKER_TAG_INFOS) throw Error(16);
325
} // ExifTags::registerMakerTagInfo
327
int ExifTags::tagInfoIdx(uint16_t tag, IfdId ifdId)
329
const TagInfo* tagInfo = tagInfos_[ifdId];
330
if (tagInfo == 0) return -1;
332
for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
333
if (tagInfo[idx].tag_ == tag) return idx;
336
} // ExifTags::tagInfoIdx
338
const TagInfo* ExifTags::makerTagInfo(uint16_t tag, IfdId ifdId)
341
for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
342
if (i == MAX_MAKER_TAG_INFOS) return 0;
344
for (int k = 0; makerTagInfos_[i][k].tag_ != 0xffff; ++k) {
345
if (makerTagInfos_[i][k].tag_ == tag) return &makerTagInfos_[i][k];
349
} // ExifTags::makerTagInfo
351
const TagInfo* ExifTags::makerTagInfo(const std::string& tagName,
355
for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
356
if (i == MAX_MAKER_TAG_INFOS) return 0;
358
for (int k = 0; makerTagInfos_[i][k].tag_ != 0xffff; ++k) {
359
if (makerTagInfos_[i][k].name_ == tagName) {
360
return &makerTagInfos_[i][k];
365
} // ExifTags::makerTagInfo
367
bool ExifTags::isMakerIfd(IfdId ifdId)
370
for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
371
return i != MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != IfdId(0);
374
std::string ExifTags::tagName(uint16_t tag, IfdId ifdId)
376
if (isExifIfd(ifdId)) {
377
int idx = tagInfoIdx(tag, ifdId);
378
if (idx != -1) return tagInfos_[ifdId][idx].name_;
380
if (isMakerIfd(ifdId)) {
381
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
382
if (tagInfo != 0) return tagInfo->name_;
384
std::ostringstream os;
385
os << "0x" << std::setw(4) << std::setfill('0') << std::right
388
} // ExifTags::tagName
390
const char* ExifTags::tagDesc(uint16_t tag, IfdId ifdId)
392
if (isExifIfd(ifdId)) {
393
int idx = tagInfoIdx(tag, ifdId);
394
if (idx == -1) return unknownTag.desc_;
395
return tagInfos_[ifdId][idx].desc_;
397
if (isMakerIfd(ifdId)) {
398
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
399
if (tagInfo != 0) return tagInfo->desc_;
402
} // ExifTags::tagDesc
404
const char* ExifTags::sectionName(uint16_t tag, IfdId ifdId)
406
if (isExifIfd(ifdId)) {
407
int idx = tagInfoIdx(tag, ifdId);
408
if (idx == -1) return sectionInfo_[unknownTag.sectionId_].name_;
409
const TagInfo* tagInfo = tagInfos_[ifdId];
410
return sectionInfo_[tagInfo[idx].sectionId_].name_;
412
if (isMakerIfd(ifdId)) {
413
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
414
if (tagInfo != 0) return sectionInfo_[tagInfo->sectionId_].name_;
417
} // ExifTags::sectionName
419
const char* ExifTags::sectionDesc(uint16_t tag, IfdId ifdId)
421
if (isExifIfd(ifdId)) {
422
int idx = tagInfoIdx(tag, ifdId);
423
if (idx == -1) return sectionInfo_[unknownTag.sectionId_].desc_;
424
const TagInfo* tagInfo = tagInfos_[ifdId];
425
return sectionInfo_[tagInfo[idx].sectionId_].desc_;
427
if (isMakerIfd(ifdId)) {
428
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
429
if (tagInfo != 0) return sectionInfo_[tagInfo->sectionId_].desc_;
432
} // ExifTags::sectionDesc
434
uint16_t ExifTags::tag(const std::string& tagName, IfdId ifdId)
436
uint16_t tag = 0xffff;
437
if (isExifIfd(ifdId)) {
438
const TagInfo* tagInfo = tagInfos_[ifdId];
441
for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
442
if (tagInfo[idx].name_ == tagName) break;
444
tag = tagInfo[idx].tag_;
447
if (isMakerIfd(ifdId)) {
448
const TagInfo* tagInfo = makerTagInfo(tagName, ifdId);
449
if (tagInfo != 0) tag = tagInfo->tag_;
452
if (!isHex(tagName, 4, "0x")) throw Error(7, tagName, ifdId);
453
std::istringstream is(tagName);
454
is >> std::hex >> tag;
459
IfdId ExifTags::ifdIdByIfdItem(const std::string& ifdItem)
462
for (i = int(lastIfdId) - 1; i > 0; --i) {
463
if (ifdInfo_[i].item_ == ifdItem) break;
468
const char* ExifTags::ifdName(IfdId ifdId)
470
return ifdInfo_[ifdId].name_;
473
const char* ExifTags::ifdItem(IfdId ifdId)
475
return ifdInfo_[ifdId].item_;
478
const char* ExifTags::sectionName(SectionId sectionId)
480
return sectionInfo_[sectionId].name_;
483
SectionId ExifTags::sectionId(const std::string& sectionName)
486
for (i = int(lastSectionId) - 1; i > 0; --i) {
487
if (sectionInfo_[i].name_ == sectionName) break;
492
TypeId ExifTags::tagType(uint16_t tag, IfdId ifdId)
494
if (isExifIfd(ifdId)) {
495
int idx = tagInfoIdx(tag, ifdId);
496
if (idx != -1) return tagInfos_[ifdId][idx].typeId_;
498
if (isMakerIfd(ifdId)) {
499
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
500
if (tagInfo != 0) return tagInfo->typeId_;
502
return unknownTag.typeId_;
505
std::ostream& ExifTags::printTag(std::ostream& os,
510
if (value.count() == 0) return os;
511
PrintFct fct = printValue;
512
if (isExifIfd(ifdId)) {
513
int idx = tagInfoIdx(tag, ifdId);
515
fct = tagInfos_[ifdId][idx].printFct_;
518
if (isMakerIfd(ifdId)) {
519
const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
520
if (tagInfo != 0) fct = tagInfo->printFct_;
522
return fct(os, value);
523
} // ExifTags::printTag
525
void ExifTags::taglist(std::ostream& os)
527
for (int i=0; ifdTagInfo[i].tag_ != 0xffff; ++i) {
528
os << ifdTagInfo[i] << "\n";
530
for (int i=0; exifTagInfo[i].tag_ != 0xffff; ++i) {
531
os << exifTagInfo[i] << "\n";
533
for (int i=0; iopTagInfo[i].tag_ != 0xffff; ++i) {
534
os << iopTagInfo[i] << "\n";
536
for (int i=0; gpsTagInfo[i].tag_ != 0xffff; ++i) {
537
os << gpsTagInfo[i] << "\n";
539
} // ExifTags::taglist
541
void ExifTags::makerTaglist(std::ostream& os, IfdId ifdId)
544
for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
545
if (i != MAX_MAKER_TAG_INFOS) {
546
const TagInfo* mnTagInfo = makerTagInfos_[i];
547
for (int k=0; mnTagInfo[k].tag_ != 0xffff; ++k) {
548
os << mnTagInfo[k] << "\n";
551
} // ExifTags::makerTaglist
553
const char* ExifKey::familyName_ = "Exif";
555
ExifKey::ExifKey(const std::string& key)
556
: tag_(0), ifdId_(ifdIdNotSet), ifdItem_(""),
562
ExifKey::ExifKey(uint16_t tag, const std::string& ifdItem)
563
: tag_(0), ifdId_(ifdIdNotSet), ifdItem_(""),
566
IfdId ifdId = ExifTags::ifdIdByIfdItem(ifdItem);
567
if (ExifTags::isMakerIfd(ifdId)) {
568
MakerNote::AutoPtr makerNote = MakerNoteFactory::create(ifdId);
569
if (makerNote.get() == 0) throw Error(23, ifdId);
577
ExifKey::ExifKey(const Entry& e)
578
: tag_(e.tag()), ifdId_(e.ifdId()),
579
ifdItem_(ExifTags::ifdItem(e.ifdId())),
580
idx_(e.idx()), key_("")
585
ExifKey::ExifKey(const ExifKey& rhs)
586
: tag_(rhs.tag_), ifdId_(rhs.ifdId_), ifdItem_(rhs.ifdItem_),
587
idx_(rhs.idx_), key_(rhs.key_)
595
ExifKey& ExifKey::operator=(const ExifKey& rhs)
597
if (this == &rhs) return *this;
601
ifdItem_ = rhs.ifdItem_;
607
std::string ExifKey::tagName() const
609
return ExifTags::tagName(tag_, ifdId_);
612
ExifKey::AutoPtr ExifKey::clone() const
614
return AutoPtr(clone_());
617
ExifKey* ExifKey::clone_() const
619
return new ExifKey(*this);
622
std::string ExifKey::sectionName() const
624
return ExifTags::sectionName(tag(), ifdId());
627
void ExifKey::decomposeKey()
629
// Get the family name, IFD name and tag name parts of the key
630
std::string::size_type pos1 = key_.find('.');
631
if (pos1 == std::string::npos) throw Error(6, key_);
632
std::string familyName = key_.substr(0, pos1);
633
if (familyName != std::string(familyName_)) {
634
throw Error(6, key_);
636
std::string::size_type pos0 = pos1 + 1;
637
pos1 = key_.find('.', pos0);
638
if (pos1 == std::string::npos) throw Error(6, key_);
639
std::string ifdItem = key_.substr(pos0, pos1 - pos0);
640
if (ifdItem == "") throw Error(6, key_);
641
std::string tagName = key_.substr(pos1 + 1);
642
if (tagName == "") throw Error(6, key_);
645
IfdId ifdId = ExifTags::ifdIdByIfdItem(ifdItem);
646
if (ifdId == ifdIdNotSet) throw Error(6, key_);
647
if (ExifTags::isMakerIfd(ifdId)) {
648
MakerNote::AutoPtr makerNote = MakerNoteFactory::create(ifdId);
649
if (makerNote.get() == 0) throw Error(6, key_);
652
uint16_t tag = ExifTags::tag(tagName, ifdId);
654
// Translate hex tag name (0xabcd) to a real tag name if there is one
655
tagName = ExifTags::tagName(tag, ifdId);
660
key_ = familyName + "." + ifdItem + "." + tagName;
663
void ExifKey::makeKey()
665
key_ = std::string(familyName_)
667
+ "." + ExifTags::tagName(tag_, ifdId_);
670
// *************************************************************************
673
bool isExifIfd(IfdId ifdId)
677
case ifd0Id: rc = true; break;
678
case exifIfdId: rc = true; break;
679
case gpsIfdId: rc = true; break;
680
case iopIfdId: rc = true; break;
681
case ifd1Id: rc = true; break;
682
default: rc = false; break;
687
std::ostream& operator<<(std::ostream& os, const TagInfo& ti)
689
ExifKey exifKey(ti.tag_, ExifTags::ifdItem(ti.ifdId_));
690
return os << ExifTags::tagName(ti.tag_, ti.ifdId_) << ", "
691
<< std::dec << ti.tag_ << ", "
692
<< "0x" << std::setw(4) << std::setfill('0')
693
<< std::right << std::hex << ti.tag_ << ", "
694
<< ExifTags::ifdName(ti.ifdId_) << ", "
695
<< exifKey.key() << ", "
696
<< TypeInfo::typeName(
697
ExifTags::tagType(ti.tag_, ti.ifdId_)) << ", "
698
<< ExifTags::tagDesc(ti.tag_, ti.ifdId_);
701
std::ostream& operator<<(std::ostream& os, const Rational& r)
703
return os << r.first << "/" << r.second;
706
std::istream& operator>>(std::istream& is, Rational& r)
711
is >> nominator >> c >> denominator;
712
if (is && c == '/') r = std::make_pair(nominator, denominator);
716
std::ostream& operator<<(std::ostream& os, const URational& r)
718
return os << r.first << "/" << r.second;
721
std::istream& operator>>(std::istream& is, URational& r)
724
uint32_t denominator;
726
is >> nominator >> c >> denominator;
727
if (is && c == '/') r = std::make_pair(nominator, denominator);
731
std::ostream& printValue(std::ostream& os, const Value& value)
736
std::ostream& printLong(std::ostream& os, const Value& value)
738
Rational r = value.toRational();
739
if (r.second != 0) return os << static_cast<long>(r.first) / r.second;
740
return os << "(" << value << ")";
743
std::ostream& printFloat(std::ostream& os, const Value& value)
745
Rational r = value.toRational();
746
if (r.second != 0) return os << static_cast<float>(r.first) / r.second;
747
return os << "(" << value << ")";
750
std::ostream& printUnit(std::ostream& os, const Value& value)
752
long unit = value.toLong();
754
case 2: os << "inch"; break;
755
case 3: os << "cm"; break;
756
default: os << "(" << unit << ")"; break;
761
std::ostream& print0x0103(std::ostream& os, const Value& value)
763
long compression = value.toLong();
764
switch (compression) {
765
case 1: os << "TIFF"; break;
766
case 6: os << "JPEG"; break;
767
default: os << "(" << compression << ")"; break;
772
std::ostream& print0x0106(std::ostream& os, const Value& value)
774
long photo = value.toLong();
776
case 2: os << "RGB"; break;
777
case 6: os << "YCbCr"; break;
778
default: os << "(" << photo << ")"; break;
783
std::ostream& print0x0112(std::ostream& os, const Value& value)
785
long orientation = value.toLong();
786
switch (orientation) {
787
case 1: os << "top, left"; break;
788
case 2: os << "top, right"; break;
789
case 3: os << "bottom, right"; break;
790
case 4: os << "bottom, left"; break;
791
case 5: os << "left, top"; break;
792
case 6: os << "right, top"; break;
793
case 7: os << "right, bottom"; break;
794
case 8: os << "left, bottom"; break;
795
default: os << "(" << orientation << ")"; break;
800
std::ostream& print0x0213(std::ostream& os, const Value& value)
802
long position = value.toLong();
804
case 1: os << "Centered"; break;
805
case 2: os << "Co-sited"; break;
806
default: os << "(" << position << ")"; break;
811
std::ostream& print0x8298(std::ostream& os, const Value& value)
813
// Print the copyright information in the format Photographer, Editor
814
std::string val = value.toString();
815
std::string::size_type pos = val.find('\0');
816
if (pos != std::string::npos) {
817
std::string photographer(val, 0, pos);
818
if (photographer != " ") os << photographer;
819
std::string editor(val, pos + 1);
821
if (photographer != " ") os << ", ";
831
std::ostream& print0x829a(std::ostream& os, const Value& value)
833
Rational t = value.toRational();
834
if (t.first > 1 && t.second > 1 && t.second >= t.first) {
835
t.second = static_cast<uint32_t>(
836
static_cast<float>(t.second) / t.first + 0.5);
839
if (t.second > 1 && t.second < t.first) {
840
t.first = static_cast<uint32_t>(
841
static_cast<float>(t.first) / t.second + 0.5);
845
os << t.first << " s";
848
os << t.first << "/" << t.second << " s";
853
std::ostream& print0x829d(std::ostream& os, const Value& value)
855
Rational fnumber = value.toRational();
856
if (fnumber.second != 0) {
857
os << "F" << (float)fnumber.first / fnumber.second;
860
os << "(" << value << ")";
865
std::ostream& print0x8822(std::ostream& os, const Value& value)
867
long program = value.toLong();
869
case 0: os << "Not defined"; break;
870
case 1: os << "Manual"; break;
871
case 2: os << "Auto"; break;
872
case 3: os << "Aperture priority"; break;
873
case 4: os << "Shutter priority"; break;
874
case 5: os << "Creative program"; break;
875
case 6: os << "Action program"; break;
876
case 7: os << "Portrait mode"; break;
877
case 8: os << "Landscape mode"; break;
878
default: os << "(" << program << ")"; break;
883
std::ostream& print0x8827(std::ostream& os, const Value& value)
885
return os << value.toLong();
888
std::ostream& print0x9101(std::ostream& os, const Value& value)
890
for (long i = 0; i < value.count(); ++i) {
891
long l = value.toLong(i);
894
case 1: os << "Y"; break;
895
case 2: os << "Cb"; break;
896
case 3: os << "Cr"; break;
897
case 4: os << "R"; break;
898
case 5: os << "G"; break;
899
case 6: os << "B"; break;
900
default: os << "(" << l << ")"; break;
906
std::ostream& print0x9204(std::ostream& os, const Value& value)
908
Rational bias = value.toRational();
909
if (bias.second <= 0) {
910
os << "(" << bias.first << "/" << bias.second << ")";
912
else if (bias.first == 0) {
916
long d = lgcd(labs(bias.first), bias.second);
917
long num = labs(bias.first) / d;
918
long den = bias.second / d;
919
os << (bias.first < 0 ? "-" : "+") << num;
927
std::ostream& print0x9206(std::ostream& os, const Value& value)
929
Rational distance = value.toRational();
930
if (distance.first == 0) {
933
else if (static_cast<uint32_t>(distance.first) == 0xffffffff) {
936
else if (distance.second != 0) {
937
std::ostringstream oss;
939
os << std::fixed << std::setprecision(2)
940
<< (float)distance.first / distance.second
945
os << "(" << value << ")";
950
std::ostream& print0x9207(std::ostream& os, const Value& value)
952
long mode = value.toLong();
954
case 0: os << "Unknown"; break;
955
case 1: os << "Average"; break;
956
case 2: os << "Center weighted"; break;
957
case 3: os << "Spot"; break;
958
case 4: os << "Multispot"; break;
959
case 5: os << "Matrix"; break;
960
case 6: os << "Partial"; break;
961
default: os << "(" << mode << ")"; break;
966
std::ostream& print0x9208(std::ostream& os, const Value& value)
968
long source = value.toLong();
970
case 0: os << "Unknown"; break;
971
case 1: os << "Daylight"; break;
972
case 2: os << "Fluorescent"; break;
973
case 3: os << "Tungsten (incandescent light)"; break;
974
case 4: os << "Flash"; break;
975
case 9: os << "Fine weather"; break;
976
case 10: os << "Cloudy weather"; break;
977
case 11: os << "Shade"; break;
978
case 12: os << "Daylight fluorescent (D 5700 - 7100K)"; break;
979
case 13: os << "Day white fluorescent (N 4600 - 5400K)"; break;
980
case 14: os << "Cool white fluorescent (W 3900 - 4500K)"; break;
981
case 15: os << "White fluorescent (WW 3200 - 3700K)"; break;
982
case 17: os << "Standard light A"; break;
983
case 18: os << "Standard light B"; break;
984
case 19: os << "Standard light C"; break;
985
case 20: os << "D55"; break;
986
case 21: os << "D65"; break;
987
case 22: os << "D75"; break;
988
case 23: os << "D50"; break;
989
case 24: os << "ISO studio tungsten"; break;
990
case 255: os << "other light source"; break;
991
default: os << "(" << source << ")"; break;
996
std::ostream& print0x9209(std::ostream& os, const Value& value)
998
long flash = value.toLong();
1000
case 0x00: os << "No"; break;
1001
case 0x01: os << "Yes"; break;
1002
case 0x05: os << "Strobe return light not detected"; break;
1003
case 0x07: os << "Strobe return light detected"; break;
1004
case 0x09: os << "Yes, compulsory"; break;
1005
case 0x0d: os << "Yes, compulsory, return light not detected"; break;
1006
case 0x0f: os << "Yes, compulsory, return light detected"; break;
1007
case 0x10: os << "No, compulsory"; break;
1008
case 0x18: os << "No, auto"; break;
1009
case 0x19: os << "Yes, auto"; break;
1010
case 0x1d: os << "Yes, auto, return light not detected"; break;
1011
case 0x1f: os << "Yes, auto, return light detected"; break;
1012
case 0x20: os << "No flash function"; break;
1013
case 0x41: os << "Yes, red-eye reduction"; break;
1014
case 0x45: os << "Yes, red-eye reduction, return light not detected"; break;
1015
case 0x47: os << "Yes, red-eye reduction, return light detected"; break;
1016
case 0x49: os << "Yes, compulsory, red-eye reduction"; break;
1017
case 0x4d: os << "Yes, compulsory, red-eye reduction, return light not detected"; break;
1018
case 0x4f: os << "Yes, compulsory, red-eye reduction, return light detected"; break;
1019
case 0x59: os << "Yes, auto, red-eye reduction"; break;
1020
case 0x5d: os << "Yes, auto, red-eye reduction, return light not detected"; break;
1021
case 0x5f: os << "Yes, auto, red-eye reduction, return light detected"; break;
1022
default: os << "(" << flash << ")"; break;
1027
std::ostream& print0x920a(std::ostream& os, const Value& value)
1029
Rational length = value.toRational();
1030
if (length.second != 0) {
1031
std::ostringstream oss;
1033
os << std::fixed << std::setprecision(1)
1034
<< (float)length.first / length.second
1039
os << "(" << value << ")";
1044
// Todo: Implement this properly
1045
std::ostream& print0x9286(std::ostream& os, const Value& value)
1047
if (value.size() > 8) {
1048
DataBuf buf(value.size());
1049
value.copy(buf.pData_, bigEndian);
1050
// Hack: Skip the leading 8-Byte character code, truncate
1051
// trailing '\0's and let the stream take care of the remainder
1052
std::string userComment(reinterpret_cast<char*>(buf.pData_) + 8, buf.size_ - 8);
1053
std::string::size_type pos = userComment.find_last_not_of('\0');
1054
os << userComment.substr(0, pos + 1);
1059
std::ostream& print0xa001(std::ostream& os, const Value& value)
1061
long space = value.toLong();
1063
case 1: os << "sRGB"; break;
1064
case 0xffff: os << "Uncalibrated"; break;
1065
default: os << "(" << space << ")"; break;
1070
std::ostream& print0xa217(std::ostream& os, const Value& value)
1072
long method = value.toLong();
1074
case 1: os << "Not defined"; break;
1075
case 2: os << "One-chip color area"; break;
1076
case 3: os << "Two-chip color area"; break;
1077
case 4: os << "Three-chip color area"; break;
1078
case 5: os << "Color sequential area"; break;
1079
case 7: os << "Trilinear sensor"; break;
1080
case 8: os << "Color sequential linear"; break;
1081
default: os << "(" << method << ")"; break;
1086
std::ostream& print0xa300(std::ostream& os, const Value& value)
1088
long source = value.toLong();
1090
case 3: os << "Digital still camera"; break;
1091
default: os << "(" << source << ")"; break;
1096
std::ostream& print0xa301(std::ostream& os, const Value& value)
1098
long scene = value.toLong();
1100
case 1: os << "Directly photographed"; break;
1101
default: os << "(" << scene << ")"; break;
1106
std::ostream& print0xa402(std::ostream& os, const Value& value)
1108
long mode = value.toLong();
1110
case 0: os << "Auto"; break;
1111
case 1: os << "Manual"; break;
1112
case 2: os << "Auto bracket"; break;
1113
default: os << "(" << mode << ")"; break;
1118
std::ostream& print0xa403(std::ostream& os, const Value& value)
1120
long wb = value.toLong();
1122
case 0: os << "Auto"; break;
1123
case 1: os << "Manual"; break;
1124
default: os << "(" << wb << ")"; break;
1129
std::ostream& print0xa404(std::ostream& os, const Value& value)
1131
Rational zoom = value.toRational();
1132
if (zoom.second == 0) {
1133
os << "Digital zoom not used";
1136
std::ostringstream oss;
1138
os << std::fixed << std::setprecision(1)
1139
<< (float)zoom.first / zoom.second;
1145
std::ostream& print0xa405(std::ostream& os, const Value& value)
1147
long length = value.toLong();
1152
os << length << ".0 mm";
1157
std::ostream& print0xa406(std::ostream& os, const Value& value)
1159
long scene = value.toLong();
1161
case 0: os << "Standard"; break;
1162
case 1: os << "Landscape"; break;
1163
case 2: os << "Portrait"; break;
1164
case 3: os << "Night scene"; break;
1165
default: os << "(" << scene << ")"; break;
1170
std::ostream& print0xa407(std::ostream& os, const Value& value)
1172
long gain = value.toLong();
1174
case 0: os << "None"; break;
1175
case 1: os << "Low gain up"; break;
1176
case 2: os << "High gain up"; break;
1177
case 3: os << "Low gain down"; break;
1178
case 4: os << "High gain down"; break;
1179
default: os << "(" << gain << ")"; break;
1184
std::ostream& print0xa408(std::ostream& os, const Value& value)
1186
long contrast = value.toLong();
1188
case 0: os << "Normal"; break;
1189
case 1: os << "Soft"; break;
1190
case 2: os << "Hard"; break;
1191
default: os << "(" << contrast << ")"; break;
1196
std::ostream& print0xa409(std::ostream& os, const Value& value)
1198
long saturation = value.toLong();
1199
switch (saturation) {
1200
case 0: os << "Normal"; break;
1201
case 1: os << "Low"; break;
1202
case 2: os << "High"; break;
1203
default: os << "(" << saturation << ")"; break;
1208
std::ostream& print0xa40a(std::ostream& os, const Value& value)
1210
long sharpness = value.toLong();
1211
switch (sharpness) {
1212
case 0: os << "Normal"; break;
1213
case 1: os << "Soft"; break;
1214
case 2: os << "Hard"; break;
1215
default: os << "(" << sharpness << ")"; break;
1220
std::ostream& print0xa40c(std::ostream& os, const Value& value)
1222
long distance = value.toLong();
1224
case 0: os << "Unknown"; break;
1225
case 1: os << "Macro"; break;
1226
case 2: os << "Close view"; break;
1227
case 3: os << "Distant view"; break;
1228
default: os << "(" << distance << ")"; break;
1233
} // namespace Exiv2