~ubuntu-branches/debian/lenny/exiv2/lenny

« back to all changes in this revision

Viewing changes to src/tags.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2008-06-21 08:23:53 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080621082353-b1n4w08trwfwbfl4
Tags: 0.17.1-1
* New upstream release
  - Library transition cleared on debian-release/ d-d-a
* Version 0.17 also fixes:
  - CVE-2008-2696: DoS via metadata in images (Closes: #486328)
  - crashes when fed with wrong file (Closes: #485670)
* Urgency medium for CVE fix
* debian/patches/gcc4.3.diff unecessary for gcc-4.3
* Add /usr/share/bug/exiv2/presubj message for reportbug(1)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// ***************************************************************** -*- C++ -*-
2
2
/*
3
 
 * Copyright (C) 2004-2007 Andreas Huggel <ahuggel@gmx.net>
 
3
 * Copyright (C) 2004-2008 Andreas Huggel <ahuggel@gmx.net>
4
4
 *
5
5
 * This program is part of the Exiv2 distribution.
6
6
 *
20
20
 */
21
21
/*
22
22
  File:      tags.cpp
23
 
  Version:   $Rev: 1113 $
 
23
  Version:   $Rev: 1499 $
24
24
  Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
25
25
             Gilles Caulier (gc) <caulier.gilles@kdemail.net>
26
26
  History:   15-Jan-04, ahu: created
28
28
 */
29
29
// *****************************************************************************
30
30
#include "rcsid.hpp"
31
 
EXIV2_RCSID("@(#) $Id: tags.cpp 1113 2007-06-03 08:32:16Z ahuggel $")
 
31
EXIV2_RCSID("@(#) $Id: tags.cpp 1499 2008-06-10 03:22:59Z ahuggel $")
32
32
 
33
33
// *****************************************************************************
34
34
// included header files
55
55
#endif
56
56
 
57
57
// *****************************************************************************
 
58
// local declarations
 
59
namespace {
 
60
    // Print version string from an intermediate string
 
61
    std::ostream& printVersion(std::ostream& os, const std::string& str);
 
62
}
 
63
 
 
64
// *****************************************************************************
58
65
// class member definitions
59
66
namespace Exiv2 {
60
67
 
61
 
    IfdInfo::IfdInfo(IfdId ifdId, const char* name, const char* item)
62
 
        : ifdId_(ifdId), name_(name), item_(item)
63
 
    {
64
 
    }
65
 
 
66
 
    // Todo: Allow to register new IfdInfo entries from elsewhere (the makernotes)
 
68
    IfdInfo::Item::Item(const std::string& item)
 
69
    {
 
70
        i_ = item;
 
71
    }
 
72
 
 
73
    bool IfdInfo::operator==(IfdId ifdId) const
 
74
    {
 
75
        return ifdId_ == ifdId;
 
76
    }
 
77
 
 
78
    bool IfdInfo::operator==(Item item) const
 
79
    {
 
80
        return std::string(item_) == item.i_;
 
81
    }
 
82
 
67
83
    // Important: IFD item must be unique!
68
84
    const IfdInfo ExifTags::ifdInfo_[] = {
69
 
        IfdInfo(ifdIdNotSet, "(Unknown IFD)", "(Unknown item)"),
70
 
        IfdInfo(ifd0Id, "IFD0", "Image"),
71
 
        IfdInfo(exifIfdId, "Exif", "Photo"),  // just to avoid 'Exif.Exif.*' keys
72
 
        IfdInfo(gpsIfdId, "GPSInfo", "GPSInfo"),
73
 
        IfdInfo(iopIfdId, "Iop", "Iop"),
74
 
        IfdInfo(ifd1Id, "IFD1", "Thumbnail"),
75
 
        IfdInfo(canonIfdId, "Makernote", "Canon"),
76
 
        IfdInfo(canonCsIfdId, "Makernote", "CanonCs"),
77
 
        IfdInfo(canonSiIfdId, "Makernote", "CanonSi"),
78
 
        IfdInfo(canonCfIfdId, "Makernote", "CanonCf"),
79
 
        IfdInfo(canonPiIfdId, "Makernote", "CanonPi"),
80
 
        IfdInfo(canonPaIfdId, "Makernote", "CanonPa"),
81
 
        IfdInfo(fujiIfdId, "Makernote", "Fujifilm"),
82
 
        IfdInfo(minoltaIfdId, "Makernote", "Minolta"),
83
 
        IfdInfo(minoltaCs5DIfdId, "Makernote", "MinoltaCs5D"),
84
 
        IfdInfo(minoltaCs7DIfdId, "Makernote", "MinoltaCs7D"),
85
 
        IfdInfo(minoltaCsOldIfdId, "Makernote", "MinoltaCsOld"),
86
 
        IfdInfo(minoltaCsNewIfdId, "Makernote", "MinoltaCsNew"),
87
 
        IfdInfo(nikon1IfdId, "Makernote", "Nikon1"),
88
 
        IfdInfo(nikon2IfdId, "Makernote", "Nikon2"),
89
 
        IfdInfo(nikon3IfdId, "Makernote", "Nikon3"),
90
 
        IfdInfo(olympusIfdId, "Makernote", "Olympus"),
91
 
        IfdInfo(panasonicIfdId, "Makernote", "Panasonic"),
92
 
        IfdInfo(sigmaIfdId, "Makernote", "Sigma"),
93
 
        IfdInfo(sonyIfdId, "Makernote", "Sony"),
94
 
        IfdInfo(lastIfdId, "(Last IFD info)", "(Last IFD item)")
 
85
        { ifdIdNotSet,       "(Unknown IFD)", "(Unknown item)", 0 },
 
86
        { ifd0Id,            "IFD0",      "Image",        ExifTags::ifdTagList           },
 
87
        { exifIfdId,         "Exif",      "Photo",        ExifTags::exifTagList          }, // just to avoid 'Exif.Exif.*' keys
 
88
        { gpsIfdId,          "GPSInfo",   "GPSInfo",      ExifTags::gpsTagList           },
 
89
        { iopIfdId,          "Iop",       "Iop",          ExifTags::iopTagList           },
 
90
        { ifd1Id,            "IFD1",      "Thumbnail",    ExifTags::ifdTagList           },
 
91
        { canonIfdId,        "Makernote", "Canon",        CanonMakerNote::tagList        },
 
92
        { canonCsIfdId,      "Makernote", "CanonCs",      CanonMakerNote::tagListCs      },
 
93
        { canonSiIfdId,      "Makernote", "CanonSi",      CanonMakerNote::tagListSi      },
 
94
        { canonCfIfdId,      "Makernote", "CanonCf",      CanonMakerNote::tagListCf      },
 
95
        { canonPiIfdId,      "Makernote", "CanonPi",      CanonMakerNote::tagListPi      },
 
96
        { canonPaIfdId,      "Makernote", "CanonPa",      CanonMakerNote::tagListPa      },
 
97
        { fujiIfdId,         "Makernote", "Fujifilm",     FujiMakerNote::tagList         },
 
98
        { minoltaIfdId,      "Makernote", "Minolta",      MinoltaMakerNote::tagList      },
 
99
        { minoltaCs5DIfdId,  "Makernote", "MinoltaCs5D",  MinoltaMakerNote::tagListCs5D  },
 
100
        { minoltaCs7DIfdId,  "Makernote", "MinoltaCs7D",  MinoltaMakerNote::tagListCs7D  },
 
101
        { minoltaCsOldIfdId, "Makernote", "MinoltaCsOld", MinoltaMakerNote::tagListCsStd },
 
102
        { minoltaCsNewIfdId, "Makernote", "MinoltaCsNew", MinoltaMakerNote::tagListCsStd },
 
103
        { nikon1IfdId,       "Makernote", "Nikon1",       Nikon1MakerNote::tagList       },
 
104
        { nikon2IfdId,       "Makernote", "Nikon2",       Nikon2MakerNote::tagList       },
 
105
        { nikon3IfdId,       "Makernote", "Nikon3",       Nikon3MakerNote::tagList       },
 
106
        { olympusIfdId,      "Makernote", "Olympus",      OlympusMakerNote::tagList      },
 
107
        { panasonicIfdId,    "Makernote", "Panasonic",    PanasonicMakerNote::tagList    },
 
108
        { pentaxIfdId,       "Makernote", "Pentax",       PentaxMakerNote::tagList       },
 
109
        { sigmaIfdId,        "Makernote", "Sigma",        SigmaMakerNote::tagList        },
 
110
        { sonyIfdId,         "Makernote", "Sony",         SonyMakerNote::tagList         },
 
111
        { lastIfdId,         "(Last IFD info)", "(Last IFD item)", 0 }
95
112
    };
96
113
 
97
 
    SectionInfo::SectionInfo(
98
 
        SectionId sectionId,
99
 
        const char* name,
100
 
        const char* desc
101
 
    )
102
 
        : sectionId_(sectionId), name_(name), desc_(desc)
103
 
    {
104
 
    }
105
 
 
106
114
    const SectionInfo ExifTags::sectionInfo_[] = {
107
 
        SectionInfo(sectionIdNotSet, "(UnknownSection)", N_("Unknown section")),
108
 
        SectionInfo(imgStruct, "ImageStructure", N_("Image data structure")),
109
 
        SectionInfo(recOffset, "RecordingOffset", N_("Recording offset")),
110
 
        SectionInfo(imgCharacter, "ImageCharacteristics", N_("Image data characteristics")),
111
 
        SectionInfo(otherTags, "OtherTags", N_("Other data")),
112
 
        SectionInfo(exifFormat, "ExifFormat", N_("Exif data structure")),
113
 
        SectionInfo(exifVersion, "ExifVersion", N_("Exif version")),
114
 
        SectionInfo(imgConfig, "ImageConfig", N_("Image configuration")),
115
 
        SectionInfo(userInfo, "UserInfo", N_("User information")),
116
 
        SectionInfo(relatedFile, "RelatedFile", N_("Related file")),
117
 
        SectionInfo(dateTime, "DateTime", N_("Date and time")),
118
 
        SectionInfo(captureCond, "CaptureConditions", N_("Picture taking conditions")),
119
 
        SectionInfo(gpsTags, "GPS", N_("GPS information")),
120
 
        SectionInfo(iopTags, "Interoperability", N_("Interoperability information")),
121
 
        SectionInfo(makerTags, "Makernote", N_("Vendor specific information")),
122
 
        SectionInfo(lastSectionId, "(LastSection)", N_("Last section"))
 
115
        { sectionIdNotSet, "(UnknownSection)",     N_("Unknown section")              },
 
116
        { imgStruct,       "ImageStructure",       N_("Image data structure")         },
 
117
        { recOffset,       "RecordingOffset",      N_("Recording offset")             },
 
118
        { imgCharacter,    "ImageCharacteristics", N_("Image data characteristics")   },
 
119
        { otherTags,       "OtherTags",            N_("Other data")                   },
 
120
        { exifFormat,      "ExifFormat",           N_("Exif data structure")          },
 
121
        { exifVersion,     "ExifVersion",          N_("Exif version")                 },
 
122
        { imgConfig,       "ImageConfig",          N_("Image configuration")          },
 
123
        { userInfo,        "UserInfo",             N_("User information")             },
 
124
        { relatedFile,     "RelatedFile",          N_("Related file")                 },
 
125
        { dateTime,        "DateTime",             N_("Date and time")                },
 
126
        { captureCond,     "CaptureConditions",    N_("Picture taking conditions")    },
 
127
        { gpsTags,         "GPS",                  N_("GPS information")              },
 
128
        { iopTags,         "Interoperability",     N_("Interoperability information") },
 
129
        { makerTags,       "Makernote",            N_("Vendor specific information")  },
 
130
        { lastSectionId,   "(LastSection)",        N_("Last section")                 }
123
131
    };
124
132
 
125
133
    TagInfo::TagInfo(
169
177
        {     9, N_("JBIG B&W")                 },
170
178
        {    10, N_("JBIG Color")               },
171
179
        { 32766, N_("Next 2-bits RLE")          },
 
180
        { 32769, N_("Epson ERF Compressed")     },
172
181
        { 32771, N_("CCITT RLE 1-word")         },
173
182
        { 32773, N_("PackBits (Macintosh RLE)") },
174
183
        { 32809, N_("Thunderscan RLE")          },
184
193
        { 34676, N_("SGI Log Luminance RLE")    },
185
194
        { 34677, N_("SGI Log 24-bits packed")   },
186
195
        { 34712, N_("Leadtools JPEG 2000")      },
187
 
        { 34713, N_("Nikon NEF Compressed")     }
 
196
        { 34713, N_("Nikon NEF Compressed")     },
 
197
        { 65000, N_("Kodak DCR Compressed")     },
 
198
        { 65535, N_("Pentax PEF Compressed")    }
188
199
    };
189
200
 
190
201
    //! PhotometricInterpretation, tag 0x0106
291
302
                ifd0Id, recOffset, unsignedLong, printValue),
292
303
        TagInfo(0x0112, "Orientation", N_("Orientation"),
293
304
                N_("The image orientation viewed in terms of rows and columns."),
294
 
                ifd0Id, imgStruct, unsignedShort, EXV_PRINT_TAG(exifOrientation)),
 
305
                ifd0Id, imgStruct, unsignedShort, print0x0112),
295
306
        TagInfo(0x0115, "SamplesPerPixel", N_("Samples per Pixel"),
296
307
                N_("The number of components per pixel. Since this standard applies "
297
308
                "to RGB and YCbCr images, the value set for this tag is 3. "
325
336
                N_("The unit for measuring <XResolution> and <YResolution>. The same "
326
337
                "unit is used for both <XResolution> and <YResolution>. If "
327
338
                "the image resolution is unknown, 2 (inches) is designated."),
328
 
                ifd0Id, imgStruct, unsignedShort, EXV_PRINT_TAG(exifUnit)),
 
339
                ifd0Id, imgStruct, unsignedShort, printExifUnit),
329
340
        TagInfo(0x012d, "TransferFunction", N_("Transfer Function"),
330
341
                N_("A transfer function for the image, described in tabular style. "
331
342
                "Normally this tag is not necessary, since color space is "
342
353
                N_("The date and time of image creation. In Exif standard, "
343
354
                "it is the date and time the file was changed."),
344
355
                ifd0Id, otherTags, asciiString, printValue),
 
356
        TagInfo(0x013c, "HostComputer", N_("Host computer"),
 
357
                N_("This tag records information about the host computer used "
 
358
                "to generate the image."),
 
359
                ifd0Id, otherTags, asciiString, printValue),
345
360
        TagInfo(0x013b, "Artist", N_("Artist"),
346
361
                N_("This tag records the name of the camera owner, photographer or "
347
362
                "image creator. The detailed format is not specified, but it is "
409
424
                "<YCbCrPositioning>, it shall follow the TIFF default regardless "
410
425
                "of the value in this field. It is preferable that readers "
411
426
                "be able to support both centered and co-sited positioning."),
412
 
                ifd0Id, imgStruct, unsignedShort, EXV_PRINT_TAG(exifYCbCrPositioning)),
 
427
                ifd0Id, imgStruct, unsignedShort, print0x0213),
413
428
        TagInfo(0x0214, "ReferenceBlackWhite", N_("Reference Black/White"),
414
429
                N_("The reference black point value and reference white point "
415
430
                "value. No defaults are given in TIFF, but the values "
498
513
        TagInfo(0x9c9f, "XPSubject", N_("Windows Subject"),
499
514
                N_("Subject tag used by Windows, encoded in UCS2"),
500
515
                ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag
 
516
        TagInfo(0xc4a5, "PrintImageMatching", N_("Print Image Matching"),
 
517
                N_("Print Image Matching, descriptiont needed."),
 
518
                ifd0Id, otherTags, undefined, printValue),
501
519
        // End of list marker
502
520
        TagInfo(0xffff, "(UnknownIfdTag)", N_("Unknown IFD tag"),
503
521
                N_("Unknown IFD tag"),
565
583
        { 0x01, N_("Fired")                                                         },
566
584
        { 0x05, N_("Fired, strobe return light not detected")                       },
567
585
        { 0x07, N_("Fired, strobe return light detected")                           },
 
586
        { 0x08, N_("Yes, did not fire")                                             },
568
587
        { 0x09, N_("Yes, compulsory")                                               },
569
588
        { 0x0d, N_("Yes, compulsory, return light not detected")                    },
570
589
        { 0x0f, N_("Yes, compulsory, return light detected")                        },
571
590
        { 0x10, N_("No, compulsory")                                                },
 
591
        { 0x14, N_("No, did not fire, return not detected")                         },
572
592
        { 0x18, N_("No, auto")                                                      },
573
593
        { 0x19, N_("Yes, auto")                                                     },
574
594
        { 0x1d, N_("Yes, auto, return light not detected")                          },
575
595
        { 0x1f, N_("Yes, auto, return light detected")                              },
576
596
        { 0x20, N_("No flash function")                                             },
 
597
        { 0x20, N_("No, no flash function")                                         },
577
598
        { 0x41, N_("Yes, red-eye reduction")                                        },
578
599
        { 0x45, N_("Yes, red-eye reduction, return light not detected")             },
579
600
        { 0x47, N_("Yes, red-eye reduction, return light detected")                 },
580
601
        { 0x49, N_("Yes, compulsory, red-eye reduction")                            },
581
602
        { 0x4d, N_("Yes, compulsory, red-eye reduction, return light not detected") },
582
603
        { 0x4f, N_("Yes, compulsory, red-eye reduction, return light detected")     },
 
604
        { 0x50, N_("No, red-eye reduction")                                         },
 
605
        { 0x58, N_("No, auto, red-eye reduction")                                   },
583
606
        { 0x59, N_("Yes, auto, red-eye reduction")                                  },
584
607
        { 0x5d, N_("Yes, auto, red-eye reduction, return light not detected")       },
585
608
        { 0x5f, N_("Yes, auto, red-eye reduction, return light detected")           }
615
638
        { 1, N_("Directly photographed") }
616
639
    };
617
640
 
618
 
    //! exifCustomRendered, tag 0xa401
 
641
    //! CustomRendered, tag 0xa401
619
642
    extern const TagDetails exifCustomRendered[] = {
620
643
        { 0, N_("Normal process") },
621
644
        { 1, N_("Custom process") }
651
674
        { 4, N_("High gain down") }
652
675
    };
653
676
 
654
 
    //! Contrast, tag 0xa408
655
 
    extern const TagDetails exifContrast[] = {
 
677
    //! Contrast, tag 0xa408 and Sharpness, tag 0xa40a
 
678
    extern const TagDetails exifNormalSoftHard[] = {
656
679
        { 0, N_("Normal") },
657
680
        { 1, N_("Soft")   },
658
681
        { 2, N_("Hard")   }
665
688
        { 2, N_("High")   }
666
689
    };
667
690
 
668
 
    //! Sharpness, tag 0xa40a
669
 
    extern const TagDetails exifSharpness[] = {
670
 
        { 0, N_("Normal") },
671
 
        { 1, N_("Soft")   },
672
 
        { 2, N_("Hard")   }
673
 
    };
674
 
 
675
691
    //! SubjectDistanceRange, tag 0xa40c
676
692
    extern const TagDetails exifSubjectDistanceRange[] = {
677
693
        { 0, N_("Unknown")      },
691
707
        TagInfo(0x8822, "ExposureProgram", N_("Exposure Program"),
692
708
                N_("The class of the program used by the camera to set exposure "
693
709
                "when the picture is taken."),
694
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifExposureProgram)),
 
710
                exifIfdId, captureCond, unsignedShort, print0x8822),
695
711
        TagInfo(0x8824, "SpectralSensitivity", N_("Spectral Sensitivity"),
696
712
                N_("Indicates the spectral sensitivity of each channel of the "
697
713
                "camera used. The tag value is an ASCII string compatible "
709
725
        TagInfo(0x9000, "ExifVersion", N_("Exif Version"),
710
726
                N_("The version of this standard supported. Nonexistence of this "
711
727
                "field is taken to mean nonconformance to the standard."),
712
 
                exifIfdId, exifVersion, undefined, printValue),
 
728
                exifIfdId, exifVersion, undefined, printExifVersion),
713
729
        TagInfo(0x9003, "DateTimeOriginal", N_("Date and Time (original)"),
714
730
                N_("The date and time when the original image data was generated. "
715
731
                "For a digital still camera the date and time the picture was taken are recorded."),
756
772
                exifIfdId, captureCond, unsignedRational, print0x9206),
757
773
        TagInfo(0x9207, "MeteringMode", N_("Metering Mode"),
758
774
                N_("The metering mode."),
759
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifMeteringMode)),
 
775
                exifIfdId, captureCond, unsignedShort, print0x9207),
760
776
        TagInfo(0x9208, "LightSource", N_("Light Source"),
761
777
                N_("The kind of light source."),
762
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifLightSource)),
 
778
                exifIfdId, captureCond, unsignedShort, print0x9208),
763
779
        TagInfo(0x9209, "Flash", N_("Flash"),
764
780
                N_("This tag is recorded when an image is taken using a strobe light (flash)."),
765
781
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifFlash)),
791
807
                exifIfdId, dateTime, asciiString, printValue),
