~noskcaj/ubuntu/trusty/libextractor/merge

« back to all changes in this revision

Viewing changes to src/plugins/exiv2/tags.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-11-17 20:27:32 UTC
  • mfrom: (1.10.4 upstream) (5.2.5 sid)
  • Revision ID: james.westby@ubuntu.com-20091117202732-ipm2h3gks5bdw2vx
Tags: 0.5.23+dfsg-3
* Building against libltdl7.
* Updating to standards version 3.8.3.
* Adding maintainer homepage field to control.
* Marking maintainer homepage field to be also included in binary
  packages and changelog.
* Adding README.source.
* Simplifying autotools handling in rules.
* Updating README.source.
* Moving maintainer homepage field from control to copyright.
* Dropping la files.
* Simplyfing debhelper install files.
* Bumping versioned build-depends on debhelper.
* Adding depends to dpkg install info.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// ***************************************************************** -*- C++ -*-
2
 
/*
3
 
 * Copyright (C) 2004, 2005 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
 
 */
21
 
/*
22
 
  File:      tags.cpp
23
 
  Version:   $Rev: 596 $
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
27
 
 */
28
 
// *****************************************************************************
29
 
#include "rcsid.hpp"
30
 
EXIV2_RCSID("@(#) $Id: tags.cpp 596 2005-06-26 11:04:27Z ahuggel $");
31
 
 
32
 
// *****************************************************************************
33
 
// included header files
34
 
#include "tags.hpp"
35
 
#include "error.hpp"
36
 
#include "types.hpp"
37
 
#include "ifd.hpp"
38
 
#include "value.hpp"
39
 
#include "makernote.hpp"
40
 
#include "mn.hpp"                // To ensure that all makernotes are registered
41
 
 
42
 
#include <iostream>
43
 
#include <iomanip>
44
 
#include <sstream>
45
 
#include <utility>
46
 
#include <cstdlib>
47
 
#include <cassert>
48
 
 
49
 
// *****************************************************************************
50
 
// class member definitions
51
 
namespace Exiv2 {
52
 
 
53
 
    IfdInfo::IfdInfo(IfdId ifdId, const char* name, const char* item)
54
 
        : ifdId_(ifdId), name_(name), item_(item)
55
 
    {
56
 
    }
57
 
 
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)")
80
 
    };
81
 
 
82
 
    SectionInfo::SectionInfo(
83
 
        SectionId sectionId,
84
 
        const char* name,
85
 
        const char* desc
86
 
    )
87
 
        : sectionId_(sectionId), name_(name), desc_(desc)
88
 
    {
89
 
    }
90
 
 
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")
108
 
    };
109
 
 
110
 
    TagInfo::TagInfo(
111
 
        uint16_t tag,
112
 
        const char* name,
113
 
        const char* desc,
114
 
        IfdId ifdId,
115
 
        SectionId sectionId,
116
 
        TypeId typeId,
117
 
        PrintFct printFct
118
 
    )
119
 
        : tag_(tag), name_(name), desc_(desc), ifdId_(ifdId),
120
 
          sectionId_(sectionId), typeId_(typeId), printFct_(printFct)
121
 
    {
122
 
    }
123
 
 
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)
160
 
    };
161
 
 
162
 
    // Exif IFD Tags
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)
223
 
    };
224
 
 
225
 
    // GPS Info Tags
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)
260
 
    };
261
 
 
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)
271
 
    };
272
 
 
273
 
    // Unknown Tag
274
 
    static const TagInfo unknownTag(0xffff, "Unknown tag", "Unknown tag", ifdIdNotSet, sectionIdNotSet, asciiString, printValue);
275
 
 
276
 
    std::ostream& TagTranslator::print(std::ostream& os, const Value& value) const
277
 
    {
278
 
        if (!pTagDetails_) return os << value;
279
 
 
280
 
        long l = value.toLong();
281
 
 
282
 
        long e = pTagDetails_[0].val_;
283
 
        int i = 1;
284
 
        for (; pTagDetails_[i].val_ != l && pTagDetails_[i].val_ != e; ++i) {}
285
 
        if (pTagDetails_[i].val_ == l) {
286
 
            os << pTagDetails_[i].label_;
287
 
        }
288
 
        else {
289
 
            os << "(" << l << ")";
290
 
        }
291
 
        return os;
292
 
    } // TagTranslator::print
