read also iptc and xmp
[geeqie.git] / src / exiv2.cc
1
2 #ifdef HAVE_CONFIG_H
3 #  include "config.h"
4 #endif
5
6 #ifdef HAVE_EXIV2
7
8 #include <exiv2/image.hpp>
9 #include <exiv2/exif.hpp>
10 #include <iostream>
11
12 extern "C" {
13
14 #include <glib.h> 
15 #include "exif.h"
16
17 }
18
19 struct _ExifData
20 {
21         Exiv2::ExifData exifData;
22         Exiv2::ExifData::const_iterator exifIter; /* for exif_get_next_item */
23         Exiv2::IptcData iptcData;
24         Exiv2::IptcData::const_iterator iptcIter; /* for exif_get_next_item */
25         Exiv2::XmpData xmpData;
26         Exiv2::XmpData::const_iterator xmpIter; /* for exif_get_next_item */
27
28         _ExifData(gchar *path, gint parse_color_profile)
29         {
30                 Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
31                 g_assert (image.get() != 0);
32                 image->readMetadata();
33                 exifData = image->exifData();
34                 iptcData = image->iptcData();
35                 xmpData = image->xmpData();
36         }
37
38 };
39
40 extern "C" {
41
42 ExifData *exif_read(gchar *path, gint parse_color_profile)
43 {
44         printf("exif %s\n", path);
45         try {
46                 return new ExifData(path, parse_color_profile);
47         }
48         catch (Exiv2::AnyError& e) {
49                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
50                 return 0;
51         }
52         
53 }
54
55 void exif_free(ExifData *exif)
56 {
57         
58         delete exif;
59 }
60
61 ExifItem *exif_get_item(ExifData *exif, const gchar *key)
62 {
63         try {
64                 Exiv2::Metadatum *item;
65                 try {
66                         Exiv2::ExifKey ekey(key);
67                         Exiv2::ExifData::iterator pos = exif->exifData.findKey(ekey);
68                         if (pos == exif->exifData.end()) return NULL;
69                         item = &*pos;
70                 }
71                 catch (Exiv2::AnyError& e) {
72                         try {
73                                 Exiv2::IptcKey ekey(key);
74                                 Exiv2::IptcData::iterator pos = exif->iptcData.findKey(ekey);
75                                 if (pos == exif->iptcData.end()) return NULL;
76                                 item = &*pos;
77                         }
78                         catch (Exiv2::AnyError& e) {
79                                 Exiv2::XmpKey ekey(key);
80                                 Exiv2::XmpData::iterator pos = exif->xmpData.findKey(ekey);
81                                 if (pos == exif->xmpData.end()) return NULL;
82                                 item = &*pos;
83                         }
84                 }
85                 return (ExifItem *)item;
86         }
87         catch (Exiv2::AnyError& e) {
88                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
89                 return NULL;
90         }
91 }
92
93
94 ExifItem *exif_get_first_item(ExifData *exif)
95 {
96         try {
97                 exif->exifIter = exif->exifData.begin();
98                 exif->iptcIter = exif->iptcData.begin();
99                 exif->xmpIter = exif->xmpData.begin();
100                 if (exif->exifIter != exif->exifData.end()) 
101                         {
102                         const Exiv2::Metadatum *item = &*exif->exifIter;
103                         exif->exifIter++;
104                         return (ExifItem *)item;
105                         }
106                 if (exif->iptcIter != exif->iptcData.end()) 
107                         {
108                         const Exiv2::Metadatum *item = &*exif->iptcIter;
109                         exif->iptcIter++;
110                         return (ExifItem *)item;
111                         }
112                 if (exif->xmpIter != exif->xmpData.end()) 
113                         {
114                         const Exiv2::Metadatum *item = &*exif->xmpIter;
115                         exif->xmpIter++;
116                         return (ExifItem *)item;
117                         }
118                 return NULL;
119                         
120         }
121         catch (Exiv2::AnyError& e) {
122                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
123                 return NULL;
124         }
125 }
126
127 ExifItem *exif_get_next_item(ExifData *exif)
128 {
129         try {
130                 if (exif->exifIter != exif->exifData.end())
131                         {
132                         const Exiv2::Metadatum *item = &*exif->exifIter;
133                         exif->exifIter++;
134                         return (ExifItem *)item;
135                 }
136                 if (exif->iptcIter != exif->iptcData.end())
137                         {
138                         const Exiv2::Metadatum *item = &*exif->iptcIter;
139                         exif->iptcIter++;
140                         return (ExifItem *)item;
141                 }
142                 if (exif->xmpIter != exif->xmpData.end())
143                         {
144                         const Exiv2::Metadatum *item = &*exif->xmpIter;
145                         exif->xmpIter++;
146                         return (ExifItem *)item;
147                 }
148                 return NULL;
149         }
150         catch (Exiv2::AnyError& e) {
151                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
152                 return NULL;
153         }
154 }
155
156 char *exif_item_get_tag_name(ExifItem *item)
157 {
158         try {
159                 if (!item) return NULL;
160                 return g_strdup(((Exiv2::Metadatum *)item)->key().c_str());
161         }
162         catch (Exiv2::AnyError& e) {
163                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
164                 return NULL;
165         }
166 }
167
168 guint exif_item_get_tag_id(ExifItem *item)
169 {
170         try {
171                 if (!item) return 0;
172                 return ((Exiv2::Metadatum *)item)->tag();
173         }
174         catch (Exiv2::AnyError& e) {
175                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
176                 return 0;
177         }
178 }
179
180 guint exif_item_get_elements(ExifItem *item)
181 {
182         try {
183                 if (!item) return 0;
184                 return ((Exiv2::Metadatum *)item)->count();
185         }
186         catch (Exiv2::AnyError& e) {
187                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
188                 return 0;
189         }
190 }
191
192 char *exif_item_get_data(ExifItem *item, guint *data_len)
193 {
194 }
195
196 char *exif_item_get_description(ExifItem *item)
197 {
198         try {
199                 if (!item) return NULL;
200                 return g_strdup(((Exiv2::Metadatum *)item)->tagLabel().c_str());
201         }
202         catch (std::exception& e) {
203 //              std::cout << "Caught Exiv2 exception '" << e << "'\n";
204                 return NULL;
205         }
206 }
207
208 /*
209 invalidTypeId, unsignedByte, asciiString, unsignedShort,
210   unsignedLong, unsignedRational, signedByte, undefined,
211   signedShort, signedLong, signedRational, string,
212   date, time, comment, directory,
213   xmpText, xmpAlt, xmpBag, xmpSeq,
214   langAlt, lastTypeId 
215 */
216
217 static guint format_id_trans_tbl [] = {
218         EXIF_FORMAT_UNKNOWN,
219         EXIF_FORMAT_BYTE_UNSIGNED,
220         EXIF_FORMAT_STRING,
221         EXIF_FORMAT_SHORT_UNSIGNED,
222         EXIF_FORMAT_LONG_UNSIGNED,
223         EXIF_FORMAT_RATIONAL_UNSIGNED,
224         EXIF_FORMAT_BYTE,
225         EXIF_FORMAT_UNDEFINED,
226         EXIF_FORMAT_SHORT,
227         EXIF_FORMAT_LONG,
228         EXIF_FORMAT_RATIONAL,
229         EXIF_FORMAT_STRING,
230         EXIF_FORMAT_STRING,
231         EXIF_FORMAT_STRING,
232         EXIF_FORMAT_UNDEFINED,
233         EXIF_FORMAT_STRING,
234         EXIF_FORMAT_STRING,
235         EXIF_FORMAT_STRING,
236         EXIF_FORMAT_STRING
237         };
238         
239         
240
241 guint exif_item_get_format_id(ExifItem *item)
242 {
243         try {
244                 if (!item) return EXIF_FORMAT_UNKNOWN;
245                 guint id = ((Exiv2::Metadatum *)item)->typeId();
246                 if (id >= (sizeof(format_id_trans_tbl) / sizeof(format_id_trans_tbl[0])) ) return EXIF_FORMAT_UNKNOWN;
247                 return format_id_trans_tbl[id];
248         }
249         catch (Exiv2::AnyError& e) {
250                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
251                 return EXIF_FORMAT_UNKNOWN;
252         }
253 }
254
255 const char *exif_item_get_format_name(ExifItem *item, gint brief)
256 {
257         try {
258                 if (!item) return NULL;
259                 return ((Exiv2::Metadatum *)item)->typeName();
260         }
261         catch (Exiv2::AnyError& e) {
262                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
263                 return NULL;
264         }
265 }
266
267
268 gchar *exif_item_get_data_as_text(ExifItem *item)
269 {
270         try {
271                 if (!item) return NULL;
272 //              std::stringstream str;  // does not work with Exiv2::Metadatum because operator<< is not virtual
273 //              str << *((Exiv2::Metadatum *)item);
274 //              return g_strdup(str.str().c_str());
275                 return g_strdup(((Exiv2::Metadatum *)item)->toString().c_str());
276         }
277         catch (Exiv2::AnyError& e) {
278                 return NULL;
279         }
280 }
281
282
283 gint exif_item_get_integer(ExifItem *item, gint *value)
284 {
285         try {
286                 if (!item) return 0;
287                 return ((Exiv2::Metadatum *)item)->toLong();
288         }
289         catch (Exiv2::AnyError& e) {
290                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
291                 return 0;
292         }
293 }
294
295 ExifRational *exif_item_get_rational(ExifItem *item, gint *sign)
296 {
297         try {
298                 if (!item) return NULL;
299                 Exiv2::Rational v = ((Exiv2::Metadatum *)item)->toRational();
300                 static ExifRational ret;
301                 ret.num = v.first;
302                 ret.den = v.second;
303                 return &ret;
304         }
305         catch (Exiv2::AnyError& e) {
306                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
307                 return NULL;
308         }
309 }
310
311 const gchar *exif_get_tag_description_by_key(const gchar *key)
312 {
313         try {
314                 Exiv2::ExifKey ekey(key);
315                 return Exiv2::ExifTags::tagLabel(ekey.tag(), ekey.ifdId ());
316         }
317         catch (Exiv2::AnyError& e) {
318                 std::cout << "Caught Exiv2 exception '" << e << "'\n";
319                 return NULL;
320         }
321 }
322
323 gint format_raw_img_exif_offsets_fd(int fd, const gchar *path,
324                                     unsigned char *header_data, const guint header_len,
325                                     guint *image_offset, guint *exif_offset)
326 {
327         return 0;
328 }
329
330 }
331
332 #endif 
333 /* HAVE_EXIV2 */