792
808
        TagInfo(0xa000, "FlashpixVersion", N_("FlashPix Version"),
793
809
                N_("The FlashPix format version supported by a FPXR file."),
794
 
                exifIfdId, exifVersion, undefined, printValue),
 
810
                exifIfdId, exifVersion, undefined, printExifVersion),
795
811
        TagInfo(0xa001, "ColorSpace", N_("Color Space"),
796
812
                N_("The color space information tag is always "
797
813
                "recorded as the color space specifier. Normally sRGB "
800
816
                "sRGB is used, Uncalibrated is set. Image data "
801
817
                "recorded as Uncalibrated can be treated as sRGB when it is "
802
818
                "converted to FlashPix."),
803
 
                exifIfdId, imgCharacter, unsignedShort, EXV_PRINT_TAG(exifColorSpace)),
 
819
                exifIfdId, imgCharacter, unsignedShort, print0xa001),
804
820
        TagInfo(0xa002, "PixelXDimension", N_("Pixel X Dimension"),
805
821
                N_("Information specific to compressed data. When a "
806
822
                "compressed file is recorded, the valid width of the "
852
868
        TagInfo(0xa210, "FocalPlaneResolutionUnit", N_("Focal Plane Resolution Unit"),
853
869
                N_("Indicates the unit for measuring <FocalPlaneXResolution> and "
854
870
                "<FocalPlaneYResolution>. This value is the same as the <ResolutionUnit>."),
855
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifUnit)),
 
871
                exifIfdId, captureCond, unsignedShort, printExifUnit),