293
 
 
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_[] = {
298
 
        0,
299
 
        ifdTagInfo, exifTagInfo, gpsTagInfo, iopTagInfo, ifdTagInfo,
300
 
        0
301
 
    };
302
 
 
303
 
    // Lookup list for registered makernote tag info tables
304
 
    const TagInfo* ExifTags::makerTagInfos_[];
305
 
 
306
 
    // All makernote ifd ids, in the same order as the tag infos in makerTagInfos_
307
 
    IfdId ExifTags::makerIfdIds_[];
308
 
 
309
 
    void ExifTags::registerBaseTagInfo(IfdId ifdId)
310
 
    {
311
 
        registerMakerTagInfo(ifdId, ifdTagInfo);
312
 
    }
313
 
 
314
 
    void ExifTags::registerMakerTagInfo(IfdId ifdId, const TagInfo* tagInfo)
315
 
    {
316
 
        int i = 0;
317
 
        for (; i < MAX_MAKER_TAG_INFOS; ++i) {
318
 
            if (makerIfdIds_[i] == 0) {
319
 
                makerIfdIds_[i] = ifdId;
320
 
                makerTagInfos_[i] = tagInfo;
321
 
                break;
322
 
            }
323
 
        }
324
 
        if (i == MAX_MAKER_TAG_INFOS) throw Error(16);
325
 
    } // ExifTags::registerMakerTagInfo
326
 
 
327
 
    int ExifTags::tagInfoIdx(uint16_t tag, IfdId ifdId)
328
 
    {
329
 
        const TagInfo* tagInfo = tagInfos_[ifdId];
330
 
        if (tagInfo == 0) return -1;
331
 
        int idx;
332
 
        for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
333
 
            if (tagInfo[idx].tag_ == tag) return idx;
334
 
        }
335
 
        return -1;
336
 
    } // ExifTags::tagInfoIdx
337
 
 
338
 
    const TagInfo* ExifTags::makerTagInfo(uint16_t tag, IfdId ifdId)
339
 
    {
340
 
        int i = 0;
341
 
        for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
342
 
        if (i == MAX_MAKER_TAG_INFOS) return 0;
343
 
 
344
 
        for (int k = 0; makerTagInfos_[i][k].tag_ != 0xffff; ++k) {
345
 
            if (makerTagInfos_[i][k].tag_ == tag) return &makerTagInfos_[i][k];
346
 
        }
347
 
 
348
 
        return 0;
349
 
    } // ExifTags::makerTagInfo
350
 
 
351
 
    const TagInfo* ExifTags::makerTagInfo(const std::string& tagName,
352
 
                                          IfdId ifdId)
353
 
    {
354
 
        int i = 0;
355
 
        for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
356
 
        if (i == MAX_MAKER_TAG_INFOS) return 0;
357
 
 
358
 
        for (int k = 0; makerTagInfos_[i][k].tag_ != 0xffff; ++k) {
359
 
            if (makerTagInfos_[i][k].name_ == tagName) {
360
 
                return &makerTagInfos_[i][k];
361
 
            }
362
 
        }
363
 
 
364
 
        return 0;
365
 
    } // ExifTags::makerTagInfo
366
 
 
367
 
    bool ExifTags::isMakerIfd(IfdId ifdId)
368
 
    {
369
 
        int i = 0;
370
 
        for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
371
 
        return i != MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != IfdId(0);
372
 
    }
373
 
 
374
 
    std::string ExifTags::tagName(uint16_t tag, IfdId ifdId)
375
 
    {
376
 
        if (isExifIfd(ifdId)) {
377
 
            int idx = tagInfoIdx(tag, ifdId);
378
 
            if (idx != -1) return tagInfos_[ifdId][idx].name_;
379
 
        }
380
 
        if (isMakerIfd(ifdId)) {
381
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
382
 
            if (tagInfo != 0) return tagInfo->name_;
383
 
        }
384
 
        std::ostringstream os;
385
 
        os << "0x" << std::setw(4) << std::setfill('0') << std::right
386
 
           << std::hex << tag;
387
 
        return os.str();
388
 
    } // ExifTags::tagName
