aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/exiv2_extractor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/exiv2_extractor.cc')
-rw-r--r--src/plugins/exiv2_extractor.cc879
1 files changed, 708 insertions, 171 deletions
diff --git a/src/plugins/exiv2_extractor.cc b/src/plugins/exiv2_extractor.cc
index c3bd91a..8cd7f20 100644
--- a/src/plugins/exiv2_extractor.cc
+++ b/src/plugins/exiv2_extractor.cc
@@ -2,7 +2,7 @@
2/* 2/*
3 * This program is free software; you can redistribute it and/or 3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License 4 * modify it under the terms of the GNU General Public License
5 * as published by the Free Software Foundation; either version 2 5 * as published by the Free Software Foundation; either version 3
6 * of the License, or (at your option) any later version. 6 * of the License, or (at your option) any later version.
7 * 7 *
8 * This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
@@ -14,74 +14,588 @@
14 * along with this program; if not, write to the Free Software 14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 */ 16 */
17/*! 17/**
18 @file exiv2_extractor.cc 18 * @file plugins/exiv2_extractor.cc
19 @brief libextractor plugin for Exif using exiv2 19 * @brief libextractor plugin for Exif using exiv2
20 @version $Rev$ 20 * @author Andreas Huggel (ahu)
21 @author Andreas Huggel (ahu) 21 * @author Christian Grothoff
22 <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> 22 */
23 @date 30-Jun-05, ahu: created; 15-Dec-09, cg: updated 23#include "platform.h"
24*/ 24#include "extractor.h"
25
26#include <iostream> 25#include <iostream>
27#include <iomanip> 26#include <iomanip>
28#include <cassert> 27#include <cassert>
29#include <cstring> 28#include <cstring>
30#include <math.h> 29#include <math.h>
31
32#include "platform.h"
33#include "extractor.h"
34
35#include <exiv2/exif.hpp> 30#include <exiv2/exif.hpp>
31#include <exiv2/error.hpp>
36#include <exiv2/image.hpp> 32#include <exiv2/image.hpp>
37#include <exiv2/futils.hpp> 33#include <exiv2/futils.hpp>
38 34
35/**
36 * Should we suppress exiv2 warnings?
37 */
39#define SUPPRESS_WARNINGS 1 38#define SUPPRESS_WARNINGS 1
40 39
41#define ADD(s, type) do { if (0!=proc(proc_cls, "exiv2", type, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1)) return 1; } while (0)
42 40
43static int 41/**
44addExiv2Tag(const Exiv2::ExifData& exifData, 42 * Implementation of EXIV2's BasicIO interface based
45 const std::string& key, 43 * on the 'struct EXTRACTOR_ExtractContext.
46 enum EXTRACTOR_MetaType type, 44 */
47 EXTRACTOR_MetaDataProcessor proc, 45class ExtractorIO:Exiv2::BasicIo
48 void *proc_cls)
49{ 46{
50 const char * str; 47private:
51 48
52 Exiv2::ExifKey ek(key); 49 /**
53 Exiv2::ExifData::const_iterator md = exifData.findKey(ek); 50 * Extract context we are using.
54 if (md != exifData.end()) { 51 */
55 std::string ccstr = Exiv2::toString(*md); 52 struct EXTRACTOR_ExtractContext *ec;
56 str = ccstr.c_str(); 53
57 while ( (strlen(str) > 0) && isspace((unsigned char) str[0])) str++; 54public:
58 if (strlen(str) > 0) 55
59 ADD (str, type); 56 /**
60 md++; 57 * Constructor.
58 *
59 * @param s_ec extract context to wrap
60 */
61 ExtractorIO (struct EXTRACTOR_ExtractContext *s_ec)
62 {
63 ec = s_ec;
61 } 64 }
65
66 /**
67 * Destructor.
68 */
69 virtual ~ExtractorIO ()
70 {
71 /* nothing to do */
72 }
73
74 /**
75 * Open stream.
76 *
77 * @return 0 (always successful)
78 */
79 virtual int open ();
80
81 /**
82 * Close stream.
83 *
84 * @return 0 (always successful)
85 */
86 virtual int close ();
87
88 /**
89 * Read up to 'rcount' bytes into a buffer
90 *
91 * @param rcount number of bytes to read
92 * @return buffer with data read, empty buffer (!) on failure (!)
93 */
94 virtual Exiv2::DataBuf read (long rcount);
95
96 /**
97 * Read up to 'rcount' bytes into 'buf'.
98 *
99 * @param buf buffer to fill
100 * @param rcount size of 'buf'
101 * @return number of bytes read successfully, 0 on failure (!)
102 */
103 virtual long read (Exiv2::byte *buf,
104 long rcount);
105
106 /**
107 * Read a single character.
108 *
109 * @return the character
110 * @throw exception on errors
111 */
112 virtual int getb ();
113
114 /**
115 * Write to stream.
116 *
117 * @param data data to write
118 * @param wcount how many bytes to write
119 * @return -1 (always fails)
120 */
121 virtual long write (const Exiv2::byte *data,
122 long wcount);
123
124 /**
125 * Write to stream.
126 *
127 * @param src stream to copy
128 * @return -1 (always fails)
129 */
130 virtual long write (Exiv2::BasicIo &src);
131
132 /**
133 * Write a single byte.
134 *
135 * @param data byte to write
136 * @return -1 (always fails)
137 */
138 virtual int putb (Exiv2::byte data);
139
140 /**
141 * Not supported.
142 *
143 * @throws error
144 */
145 virtual void transfer (Exiv2::BasicIo& src);
146
147 /**
148 * Seek to the given offset.
149 *
150 * @param offset desired offset
151 * @parma pos offset is relative to where?
152 * @return -1 on failure, 0 on success
153 */
154 virtual int seek (long offset,
155 Exiv2::BasicIo::Position pos);
156
157 /**
158 * Not supported.
159 *
160 * @throws error
161 */
162 virtual Exiv2::byte* mmap (bool isWritable);
163
164 /**
165 * Not supported.
166 *
167 * @return -1 (error)
168 */
169 virtual int munmap ();
170
171 /**
172 * Return our current offset in the file.
173 *
174 * @return -1 on error
175 */
176 virtual long int tell (void) const;
177
178 /**
179 * Return overall size of the file.
180 *
181 * @return -1 on error
182 */
183 virtual long int size (void) const;
184
185 /**
186 * Check if file is open.
187 *
188 * @return true (always).
189 */
190 virtual bool isopen () const;
191
192 /**
193 * Check if this file source is in error mode.
194 *
195 * @return 0 (always all is fine).
196 */
197 virtual int error () const;
198
199 /**
200 * Check if current position of the file is at the end
201 *
202 * @return true if at EOF, false if not.
203 */
204 virtual bool eof () const;
205
206 /**
207 * Not supported.
208 *
209 * @throws error
210 */
211 virtual std::string path () const;
212
213#ifdef EXV_UNICODE_PATH
214 /**
215 * Not supported.
216 *
217 * @throws error
218 */
219 virtual std::wstring wpath () const;
220#endif
221
222 /**
223 * Not supported.
224 *
225 * @throws error
226 */
227 virtual Exiv2::BasicIo::AutoPtr temporary () const;
228
229};
230
231
232/**
233 * Open stream.
234 *
235 * @return 0 (always successful)
236 */
237int
238ExtractorIO::open ()
239{
62 return 0; 240 return 0;
63} 241}
64 242
243/**
244 * Close stream.
245 *
246 * @return 0 (always successful)
247 */
248int
249ExtractorIO::close ()
250{
251 return 0;
252}
65 253
66static int 254
67addIptcData(const Exiv2::IptcData& iptcData, 255/**
68 const std::string& key, 256 * Read up to 'rcount' bytes into a buffer
69 enum EXTRACTOR_MetaType type, 257 *
70 EXTRACTOR_MetaDataProcessor proc, 258 * @param rcount number of bytes to read
71 void *proc_cls) 259 * @return buffer with data read, empty buffer (!) on failure (!)
260 */
261Exiv2::DataBuf
262ExtractorIO::read (long rcount)
72{ 263{
73 const char * str; 264 void *data;
265 ssize_t ret;
266
267 if (-1 == (ret = ec->read (ec->cls, &data, rcount)))
268 return Exiv2::DataBuf (NULL, 0);
269 return Exiv2::DataBuf ((const Exiv2::byte *) data, ret);
270}
271
272
273/**
274 * Read up to 'rcount' bytes into 'buf'.
275 *
276 * @param buf buffer to fill
277 * @param rcount size of 'buf'
278 * @return number of bytes read successfully, 0 on failure (!)
279 */
280long
281ExtractorIO::read (Exiv2::byte *buf,
282 long rcount)
283{
284 void *data;
285 ssize_t ret;
74 286
75 Exiv2::IptcKey ek(key); 287 if (-1 == (ret = ec->read (ec->cls, &data, rcount)))
76 Exiv2::IptcData::const_iterator md = iptcData.findKey(ek); 288 return 0;
77 while (md != iptcData.end()) 289 memcpy (buf, data, ret);
290 return ret;
291}
292
293
294/**
295 * Read a single character.
296 *
297 * @return the character
298 * @throw exception on errors
299 */
300int
301ExtractorIO::getb ()
302{
303 void *data;
304 char *r;
305
306 if (1 != ec->read (ec->cls, &data, 1))
307 throw Exiv2::BasicError<char> (42 /* error code */);
308 r = (char *) data;
309 return *r;
310}
311
312
313/**
314 * Write to stream.
315 *
316 * @param data data to write
317 * @param wcount how many bytes to write
318 * @return -1 (always fails)
319 */
320long
321ExtractorIO::write (const Exiv2::byte *data,
322 long wcount)
323{
324 return -1;
325}
326
327
328/**
329 * Write to stream.
330 *
331 * @param src stream to copy
332 * @return -1 (always fails)
333 */
334long
335ExtractorIO::write (Exiv2::BasicIo &src)
336{
337 return -1;
338}
339
340
341/**
342 * Write a single byte.
343 *
344 * @param data byte to write
345 * @return -1 (always fails)
346 */
347int
348ExtractorIO::putb (Exiv2::byte data)
349{
350 return -1;
351}
352
353
354/**
355 * Not supported.
356 *
357 * @throws error
358 */
359void
360ExtractorIO::transfer (Exiv2::BasicIo& src)
361{
362 throw Exiv2::BasicError<char> (42 /* error code */);
363}
364
365
366/**
367 * Seek to the given offset.
368 *
369 * @param offset desired offset
370 * @parma pos offset is relative to where?
371 * @return -1 on failure, 0 on success
372 */
373int
374ExtractorIO::seek (long offset,
375 Exiv2::BasicIo::Position pos)
376{
377 int rel;
378
379 switch (pos)
78 { 380 {
79 if (0 != strcmp (Exiv2::toString(md->key()).c_str(), key.c_str())) 381 case beg: // Exiv2::BasicIo::beg:
382 rel = SEEK_SET;
383 break;
384 case cur:
385 rel = SEEK_CUR;
386 break;
387 case end:
388 rel = SEEK_END;
389 break;
390 default:
391 abort ();
392 }
393 if (-1 == ec->seek (ec->cls, offset, rel))
394 return -1;
395 return 0;
396}
397
398
399/**
400 * Not supported.
401 *
402 * @throws error
403 */
404Exiv2::byte *
405ExtractorIO::mmap (bool isWritable)
406{
407 throw Exiv2::BasicError<char> (42 /* error code */);
408}
409
410
411/**
412 * Not supported.
413 *
414 * @return -1 error
415 */
416int
417ExtractorIO::munmap ()
418{
419 return -1;
420}
421
422
423/**
424 * Return our current offset in the file.
425 *
426 * @return -1 on error
427 */
428long int
429ExtractorIO::tell (void) const
430{
431 return (long) ec->seek (ec->cls, 0, SEEK_CUR);
432}
433
434
435/**
436 * Return overall size of the file.
437 *
438 * @return -1 on error
439 */
440long int
441ExtractorIO::size (void) const
442{
443 return (long) ec->get_size (ec->cls);
444}
445
446
447/**
448 * Check if file is open.
449 *
450 * @return true (always).
451 */
452bool
453ExtractorIO::isopen () const
454{
455 return true;
456}
457
458
459/**
460 * Check if this file source is in error mode.
461 *
462 * @return 0 (always all is fine).
463 */
464int
465ExtractorIO::error () const
466{
467 return 0;
468}
469
470
471/**
472 * Check if current position of the file is at the end
473 *
474 * @return true if at EOF, false if not.
475 */
476bool
477ExtractorIO::eof () const
478{
479 return size () == tell ();
480}
481
482
483/**
484 * Not supported.
485 *
486 * @throws error
487 */
488std::string
489ExtractorIO::path () const
490{
491 throw Exiv2::BasicError<char> (42 /* error code */);
492}
493
494
495#ifdef EXV_UNICODE_PATH
496/**
497 * Not supported.
498 *
499 * @throws error
500 */
501std::string
502ExtractorIO::wpath () const
503{
504 throw Exiv2::BasicError<char> (42 /* error code */);
505}
506#endif
507
508
509/**
510 * Not supported.
511 *
512 * @throws error
513 */
514Exiv2::BasicIo::AutoPtr
515ExtractorIO::temporary () const
516{
517 throw Exiv2::BasicError<char> (42 /* error code */);
518}
519
520
521/**
522 * Pass the given UTF-8 string to the 'proc' callback using
523 * the given type. Uses 'return 1' if 'proc' returns non-0.
524 *
525 * @param s 0-terminated UTF8 string value with the meta data
526 * @param type libextractor type for the meta data
527 */
528#define ADD(s, type) do { if (0 != proc (proc_cls, "exiv2", type, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) return 1; } while (0)
529
530
531/**
532 * Try to find a given key in the exifData and if a value is
533 * found, pass it to 'proc'.
534 *
535 * @param exifData metadata set to inspect
536 * @param key key to lookup in exifData
537 * @param type extractor type to use
538 * @param proc function to call with results
539 * @param proc_cls closurer for proc
540 * @return 0 to continue extracting, 1 to abort
541 */
542static int
543addExiv2Tag (const Exiv2::ExifData& exifData,
544 const std::string& key,
545 enum EXTRACTOR_MetaType type,
546 EXTRACTOR_MetaDataProcessor proc,
547 void *proc_cls)
548{
549 const char *str;
550 Exiv2::ExifKey ek (key);
551 Exiv2::ExifData::const_iterator md = exifData.findKey (ek);
552
553 if (exifData.end () == md)
554 return 0; /* not found */
555 std::string ccstr = Exiv2::toString(*md);
556 str = ccstr.c_str();
557 /* skip over whitespace */
558 while ( (strlen (str) > 0) && isspace ((unsigned char) str[0]))
559 str++;
560 if (strlen (str) > 0)
561 ADD (str, type);
562 md++;
563 return 0;
564}
565
566
567/**
568 * Try to find a given key in the iptcData and if a value is
569 * found, pass it to 'proc'.
570 *
571 * @param ipctData metadata set to inspect
572 * @param key key to lookup in exifData
573 * @param type extractor type to use
574 * @param proc function to call with results
575 * @param proc_cls closurer for proc
576 * @return 0 to continue extracting, 1 to abort
577 */
578static int
579addIptcData (const Exiv2::IptcData& iptcData,
580 const std::string& key,
581 enum EXTRACTOR_MetaType type,
582 EXTRACTOR_MetaDataProcessor proc,
583 void *proc_cls)
584{
585 const char *str;
586 Exiv2::IptcKey ek (key);
587 Exiv2::IptcData::const_iterator md = iptcData.findKey (ek);
588
589 while (iptcData.end () != md)
590 {
591 if (0 != strcmp (Exiv2::toString (md->key ()).c_str (), key.c_str ()))
80 break; 592 break;
81 std::string ccstr = Exiv2::toString(*md); 593 std::string ccstr = Exiv2::toString (*md);
82 str = ccstr.c_str(); 594 str = ccstr.c_str ();
83 while ( (strlen(str) > 0) && isspace( (unsigned char) str[0])) str++; 595 /* skip over whitespace */
84 if (strlen(str) > 0) 596 while ((strlen (str) > 0) && isspace ((unsigned char) str[0]))
597 str++;
598 if (strlen (str) > 0)
85 ADD (str, type); 599 ADD (str, type);
86 md++; 600 md++;
87 } 601 }
@@ -89,6 +603,17 @@ addIptcData(const Exiv2::IptcData& iptcData,
89} 603}
90 604
91 605
606/**
607 * Try to find a given key in the xmpData and if a value is
608 * found, pass it to 'proc'.
609 *
610 * @param xmpData metadata set to inspect
611 * @param key key to lookup in exifData
612 * @param type extractor type to use
613 * @param proc function to call with results
614 * @param proc_cls closurer for proc
615 * @return 0 to continue extracting, 1 to abort
616 */
92static int 617static int
93addXmpData(const Exiv2::XmpData& xmpData, 618addXmpData(const Exiv2::XmpData& xmpData,
94 const std::string& key, 619 const std::string& key,
@@ -97,149 +622,163 @@ addXmpData(const Exiv2::XmpData& xmpData,
97 void *proc_cls) 622 void *proc_cls)
98{ 623{
99 const char * str; 624 const char * str;
100 625 Exiv2::XmpKey ek (key);
101 Exiv2::XmpKey ek(key); 626 Exiv2::XmpData::const_iterator md = xmpData.findKey (ek);
102 Exiv2::XmpData::const_iterator md = xmpData.findKey(ek); 627
103 while (md != xmpData.end()) 628 while (xmpData.end () != md)
104 { 629 {
105 if (0 != strcmp (Exiv2::toString(md->key()).c_str(), key.c_str())) 630 if (0 != strcmp (Exiv2::toString (md->key ()).c_str (), key.c_str ()))
106 break; 631 break;
107 std::string ccstr = Exiv2::toString(*md); 632 std::string ccstr = Exiv2::toString (*md);
108 str = ccstr.c_str(); 633 str = ccstr.c_str ();
109 while ( (strlen(str) > 0) && isspace( (unsigned char) str[0])) str++; 634 while ( (strlen (str) > 0) && isspace ((unsigned char) str[0])) str++;
110 if (strlen(str) > 0) 635 if (strlen (str) > 0)
111 ADD (str, type); 636 ADD (str, type);
112 md++; 637 md++;
113 } 638 }
114 return 0; 639 return 0;
115} 640}
116 641
117#define ADDEXIV(s,t) do { if (0 != addExiv2Tag (exifData, s, t, proc, proc_cls)) return 1; } while (0)
118#define ADDIPTC(s,t) do { if (0 != addIptcData (iptcData, s, t, proc, proc_cls)) return 1; } while (0)
119#define ADDXMP(s,t) do { if (0 != addXmpData (xmpData, s, t, proc, proc_cls)) return 1; } while (0)
120 642
643/**
644 * Call 'addExiv2Tag' for the given key-type combination.
645 * Uses 'return' if addExiv2Tag returns non-0.
646 *
647 * @param s key to lookup
648 * @param type libextractor type to use for the meta data found under the given key
649 */
650#define ADDEXIV(s,t) do { if (0 != addExiv2Tag (exifData, s, t, ec->proc, ec->cls)) return; } while (0)
121 651
122extern "C" { 652
123 653/**
124 int 654 * Call 'addIptcData' for the given key-type combination.
125 EXTRACTOR_exiv2_extract (const char *data, 655 * Uses 'return' if addIptcData returns non-0.
126 size_t size, 656 *
127 EXTRACTOR_MetaDataProcessor proc, 657 * @param s key to lookup
128 void *proc_cls, 658 * @param type libextractor type to use for the meta data found under the given key
129 const char *options) 659 */
130 { 660#define ADDIPTC(s,t) do { if (0 != addIptcData (iptcData, s, t, ec->proc, ec->cls)) return; } while (0)
131 try 661
132 { 662
133 Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open( (Exiv2::byte*) data, 663/**
134 size); 664 * Call 'addXmpData' for the given key-type combination.
135 if (image.get() == 0) 665 * Uses 'return' if addXmpData returns non-0.
136 return 0; 666 *
137 image->readMetadata(); 667 * @param s key to lookup
138 Exiv2::ExifData &exifData = image->exifData(); 668 * @param type libextractor type to use for the meta data found under the given key
139 if (!exifData.empty()) 669 */
140 { 670#define ADDXMP(s,t) do { if (0 != addXmpData (xmpData, s, t, ec->proc, ec->cls)) return; } while (0)
141 Exiv2::ExifData::const_iterator md; 671
142 672
143 /* FIXME: this should be a loop over data, 673/**
144 not a looooong block of code */ 674 * Main entry method for the 'exiv2' extraction plugin.
145 ADDEXIV ("Exif.Image.Copyright", EXTRACTOR_METATYPE_COPYRIGHT); 675 *
146 ADDEXIV ("Exif.Photo.UserComment", EXTRACTOR_METATYPE_COMMENT); 676 * @param ec extraction context provided to the plugin
147 ADDEXIV ("Exif.GPSInfo.GPSLatitudeRef", EXTRACTOR_METATYPE_GPS_LATITUDE_REF); 677 */
148 ADDEXIV ("Exif.GPSInfo.GPSLatitude", EXTRACTOR_METATYPE_GPS_LATITUDE); 678extern "C" void
149 ADDEXIV ("Exif.GPSInfo.GPSLongitudeRef", EXTRACTOR_METATYPE_GPS_LONGITUDE_REF); 679EXTRACTOR_exiv2_extract_method (struct EXTRACTOR_ExtractContext *ec)
150 ADDEXIV ("Exif.GPSInfo.GPSLongitude", EXTRACTOR_METATYPE_GPS_LONGITUDE); 680{
151 ADDEXIV ("Exif.Image.Make", EXTRACTOR_METATYPE_CAMERA_MAKE); 681 try
152 ADDEXIV ("Exif.Image.Model", EXTRACTOR_METATYPE_CAMERA_MODEL); 682 {
153 ADDEXIV ("Exif.Image.Orientation", EXTRACTOR_METATYPE_ORIENTATION); 683 std::auto_ptr<Exiv2::BasicIo> eio = new ExtractorIO (ec);
154 ADDEXIV ("Exif.Photo.DateTimeOriginal", EXTRACTOR_METATYPE_CREATION_DATE); 684 Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open (eio);
155 ADDEXIV ("Exif.Photo.ExposureBiasValue", EXTRACTOR_METATYPE_EXPOSURE_BIAS); 685 if (0 == image.get ())
156 ADDEXIV ("Exif.Photo.Flash", EXTRACTOR_METATYPE_FLASH); 686 return;
157 ADDEXIV ("Exif.CanonSi.FlashBias", EXTRACTOR_METATYPE_FLASH_BIAS); 687 image->readMetadata ();
158 ADDEXIV ("Exif.Panasonic.FlashBias", EXTRACTOR_METATYPE_FLASH_BIAS); 688 Exiv2::ExifData &exifData = image->exifData ();
159 ADDEXIV ("Exif.Olympus.FlashBias", EXTRACTOR_METATYPE_FLASH_BIAS); 689 if (! exifData.empty ())
160 ADDEXIV ("Exif.Photo.FocalLength", EXTRACTOR_METATYPE_FOCAL_LENGTH); 690 {
161 ADDEXIV ("Exif.Photo.FocalLengthIn35mmFilm", EXTRACTOR_METATYPE_FOCAL_LENGTH_35MM); 691 ADDEXIV ("Exif.Image.Copyright", EXTRACTOR_METATYPE_COPYRIGHT);
162 ADDEXIV ("Exif.Photo.ISOSpeedRatings", EXTRACTOR_METATYPE_ISO_SPEED); 692 ADDEXIV ("Exif.Photo.UserComment", EXTRACTOR_METATYPE_COMMENT);
163 ADDEXIV ("Exif.CanonSi.ISOSpeed", EXTRACTOR_METATYPE_ISO_SPEED); 693 ADDEXIV ("Exif.GPSInfo.GPSLatitudeRef", EXTRACTOR_METATYPE_GPS_LATITUDE_REF);
164 ADDEXIV ("Exif.Nikon1.ISOSpeed", EXTRACTOR_METATYPE_ISO_SPEED); 694 ADDEXIV ("Exif.GPSInfo.GPSLatitude", EXTRACTOR_METATYPE_GPS_LATITUDE);
165 ADDEXIV ("Exif.Nikon2.ISOSpeed", EXTRACTOR_METATYPE_ISO_SPEED); 695 ADDEXIV ("Exif.GPSInfo.GPSLongitudeRef", EXTRACTOR_METATYPE_GPS_LONGITUDE_REF);
166 ADDEXIV ("Exif.Nikon3.ISOSpeed", EXTRACTOR_METATYPE_ISO_SPEED); 696 ADDEXIV ("Exif.GPSInfo.GPSLongitude", EXTRACTOR_METATYPE_GPS_LONGITUDE);
167 ADDEXIV ("Exif.Photo.ExposureProgram", EXTRACTOR_METATYPE_EXPOSURE_MODE); 697 ADDEXIV ("Exif.Image.Make", EXTRACTOR_METATYPE_CAMERA_MAKE);
168 ADDEXIV ("Exif.CanonCs.ExposureProgram", EXTRACTOR_METATYPE_EXPOSURE_MODE); 698 ADDEXIV ("Exif.Image.Model", EXTRACTOR_METATYPE_CAMERA_MODEL);
169 ADDEXIV ("Exif.Photo.MeteringMode", EXTRACTOR_METATYPE_METERING_MODE); 699 ADDEXIV ("Exif.Image.Orientation", EXTRACTOR_METATYPE_ORIENTATION);
170 ADDEXIV ("Exif.CanonCs.Macro", EXTRACTOR_METATYPE_MACRO_MODE); 700 ADDEXIV ("Exif.Photo.DateTimeOriginal", EXTRACTOR_METATYPE_CREATION_DATE);
171 ADDEXIV ("Exif.Fujifilm.Macro", EXTRACTOR_METATYPE_MACRO_MODE); 701 ADDEXIV ("Exif.Photo.ExposureBiasValue", EXTRACTOR_METATYPE_EXPOSURE_BIAS);
172 ADDEXIV ("Exif.Olympus.Macro", EXTRACTOR_METATYPE_MACRO_MODE); 702 ADDEXIV ("Exif.Photo.Flash", EXTRACTOR_METATYPE_FLASH);
173 ADDEXIV ("Exif.Panasonic.Macro", EXTRACTOR_METATYPE_MACRO_MODE); 703 ADDEXIV ("Exif.CanonSi.FlashBias", EXTRACTOR_METATYPE_FLASH_BIAS);
174 ADDEXIV ("Exif.CanonCs.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY); 704 ADDEXIV ("Exif.Panasonic.FlashBias", EXTRACTOR_METATYPE_FLASH_BIAS);
175 ADDEXIV ("Exif.Fujifilm.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY); 705 ADDEXIV ("Exif.Olympus.FlashBias", EXTRACTOR_METATYPE_FLASH_BIAS);
176 ADDEXIV ("Exif.Sigma.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY); 706 ADDEXIV ("Exif.Photo.FocalLength", EXTRACTOR_METATYPE_FOCAL_LENGTH);
177 ADDEXIV ("Exif.Nikon1.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY); 707 ADDEXIV ("Exif.Photo.FocalLengthIn35mmFilm", EXTRACTOR_METATYPE_FOCAL_LENGTH_35MM);
178 ADDEXIV ("Exif.Nikon2.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY); 708 ADDEXIV ("Exif.Photo.ISOSpeedRatings", EXTRACTOR_METATYPE_ISO_SPEED);
179 ADDEXIV ("Exif.Nikon3.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY); 709 ADDEXIV ("Exif.CanonSi.ISOSpeed", EXTRACTOR_METATYPE_ISO_SPEED);
180 ADDEXIV ("Exif.Olympus.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY); 710 ADDEXIV ("Exif.Nikon1.ISOSpeed", EXTRACTOR_METATYPE_ISO_SPEED);
181 ADDEXIV ("Exif.Panasonic.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY); 711 ADDEXIV ("Exif.Nikon2.ISOSpeed", EXTRACTOR_METATYPE_ISO_SPEED);
182 ADDEXIV ("Exif.CanonSi.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE); 712 ADDEXIV ("Exif.Nikon3.ISOSpeed", EXTRACTOR_METATYPE_ISO_SPEED);
183 ADDEXIV ("Exif.Fujifilm.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE); 713 ADDEXIV ("Exif.Photo.ExposureProgram", EXTRACTOR_METATYPE_EXPOSURE_MODE);
184 ADDEXIV ("Exif.Sigma.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE); 714 ADDEXIV ("Exif.CanonCs.ExposureProgram", EXTRACTOR_METATYPE_EXPOSURE_MODE);
185 ADDEXIV ("Exif.Nikon1.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE); 715 ADDEXIV ("Exif.Photo.MeteringMode", EXTRACTOR_METATYPE_METERING_MODE);
186 ADDEXIV ("Exif.Nikon2.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE); 716 ADDEXIV ("Exif.CanonCs.Macro", EXTRACTOR_METATYPE_MACRO_MODE);
187 ADDEXIV ("Exif.Nikon3.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE); 717 ADDEXIV ("Exif.Fujifilm.Macro", EXTRACTOR_METATYPE_MACRO_MODE);
188 ADDEXIV ("Exif.Olympus.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE); 718 ADDEXIV ("Exif.Olympus.Macro", EXTRACTOR_METATYPE_MACRO_MODE);
189 ADDEXIV ("Exif.Panasonic.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE); 719 ADDEXIV ("Exif.Panasonic.Macro", EXTRACTOR_METATYPE_MACRO_MODE);
190 720 ADDEXIV ("Exif.CanonCs.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY);
191 ADDEXIV ("Exif.Photo.FNumber", EXTRACTOR_METATYPE_APERTURE); 721 ADDEXIV ("Exif.Fujifilm.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY);
192 md = exifData.findKey(Exiv2::ExifKey("Exif.Photo.ApertureValue")); 722 ADDEXIV ("Exif.Sigma.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY);
193 if (md != exifData.end()) { 723 ADDEXIV ("Exif.Nikon1.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY);
724 ADDEXIV ("Exif.Nikon2.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY);
725 ADDEXIV ("Exif.Nikon3.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY);
726 ADDEXIV ("Exif.Olympus.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY);
727 ADDEXIV ("Exif.Panasonic.Quality", EXTRACTOR_METATYPE_IMAGE_QUALITY);
728 ADDEXIV ("Exif.CanonSi.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE);
729 ADDEXIV ("Exif.Fujifilm.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE);
730 ADDEXIV ("Exif.Sigma.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE);
731 ADDEXIV ("Exif.Nikon1.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE);
732 ADDEXIV ("Exif.Nikon2.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE);
733 ADDEXIV ("Exif.Nikon3.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE);
734 ADDEXIV ("Exif.Olympus.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE);
735 ADDEXIV ("Exif.Panasonic.WhiteBalance", EXTRACTOR_METATYPE_WHITE_BALANCE);
736 ADDEXIV ("Exif.Photo.FNumber", EXTRACTOR_METATYPE_APERTURE);
737 ADDEXIV ("Exif.Photo.ExposureTime", EXTRACTOR_METATYPE_EXPOSURE);
738
739#if FIXME
740 /* FIXME: the 'ADD' macro below won't work as we don't have 'proc' and 'proc_cls' in
741 this scope... */
742 Exiv2::ExifData::const_iterator md = exifData.findKey(Exiv2::ExifKey("Exif.Photo.ApertureValue"));
743 if (exifData.end() != md)
744 {
194 std::ostringstream os; 745 std::ostringstream os;
195 os << std::fixed << std::setprecision(1) 746 os << std::fixed << std::setprecision(1)
196 << "F" << exp(log(2.0) * md->toFloat() / 2); 747 << "F" << exp(log(2.0) * md->toFloat() / 2);
197 ADD (os.str().c_str(), EXTRACTOR_METATYPE_APERTURE); 748 ADD (os.str().c_str(), EXTRACTOR_METATYPE_APERTURE);
198 } 749 }
199 750
200 ADDEXIV ("Exif.Photo.ExposureTime", EXTRACTOR_METATYPE_EXPOSURE); 751 md = exifData.findKey(Exiv2::ExifKey("Exif.Photo.ShutterSpeedValue"));
201 md = exifData.findKey(Exiv2::ExifKey("Exif.Photo.ShutterSpeedValue")); 752 if (exifData.end() != md)
202 if (md != exifData.end()) { 753 {
203 double tmp = exp(log(2.0) * md->toFloat()) + 0.5; 754 double tmp = exp(log(2.0) * md->toFloat()) + 0.5;
204 std::ostringstream os; 755 std::ostringstream os;
205 if (tmp > 1) { 756 if (tmp > 1)
206 os << "1/" << static_cast<long>(tmp) << " s"; 757 {
207 } 758 os << "1/" << static_cast<long>(tmp) << " s";
208 else { 759 }
209 os << static_cast<long>(1/tmp) << " s"; 760 else
210 } 761 {
762 os << static_cast<long>(1/tmp) << " s";
763 }
211 ADD (os.str().c_str(), EXTRACTOR_METATYPE_EXPOSURE); 764 ADD (os.str().c_str(), EXTRACTOR_METATYPE_EXPOSURE);
212 } 765 }
213 766#endif
214 /* this can sometimes be wrong (corrupt exiv2 data?). 767 }
215 Either way, we should get the data directly from 768
216 the specific file format parser (i.e. jpeg, tiff). */ 769 Exiv2::IptcData &iptcData = image->iptcData();
217 // Exif Resolution 770 if (! iptcData.empty())
218 unsigned long xdim = 0; 771 {
219 unsigned long ydim = 0;
220 md = exifData.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension"));
221 if (md != exifData.end()) xdim = md->toLong();
222 md = exifData.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension"));
223 if (md != exifData.end()) ydim = md->toLong();
224 if ( (xdim != 0) && (ydim != 0))
225 {
226 std::ostringstream os;
227 os << xdim << "x" << ydim;
228 ADD (os.str().c_str(), EXTRACTOR_METATYPE_IMAGE_DIMENSIONS);
229 }
230 }
231
232 Exiv2::IptcData &iptcData = image->iptcData();
233 if (! iptcData.empty()) {
234 ADDIPTC ("Iptc.Application2.Keywords", EXTRACTOR_METATYPE_KEYWORDS); 772 ADDIPTC ("Iptc.Application2.Keywords", EXTRACTOR_METATYPE_KEYWORDS);
235 ADDIPTC ("Iptc.Application2.City", EXTRACTOR_METATYPE_LOCATION_CITY); 773 ADDIPTC ("Iptc.Application2.City", EXTRACTOR_METATYPE_LOCATION_CITY);
236 ADDIPTC ("Iptc.Application2.SubLocation", EXTRACTOR_METATYPE_LOCATION_SUBLOCATION); 774 ADDIPTC ("Iptc.Application2.SubLocation", EXTRACTOR_METATYPE_LOCATION_SUBLOCATION);
237 ADDIPTC ("Iptc.Application2.CountryName", EXTRACTOR_METATYPE_LOCATION_COUNTRY); 775 ADDIPTC ("Iptc.Application2.CountryName", EXTRACTOR_METATYPE_LOCATION_COUNTRY);
238 ADDIPTC ("Xmp.photoshop.Country", EXTRACTOR_METATYPE_RATING); 776 ADDIPTC ("Xmp.photoshop.Country", EXTRACTOR_METATYPE_RATING);
239 } 777 }
240 778
241 Exiv2::XmpData &xmpData = image->xmpData(); 779 Exiv2::XmpData &xmpData = image->xmpData();
242 if (! xmpData.empty()) { 780 if (! xmpData.empty())
781 {
243 ADDXMP ("Xmp.photoshop.City", EXTRACTOR_METATYPE_LOCATION_CITY); 782 ADDXMP ("Xmp.photoshop.City", EXTRACTOR_METATYPE_LOCATION_CITY);
244 ADDXMP ("Xmp.xmp.Rating", EXTRACTOR_METATYPE_RATING); 783 ADDXMP ("Xmp.xmp.Rating", EXTRACTOR_METATYPE_RATING);
245 ADDXMP ("Xmp.MicrosoftPhoto.Rating", EXTRACTOR_METATYPE_RATING); 784 ADDXMP ("Xmp.MicrosoftPhoto.Rating", EXTRACTOR_METATYPE_RATING);
@@ -248,14 +787,12 @@ extern "C" {
248 ADDXMP ("Xmp.lr.hierarchicalSubject", EXTRACTOR_METATYPE_SUBJECT); 787 ADDXMP ("Xmp.lr.hierarchicalSubject", EXTRACTOR_METATYPE_SUBJECT);
249 } 788 }
250 } 789 }
251 catch (const Exiv2::AnyError& e) { 790 catch (const Exiv2::AnyError& e)
791 {
252#ifndef SUPPRESS_WARNINGS 792#ifndef SUPPRESS_WARNINGS
253 std::cout << "Caught Exiv2 exception '" << e << "'\n"; 793 std::cout << "Caught Exiv2 exception '" << e << "'\n";
254#endif 794#endif
255 } 795 }
256
257 return 0;
258 }
259
260
261} 796}
797
798/* end of exiv2_extractor.cc */