856
872
        TagInfo(0xa214, "SubjectLocation", N_("Subject Location"),
857
873
                N_("Indicates the location of the main subject in the scene. The "
858
874
                "value of this tag represents the pixel at the center of the "
866
882
                exifIfdId, captureCond, unsignedRational, printValue),
867
883
        TagInfo(0xa217, "SensingMethod", N_("Sensing Method"),
868
884
                N_("Indicates the image sensor type on the camera or input device."),
869
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifSensingMethod)),
 
885
                exifIfdId, captureCond, unsignedShort, print0xa217),
870
886
        TagInfo(0xa300, "FileSource", N_("File Source"),
871
887
                N_("Indicates the image source. If a DSC recorded the image, "
872
888
                "this tag value of this tag always be set to 3, indicating "
873
889
                "that the image was recorded on a DSC."),
874
 
                exifIfdId, captureCond, undefined, EXV_PRINT_TAG(exifFileSource)),
 
890
                exifIfdId, captureCond, undefined, print0xa300),
875
891
        TagInfo(0xa301, "SceneType", N_("Scene Type"),
876
892
                N_("Indicates the type of scene. If a DSC recorded the image, "
877
893
                "this tag value must always be set to 1, indicating that the "
878
894
                "image was directly photographed."),
879
 
                exifIfdId, captureCond, undefined, EXV_PRINT_TAG(exifSceneType)),
 
895
                exifIfdId, captureCond, undefined, print0xa301),
880
896
        TagInfo(0xa302, "CFAPattern", N_("Color Filter Array Pattern"),
881
897
                N_("Indicates the color filter array (CFA) geometric pattern of the "
882
898
                "image sensor when a one-chip color area sensor is used. "
887
903
                "data, such as rendering geared to output. When special "
888
904
                "processing is performed, the reader is expected to disable "
889
905
                "or minimize any further processing."),
890
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifCustomRendered)),
 
906
                exifIfdId, captureCond, unsignedShort, print0xa401),
891
907
        TagInfo(0xa402, "ExposureMode", N_("Exposure Mode"),
892
908
                N_("This tag indicates the exposure mode set when the image was "
893
909
                "shot. In auto-bracketing mode, the camera shoots a series of "
894
910
                "frames of the same scene at different exposure settings."),
895
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifExposureMode)),
 
911
                exifIfdId, captureCond, unsignedShort, print0xa402),
896
912
        TagInfo(0xa403, "WhiteBalance", N_("White Balance"),
897
913
                N_("This tag indicates the white balance mode set when the image was shot."),
898
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifWhiteBalance)),
 
914
                exifIfdId, captureCond, unsignedShort, print0xa403),