389
 
 
390
 
    const char* ExifTags::tagDesc(uint16_t tag, IfdId ifdId)
391
 
    {
392
 
        if (isExifIfd(ifdId)) {
393
 
            int idx = tagInfoIdx(tag, ifdId);
394
 
            if (idx == -1) return unknownTag.desc_;
395
 
            return tagInfos_[ifdId][idx].desc_;
396
 
        }
397
 
        if (isMakerIfd(ifdId)) {
398
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
399
 
            if (tagInfo != 0) return tagInfo->desc_;
400
 
        }
401
 
        return "";
402
 
    } // ExifTags::tagDesc
403
 
 
404
 
    const char* ExifTags::sectionName(uint16_t tag, IfdId ifdId)
405
 
    {
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_;
411
 
        }
412
 
        if (isMakerIfd(ifdId)) {
413
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
414
 
            if (tagInfo != 0) return sectionInfo_[tagInfo->sectionId_].name_;
415
 
        }
416
 
        return "";
417
 
    } // ExifTags::sectionName
418
 
 
419
 
    const char* ExifTags::sectionDesc(uint16_t tag, IfdId ifdId)
420
 
    {
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_;
426
 
        }
427
 
        if (isMakerIfd(ifdId)) {
428
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
429
 
            if (tagInfo != 0) return sectionInfo_[tagInfo->sectionId_].desc_;
430
 
        }
431
 
        return "";
432
 
    } // ExifTags::sectionDesc
433
 
 
434
 
    uint16_t ExifTags::tag(const std::string& tagName, IfdId ifdId)
435
 
    {
436
 
        uint16_t tag = 0xffff;
437
 
        if (isExifIfd(ifdId)) {
438
 
            const TagInfo* tagInfo = tagInfos_[ifdId];
439
 
            if (tagInfo) {
440
 
                int idx;
441
 
                for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
442
 
                    if (tagInfo[idx].name_ == tagName) break;
443
 
                }
444
 
                tag = tagInfo[idx].tag_;
445
 
            }
446
 
        }
447
 
        if (isMakerIfd(ifdId)) {
448
 
            const TagInfo* tagInfo = makerTagInfo(tagName, ifdId);
449
 
            if (tagInfo != 0) tag = tagInfo->tag_;
450
 
        }
451
 
        if (tag == 0xffff) {
452
 
            if (!isHex(tagName, 4, "0x")) throw Error(7, tagName, ifdId);
453
 
            std::istringstream is(tagName);
454
 
            is >> std::hex >> tag;
455
 
        }
456
 
        return tag;
457
 
    } // ExifTags::tag
458
 
 
459
 
    IfdId ExifTags::ifdIdByIfdItem(const std::string& ifdItem)
460
 
    {
461
 
        int i;
462
 
        for (i = int(lastIfdId) - 1; i > 0; --i) {
463
 
            if (ifdInfo_[i].item_ == ifdItem) break;
464
 
        }
465
 
        return IfdId(i);
466
 
    }
467
 
 
468
 
    const char* ExifTags::ifdName(IfdId ifdId)
469
 
    {
470
 
        return ifdInfo_[ifdId].name_;
471
 
    }
472
 
 
473
 
    const char* ExifTags::ifdItem(IfdId ifdId)
474
 
    {
475
 
        return ifdInfo_[ifdId].item_;
476
 
    }
477
 
 
478
 
    const char* ExifTags::sectionName(SectionId sectionId)
479
 
    {
480
 
        return sectionInfo_[sectionId].name_;
481
 
    }
482
 
 
483
 
    SectionId ExifTags::sectionId(const std::string& sectionName)
484
 
    {
485
 
        int i;
486
 
        for (i = int(lastSectionId) - 1; i > 0; --i) {
487
 
            if (sectionInfo_[i].name_ == sectionName) break;
488
 
        }
489
 
        return SectionId(i);
490
 
    }
