1 // ***************************************************************** -*- C++ -*-
2 /*
3  * Copyright (C) 2004-2017 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., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
20  */
21 /*
22   File:      easyaccess.cpp
23   Version:   $Rev: 4719 $
24  */
25 // *****************************************************************************
26 #include "rcsid_int.hpp"
27 EXIV2_RCSID("@(#) $Id: easyaccess.cpp 4719 2017-03-08 20:42:28Z robinwmills $")
28 
29 // *****************************************************************************
30 // included header files
31 #include "easyaccess.hpp"
32 
33 // *****************************************************************************
34 namespace {
35 
36     using namespace Exiv2;
37 
38     /*!
39       @brief Search \em ed for a Metadatum specified by the \em keys.
40              The \em keys are searched in the order of their appearance, the
41              first available Metadatum is returned.
42 
43       @param ed The %Exif metadata container to search
44       @param keys Array of keys to look for
45       @param count Number of elements in the array
46      */
findMetadatum(const ExifData & ed,const char * keys[],int count)47     ExifData::const_iterator findMetadatum(const ExifData& ed,
48                                            const char* keys[],
49                                            int count)
50     {
51         for (int i = 0; i < count; ++i) {
52             ExifData::const_iterator pos = ed.findKey(ExifKey(keys[i]));
53             if (pos != ed.end()) return pos;
54         }
55         return ed.end();
56     } // findMetadatum
57 
58 } // anonymous namespace
59 
60 // *****************************************************************************
61 // class member definitions
62 namespace Exiv2 {
63 
orientation(const ExifData & ed)64     ExifData::const_iterator orientation(const ExifData& ed)
65     {
66         static const char* keys[] = {
67             "Exif.Image.Orientation",
68             "Exif.Panasonic.Rotation",
69             "Exif.MinoltaCs5D.Rotation",
70             "Exif.MinoltaCs5D.Rotation2",
71             "Exif.MinoltaCs7D.Rotation",
72             "Exif.Sony1MltCsA100.Rotation",
73             "Exif.Sony1Cs.Rotation",
74             "Exif.Sony2Cs.Rotation",
75             "Exif.Sony1Cs2.Rotation",
76             "Exif.Sony2Cs2.Rotation",
77             "Exif.Sony1MltCsA100.Rotation"
78         };
79         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
80     }
81 
isoSpeed(const ExifData & ed)82     ExifData::const_iterator isoSpeed(const ExifData& ed)
83     {
84         static const char* keys[] = {
85             "Exif.Photo.ISOSpeedRatings",
86             "Exif.Image.ISOSpeedRatings",
87             "Exif.CanonSi.ISOSpeed",
88             "Exif.CanonCs.ISOSpeed",
89             "Exif.Nikon1.ISOSpeed",
90             "Exif.Nikon2.ISOSpeed",
91             "Exif.Nikon3.ISOSpeed",
92             "Exif.NikonIi.ISO",
93             "Exif.NikonIi.ISO2",
94             "Exif.MinoltaCsNew.ISOSetting",
95             "Exif.MinoltaCsOld.ISOSetting",
96             "Exif.MinoltaCs5D.ISOSpeed",
97             "Exif.MinoltaCs7D.ISOSpeed",
98             "Exif.Sony1Cs.ISOSetting",
99             "Exif.Sony2Cs.ISOSetting",
100             "Exif.Sony1Cs2.ISOSetting",
101             "Exif.Sony2Cs2.ISOSetting",
102             "Exif.Sony1MltCsA100.ISOSetting",
103             "Exif.Pentax.ISO",
104             "Exif.PentaxDng.ISO",
105             "Exif.Olympus.ISOSpeed",
106             "Exif.Samsung2.ISO",
107             "Exif.Casio.ISO",
108             "Exif.Casio2.ISO",
109             "Exif.Casio2.ISOSpeed"
110         };
111 
112         struct SensKeyNameList {
113             int count;
114             const char* keys[3];
115         };
116 
117         // covers Exif.Phot.SensitivityType values 1-7. Note that SOS, REI and
118         // ISO do differ in their meaning. Values coming first in a list (and
119         // existing as a tag) are picked up first and used as the "ISO" value.
120         static const SensKeyNameList sensitivityKey[] = {
121             { 1, { "Exif.Photo.StandardOutputSensitivity" }},
122             { 1, { "Exif.Photo.RecommendedExposureIndex" }},
123             { 1, { "Exif.Photo.ISOSpeed" }},
124             { 2, { "Exif.Photo.RecommendedExposureIndex", "Exif.Photo.StandardOutputSensitivity" }},
125             { 2, { "Exif.Photo.ISOSpeed", "Exif.Photo.StandardOutputSensitivity" }},
126             { 2, { "Exif.Photo.ISOSpeed", "Exif.Photo.RecommendedExposureIndex" }},
127             { 3, { "Exif.Photo.ISOSpeed", "Exif.Photo.RecommendedExposureIndex", "Exif.Photo.StandardOutputSensitivity" }}
128         };
129 
130         static const char* sensitivityType[] = {
131             "Exif.Photo.SensitivityType"
132         };
133 
134         // Find the first ISO value which is not "0"
135         const int cnt = EXV_COUNTOF(keys);
136         ExifData::const_iterator md = ed.end();
137         long iso_val = -1;
138         for (int idx = 0; idx < cnt; ) {
139             md = findMetadatum(ed, keys + idx, cnt - idx);
140             if (md == ed.end()) break;
141             std::ostringstream os;
142             md->write(os, &ed);
143             bool ok = false;
144             iso_val = parseLong(os.str(), ok);
145             if (ok && iso_val > 0) break;
146             while (strcmp(keys[idx++], md->key().c_str()) != 0 && idx < cnt) {}
147             md = ed.end();
148         }
149 
150         // there is either a possible ISO "overflow" or no legacy
151         // ISO tag at all. Check for SensitivityType tag and the referenced
152         // ISO value (see EXIF 2.3 Annex G)
153         long iso_tmp_val = -1;
154         while (iso_tmp_val == -1 && (iso_val == 65535 || md == ed.end())) {
155             ExifData::const_iterator md_st = ed.end();
156             md_st = findMetadatum(ed, sensitivityType, 1);
157             // no SensitivityType? exit with existing data
158             if (md_st == ed.end())
159                 break;
160             // otherwise pick up actual value and grab value accordingly
161             std::ostringstream os;
162             md_st->write(os, &ed);
163             bool ok = false;
164             long st_val = parseLong(os.str(), ok);
165             // SensivityType out of range or cannot be parsed properly
166             if (!ok || st_val < 1 || st_val > 7)
167                 break;
168             // pick up list of ISO tags, and check for at least one of
169             // them available.
170             const SensKeyNameList *sensKeys = &sensitivityKey[st_val - 1];
171             md_st = ed.end();
172             for (int idx = 0; idx < sensKeys->count; md_st = ed.end()) {
173                 md_st = findMetadatum(ed, const_cast<const char**>(sensKeys->keys), sensKeys->count);
174                 if (md_st == ed.end())
175                     break;
176                 std::ostringstream os_iso;
177                 md_st->write(os_iso, &ed);
178                 ok = false;
179                 iso_tmp_val = parseLong(os_iso.str(), ok);
180                 // something wrong with the value
181                 if (ok || iso_tmp_val > 0) {
182                     md = md_st;
183                     break;
184                 }
185                 while (strcmp(sensKeys->keys[idx++], md_st->key().c_str()) != 0 && idx < cnt) {}
186             }
187             break;
188         }
189 
190         return md;
191     }
192 
flashBias(const ExifData & ed)193     ExifData::const_iterator flashBias(const ExifData& ed)
194     {
195         static const char* keys[] = {
196             "Exif.CanonSi.FlashBias",
197             "Exif.Panasonic.FlashBias",
198             "Exif.Olympus.FlashBias",
199             "Exif.OlympusCs.FlashExposureComp",
200             "Exif.Minolta.FlashExposureComp",
201             "Exif.SonyMinolta.FlashExposureComp",
202             "Exif.Sony1.FlashExposureComp",
203             "Exif.Sony2.FlashExposureComp"
204         };
205         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
206     }
207 
exposureMode(const ExifData & ed)208     ExifData::const_iterator exposureMode(const ExifData& ed)
209     {
210         static const char* keys[] = {
211             "Exif.Photo.ExposureProgram",
212             "Exif.Image.ExposureProgram",
213             "Exif.CanonCs.ExposureProgram",
214             "Exif.MinoltaCs7D.ExposureMode",
215             "Exif.MinoltaCs5D.ExposureMode",
216             "Exif.MinoltaCsNew.ExposureMode",
217             "Exif.MinoltaCsOld.ExposureMode",
218             "Exif.Sony1MltCsA100.ExposureMode",
219             "Exif.Sony1Cs.ExposureProgram",
220             "Exif.Sony2Cs.ExposureProgram",
221             "Exif.Sigma.ExposureMode"
222         };
223         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
224     }
225 
sceneMode(const ExifData & ed)226     ExifData::const_iterator sceneMode(const ExifData& ed)
227     {
228         static const char* keys[] = {
229             "Exif.CanonCs.EasyMode",
230             "Exif.Fujifilm.PictureMode",
231             "Exif.MinoltaCsNew.SubjectProgram",
232             "Exif.MinoltaCsOld.SubjectProgram",
233             "Exif.Minolta.SceneMode",
234             "Exif.SonyMinolta.SceneMode",
235             "Exif.Sony1.SceneMode",
236             "Exif.Sony2.SceneMode",
237             "Exif.OlympusCs.SceneMode",
238             "Exif.Panasonic.ShootingMode",
239             "Exif.Panasonic.SceneMode",
240             "Exif.Pentax.PictureMode",
241             "Exif.PentaxDng.PictureMode",
242             "Exif.Photo.SceneCaptureType"
243         };
244         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
245     }
246 
macroMode(const ExifData & ed)247     ExifData::const_iterator macroMode(const ExifData& ed)
248     {
249         static const char* keys[] = {
250             "Exif.CanonCs.Macro",
251             "Exif.Fujifilm.Macro",
252             "Exif.Olympus.Macro",
253             "Exif.OlympusCs.MacroMode",
254             "Exif.Panasonic.Macro",
255             "Exif.MinoltaCsNew.MacroMode",
256             "Exif.MinoltaCsOld.MacroMode",
257             "Exif.Sony1.Macro",
258             "Exif.Sony2.Macro"
259         };
260         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
261     }
262 
imageQuality(const ExifData & ed)263     ExifData::const_iterator imageQuality(const ExifData& ed)
264     {
265         static const char* keys[] = {
266             "Exif.CanonCs.Quality",
267             "Exif.Fujifilm.Quality",
268             "Exif.Sigma.Quality",
269             "Exif.Nikon1.Quality",
270             "Exif.Nikon2.Quality",
271             "Exif.Nikon3.Quality",
272             "Exif.Olympus.Quality",
273             "Exif.OlympusCs.Quality",
274             "Exif.Panasonic.Quality",
275             "Exif.Minolta.Quality",
276             "Exif.MinoltaCsNew.Quality",
277             "Exif.MinoltaCsOld.Quality",
278             "Exif.MinoltaCs5D.Quality",
279             "Exif.MinoltaCs7D.Quality",
280             "Exif.Sony1MltCsA100.Quality",
281             "Exif.Sony1.JPEGQuality",
282             "Exif.Sony1.Quality",
283             "Exif.Sony1Cs.Quality",
284             "Exif.Sony2.JPEGQuality",
285             "Exif.Sony2.Quality",
286             "Exif.Sony2Cs.Quality",
287             "Exif.Casio.Quality",
288             "Exif.Casio2.QualityMode",
289             "Exif.Casio2.Quality"
290         };
291         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
292     }
293 
whiteBalance(const ExifData & ed)294     ExifData::const_iterator whiteBalance(const ExifData& ed)
295     {
296         static const char* keys[] = {
297             "Exif.CanonSi.WhiteBalance",
298             "Exif.Fujifilm.WhiteBalance",
299             "Exif.Sigma.WhiteBalance",
300             "Exif.Nikon1.WhiteBalance",
301             "Exif.Nikon2.WhiteBalance",
302             "Exif.Nikon3.WhiteBalance",
303             "Exif.Olympus.WhiteBalance",
304             "Exif.OlympusCs.WhiteBalance",
305             "Exif.Panasonic.WhiteBalance",
306             "Exif.MinoltaCs5D.WhiteBalance",
307             "Exif.MinoltaCs7D.WhiteBalance",
308             "Exif.MinoltaCsNew.WhiteBalance",
309             "Exif.MinoltaCsOld.WhiteBalance",
310             "Exif.Minolta.WhiteBalance",
311             "Exif.Sony1MltCsA100.WhiteBalance",
312             "Exif.SonyMinolta.WhiteBalance",
313             "Exif.Sony1.WhiteBalance",
314             "Exif.Sony2.WhiteBalance",
315             "Exif.Sony1.WhiteBalance2",
316             "Exif.Sony2.WhiteBalance2",
317             "Exif.Casio.WhiteBalance",
318             "Exif.Casio2.WhiteBalance",
319             "Exif.Casio2.WhiteBalance2",
320             "Exif.Photo.WhiteBalance"
321         };
322         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
323     }
324 
lensName(const ExifData & ed)325     ExifData::const_iterator lensName(const ExifData& ed)
326     {
327         static const char* keys[] = {
328             // Exif.Canon.LensModel only reports focal length.
329             // Try Exif.CanonCs.LensType first.
330             "Exif.CanonCs.LensType",
331             "Exif.Photo.LensModel",
332             "Exif.NikonLd1.LensIDNumber",
333             "Exif.NikonLd2.LensIDNumber",
334             "Exif.NikonLd3.LensIDNumber",
335             "Exif.Pentax.LensType",
336             "Exif.PentaxDng.LensType",
337             "Exif.Minolta.LensID",
338             "Exif.SonyMinolta.LensID",
339             "Exif.Sony1.LensID",
340             "Exif.Sony2.LensID",
341             "Exif.OlympusEq.LensType",
342             "Exif.Panasonic.LensType",
343             "Exif.Samsung2.LensType"
344         };
345         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
346     }
347 
saturation(const ExifData & ed)348     ExifData::const_iterator saturation(const ExifData& ed)
349     {
350         static const char* keys[] = {
351             "Exif.Photo.Saturation",
352             "Exif.CanonCs.Saturation",
353             "Exif.MinoltaCsNew.Saturation",
354             "Exif.MinoltaCsOld.Saturation",
355             "Exif.MinoltaCs7D.Saturation",
356             "Exif.MinoltaCs5D.Saturation",
357             "Exif.Fujifilm.Color",
358             "Exif.Nikon3.Saturation",
359             "Exif.Panasonic.Saturation",
360             "Exif.Pentax.Saturation",
361             "Exif.PentaxDng.Saturation",
362             "Exif.Sigma.Saturation",
363             "Exif.Casio.Saturation",
364             "Exif.Casio2.Saturation",
365             "Exif.Casio2.Saturation2"
366         };
367         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
368     }
369 
sharpness(const ExifData & ed)370     ExifData::const_iterator sharpness(const ExifData& ed)
371     {
372         static const char* keys[] = {
373             "Exif.Photo.Sharpness",
374             "Exif.CanonCs.Sharpness",
375             "Exif.Fujifilm.Sharpness",
376             "Exif.MinoltaCsNew.Sharpness",
377             "Exif.MinoltaCsOld.Sharpness",
378             "Exif.MinoltaCs7D.Sharpness",
379             "Exif.MinoltaCs5D.Sharpness",
380             "Exif.Olympus.SharpnessFactor",
381             "Exif.Panasonic.Sharpness",
382             "Exif.Pentax.Sharpness",
383             "Exif.PentaxDng.Sharpness",
384             "Exif.Sigma.Sharpness",
385             "Exif.Casio.Sharpness",
386             "Exif.Casio2.Sharpness",
387             "Exif.Casio2.Sharpness2"
388         };
389         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
390     }
391 
contrast(const ExifData & ed)392     ExifData::const_iterator contrast(const ExifData& ed)
393     {
394         static const char* keys[] = {
395             "Exif.Photo.Contrast",
396             "Exif.CanonCs.Contrast",
397             "Exif.Fujifilm.Tone",
398             "Exif.MinoltaCsNew.Contrast",
399             "Exif.MinoltaCsOld.Contrast",
400             "Exif.MinoltaCs7D.Contrast",
401             "Exif.MinoltaCs5D.Contrast",
402             "Exif.Olympus.Contrast",
403             "Exif.Panasonic.Contrast",
404             "Exif.Pentax.Contrast",
405             "Exif.PentaxDng.Contrast",
406             "Exif.Sigma.Contrast",
407             "Exif.Casio.Contrast",
408             "Exif.Casio2.Contrast",
409             "Exif.Casio2.Contrast2"
410 
411         };
412         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
413     }
414 
sceneCaptureType(const ExifData & ed)415     ExifData::const_iterator sceneCaptureType(const ExifData& ed)
416     {
417         static const char* keys[] = {
418             "Exif.Photo.SceneCaptureType",
419             "Exif.Olympus.SpecialMode"
420         };
421         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
422     }
423 
meteringMode(const ExifData & ed)424     ExifData::const_iterator meteringMode(const ExifData& ed)
425     {
426         static const char* keys[] = {
427             "Exif.Photo.MeteringMode",
428             "Exif.Image.MeteringMode",
429             "Exif.CanonCs.MeteringMode",
430             "Exif.Sony1MltCsA100.MeteringMode"
431         };
432         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
433     }
434 
make(const ExifData & ed)435     ExifData::const_iterator make(const ExifData& ed)
436     {
437         static const char* keys[] = {
438             "Exif.Image.Make"
439         };
440         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
441     }
442 
model(const ExifData & ed)443     ExifData::const_iterator model(const ExifData& ed)
444     {
445         static const char* keys[] = {
446             "Exif.Image.Model"
447         };
448         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
449     }
450 
exposureTime(const ExifData & ed)451     ExifData::const_iterator exposureTime(const ExifData& ed)
452     {
453         static const char* keys[] = {
454             "Exif.Photo.ExposureTime",
455             "Exif.Image.ExposureTime",
456             "Exif.Samsung2.ExposureTime"
457         };
458         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
459     }
460 
fNumber(const ExifData & ed)461     ExifData::const_iterator fNumber(const ExifData& ed)
462     {
463         static const char* keys[] = {
464             "Exif.Photo.FNumber",
465             "Exif.Image.FNumber",
466             "Exif.Samsung2.FNumber"
467         };
468         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
469     }
470 
subjectDistance(const ExifData & ed)471     ExifData::const_iterator subjectDistance(const ExifData& ed)
472     {
473         static const char* keys[] = {
474             "Exif.Photo.SubjectDistance",
475             "Exif.Image.SubjectDistance",
476             "Exif.CanonSi.SubjectDistance",
477             "Exif.CanonFi.FocusDistanceUpper",
478             "Exif.CanonFi.FocusDistanceLower",
479             "Exif.MinoltaCsNew.FocusDistance",
480             "Exif.Nikon1.FocusDistance",
481             "Exif.Nikon3.FocusDistance",
482             "Exif.NikonLd2.FocusDistance",
483             "Exif.NikonLd3.FocusDistance",
484             "Exif.Olympus.FocusDistance",
485             "Exif.OlympusFi.FocusDistance",
486             "Exif.Casio.ObjectDistance",
487             "Exif.Casio2.ObjectDistance"
488         };
489         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
490     }
491 
serialNumber(const ExifData & ed)492     ExifData::const_iterator serialNumber(const ExifData& ed)
493     {
494         static const char* keys[] = {
495             "Exif.Image.CameraSerialNumber",
496             "Exif.Canon.SerialNumber",
497             "Exif.Nikon3.SerialNumber",
498             "Exif.Nikon3.SerialNO",
499             "Exif.Fujifilm.SerialNumber",
500             "Exif.Olympus.SerialNumber2",
501             "Exif.Sigma.SerialNumber"
502         };
503         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
504     }
505 
focalLength(const ExifData & ed)506     ExifData::const_iterator focalLength(const ExifData& ed)
507     {
508         static const char* keys[] = {
509             "Exif.Photo.FocalLength",
510             "Exif.Image.FocalLength",
511             "Exif.Canon.FocalLength",
512             "Exif.NikonLd2.FocalLength",
513             "Exif.NikonLd3.FocalLength",
514             "Exif.MinoltaCsNew.FocalLength",
515             "Exif.Pentax.FocalLength",
516             "Exif.PentaxDng.FocalLength",
517             "Exif.Casio2.FocalLength"
518         };
519         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
520     }
521 
afPoint(const ExifData & ed)522     ExifData::const_iterator afPoint(const ExifData& ed)
523     {
524         static const char* keys[] = {
525             "Exif.CanonPi.AFPointsUsed",
526             "Exif.CanonPi.AFPointsUsed20D",
527             "Exif.CanonSi.AFPointUsed",
528             "Exif.CanonCs.AFPoint",
529             "Exif.MinoltaCs7D.AFPoints",
530             "Exif.Nikon1.AFFocusPos",
531             "Exif.NikonAf.AFPoint",
532             "Exif.NikonAf.AFPointsInFocus",
533             "Exif.NikonAf2.AFPointsUsed",
534             "Exif.NikonAf2.PrimaryAFPoint",
535             "Exif.OlympusFi.AFPoint",
536             "Exif.Pentax.AFPoint",
537             "Exif.Pentax.AFPointInFocus",
538             "Exif.PentaxDng.AFPoint",
539             "Exif.PentaxDng.AFPointInFocus",
540             "Exif.Sony1Cs.LocalAFAreaPoint",
541             "Exif.Sony2Cs.LocalAFAreaPoint",
542             "Exif.Sony1Cs2.LocalAFAreaPoint",
543             "Exif.Sony2Cs2.LocalAFAreaPoint",
544             "Exif.Sony1MltCsA100.LocalAFAreaPoint",
545             "Exif.Casio.AFPoint",
546             "Exif.Casio2.AFPointPosition"
547         };
548         return findMetadatum(ed, keys, EXV_COUNTOF(keys));
549     }
550 
551 }                                       // namespace Exiv2
552