899
915
        TagInfo(0xa404, "DigitalZoomRatio", N_("Digital Zoom Ratio"),
900
916
                N_("This tag indicates the digital zoom ratio when the image was "
901
917
                "shot. If the numerator of the recorded value is 0, this "
911
927
                N_("This tag indicates the type of scene that was shot. It can "
912
928
                "also be used to record the mode in which the image was "
913
929
                "shot. Note that this differs from the <SceneType> tag."),
914
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifSceneCaptureType)),
 
930
                exifIfdId, captureCond, unsignedShort, print0xa406),
915
931
        TagInfo(0xa407, "GainControl", N_("Gain Control"),
916
932
                N_("This tag indicates the degree of overall image gain adjustment."),
917
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifGainControl)),
 
933
                exifIfdId, captureCond, unsignedShort, print0xa407),
918
934
        TagInfo(0xa408, "Contrast", N_("Contrast"),
919
935
                N_("This tag indicates the direction of contrast processing "
920
936
                "applied by the camera when the image was shot."),
921
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifContrast)),
 
937
                exifIfdId, captureCond, unsignedShort, printNormalSoftHard),
922
938
        TagInfo(0xa409, "Saturation", N_("Saturation"),
923
939
                N_("This tag indicates the direction of saturation processing "
924
940
                "applied by the camera when the image was shot."),
925
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifSaturation)),
 
941
                exifIfdId, captureCond, unsignedShort, print0xa409),
926
942
        TagInfo(0xa40a, "Sharpness", N_("Sharpness"),
927
943
                N_("This tag indicates the direction of sharpness processing "
928
944
                "applied by the camera when the image was shot."),
929
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifSharpness)),
 
945
                exifIfdId, captureCond, unsignedShort, printNormalSoftHard),
930
946
        TagInfo(0xa40b, "DeviceSettingDescription", N_("Device Setting Description"),
931
947
                N_("This tag indicates information on the picture-taking "
932
948
                "conditions of a particular camera model. The tag is used "
934
950
                exifIfdId, captureCond, undefined, printValue),
935
951
        TagInfo(0xa40c, "SubjectDistanceRange", N_("Subject Distance Range"),
936
952
                N_("This tag indicates the distance to the subject."),
937
 
                exifIfdId, captureCond, unsignedShort, EXV_PRINT_TAG(exifSubjectDistanceRange)),
 
953
                exifIfdId, captureCond, unsignedShort, print0xa40c),
938
954
        TagInfo(0xa420, "ImageUniqueID", N_("Image Unique ID"),
939
955
                N_("This tag indicates an identifier assigned uniquely to "
940
956
                "each image. It is recorded as an ASCII string equivalent "
969
985
        { 1, N_("Below sea level") }
970
986
    };
971
987
 
 
988
    //! GPS status, tag 0x0009
 
989
    extern const TagDetails exifGPSStatus[] = {
 
990
        { 'A', N_("Measurement in progress")      },
 
991
        { 'V', N_("Measurement Interoperability") }
 
992
    };
 
993
 
 
994
    //! GPS measurement mode, tag 0x000a
 
995
    extern const TagDetails exifGPSMeasureMode[] = {
 
996
        { '2', N_("Two-dimensional measurement")   },
 
997
        { '3', N_("Three-dimensional measurement") }
 
998
    };
 
999
 
972
1000
    //! GPS speed reference, tag 0x000c
973
1001
    extern const TagDetails exifGPSSpeedRef[] = {
974
 
        { 75, N_("km/h")  },
975
 
        { 77, N_("mph")   },
976
 
        { 78, N_("knots") }
 
1002
        { 'K', N_("km/h")  },
 
1003
        { 'M', N_("mph")   },
 
1004
        { 'N', N_("knots") }
 
1005
    };
 
1006
 
 
1007
    //! GPS direction ref, tags 0x000e, 0x0010, 0x0017
 
1008
    extern const TagDetails exifGPSDirRef[] = {
 
1009
        { 'T', N_("True direction")     },
 
1010
        { 'M', N_("Magnetic direction") }
 
1011
    };
 
1012
 
 
1013
    //! GPS Destination distance ref, tag 0x0019
 
1014
    extern const TagDetails exifGPSDestDistanceRef[] = {
 
1015
        { 'K', N_("Kilometers") },
 
1016
        { 'M', N_("Miles")      },
 
1017
        { 'N', N_("Knots")      }
 
1018
    };
 
1019
 
 
1020
    //! GPS Differential, tag 0x001e
 
1021
    extern const TagDetails exifGPSDifferential[] = {
 
1022
        { 0, N_("Without correction") },
 
1023
        { 1, N_("Correction applied") }
977
1024
    };
978
1025
 
979
1026
    // GPS Info Tags
984
1031
                "present. (Note: The <GPSVersionID> tag is given in bytes, "
985
1032
                "unlike the <ExifVersion> tag. When the version is "
986
1033
                "2.0.0.0, the tag value is 02000000.H)."),
987
 
                gpsIfdId, gpsTags, unsignedByte, printValue),
 
1034
                gpsIfdId, gpsTags, unsignedByte, print0x0000),
988
1035
        TagInfo(0x0001, "GPSLatitudeRef", N_("GPS Latitude Reference"),
989
1036
                N_("Indicates whether the latitude is north or south latitude. The "
990
1037
                "ASCII value 'N' indicates north latitude, and 'S' is south latitude."),
1016
1063
                "and the altitude is indicated as an absolute value in the "
1017
1064
                "GSPAltitude tag. The reference unit is meters. Note that this tag "
1018
1065
                "is BYTE type, unlike other reference tags."),
1019
 
                gpsIfdId, gpsTags, unsignedByte, EXV_PRINT_TAG(exifGPSAltitudeRef)),
 
1066
                gpsIfdId, gpsTags, unsignedByte, print0x0005),
1020
1067
        TagInfo(0x0006, "GPSAltitude", N_("GPS Altitude"),
1021
1068
                N_("Indicates the altitude based on the reference in GPSAltitudeRef. "
1022
1069
                "Altitude is expressed as one RATIONAL value. The reference unit is meters."),
1037
1084
                N_("Indicates the status of the GPS receiver when the image is recorded. "
1038
1085
                "\"A\" means measurement is in progress, and \"V\" means the measurement "
1039
1086
                "is Interoperability."),
1040
 
                gpsIfdId, gpsTags, asciiString, printValue),
 
1087
                gpsIfdId, gpsTags, asciiString, print0x0009),
1041
1088
        TagInfo(0x000a, "GPSMeasureMode", N_("GPS Measure Mode"),
1042
1089
                N_("Indicates the GPS measurement mode. \"2\" means two-dimensional measurement and \"3\" "
1043
1090
                "means three-dimensional measurement is in progress."),
1044
 
                gpsIfdId, gpsTags, asciiString, printValue),
 
1091
                gpsIfdId, gpsTags, asciiString, print0x000a),
1045
1092
        TagInfo(0x000b, "GPSDOP", N_("GPS Data Degree of Precision"),
1046
1093
                N_("Indicates the GPS DOP (data degree of precision). An HDOP value is written "
1047
1094
                "during two-dimensional measurement, and PDOP during three-dimensional measurement."),
1049
1096
        TagInfo(0x000c, "GPSSpeedRef", N_("GPS Speed Reference"),
1050
1097
                N_("Indicates the unit used to express the GPS receiver speed of movement. "
1051
1098
                "\"K\" \"M\" and \"N\" represents kilometers per hour, miles per hour, and knots."),
1052
 
                gpsIfdId, gpsTags, asciiString, EXV_PRINT_TAG(exifGPSSpeedRef)),
 
1099
                gpsIfdId, gpsTags, asciiString, print0x000c),
1053
1100
        TagInfo(0x000d, "GPSSpeed", N_("GPS Speed"),
1054
1101
                N_("Indicates the speed of GPS receiver movement."),
1055
1102
                gpsIfdId, gpsTags, unsignedRational, printValue),
1056
1103
        TagInfo(0x000e, "GPSTrackRef", N_("GPS Track Ref"),
1057
1104
                N_("Indicates the reference for giving the direction of GPS receiver movement. "
1058
1105
                "\"T\" denotes true direction and \"M\" is magnetic direction."),
1059
 
                gpsIfdId, gpsTags, asciiString, printValue),
 
1106
                gpsIfdId, gpsTags, asciiString, printGPSDirRef),