491
 
 
492
 
    TypeId ExifTags::tagType(uint16_t tag, IfdId ifdId)
493
 
    {
494
 
        if (isExifIfd(ifdId)) {
495
 
            int idx = tagInfoIdx(tag, ifdId);
496
 
            if (idx != -1) return tagInfos_[ifdId][idx].typeId_;
497
 
        }
498
 
        if (isMakerIfd(ifdId)) {
499
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
500
 
            if (tagInfo != 0) return tagInfo->typeId_;
501
 
        }
502
 
        return unknownTag.typeId_;
503
 
    }
504
 
 
505
 
    std::ostream& ExifTags::printTag(std::ostream& os,
506
 
                                     uint16_t tag,
507
 
                                     IfdId ifdId,
508
 
                                     const Value& value)
509
 
    {
510
 
        if (value.count() == 0) return os;
511
 
        PrintFct fct = printValue;
512
 
        if (isExifIfd(ifdId)) {
513
 
            int idx = tagInfoIdx(tag, ifdId);
514
 
            if (idx != -1) {
515
 
                fct = tagInfos_[ifdId][idx].printFct_;
516
 
            }
517
 
        }
518
 
        if (isMakerIfd(ifdId)) {
519
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
520
 
            if (tagInfo != 0) fct = tagInfo->printFct_;
521
 
        }
522
 
        return fct(os, value);
523
 
    } // ExifTags::printTag
524
 
 
525
 
    void ExifTags::taglist(std::ostream& os)
526
 
    {
527
 
        for (int i=0; ifdTagInfo[i].tag_ != 0xffff; ++i) {
528
 
            os << ifdTagInfo[i] << "\n";
529
 
        }
530
 
        for (int i=0; exifTagInfo[i].tag_ != 0xffff; ++i) {
531
 
            os << exifTagInfo[i] << "\n";
532
 
        }
533
 
        for (int i=0; iopTagInfo[i].tag_ != 0xffff; ++i) {
534
 
            os << iopTagInfo[i] << "\n";
535
 
        }
536
 
        for (int i=0; gpsTagInfo[i].tag_ != 0xffff; ++i) {
537
 
            os << gpsTagInfo[i] << "\n";
538
 
        }
539
 
    } // ExifTags::taglist
540
 
 
541
 
    void ExifTags::makerTaglist(std::ostream& os, IfdId ifdId)
542
 
    {
543
 
        int i = 0;
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";
549
 
            }
550
 
        }
551
 
    } // ExifTags::makerTaglist
552
 
 
553
 
    const char* ExifKey::familyName_ = "Exif";
554
 
 
555
 
    ExifKey::ExifKey(const std::string& key)
556
 
        : tag_(0), ifdId_(ifdIdNotSet), ifdItem_(""),
557
 
          idx_(0), key_(key)
558
 
    {
559
 
        decomposeKey();
560
 
    }
561
 
 
562
 
    ExifKey::ExifKey(uint16_t tag, const std::string& ifdItem)
563
 
        : tag_(0), ifdId_(ifdIdNotSet), ifdItem_(""),
564
 
          idx_(0), key_("")
565
 
    {
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);
570
 
        }
571
 
        tag_ = tag;
572
 
        ifdId_ = ifdId;
573
 
        ifdItem_ = ifdItem;
574
 
        makeKey();
575
 
    }
576
 
 
577
 
    ExifKey::ExifKey(const Entry& e)
578
 
        : tag_(e.tag()), ifdId_(e.ifdId()),
579
 
          ifdItem_(ExifTags::ifdItem(e.ifdId())),
580
 
          idx_(e.idx()), key_("")
581
 
    {
582
 
        makeKey();
583
 
    }
584
 
 
585
 
    ExifKey::ExifKey(const ExifKey& rhs)
586
 
        : tag_(rhs.tag_), ifdId_(rhs.ifdId_), ifdItem_(rhs.ifdItem_),
587
 
          idx_(rhs.idx_), key_(rhs.key_)
588
 
    {
589
 
    }
