• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* exif.hxx
2  *
3  * Copyright  2002,2003 Hans Meine <hans_meine@gmx.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301  USA.
19  */
20 
21 #ifndef EXIF_HXX
22 #define EXIF_HXX
23 
24 #include <libexif/exif-entry.h>
25 #include <libexif/exif-content.h>
26 #include <libexif/exif-ifd.h>
27 #include <libexif/exif-data.h>
28 #include <libexif/exif-format.h>
29 #include <libexif/exif-utils.h>
30 #include <stdexcept>
31 #include <string>
32 
33 namespace Exif {
34 
35 #ifndef EXIF_NO_EXCEPTIONS
36 struct InvalidIndex : std::runtime_error
37 {
InvalidIndexExif::InvalidIndex38     InvalidIndex(const std::string& s)
39     : std::runtime_error(s) {}
40 };
41 
42 struct InvalidFormat : std::runtime_error
43 {
InvalidFormatExif::InvalidFormat44     InvalidFormat(const std::string& s)
45     : std::runtime_error(s) {}
46 };
47 
48 struct IOError : std::runtime_error
49 {
IOErrorExif::IOError50     IOError(const std::string& s)
51     : std::runtime_error(s) {}
52 };
53 #endif // EXIF_NO_EXCEPTIONS
54 
55 struct Entry
56 {
57     ExifEntry *entry_;
58 
59         // construct an empty entry, FIXME: is this needed in the public API?
EntryExif::Entry60     Entry()
61     : entry_(exif_entry_new())
62     {}
63 
64         // construct an entry for the given tag
EntryExif::Entry65     Entry(ExifTag tag)
66     : entry_(exif_entry_new())
67     {
68         exif_entry_initialize(entry_, tag);
69     }
70 
71         // copy constructor
EntryExif::Entry72     Entry(Entry const &other)
73     : entry_(other.entry_)
74     {
75         exif_entry_ref(entry_);
76     }
77 
78         // internal, do not use directly
EntryExif::Entry79     Entry(ExifEntry *entry)
80     : entry_(entry)
81     {
82         exif_entry_ref(entry_);
83     }
84 
~EntryExif::Entry85     ~Entry()
86     {
87         exif_entry_unref(entry_);
88     }
89 
operator =Exif::Entry90     Entry &operator=(Entry const &other)
91     {
92         exif_entry_unref(entry_);
93         entry_ = other.entry_;
94         exif_entry_ref(entry_);
95         return *this;
96     }
97 
tagExif::Entry98     ExifTag tag() const
99     {
100         return entry_->tag;
101     }
102 
103 /*
104     void setTag(ExifTag tag)
105     {
106         entry_->tag = tag;
107     }
108 */
109 
formatExif::Entry110     ExifFormat format() const
111     {
112         return entry_->format;
113     }
114 
115 /*
116     void setFormat(ExifFormat format)
117     {
118         entry_->format = format;
119     }
120 */
121 
componentsExif::Entry122     unsigned long components() const
123     {
124         return entry_->components;
125     }
126 
127 /*
128     void setComponents(unsigned long components)
129     {
130         entry_->components = components;
131     }
132 
133     void initialize(ExifTag tag)
134     {
135         exif_entry_initialize(entry_, tag);
136     }
137 */
138 
getByteExif::Entry139     ExifByte getByte(unsigned int index) const
140     {
141 #ifndef EXIF_NO_EXCEPTIONS
142         if(entry_->format != EXIF_FORMAT_BYTE)
143             throw InvalidFormat(
144                 "Exif::Entry::getByte(): Format is not EXIF_FORMAT_BYTE");
145         if(index >= components())
146             throw InvalidIndex(
147                 "Exif::getByte: component index out of range");
148 #endif
149         return *(entry_->data
150                  + index * exif_format_get_size(entry_->format));
151     }
152 
getAsciiExif::Entry153     const ExifAscii getAscii() const
154     {
155 #ifndef EXIF_NO_EXCEPTIONS
156         if(entry_->format != EXIF_FORMAT_ASCII)
157             throw InvalidFormat(
158                 "Exif::Entry::getAscii(): Format is not EXIF_FORMAT_ASCII");
159 #endif
160         return (ExifAscii)entry_->data;
161     }
162 
getShortExif::Entry163     ExifShort getShort(unsigned int index) const
164     {
165 #ifndef EXIF_NO_EXCEPTIONS
166         if(entry_->format != EXIF_FORMAT_SHORT)
167             throw InvalidFormat(
168                 "Exif::Entry::getShort(): Format is not EXIF_FORMAT_SHORT");
169         if(index >= components())
170             throw InvalidIndex(
171                 "Exif::getShort: component index out of range");
172 #endif
173         return exif_get_short(entry_->data
174                               + index * exif_format_get_size(entry_->format),
175                               exif_data_get_byte_order(entry_->parent->parent));
176     }
177 
getLongExif::Entry178     ExifLong getLong(unsigned int index) const
179     {
180 #ifndef EXIF_NO_EXCEPTIONS
181         if(entry_->format != EXIF_FORMAT_LONG)
182             throw InvalidFormat(
183                 "Exif::Entry::getLong(): Format is not EXIF_FORMAT_LONG");
184         if(index >= components())
185             throw InvalidIndex(
186                 "Exif::getLong: component index out of range");
187 #endif
188         return exif_get_long(entry_->data
189                              + index * exif_format_get_size(entry_->format),
190                              exif_data_get_byte_order(entry_->parent->parent));
191     }
192 
getSLongExif::Entry193     ExifSLong getSLong(unsigned int index) const
194     {
195 #ifndef EXIF_NO_EXCEPTIONS
196         if(entry_->format != EXIF_FORMAT_SLONG)
197             throw InvalidFormat(
198                 "Exif::Entry::getSLong(): Format is not EXIF_FORMAT_SLONG");
199         if(index >= components())
200             throw InvalidIndex(
201                 "Exif::getSLong: component index out of range");
202 #endif
203         return exif_get_slong(entry_->data
204                               + index * exif_format_get_size(entry_->format),
205                               exif_data_get_byte_order(entry_->parent->parent));
206     }
207 
getRationalExif::Entry208     ExifRational getRational(unsigned int index) const
209     {
210 #ifndef EXIF_NO_EXCEPTIONS
211         if(entry_->format != EXIF_FORMAT_RATIONAL)
212             throw InvalidFormat(
213                 "Exif::Entry::getRational(): Format is not EXIF_FORMAT_RATIONAL");
214         if(index >= components())
215             throw InvalidIndex(
216                 "Exif::getRational: component index out of range");
217 #endif
218         return exif_get_rational(entry_->data
219                                  + index * exif_format_get_size(entry_->format),
220                                  exif_data_get_byte_order(entry_->parent->parent));
221     }
222 
getSRationalExif::Entry223     ExifSRational getSRational(unsigned int index) const
224     {
225 #ifndef EXIF_NO_EXCEPTIONS
226         if(entry_->format != EXIF_FORMAT_SRATIONAL)
227             throw InvalidFormat(
228                 "Exif::Entry::getSRational(): Format is not EXIF_FORMAT_SRATIONAL");
229         if(index >= components())
230             throw InvalidIndex(
231                 "Exif::getSRational: component index out of range");
232 #endif
233         return exif_get_srational(entry_->data
234                                   + index * exif_format_get_size(entry_->format),
235                                   exif_data_get_byte_order(entry_->parent->parent));
236     }
237 
setByteExif::Entry238     void setByte(unsigned int index, ExifByte value) const
239     {
240 #ifndef EXIF_NO_EXCEPTIONS
241         if(entry_->format != EXIF_FORMAT_BYTE)
242             throw InvalidFormat(
243                 "Exif::Entry::setByte(): Format is not EXIF_FORMAT_BYTE");
244         if(index >= components())
245             throw InvalidIndex(
246                 "Exif::setByte: component index out of range");
247 #endif
248         *(entry_->data
249           + index * exif_format_get_size(entry_->format)) = value;
250     }
251 
252 /*
253     const ExifAscii setAscii() const
254     {
255 #ifndef EXIF_NO_EXCEPTIONS
256         if(entry_->format != EXIF_FORMAT_ASCII)
257             throw InvalidFormat(
258                 "Exif::Entry::setAscii(): Format is not EXIF_FORMAT_ASCII");
259 #endif
260         return (ExifAscii)entry_->data;
261     }
262 */
263 
setShortExif::Entry264     void setShort(unsigned int index, ExifShort value) const
265     {
266 #ifndef EXIF_NO_EXCEPTIONS
267         if(entry_->format != EXIF_FORMAT_SHORT)
268             throw InvalidFormat(
269                 "Exif::Entry::setShort(): Format is not EXIF_FORMAT_SHORT");
270         if(index >= components())
271             throw InvalidIndex(
272                 "Exif::setShort: component index out of range");
273 #endif
274         return exif_set_short(entry_->data
275                               + index * exif_format_get_size(entry_->format),
276                               exif_data_get_byte_order(entry_->parent->parent),
277                               value);
278     }
279 
setLongExif::Entry280     void setLong(unsigned int index, ExifLong value) const
281     {
282 #ifndef EXIF_NO_EXCEPTIONS
283         if(entry_->format != EXIF_FORMAT_LONG)
284             throw InvalidFormat(
285                 "Exif::Entry::setLong(): Format is not EXIF_FORMAT_LONG");
286         if(index >= components())
287             throw InvalidIndex(
288                 "Exif::setLong: component index out of range");
289 #endif
290         return exif_set_long(entry_->data
291                              + index * exif_format_get_size(entry_->format),
292                              exif_data_get_byte_order(entry_->parent->parent),
293                              value);
294     }
295 
setSLongExif::Entry296     void setSLong(unsigned int index, ExifSLong value) const
297     {
298 #ifndef EXIF_NO_EXCEPTIONS
299         if(entry_->format != EXIF_FORMAT_SLONG)
300             throw InvalidFormat(
301                 "Exif::Entry::setSLong(): Format is not EXIF_FORMAT_SLONG");
302         if(index >= components())
303             throw InvalidIndex(
304                 "Exif::setSLong: component index out of range");
305 #endif
306         return exif_set_slong(entry_->data
307                               + index * exif_format_get_size(entry_->format),
308                               exif_data_get_byte_order(entry_->parent->parent),
309                               value);
310     }
311 
setRationalExif::Entry312     void setRational(unsigned int index, ExifRational value) const
313     {
314 #ifndef EXIF_NO_EXCEPTIONS
315         if(entry_->format != EXIF_FORMAT_RATIONAL)
316             throw InvalidFormat(
317                 "Exif::Entry::setRational(): Format is not EXIF_FORMAT_RATIONAL");
318         if(index >= components())
319             throw InvalidIndex(
320                 "Exif::setRational: component index out of range");
321 #endif
322         return exif_set_rational(entry_->data
323                                  + index * exif_format_get_size(entry_->format),
324                                  exif_data_get_byte_order(entry_->parent->parent),
325                                  value);
326     }
327 
setSRationalExif::Entry328     void setSRational(unsigned int index, ExifSRational value) const
329     {
330 #ifndef EXIF_NO_EXCEPTIONS
331         if(entry_->format != EXIF_FORMAT_SRATIONAL)
332             throw InvalidFormat(
333                 "Exif::Entry::setSRational(): Format is not EXIF_FORMAT_SRATIONAL");
334         if(index >= components())
335             throw InvalidIndex(
336                 "Exif::setSRational: component index out of range");
337 #endif
338         return exif_set_srational(entry_->data
339                                   + index * exif_format_get_size(entry_->format),
340                                   exif_data_get_byte_order(entry_->parent->parent),
341                                   value);
342     }
343 
valueExif::Entry344     const char *value()
345     {
346         return exif_entry_get_value(entry_);
347     }
348 
briefValueExif::Entry349     const char *briefValue()
350     {
351         return exif_entry_get_value_brief(entry_);
352     }
353 
dumpExif::Entry354     void dump(unsigned int indent = 0) const
355     {
356         exif_entry_dump(entry_, indent);
357     }
358 };
359 
360 struct Content
361 {
362     ExifContent *content_;
363 
ContentExif::Content364     Content()
365     : content_(exif_content_new())
366     {}
367 
ContentExif::Content368     Content(Content const &other)
369     : content_(other.content_)
370     {
371         exif_content_ref(content_);
372     }
373 
374         // internal, do not use directly
ContentExif::Content375     Content(ExifContent *content)
376     : content_(content)
377     {
378         exif_content_ref(content_);
379     }
380 
~ContentExif::Content381     ~Content()
382     {
383         exif_content_unref(content_);
384     }
385 
operator =Exif::Content386     Content &operator=(Content const &other)
387     {
388         exif_content_unref(content_);
389         content_ = other.content_;
390         exif_content_ref(content_);
391         return *this;
392     }
393 
operator []Exif::Content394     Entry operator[](ExifTag tag)
395     {
396         ExifEntry *result = exif_content_get_entry(content_, tag);
397         if(result)
398             return Entry(result);
399 #ifndef EXIF_NO_EXCEPTIONS
400         throw InvalidIndex(
401             "Exif::Content: IFD does not contain given tag");
402 #endif
403         return Entry();
404     }
405 
operator []Exif::Content406     Entry operator[](unsigned int index)
407     {
408         if(index < size())
409             return Entry(content_->entries[index]);
410 #ifndef EXIF_NO_EXCEPTIONS
411         throw InvalidIndex(
412             "Exif::Content: numeric entry index out of range");
413 #endif // EXIF_NO_EXCEPTIONS
414         return Entry();
415     }
416 
sizeExif::Content417     unsigned int size() const
418     {
419         // FIXME: content_ should never be NULL, so this is unneeded!?
420         return content_ ? content_->count : 0;
421     }
422 
addExif::Content423     void add(Entry &entry)
424     {
425         exif_content_add_entry(content_, entry.entry_);
426     }
427 
removeExif::Content428     void remove(Entry &entry)
429     {
430         exif_content_remove_entry(content_, entry.entry_);
431     }
432 
433         // for your convenience
valueExif::Content434     const char *value(ExifTag tag)
435     {
436         return exif_content_get_value(content_, tag);
437     }
438 
439         // for your convenience
briefValueExif::Content440     const char *briefValue(ExifTag tag)
441     {
442         return exif_content_get_value_brief(content_, tag);
443     }
444 
dumpExif::Content445     void dump(unsigned int indent = 0) const
446     {
447         exif_content_dump(content_, indent);
448     }
449 };
450 
451 struct Data
452 {
453     ExifData *data_;
454 
DataExif::Data455     Data()
456     : data_(exif_data_new())
457     {}
458 
DataExif::Data459     Data(const char *path, bool *success = 0)
460     : data_(exif_data_new_from_file(path))
461     {
462         if(success)
463             *success = data_;
464 #ifndef EXIF_NO_EXCEPTIONS
465         else
466             if(!data_)
467                 throw IOError("Exif::Data: Could not load file");
468 #endif // EXIF_NO_EXCEPTIONS
469         if(!data_)
470             exif_data_new();
471     }
472 
DataExif::Data473     Data(const unsigned char *data,
474          unsigned int size)
475     : data_(exif_data_new_from_data(data, size))
476     {}
477 
DataExif::Data478     Data(Data const &other)
479     : data_(other.data_)
480     {
481         exif_data_ref(data_);
482     }
483 
~DataExif::Data484     ~Data()
485     {
486         exif_data_unref(data_);
487     }
488 
operator =Exif::Data489     Data &operator=(Data const &other)
490     {
491         exif_data_unref(data_);
492         data_ = other.data_;
493         exif_data_ref(data_);
494         return *this;
495     }
496 
saveExif::Data497     void save(unsigned char **d, unsigned int *size)
498     {
499         exif_data_save_data(data_, d, size);
500     }
501 
sizeExif::Data502     unsigned int size() const
503     {
504         return EXIF_IFD_COUNT;
505     }
506 
operator []Exif::Data507     Content operator[](unsigned int index)
508     {
509         if(index < size())
510             return Content(data_->ifd[index]);
511 #ifndef EXIF_NO_EXCEPTIONS
512         throw InvalidIndex(
513             "Exif::Data: IFD index out of range");
514 #endif // EXIF_NO_EXCEPTIONS
515         return Content();
516     }
517 
byteOrderExif::Data518     ExifByteOrder byteOrder() const
519     {
520         return exif_data_get_byte_order(data_);
521     }
522 
setByteOrderExif::Data523     void setByteOrder(ExifByteOrder bo) const
524     {
525         exif_data_set_byte_order(data_, bo);
526     }
527 
dumpExif::Data528     void dump()
529     {
530         exif_data_dump(data_);
531     }
532 };
533 
534 } // namespace Exif
535 
536 #endif // EXIF_HXX
537