1060
1107
        TagInfo(0x000f, "GPSTrack", N_("GPS Track"),
1061
1108
                N_("Indicates the direction of GPS receiver movement. The range of values is "
1062
1109
                "from 0.00 to 359.99."),
1064
1111
        TagInfo(0x0010, "GPSImgDirectionRef", N_("GPS Image Direction Reference"),
1065
1112
                N_("Indicates the reference for giving the direction of the image when it is captured. "
1066
1113
                "\"T\" denotes true direction and \"M\" is magnetic direction."),
1067
 
                gpsIfdId, gpsTags, asciiString, printValue),
 
1114
                gpsIfdId, gpsTags, asciiString, printGPSDirRef),
1068
1115
        TagInfo(0x0011, "GPSImgDirection", N_("GPS Image Direction"),
1069
1116
                N_("Indicates the direction of the image when it was captured. The range of values "
1070
1117
                "is from 0.00 to 359.99."),
1099
1146
        TagInfo(0x0017, "GPSDestBearingRef", N_("GPS Destination Bearing Reference"),
1100
1147
                N_("Indicates the reference used for giving the bearing to the destination point. "
1101
1148
                "\"T\" denotes true direction and \"M\" is magnetic direction."),
1102
 
                gpsIfdId, gpsTags, asciiString, printValue),
 
1149
                gpsIfdId, gpsTags, asciiString, printGPSDirRef),
1103
1150
        TagInfo(0x0018, "GPSDestBearing", N_("GPS Destination Bearing"),
1104
1151
                N_("Indicates the bearing to the destination point. The range of values is from "
1105
1152
                "0.00 to 359.99."),
1107
1154
        TagInfo(0x0019, "GPSDestDistanceRef", N_("GPS Destination Distance Reference"),
1108
1155
                N_("Indicates the unit used to express the distance to the destination point. "
1109
1156
                "\"K\", \"M\" and \"N\" represent kilometers, miles and knots."),
1110
 
                gpsIfdId, gpsTags, asciiString, printValue),
 
1157
                gpsIfdId, gpsTags, asciiString, print0x0019),
1111
1158
        TagInfo(0x001a, "GPSDestDistance", N_("GPS Destination Distance"),
1112
1159
                N_("Indicates the distance to the destination point."),
1113
1160
                gpsIfdId, gpsTags, unsignedRational, printValue),
1126
1173
                gpsIfdId, gpsTags, asciiString, printValue),
1127
1174
        TagInfo(0x001e, "GPSDifferential", N_("GPS Differential"),
1128
1175
                N_("Indicates whether differential correction is applied to the GPS receiver."),
1129
 
                gpsIfdId, gpsTags, unsignedShort, printValue),
 
1176
                gpsIfdId, gpsTags, unsignedShort, print0x001e),
1130
1177
        // End of list marker
1131
1178
        TagInfo(0xffff, "(UnknownGpsTag)", N_("Unknown GPSInfo tag"),
1132
1179
                N_("Unknown GPSInfo tag"),
1149
1196
                iopIfdId, iopTags, asciiString, printValue),
1150
1197
        TagInfo(0x0002, "InteroperabilityVersion", N_("Interoperability Version"),
1151
1198
                N_("Interoperability version"),
1152
 
                iopIfdId, iopTags, undefined, printValue),
 
1199
                iopIfdId, iopTags, undefined, printExifVersion),
1153
1200
        TagInfo(0x1000, "RelatedImageFileFormat", N_("Related Image File Format"),
1154
1201
                N_("File format of image file"),
1155
1202
                iopIfdId, iopTags, asciiString, printValue),
1175
1222
                                    N_("Unknown tag"),
1176
1223
                                    ifdIdNotSet, sectionIdNotSet, asciiString, printValue);
1177
1224
 
1178
 
    // Tag lookup lists with tag names, desc and where they (preferably) belong to;
1179
 
    // this is an array with pointers to one list per IFD. The IfdId is used as the
1180
 
    // index into the array.
1181
 
    const TagInfo* ExifTags::tagInfos_[] = {
1182
 
        0,
1183
 
        ifdTagInfo, exifTagInfo, gpsTagInfo, iopTagInfo, ifdTagInfo,
1184
 
        0
1185
 
    };
1186
 
 
1187
 
    // Lookup list for registered makernote tag info tables
1188
 
    const TagInfo* ExifTags::makerTagInfos_[];
1189
 
 
1190
 
    // All makernote ifd ids, in the same order as the tag infos in makerTagInfos_
1191
 
    IfdId ExifTags::makerIfdIds_[];
1192
 
 
1193
 
    void ExifTags::registerBaseTagInfo(IfdId ifdId)
1194
 
    {
1195
 
        registerMakerTagInfo(ifdId, ifdTagInfo);
1196
 
    }
1197
 
 
1198
 
    void ExifTags::registerMakerTagInfo(IfdId ifdId, const TagInfo* tagInfo)
1199
 
    {
1200
 
        int i = 0;
1201
 
        for (; i < MAX_MAKER_TAG_INFOS; ++i) {
1202
 
            if (makerIfdIds_[i] == 0) {
1203
 
                makerIfdIds_[i] = ifdId;
1204
 
                makerTagInfos_[i] = tagInfo;
1205
 
                break;
1206
 
            }
1207
 
        }
1208
 
        if (i == MAX_MAKER_TAG_INFOS) throw Error(16);
1209
 
    } // ExifTags::registerMakerTagInfo
1210
 
 
1211
 
    int ExifTags::tagInfoIdx(uint16_t tag, IfdId ifdId)
1212
 
    {
1213
 
        const TagInfo* tagInfo = tagInfos_[ifdId];
1214
 
        if (tagInfo == 0) return -1;
1215
 
        int idx;
1216
 
        for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
1217
 
            if (tagInfo[idx].tag_ == tag) return idx;
1218
 
        }
1219
 
        return -1;
1220
 
    } // ExifTags::tagInfoIdx
1221
 
 
1222
 
    const TagInfo* ExifTags::makerTagInfo(uint16_t tag, IfdId ifdId)
1223
 
    {
1224
 
        int i = 0;
1225
 
        for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
1226
 
        if (i == MAX_MAKER_TAG_INFOS) return 0;
1227
 
 
1228
 
        for (int k = 0; makerTagInfos_[i][k].tag_ != 0xffff; ++k) {
1229
 
            if (makerTagInfos_[i][k].tag_ == tag) return &makerTagInfos_[i][k];
1230
 
        }
1231
 
 
1232
 
        return 0;
1233
 
    } // ExifTags::makerTagInfo
1234
 
 
1235
 
    const TagInfo* ExifTags::makerTagInfo(const std::string& tagName,
1236
 
                                          IfdId ifdId)
1237
 
    {
1238
 
        int i = 0;
1239
 
        for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
1240
 
        if (i == MAX_MAKER_TAG_INFOS) return 0;
1241
 
 
1242
 
        for (int k = 0; makerTagInfos_[i][k].tag_ != 0xffff; ++k) {
1243
 
            if (makerTagInfos_[i][k].name_ == tagName) {
1244
 
                return &makerTagInfos_[i][k];
1245
 
            }
1246
 
        }
1247
 
 
1248
 
        return 0;
1249
 
    } // ExifTags::makerTagInfo
 
1225
    const TagInfo* ExifTags::tagList(IfdId ifdId)
 
1226
    {
 
1227
        const IfdInfo* ii = find(ifdInfo_, ifdId);
 
1228
        if (ii == 0 || ii->tagList_ == 0) return 0;
 
1229
        return ii->tagList_();
 
1230
    } // ExifTags::tagList
 
1231
 
 
1232
    const TagInfo* ExifTags::tagInfo(uint16_t tag, IfdId ifdId)
 
1233
    {
 
1234
        const TagInfo* ti = tagList(ifdId);
 
1235
        if (ti == 0) return 0;
 
1236
        for (int idx = 0; ti[idx].tag_ != 0xffff; ++idx) {
 
1237
            if (ti[idx].tag_ == tag) return &ti[idx];
 
1238
        }
 
1239
        return 0;
 
1240
    } // ExifTags::tagInfo
 
1241
 
 
1242
    const TagInfo* ExifTags::tagInfo(const std::string& tagName, IfdId ifdId)
 
1243
    {
 
1244
        const TagInfo* ti = tagList(ifdId);
 
1245
        if (ti == 0) return 0;
 
1246
        for (int idx = 0; ti[idx].tag_ != 0xffff; ++idx) {
 
1247
            if (std::string(ti[idx].name_) == tagName) return &ti[idx];
 
1248
        }
 
1249
        return 0;
 
1250
    } // ExifTags::tagInfo
1250
1251
 
1251
1252
    bool ExifTags::isMakerIfd(IfdId ifdId)