590
 
 
591
 
    ExifKey::~ExifKey()
592
 
    {
593
 
    }
594
 
 
595
 
    ExifKey& ExifKey::operator=(const ExifKey& rhs)
596
 
    {
597
 
        if (this == &rhs) return *this;
598
 
        Key::operator=(rhs);
599
 
        tag_ = rhs.tag_;
600
 
        ifdId_ = rhs.ifdId_;
601
 
        ifdItem_ = rhs.ifdItem_;
602
 
        idx_ = rhs.idx_;
603
 
        key_ = rhs.key_;
604
 
        return *this;
605
 
    }
606
 
 
607
 
    std::string ExifKey::tagName() const
608
 
    {
609
 
        return ExifTags::tagName(tag_, ifdId_);
610
 
    }
611
 
 
612
 
    ExifKey::AutoPtr ExifKey::clone() const
613
 
    {
614
 
        return AutoPtr(clone_());
615
 
    }
616
 
 
617
 
    ExifKey* ExifKey::clone_() const
618
 
    {
619
 
        return new ExifKey(*this);
620
 
    }
621
 
 
622
 
    std::string ExifKey::sectionName() const
623
 
    {
624
 
        return ExifTags::sectionName(tag(), ifdId());
625
 
    }
626
 
 
627
 
    void ExifKey::decomposeKey()
628
 
    {
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_);
635
 
        }
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_);
643
 
 
644
 
        // Find IfdId
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_);
650
 
        }
651
 
        // Convert tag
652
 
        uint16_t tag = ExifTags::tag(tagName, ifdId);
653
 
 
654
 
        // Translate hex tag name (0xabcd) to a real tag name if there is one
655
 
        tagName = ExifTags::tagName(tag, ifdId);
656
 
 
657
 
        tag_ = tag;
658
 
        ifdId_ = ifdId;
659
 
        ifdItem_ = ifdItem;
660
 
        key_ = familyName + "." + ifdItem + "." + tagName;
661
 
    }
662
 
 
663
 
    void ExifKey::makeKey()
664
 
    {
665
 
        key_ =   std::string(familyName_)
666
 
               + "." + ifdItem_
667
 
               + "." + ExifTags::tagName(tag_, ifdId_);
668
 
    }
669
 
 
670
 
    // *************************************************************************
671
 
    // free functions
672
 
 
673
 
    bool isExifIfd(IfdId ifdId)
674
 
    {
675
 
        bool rc;
676
 
        switch (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;
683
 
        }
684
 
        return rc;
685
 
    } // isExifIfd
686
 
 
687
 
    std::ostream& operator<<(std::ostream& os, const TagInfo& ti)
688
 
    {
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_);
699
 
    }
700
 
 
701
 
    std::ostream& operator<<(std::ostream& os, const Rational& r)
702
 
    {
703
 
        return os << r.first << "/" << r.second;
704
 
    }
705
 
 
706
 
    std::istream& operator>>(std::istream& is, Rational& r)
707
 
    {
708
 
        int32_t nominator;
709
 
        int32_t denominator;
710
 
        char c;
711
 
        is >> nominator >> c >> denominator;
712
 
        if (is && c == '/') r = std::make_pair(nominator, denominator);
713
 
        return is;
714
 
    }
715
 
 
716
 
    std::ostream& operator<<(std::ostream& os, const URational& r)
717
 
    {
718
 
        return os << r.first << "/" << r.second;
719
 
    }
720
 
 
721
 
    std::istream& operator>>(std::istream& is, URational& r)
722
 
    {
723
 
        uint32_t nominator;
724
 
        uint32_t denominator;
725
 
        char c;
726
 
        is >> nominator >> c >> denominator;
727
 
        if (is && c == '/') r = std::make_pair(nominator, denominator);
728
 
        return is;
729
 
    }
730
 
 
731
 
    std::ostream& printValue(std::ostream& os, const Value& value)
732
 
    {
733
 
        return os << value;
734
 
    }
735
 
 
736
 
    std::ostream& printLong(std::ostream& os, const Value& value)
737
 
    {
738
 
        Rational r = value.toRational();
739
 
        if (r.second != 0) return os << static_cast<long>(r.first) / r.second;
740
 
        return os << "(" << value << ")";
741
 
    } // printLong
742
 
 
743
 
    std::ostream& printFloat(std::ostream& os, const Value& value)
744
 
    {
745
 
        Rational r = value.toRational();
746
 
        if (r.second != 0) return os << static_cast<float>(r.first) / r.second;
747
 
        return os << "(" << value << ")";
748
 
    } // printFloat
749
 
 
750
 
    std::ostream& printUnit(std::ostream& os, const Value& value)
751
 
    {
752
 
        long unit = value.toLong();
753
 
        switch (unit) {
754
 
        case 2:  os << "inch"; break;
755
 
        case 3:  os << "cm"; break;
756
 
        default: os << "(" << unit << ")"; break;
757
 
        }
758
 
        return os;
759
 
    }
760
 
 
761
 
    std::ostream& print0x0103(std::ostream& os, const Value& value)
762
 
    {
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;
768
 
        }
769
 
        return os;
770
 
    }
771
 
 
772
 
    std::ostream& print0x0106(std::ostream& os, const Value& value)
773
 
    {
774
 
        long photo = value.toLong();
775
 
        switch (photo) {
776
 
        case 2:  os << "RGB"; break;
777
 
        case 6:  os << "YCbCr"; break;
778
 
        default: os << "(" << photo << ")"; break;
779
 
        }
780
 
        return os;
781
 
    }
782
 
 
783
 
    std::ostream& print0x0112(std::ostream& os, const Value& value)
784
 
    {
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;
796
 
        }
797
 
        return os;
798
 
    }
799
 
 
800
 
    std::ostream& print0x0213(std::ostream& os, const Value& value)
801
 
    {
802
 
        long position = value.toLong();
803
 
        switch (position) {
804
 
        case 1:  os << "Centered"; break;
805
 
        case 2:  os << "Co-sited"; break;
806
 
        default: os << "(" << position << ")"; break;
807
 
        }
808
 
        return os;
809
 
    }
810
 
 
811
 
    std::ostream& print0x8298(std::ostream& os, const Value& value)
812
 
    {
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);
820
 
            if (editor != "") {
821
 
                if (photographer != " ") os << ", ";
822
 
                os << editor;
823
 
            }
824
 
        }
825
 
        else {
826
 
            os << val;
827
 
        }
828
 
        return os;
829
 
    }
830
 
 
831
 
    std::ostream& print0x829a(std::ostream& os, const Value& value)
832
 
    {
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);
837
 
            t.first = 1;
838
 
        }
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);
842
 
            t.second = 1;
843
 
        }
844
 
        if (t.second == 1) {
845
 
            os << t.first << " s";
846
 
        }
847
 
        else {
848
 
            os << t.first << "/" << t.second << " s";
849
 
        }
850
 
        return os;
851
 
    }
852
 
 
853
 
    std::ostream& print0x829d(std::ostream& os, const Value& value)
854
 
    {
855
 
        Rational fnumber = value.toRational();
856
 
        if (fnumber.second != 0) {
857
 
            os << "F" << (float)fnumber.first / fnumber.second;
858
 
        }
859
 
        else {
860
 
            os << "(" << value << ")";
861
 
        }
862
 
        return os;
863
 
    }
864
 
 
865
 
    std::ostream& print0x8822(std::ostream& os, const Value& value)
866
 
    {
867
 
        long program = value.toLong();
868
 
        switch (program) {
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;
879
 
        }
880
 
        return os;
881
 
    }
882
 
 
883
 
    std::ostream& print0x8827(std::ostream& os, const Value& value)
884
 
    {
885
 
        return os << value.toLong();
886
 
    }
887
 
 
888
 
    std::ostream& print0x9101(std::ostream& os, const Value& value)
889
 
    {
890
 
        for (long i = 0; i < value.count(); ++i) {
891
 
            long l = value.toLong(i);
892
 
            switch (l) {
893
 
            case 0:  break;
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;
901
 
            }
902
 
        }
903
 
        return os;
904
 
    }