1252
1253
    {
1253
 
        int i = 0;
1254
 
        for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
1255
 
        return i != MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != IfdId(0);
1256
 
    }
 
1254
        bool rc = false;
 
1255
        const IfdInfo* ii = find(ifdInfo_, ifdId);
 
1256
        if (ii != 0 && std::string(ii->name_) == "Makernote") {
 
1257
            rc = true;
 
1258
        }
 
1259
        return rc;
 
1260
    } // ExifTags::isMakerIfd
1257
1261
 
1258
1262
    std::string ExifTags::tagName(uint16_t tag, IfdId ifdId)
1259
1263
    {
1260
 
        if (isExifIfd(ifdId)) {
1261
 
            int idx = tagInfoIdx(tag, ifdId);
1262
 
            if (idx != -1) return tagInfos_[ifdId][idx].name_;
1263
 
        }
1264
 
        if (isMakerIfd(ifdId)) {
1265
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1266
 
            if (tagInfo != 0) return tagInfo->name_;
1267
 
        }
 
1264
        const TagInfo* ti = tagInfo(tag, ifdId);
 
1265
        if (ti != 0) return ti->name_;
1268
1266
        std::ostringstream os;
1269
1267
        os << "0x" << std::setw(4) << std::setfill('0') << std::right
1270
1268
           << std::hex << tag;
1278
1276
 
1279
1277
    const char* ExifTags::tagLabel(uint16_t tag, IfdId ifdId)
1280
1278
    {
1281
 
        if (isExifIfd(ifdId)) {
1282
 
            int idx = tagInfoIdx(tag, ifdId);
1283
 
            if (idx == -1) return _(unknownTag.title_);
1284
 
            return _(tagInfos_[ifdId][idx].title_);
1285
 
        }
1286
 
        if (isMakerIfd(ifdId)) {
1287
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1288
 
            if (tagInfo != 0) return _(tagInfo->title_);
1289
 
        }
1290
 
        return "";
 
1279
        const TagInfo* ti = tagInfo(tag, ifdId);
 
1280
        if (ti == 0) return "";
 
1281
        return _(ti->title_);
1291
1282
    } // ExifTags::tagLabel
1292
1283
 
1293
1284
    const char* ExifTags::tagDesc(uint16_t tag, IfdId ifdId)
1294
1285
    {
1295
 
        if (isExifIfd(ifdId)) {
1296
 
            int idx = tagInfoIdx(tag, ifdId);
1297
 
            if (idx == -1) return _(unknownTag.desc_);
1298
 
            return _(tagInfos_[ifdId][idx].desc_);
1299
 
        }
1300
 
        if (isMakerIfd(ifdId)) {
1301
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1302
 
            if (tagInfo != 0) return _(tagInfo->desc_);
1303
 
        }
1304
 
        return "";
 
1286
        const TagInfo* ti = tagInfo(tag, ifdId);
 
1287
        if (ti == 0) return "";
 
1288
        return _(ti->desc_);
1305
1289
    } // ExifTags::tagDesc
1306
1290
 
1307
 
    const char* ExifTags::sectionName(uint16_t tag, IfdId ifdId)
1308
 
    {
1309
 
        if (isExifIfd(ifdId)) {
1310
 
            int idx = tagInfoIdx(tag, ifdId);
1311
 
            if (idx == -1) return sectionInfo_[unknownTag.sectionId_].name_;
1312
 
            const TagInfo* tagInfo = tagInfos_[ifdId];
1313
 
            return sectionInfo_[tagInfo[idx].sectionId_].name_;
1314
 
        }
1315
 
        if (isMakerIfd(ifdId)) {
1316
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1317
 
            if (tagInfo != 0) return sectionInfo_[tagInfo->sectionId_].name_;
1318
 
        }
1319
 
        return "";
1320
 
    } // ExifTags::sectionName
1321
 
 
1322
 
    const char* ExifTags::sectionDesc(uint16_t tag, IfdId ifdId)
1323
 
    {
1324
 
        if (isExifIfd(ifdId)) {
1325
 
            int idx = tagInfoIdx(tag, ifdId);
1326
 
            if (idx == -1) return _(sectionInfo_[unknownTag.sectionId_].desc_);
1327
 
            const TagInfo* tagInfo = tagInfos_[ifdId];
1328
 
            return _(sectionInfo_[tagInfo[idx].sectionId_].desc_);
1329
 
        }
1330
 
        if (isMakerIfd(ifdId)) {
1331
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1332
 
            if (tagInfo != 0) return _(sectionInfo_[tagInfo->sectionId_].desc_);
1333
 
        }
1334
 
        return "";
1335
 
    } // ExifTags::sectionDesc
 
1291
    TypeId ExifTags::tagType(uint16_t tag, IfdId ifdId)
 
1292
    {
 
1293
        const TagInfo* ti = tagInfo(tag, ifdId);
 
1294
        if (ti == 0) return unknownTag.typeId_;
 
1295
        return ti->typeId_;
 
1296
    } // ExifTags::tagType
1336
1297
 
1337
1298
    uint16_t ExifTags::tag(const std::string& tagName, IfdId ifdId)
1338
1299
    {
1339
 
        uint16_t tag = 0xffff;
1340
 
        if (isExifIfd(ifdId)) {
1341
 
            const TagInfo* tagInfo = tagInfos_[ifdId];
1342
 
            if (tagInfo) {
1343
 
                int idx;
1344
 
                for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
1345
 
                    if (tagInfo[idx].name_ == tagName) break;
1346
 
                }
1347
 
                tag = tagInfo[idx].tag_;
1348
 
            }
1349
 
        }
1350
 
        if (isMakerIfd(ifdId)) {
1351
 
            const TagInfo* tagInfo = makerTagInfo(tagName, ifdId);
1352
 
            if (tagInfo != 0) tag = tagInfo->tag_;
1353
 
        }
1354
 
        if (tag == 0xffff) {
1355
 
            if (!isHex(tagName, 4, "0x")) throw Error(7, tagName, ifdId);
1356
 
            std::istringstream is(tagName);
1357
 
            is >> std::hex >> tag;
1358
 
        }
 
1300
        const TagInfo* ti = tagInfo(tagName, ifdId);
 
1301
        if (ti != 0) return ti->tag_;
 
1302
        if (!isHex(tagName, 4, "0x")) throw Error(7, tagName, ifdId);
 
1303
        std::istringstream is(tagName);
 
1304
        uint16_t tag;
 
1305
        is >> std::hex >> tag;
1359
1306
        return tag;
1360
1307
    } // ExifTags::tag
1361
1308
 
1362
1309
    IfdId ExifTags::ifdIdByIfdItem(const std::string& ifdItem)
1363
1310
    {
1364
 
        int i;
1365
 
        for (i = int(lastIfdId) - 1; i > 0; --i) {
1366
 
            if (ifdInfo_[i].item_ == ifdItem) break;
1367
 
        }
1368
 
        return IfdId(i);
 
1311
        IfdId ifdId = ifdIdNotSet;
 
1312
        const IfdInfo* ii = find(ifdInfo_, IfdInfo::Item(ifdItem));
 
1313
        if (ii != 0) ifdId = ii->ifdId_;
 
1314
        return ifdId;
1369
1315
    }
1370
1316
 
 
1317
    const char* ExifTags::sectionName(uint16_t tag, IfdId ifdId)
 
1318
    {
 
1319
        const TagInfo* ti = tagInfo(tag, ifdId);
 
1320
        if (ti == 0) return sectionInfo_[unknownTag.sectionId_].name_;
 
1321
        return sectionInfo_[ti->sectionId_].name_;
 
1322
    } // ExifTags::sectionName
 
1323
 
 
1324
    const char* ExifTags::sectionDesc(uint16_t tag, IfdId ifdId)
 
1325
    {
 
1326
        const TagInfo* ti = tagInfo(tag, ifdId);
 
1327
        if (ti == 0) return _(sectionInfo_[unknownTag.sectionId_].desc_);
 
1328
        return _(sectionInfo_[ti->sectionId_].desc_);
 
1329
    } // ExifTags::sectionDesc
 
1330
 
1371
1331
    const char* ExifTags::ifdName(IfdId ifdId)
1372
1332
    {
1373
 
        return ifdInfo_[ifdId].name_;
1374
 
    }
 
1333
        const IfdInfo* ii = find(ifdInfo_, ifdId);
 
1334
        if (ii == 0) return ifdInfo_[0].name_;
 
1335
        return ii->name_;
 
1336
    } // ExifTags::ifdName