905
 
 
906
 
    std::ostream& print0x9204(std::ostream& os, const Value& value)
907
 
    {
908
 
        Rational bias = value.toRational();
909
 
        if (bias.second <= 0) {
910
 
            os << "(" << bias.first << "/" << bias.second << ")";
911
 
        }
912
 
        else if (bias.first == 0) {
913
 
            os << "0";
914
 
        }
915
 
        else {
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;
920
 
            if (den != 1) {
921
 
                os << "/" << den;
922
 
            }
923
 
        }
924
 
        return os;
925
 
    }
926
 
 
927
 
    std::ostream& print0x9206(std::ostream& os, const Value& value)
928
 
    {
929
 
        Rational distance = value.toRational();
930
 
        if (distance.first == 0) {
931
 
            os << "Unknown";
932
 
        }
933
 
        else if (static_cast<uint32_t>(distance.first) == 0xffffffff) {
934
 
            os << "Infinity";
935
 
        }
936
 
        else if (distance.second != 0) {
937
 
            std::ostringstream oss;
938
 
            oss.copyfmt(os);
939
 
            os << std::fixed << std::setprecision(2)
940
 
               << (float)distance.first / distance.second
941
 
               << " m";
942
 
            os.copyfmt(oss);
943
 
        }
944
 
        else {
945
 
            os << "(" << value << ")";
946
 
        }
947
 
        return os;
948
 
    }
949
 
 
950
 
    std::ostream& print0x9207(std::ostream& os, const Value& value)
951
 
    {
952
 
        long mode = value.toLong();
953
 
        switch (mode) {
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;
962
 
        }
963
 
        return os;
964
 
    }
965
 
 
966
 
    std::ostream& print0x9208(std::ostream& os, const Value& value)
967
 
    {
968
 
        long source = value.toLong();
969
 
        switch (source) {
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;
992
 
        }
993
 
        return os;
994
 
    }
995
 
 
996
 
    std::ostream& print0x9209(std::ostream& os, const Value& value)
997
 
    {
998
 
        long flash = value.toLong();
999
 
        switch (flash) {
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;
1023
 
        }
1024
 
        return os;
1025
 
    }
1026
 
 
1027
 
    std::ostream& print0x920a(std::ostream& os, const Value& value)
1028
 
    {
1029
 
        Rational length = value.toRational();
1030
 
        if (length.second != 0) {
1031
 
            std::ostringstream oss;
1032
 
            oss.copyfmt(os);
1033
 
            os << std::fixed << std::setprecision(1)
1034
 
               << (float)length.first / length.second
1035
 
               << " mm";
1036
 
            os.copyfmt(oss);
1037
 
        }
1038
 
        else {
1039
 
            os << "(" << value << ")";
1040
 
        }
1041
 
        return os;
1042
 
    }
1043
 
 
1044
 
    // Todo: Implement this properly
1045
 
    std::ostream& print0x9286(std::ostream& os, const Value& value)
1046
 
    {
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);
1055
 
        }
1056
 
        return os;
1057
 
    }
1058
 
 
1059
 
    std::ostream& print0xa001(std::ostream& os, const Value& value)
1060
 
    {
1061
 
        long space = value.toLong();
1062
 
        switch (space) {
1063
 
        case 1:      os << "sRGB"; break;
1064
 
        case 0xffff: os << "Uncalibrated"; break;
1065
 
        default:     os << "(" << space << ")"; break;
1066
 
        }
1067
 
        return os;
1068
 
    }
1069
 
 
1070
 
    std::ostream& print0xa217(std::ostream& os, const Value& value)
1071
 
    {
1072
 
        long method = value.toLong();
1073
 
        switch (method) {
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;
1082
 
        }
1083
 
        return os;
1084
 
    }
1085
 
 
1086
 
    std::ostream& print0xa300(std::ostream& os, const Value& value)
1087
 
    {
1088
 
        long source = value.toLong();
1089
 
        switch (source) {
1090
 
        case 3:      os << "Digital still camera"; break;
1091
 
        default:     os << "(" << source << ")"; break;
1092
 
        }
1093
 
        return os;
1094
 
    }