1375
1337
 
1376
1338
    const char* ExifTags::ifdItem(IfdId ifdId)
1377
1339
    {
1378
 
        return ifdInfo_[ifdId].item_;
1379
 
    }
 
1340
        const IfdInfo* ii = find(ifdInfo_, ifdId);
 
1341
        if (ii == 0) return ifdInfo_[0].item_;
 
1342
        return ii->item_;
 
1343
    } // ExifTags::ifdItem
1380
1344
 
1381
1345
    const char* ExifTags::sectionName(SectionId sectionId)
1382
1346
    {
1383
1347
        return sectionInfo_[sectionId].name_;
1384
 
    }
 
1348
    } // ExifTags::sectionName
1385
1349
 
1386
1350
    SectionId ExifTags::sectionId(const std::string& sectionName)
1387
1351
    {
1390
1354
            if (sectionInfo_[i].name_ == sectionName) break;
1391
1355
        }
1392
1356
        return SectionId(i);
1393
 
    }
1394
 
 
1395
 
    TypeId ExifTags::tagType(uint16_t tag, IfdId ifdId)
1396
 
    {
1397
 
        if (isExifIfd(ifdId)) {
1398
 
            int idx = tagInfoIdx(tag, ifdId);
1399
 
            if (idx != -1) return tagInfos_[ifdId][idx].typeId_;
1400
 
        }
1401
 
        if (isMakerIfd(ifdId)) {
1402
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1403
 
            if (tagInfo != 0) return tagInfo->typeId_;
1404
 
        }
1405
 
        return unknownTag.typeId_;
1406
 
    }
 
1357
    } // ExifTags::sectionId
1407
1358
 
1408
1359
    std::ostream& ExifTags::printTag(std::ostream& os,
1409
1360
                                     uint16_t tag,
1412
1363
    {
1413
1364
        if (value.count() == 0) return os;
1414
1365
        PrintFct fct = printValue;
1415
 
        if (isExifIfd(ifdId)) {
1416
 
            int idx = tagInfoIdx(tag, ifdId);
1417
 
            if (idx != -1) {
1418
 
                fct = tagInfos_[ifdId][idx].printFct_;
1419
 
            }
1420
 
        }
1421
 
        if (isMakerIfd(ifdId)) {
1422
 
            const TagInfo* tagInfo = makerTagInfo(tag, ifdId);
1423
 
            if (tagInfo != 0) fct = tagInfo->printFct_;
1424
 
        }
 
1366
        const TagInfo* ti = tagInfo(tag, ifdId);
 
1367
        if (ti != 0) fct = ti->printFct_;
1425
1368
        return fct(os, value);
1426
1369
    } // ExifTags::printTag
1427
1370
 
1441
1384
        }
1442
1385
    } // ExifTags::taglist
1443
1386
 
1444
 
    void ExifTags::makerTaglist(std::ostream& os, IfdId ifdId)
 
1387
    void ExifTags::taglist(std::ostream& os, IfdId ifdId)
1445
1388
    {
1446
 
        int i = 0;
1447
 
        for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i);
1448
 
        if (i != MAX_MAKER_TAG_INFOS) {
1449
 
            const TagInfo* mnTagInfo = makerTagInfos_[i];
1450
 
            for (int k=0; mnTagInfo[k].tag_ != 0xffff; ++k) {
1451
 
                os << mnTagInfo[k] << "\n";
 
1389
        const TagInfo* ti = tagList(ifdId);
 
1390
        if (ti != 0) {
 
1391
            for (int k = 0; ti[k].tag_ != 0xffff; ++k) {
 
1392
                os << ti[k] << "\n";
1452
1393
            }
1453
1394
        }
1454
 
    } // ExifTags::makerTaglist
 
1395
    } // ExifTags::taglist
1455
1396
 
1456
1397
    const char* ExifKey::familyName_ = "Exif";
1457
1398
 
1617
1558
        int32_t denominator;
1618
1559
        char c;
1619
1560
        is >> nominator >> c >> denominator;
1620
 
        if (is && c == '/') r = std::make_pair(nominator, denominator);
 
1561
        if (c != '/') is.setstate(std::ios::failbit);
 
1562
        if (is) r = std::make_pair(nominator, denominator);
1621
1563
        return is;
1622
1564
    }
1623
1565
 
1630
1572
    {
1631
1573
        uint32_t nominator;
1632
1574
        uint32_t denominator;
1633
 
        char c;
 
1575
        char c('\0');
1634
1576
        is >> nominator >> c >> denominator;
1635
 
        if (is && c == '/') r = std::make_pair(nominator, denominator);
 
1577
        if (c != '/') is.setstate(std::ios::failbit);
 
1578
        if (is) r = std::make_pair(nominator, denominator);
1636
1579
        return is;
1637
1580
    }
1638
1581
 
1669
1612
            for (int i = 0; i < n + 1; ++i) {
1670
1613
                const int32_t z = value.toRational(i).first;
1671
1614
                const int32_t d = value.toRational(i).second;
 
1615
                if (d == 0) return os << "(" << value << ")";
1672
1616
                // Hack: Need Value::toDouble
1673
1617
                double b = static_cast<double>(z)/d;
1674
1618
                const int p = z % d == 0 ? 0 : prec[i];
1742
1686
 
1743
1687
    } // printUcs2
1744
1688
 
 
1689
    std::ostream& printExifUnit(std::ostream& os, const Value& value)
 
1690
    {
 
1691
        return EXV_PRINT_TAG(exifUnit)(os, value);
 
1692
    }
 
1693
 
 
1694
    std::ostream& print0x0000(std::ostream& os, const Value& value)
 
1695
    {
 
1696
        if (value.size() != 4 || value.typeId() != unsignedByte) {
 
1697
            return os << value;
 
1698
        }
 
1699
 
 
1700
        for (int i = 0; i < 3; i++) {
 
1701
            os << value.toLong(i);
 
1702
            os << ".";
 
1703
        }
 
1704
        os << value.toLong(3);
 
1705
 
 
1706
        return os;
 
1707
    }
 
1708
 
 
1709
    std::ostream& print0x0005(std::ostream& os, const Value& value)
 
1710
    {
 
1711
        return EXV_PRINT_TAG(exifGPSAltitudeRef)(os, value);
 
1712
    }
 
1713
 
1745
1714
    std::ostream& print0x0006(std::ostream& os, const Value& value)