1095
 
 
1096
 
    std::ostream& print0xa301(std::ostream& os, const Value& value)
1097
 
    {
1098
 
        long scene = value.toLong();
1099
 
        switch (scene) {
1100
 
        case 1:      os << "Directly photographed"; break;
1101
 
        default:     os << "(" << scene << ")"; break;
1102
 
        }
1103
 
        return os;
1104
 
    }
1105
 
 
1106
 
    std::ostream& print0xa402(std::ostream& os, const Value& value)
1107
 
    {
1108
 
        long mode = value.toLong();
1109
 
        switch (mode) {
1110
 
        case 0: os << "Auto"; break;
1111
 
        case 1: os << "Manual"; break;
1112
 
        case 2: os << "Auto bracket"; break;
1113
 
        default: os << "(" << mode << ")"; break;
1114
 
        }
1115
 
        return os;
1116
 
    }
1117
 
 
1118
 
    std::ostream& print0xa403(std::ostream& os, const Value& value)
1119
 
    {
1120
 
        long wb = value.toLong();
1121
 
        switch (wb) {
1122
 
        case 0: os << "Auto"; break;
1123
 
        case 1: os << "Manual"; break;
1124
 
        default: os << "(" << wb << ")"; break;
1125
 
        }
1126
 
        return os;
1127
 
    }
1128
 
 
1129
 
    std::ostream& print0xa404(std::ostream& os, const Value& value)
1130
 
    {
1131
 
        Rational zoom = value.toRational();
1132
 
        if (zoom.second == 0) {
1133
 
            os << "Digital zoom not used";
1134
 
        }
1135
 
        else {
1136
 
            std::ostringstream oss;
1137
 
            oss.copyfmt(os);
1138
 
            os << std::fixed << std::setprecision(1)
1139
 
               << (float)zoom.first / zoom.second;
1140
 
            os.copyfmt(oss);
1141
 
        }
1142
 
        return os;
1143
 
    }
1144
 
 
1145
 
    std::ostream& print0xa405(std::ostream& os, const Value& value)
1146
 
    {
1147
 
        long length = value.toLong();
1148
 
        if (length == 0) {
1149
 
            os << "Unknown";
1150
 
        }
1151
 
        else {
1152
 
            os << length << ".0 mm";
1153
 
        }
1154
 
        return os;
1155
 
    }
1156
 
 
1157
 
    std::ostream& print0xa406(std::ostream& os, const Value& value)
1158
 
    {
1159
 
        long scene = value.toLong();
1160
 
        switch (scene) {
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;
1166
 
        }
1167
 
        return os;
1168
 
    }
1169
 
 
1170
 
    std::ostream& print0xa407(std::ostream& os, const Value& value)
1171
 
    {
1172
 
        long gain = value.toLong();
1173
 
        switch (gain) {
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;
1180
 
        }
1181
 
        return os;
1182
 
    }
1183
 
 
1184
 
    std::ostream& print0xa408(std::ostream& os, const Value& value)
1185
 
    {
1186
 
        long contrast = value.toLong();
1187
 
        switch (contrast) {
1188
 
        case 0: os << "Normal"; break;
1189
 
        case 1: os << "Soft"; break;
1190
 
        case 2: os << "Hard"; break;
1191
 
        default: os << "(" << contrast << ")"; break;
1192
 
        }
1193
 
        return os;
1194
 
    }
1195
 
 
1196
 
    std::ostream& print0xa409(std::ostream& os, const Value& value)
1197
 
    {
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;
1204
 
        }
1205
 
        return os;
1206
 
    }
1207
 
 
1208
 
    std::ostream& print0xa40a(std::ostream& os, const Value& value)
1209
 
    {
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;
1216
 
        }
1217
 
        return os;
1218
 
    }
1219
 
 
1220
 
    std::ostream& print0xa40c(std::ostream& os, const Value& value)
1221
 
    {
1222
 
        long distance = value.toLong();
1223
 
        switch (distance) {
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;
1229
 
        }
1230
 
        return os;
1231
 
    }
1232
 
 
1233
 
}                                       // namespace Exiv2