1746
1715
    {
1747
1716
        std::ostringstream oss;
1748
1717
        oss.copyfmt(os);
1749
1718
        const int32_t d = value.toRational().second;
 
1719
        if (d == 0) return os << "(" << value << ")";
1750
1720
        const int p = d > 1 ? 1 : 0;
1751
1721
        os << std::fixed << std::setprecision(p) << value.toFloat() << " m";
1752
1722
        os.copyfmt(oss);
1757
1727
    std::ostream& print0x0007(std::ostream& os, const Value& value)
1758
1728
    {
1759
1729
        if (value.count() == 3) {
 
1730
            for (int i = 0; i < 3; ++i) {
 
1731
                if (value.toRational(i).second == 0) {
 
1732
                    return os << "(" << value << ")";
 
1733
                }
 
1734
            }
1760
1735
            std::ostringstream oss;
1761
1736
            oss.copyfmt(os);
1762
1737
            const float sec = 3600 * value.toFloat(0)
1783
1758
        return os;
1784
1759
    }
1785
1760
 
 
1761
    std::ostream& print0x0009(std::ostream& os, const Value& value)
 
1762
    {
 
1763
        return EXV_PRINT_TAG(exifGPSStatus)(os, value);
 
1764
    }
 
1765
 
 
1766
    std::ostream& print0x000a(std::ostream& os, const Value& value)
 
1767
    {
 
1768
        return EXV_PRINT_TAG(exifGPSMeasureMode)(os, value);
 
1769
    }
 
1770
 
 
1771
    std::ostream& print0x000c(std::ostream& os, const Value& value)
 
1772
    {
 
1773
        return EXV_PRINT_TAG(exifGPSSpeedRef)(os, value);
 
1774
    }
 
1775
 
 
1776
    std::ostream& print0x0019(std::ostream& os, const Value& value)
 
1777
    {
 
1778
        return EXV_PRINT_TAG(exifGPSDestDistanceRef)(os, value);
 
1779
    }
 
1780
 
 
1781
    std::ostream& print0x001e(std::ostream& os, const Value& value)
 
1782
    {
 
1783
        return EXV_PRINT_TAG(exifGPSDifferential)(os, value);
 
1784
    }
 
1785
 
 
1786
    std::ostream& print0x0112(std::ostream& os, const Value& value)
 
1787
    {
 
1788
        return EXV_PRINT_TAG(exifOrientation)(os, value);
 
1789
    }
 
1790
 
 
1791
    std::ostream& print0x0213(std::ostream& os, const Value& value)
 
1792
    {
 
1793
        return EXV_PRINT_TAG(exifYCbCrPositioning)(os, value);
 
1794
    }
 
1795
 
1786
1796
    std::ostream& print0x8298(std::ostream& os, const Value& value)
1787
1797
    {
1788
1798
        // Print the copyright information in the format Photographer, Editor
1841
1851
        return os;
1842
1852
    }
1843
1853
 
 
1854
    std::ostream& print0x8822(std::ostream& os, const Value& value)
 
1855
    {
 
1856
        return EXV_PRINT_TAG(exifExposureProgram)(os, value);
 
1857
    }
 
1858
 
1844
1859
    std::ostream& print0x8827(std::ostream& os, const Value& value)
1845
1860
    {
1846
1861
        return os << value.toLong();
1866
1881
 
1867
1882
    std::ostream& print0x9201(std::ostream& os, const Value& value)
1868
1883
    {
1869
 
        URational ur = exposureTime(value.toFloat());
 
1884
        Rational r = value.toRational();
 
1885
        if (!value.ok() || r.second == 0) return os << "(" << value << ")";
 
1886
 
 
1887
        URational ur = exposureTime(static_cast<float>(r.first) / r.second);
1870
1888
        os << ur.first;
1871
1889
        if (ur.second > 1) {
1872
1890
            os << "/" << ur.second;
1876
1894
 
1877
1895
    std::ostream& print0x9202(std::ostream& os, const Value& value)
1878
1896
    {
 
1897
        if (   value.count() == 0
 
1898
            || value.toRational().second == 0) {
 
1899
            return os << "(" << value << ")";
 
1900
        }
1879
1901
        std::ostringstream oss;
1880
1902
        oss.copyfmt(os);
1881
1903
        os << "F" << std::setprecision(2) << fnumber(value.toFloat());
1882
1904
        os.copyfmt(oss);
1883
 
 
1884
1905
        return os;
1885
1906
    }
1886
1907
 
1928
1949
        return os;
1929
1950
    }
1930
1951
 
 
1952
    std::ostream& print0x9207(std::ostream& os, const Value& value)
 
1953
    {
 
1954
        return EXV_PRINT_TAG(exifMeteringMode)(os, value);
 
1955
    }
 
1956
 
 
1957
    std::ostream& print0x9208(std::ostream& os, const Value& value)
 
1958
    {
 
1959
        return EXV_PRINT_TAG(exifLightSource)(os, value);
 
1960
    }
 
1961
 
1931
1962
    std::ostream& print0x920a(std::ostream& os, const Value& value)
1932
1963
    {
1933
1964
        Rational length = value.toRational();
1960
1991
        return os;
1961
1992
    }
1962
1993
 
 
1994
    std::ostream& print0xa001(std::ostream& os, const Value& value)
 
1995
    {
 
1996
        return EXV_PRINT_TAG(exifColorSpace)(os, value);
 
1997
    }
 
1998
 
 
1999
    std::ostream& print0xa217(std::ostream& os, const Value& value)
 
2000
    {
 
2001
        return EXV_PRINT_TAG(exifSensingMethod)(os, value);
 
2002
    }
 
2003
 
 
2004
    std::ostream& print0xa300(std::ostream& os, const Value& value)
 
2005
    {
 
2006
        return EXV_PRINT_TAG(exifFileSource)(os, value);
 
2007
    }
 
2008
 
 
2009
    std::ostream& print0xa301(std::ostream& os, const Value& value)
 
2010
    {
 
2011
        return EXV_PRINT_TAG(exifSceneType)(os, value);
 
2012
    }
 
2013
 
 
2014
    std::ostream& print0xa401(std::ostream& os, const Value& value)
 
2015
    {
 
2016
        return EXV_PRINT_TAG(exifCustomRendered)(os, value);
 
2017
    }
 
2018
 
 
2019
    std::ostream& print0xa402(std::ostream& os, const Value& value)
 
2020
    {
 
2021
        return EXV_PRINT_TAG(exifExposureMode)(os, value);
 
2022
    }
 
2023
 
 
2024
    std::ostream& print0xa403(std::ostream& os, const Value& value)
 
2025
    {
 
2026
        return EXV_PRINT_TAG(exifWhiteBalance)(os, value);
 
2027
    }
 
2028
 
1963
2029
    std::ostream& print0xa404(std::ostream& os, const Value& value)
1964
2030
    {
1965
2031
        Rational zoom = value.toRational();
1988
2054
        return os;
1989
2055
    }
1990
2056
 
 
2057
    std::ostream& print0xa406(std::ostream& os, const Value& value)
 
2058
    {
 
2059
        return EXV_PRINT_TAG(exifSceneCaptureType)(os, value);
 
2060
    }
 
2061
 
 
2062
    std::ostream& print0xa407(std::ostream& os, const Value& value)
 
2063
    {
 
2064
        return EXV_PRINT_TAG(exifGainControl)(os, value);
 
2065
    }
 
2066
 
 
2067
    std::ostream& print0xa409(std::ostream& os, const Value& value)
 
2068
    {
 
2069
        return EXV_PRINT_TAG(exifSaturation)(os, value);
 
2070
    }
 
2071
 
 
2072
    std::ostream& print0xa40c(std::ostream& os, const Value& value)
 
2073
    {
 
2074
        return EXV_PRINT_TAG(exifSubjectDistanceRange)(os, value);
 
2075
    }
 
2076
 
 
2077
    std::ostream& printGPSDirRef(std::ostream& os, const Value& value)
 
2078
    {
 
2079
        return EXV_PRINT_TAG(exifGPSDirRef)(os, value);
 
2080
    }
 
2081
 
 
2082
    std::ostream& printNormalSoftHard(std::ostream& os, const Value& value)
 
2083
    {
 
2084
        return EXV_PRINT_TAG(exifNormalSoftHard)(os, value);
 
2085
    }
 
2086
 
 
2087
    std::ostream& printExifVersion(std::ostream& os, const Value& value)
 
2088
    {
 
2089
        if (value.size() != 4 || value.typeId() != undefined) {
 
2090
            return os << "(" << value << ")";
 
2091
        }
 
2092
 
 
2093
        char s[5];
 
2094
        for (int i = 0; i < 4; ++i) {
 
2095
            s[i] = static_cast<char>(value.toLong(i));
 
2096
        }
 
2097
        s[4] = '\0';
 
2098
 
 
2099
        return printVersion(os, s);
 
2100
    }
 
2101
 
 
2102
    std::ostream& printXmpVersion(std::ostream& os, const Value& value)
 
2103
    {
 
2104
        if (value.size() != 4 || value.typeId() != xmpText) {
 
2105
            return os << "(" << value << ")";
 
2106
        }
 
2107
        
 
2108
        return printVersion(os, value.toString());
 
2109
    }
 
2110
 
 
2111
    std::ostream& printXmpDate(std::ostream& os, const Value& value)
 
2112
    {
 
2113
        if (!(value.size() == 19 || value.size() == 20) || value.typeId() != xmpText) {
 
2114
            return os << value;
 
2115
        }
 
2116
 
 
2117
        std::string stringValue = value.toString();
 
2118
        if (stringValue[19] == 'Z') {
 
2119
            stringValue = stringValue.substr(0, 19);
 
2120
        }
 
2121
        for (unsigned int i = 0; i < stringValue.length(); ++i) {
 
2122
            if (stringValue[i] == 'T') stringValue[i] = ' ';
 
2123
            if (stringValue[i] == '-') stringValue[i] = ':';
 
2124
        }
 
2125
 
 
2126
        return os << stringValue;
 
2127
    }
 
2128
 
1991
2129
    float fnumber(float apertureValue)
1992
2130
    {
1993
2131
        return static_cast<float>(std::exp(std::log(2.0) * apertureValue / 2));
2007
2145
    }
2008
2146
 
2009
2147
}                                       // namespace Exiv2
 
2148
 
 
2149
namespace {
 
2150
    std::ostream& printVersion(std::ostream& os, const std::string& str)
 
2151
    {
 
2152
        if (str.size() != 4) {
 
2153
            return os << "(" << str << ")";
 
2154
        }
 
2155
        if (str[0] != '0') os << str[0];
 
2156
        return os << str[1] << "." << str[2] << str[3];
 
2157
    }
 
2158
}