summaryrefslogtreecommitdiff
path: root/src/libexif
diff options
context:
space:
mode:
authorscuri <scuri>2008-10-17 06:10:15 +0000
committerscuri <scuri>2008-10-17 06:10:15 +0000
commit5a422aba704c375a307a902bafe658342e209906 (patch)
tree5005011e086bb863d8fb587ad3319bbec59b2447 /src/libexif
First commit - moving from LuaForge to SourceForge
Diffstat (limited to 'src/libexif')
-rw-r--r--src/libexif/_stdint.h19
-rw-r--r--src/libexif/canon/exif-mnote-data-canon.c281
-rw-r--r--src/libexif/canon/exif-mnote-data-canon.h45
-rw-r--r--src/libexif/canon/mnote-canon-entry.c590
-rw-r--r--src/libexif/canon/mnote-canon-entry.h43
-rw-r--r--src/libexif/canon/mnote-canon-tag.c75
-rw-r--r--src/libexif/canon/mnote-canon-tag.h52
-rw-r--r--src/libexif/config.h12
-rw-r--r--src/libexif/exif-byte-order.c39
-rw-r--r--src/libexif/exif-byte-order.h39
-rw-r--r--src/libexif/exif-content.c209
-rw-r--r--src/libexif/exif-content.h76
-rw-r--r--src/libexif/exif-data.c1039
-rw-r--r--src/libexif/exif-data.h104
-rw-r--r--src/libexif/exif-entry.c1383
-rw-r--r--src/libexif/exif-entry.h69
-rw-r--r--src/libexif/exif-format.c72
-rw-r--r--src/libexif/exif-format.h50
-rw-r--r--src/libexif/exif-ifd.c49
-rw-r--r--src/libexif/exif-ifd.h35
-rw-r--r--src/libexif/exif-loader.c349
-rw-r--r--src/libexif/exif-loader.h57
-rw-r--r--src/libexif/exif-log.c148
-rw-r--r--src/libexif/exif-log.h75
-rw-r--r--src/libexif/exif-mem.c95
-rw-r--r--src/libexif/exif-mem.h54
-rw-r--r--src/libexif/exif-mnote-data-priv.h76
-rw-r--r--src/libexif/exif-mnote-data.c158
-rw-r--r--src/libexif/exif-mnote-data.h54
-rw-r--r--src/libexif/exif-tag.c686
-rw-r--r--src/libexif/exif-tag.h148
-rw-r--r--src/libexif/exif-utils.c214
-rw-r--r--src/libexif/exif-utils.h81
-rw-r--r--src/libexif/exif.c1274
-rw-r--r--src/libexif/exif.h86
-rw-r--r--src/libexif/i18n.h51
-rw-r--r--src/libexif/olympus/exif-mnote-data-olympus.c403
-rw-r--r--src/libexif/olympus/exif-mnote-data-olympus.h45
-rw-r--r--src/libexif/olympus/mnote-olympus-entry.c540
-rw-r--r--src/libexif/olympus/mnote-olympus-entry.h43
-rw-r--r--src/libexif/olympus/mnote-olympus-tag.c155
-rw-r--r--src/libexif/olympus/mnote-olympus-tag.h130
-rw-r--r--src/libexif/pentax/exif-mnote-data-pentax.c209
-rw-r--r--src/libexif/pentax/exif-mnote-data-pentax.h44
-rw-r--r--src/libexif/pentax/mnote-pentax-entry.c210
-rw-r--r--src/libexif/pentax/mnote-pentax-entry.h43
-rw-r--r--src/libexif/pentax/mnote-pentax-tag.c94
-rw-r--r--src/libexif/pentax/mnote-pentax-tag.h74
48 files changed, 9877 insertions, 0 deletions
diff --git a/src/libexif/_stdint.h b/src/libexif/_stdint.h
new file mode 100644
index 0000000..401189b
--- /dev/null
+++ b/src/libexif/_stdint.h
@@ -0,0 +1,19 @@
+
+#ifndef __STDINT_H
+#define __STDINT_H
+
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef signed char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+#endif
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+#ifndef __uint32_t_defined
+#define __uint32_t_defined
+typedef unsigned int uint32_t;
+#endif
+
+#endif
diff --git a/src/libexif/canon/exif-mnote-data-canon.c b/src/libexif/canon/exif-mnote-data-canon.c
new file mode 100644
index 0000000..b1c5dab
--- /dev/null
+++ b/src/libexif/canon/exif-mnote-data-canon.c
@@ -0,0 +1,281 @@
+/* exif-mnote-data-canon.c
+ *
+ * Copyright © 2002, 2003 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright © 2003 Matthieu Castet <mat-c@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "exif-mnote-data-canon.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-utils.h>
+#include <libexif/exif-data.h>
+
+#define DEBUG
+
+static void
+exif_mnote_data_canon_clear (ExifMnoteDataCanon *n)
+{
+ ExifMnoteData *d = (ExifMnoteData *) n;
+ unsigned int i;
+
+ if (!n) return;
+
+ if (n->entries) {
+ for (i = 0; i < n->count; i++)
+ if (n->entries[i].data) {
+ exif_mem_free (d->mem, n->entries[i].data);
+ n->entries[i].data = NULL;
+ }
+ exif_mem_free (d->mem, n->entries);
+ n->entries = NULL;
+ n->count = 0;
+ }
+}
+
+static void
+exif_mnote_data_canon_free (ExifMnoteData *n)
+{
+ if (!n) return;
+
+ exif_mnote_data_canon_clear ((ExifMnoteDataCanon *) n);
+}
+
+static char *
+exif_mnote_data_canon_get_value (ExifMnoteData *note, unsigned int n, char *val, unsigned int maxlen)
+{
+ ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note;
+
+ if (!note) return NULL;
+ if (cnote->count <= n) return NULL;
+ return mnote_canon_entry_get_value (&cnote->entries[n], val, maxlen);
+}
+
+static void
+exif_mnote_data_canon_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
+{
+ ExifByteOrder o_orig;
+ ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) d;
+ unsigned int i;
+
+ if (!n) return;
+
+ o_orig = n->order;
+ n->order = o;
+ for (i = 0; i < n->count; i++) {
+ n->entries[i].order = o;
+ exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
+ n->entries[i].components, o_orig, o);
+ }
+}
+
+static void
+exif_mnote_data_canon_set_offset (ExifMnoteData *n, unsigned int o)
+{
+ if (n) ((ExifMnoteDataCanon *) n)->offset = o;
+}
+
+static void
+exif_mnote_data_canon_save (ExifMnoteData *ne,
+ unsigned char **buf, unsigned int *buf_size)
+{
+ ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
+ unsigned int i, o, s, doff;
+
+ if (!n || !buf || !buf_size) return;
+
+ /*
+ * Allocate enough memory for all entries and the number
+ * of entries.
+ */
+ *buf_size = 2 + n->count * 12 + 4;
+ *buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size);
+ if (!*buf) return;
+
+ /* Save the number of entries */
+ exif_set_short (*buf, n->order, (ExifShort) n->count);
+
+ /* Save each entry */
+ for (i = 0; i < n->count; i++) {
+ o = 2 + i * 12;
+ exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
+ exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
+ exif_set_long (*buf + o + 4, n->order,
+ n->entries[i].components);
+ o += 8;
+ s = exif_format_get_size (n->entries[i].format) *
+ n->entries[i].components;
+ if (s > 4) {
+ *buf_size += s;
+
+ /* Ensure even offsets. Set padding bytes to 0. */
+ if (s & 1) *buf_size += 1;
+ *buf = exif_mem_realloc (ne->mem, *buf,
+ sizeof (char) * *buf_size);
+ if (!*buf) return;
+ doff = *buf_size - s;
+ if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
+ exif_set_long (*buf + o, n->order, n->offset + doff);
+ } else
+ doff = o;
+
+ /*
+ * Write the data. Fill unneeded bytes with 0. Do not
+ * crash if data is NULL.
+ */
+ if (!n->entries[i].data) memset (*buf + doff, 0, s);
+ else memcpy (*buf + doff, n->entries[i].data, s);
+ if (s < 4) memset (*buf + doff + s, 0, (4 - s));
+ }
+}
+
+/* XXX
+ * FIXME: exif_mnote_data_canon_load() may fail and there is no
+ * semantics to express that.
+ * See bug #1054323 for details, especially the comment by liblit
+ * after it has supposedly been fixed:
+ *
+ * https://sourceforge.net/tracker/?func=detail&aid=1054323&group_id=12272&atid=112272
+ * Unfortunately, the "return" statements aren't commented at
+ * all, so it isn't trivial to find out what is a normal
+ * return, and what is a reaction to an error condition.
+ */
+
+static void
+exif_mnote_data_canon_load (ExifMnoteData *ne,
+ const unsigned char *buf, unsigned int buf_size)
+{
+ ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
+ ExifShort c;
+ unsigned int i, o, s;
+
+ if (!n || !buf || !buf_size || (buf_size < 6 + n->offset + 2)) return;
+
+ /* Read the number of entries and remove old ones. */
+ c = exif_get_short (buf + 6 + n->offset, n->order);
+ exif_mnote_data_canon_clear (n);
+
+ /* Parse the entries */
+ for (i = 0; i < c; i++) {
+ o = 6 + 2 + n->offset + 12 * i;
+ if (o + 8 > buf_size) return;
+
+ n->count = i + 1;
+ n->entries = exif_mem_realloc (ne->mem, n->entries,
+ sizeof (MnoteCanonEntry) * (i+1));
+ memset (&n->entries[i], 0, sizeof (MnoteCanonEntry));
+ n->entries[i].tag = exif_get_short (buf + o, n->order);
+ n->entries[i].format = exif_get_short (buf + o + 2, n->order);
+ n->entries[i].components = exif_get_long (buf + o + 4, n->order);
+ n->entries[i].order = n->order;
+
+ /*
+ * Size? If bigger than 4 bytes, the actual data is not
+ * in the entry but somewhere else (offset).
+ */
+ s = exif_format_get_size (n->entries[i].format) *
+ n->entries[i].components;
+ if (!s) return;
+ o += 8;
+ if (s > 4) o = exif_get_long (buf + o, n->order) + 6;
+ if (o + s > buf_size) return;
+
+ /* Sanity check */
+ n->entries[i].data = exif_mem_alloc (ne->mem, sizeof (char) * s);
+ if (!n->entries[i].data) return;
+ n->entries[i].size = s;
+ memcpy (n->entries[i].data, buf + o, s);
+ }
+}
+
+static unsigned int
+exif_mnote_data_canon_count (ExifMnoteData *n)
+{
+ return n ? ((ExifMnoteDataCanon *) n)->count : 0;
+}
+
+static unsigned int
+exif_mnote_data_canon_get_id (ExifMnoteData *d, unsigned int n)
+{
+ ExifMnoteDataCanon *note = (ExifMnoteDataCanon *) d;
+
+ if (!note) return 0;
+ if (note->count <= n) return 0;
+ return note->entries[n].tag;
+}
+
+static const char *
+exif_mnote_data_canon_get_name (ExifMnoteData *note, unsigned int i)
+{
+ ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note;
+
+ if (!note) return NULL;
+ if (i >= cnote->count) return NULL;
+ return mnote_canon_tag_get_name (cnote->entries[i].tag);
+}
+
+static const char *
+exif_mnote_data_canon_get_title (ExifMnoteData *note, unsigned int i)
+{
+ ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note;
+
+ if (!note) return NULL;
+ if (i >= cnote->count) return NULL;
+ return mnote_canon_tag_get_title (cnote->entries[i].tag);
+}
+
+static const char *
+exif_mnote_data_canon_get_description (ExifMnoteData *note, unsigned int i)
+{
+ ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note;
+ if (!note) return NULL;
+ if (i >= cnote->count) return NULL;
+ return mnote_canon_tag_get_description (cnote->entries[i].tag);
+}
+
+ExifMnoteData *
+exif_mnote_data_canon_new (ExifMem *mem)
+{
+ ExifMnoteData *d;
+
+ if (!mem) return NULL;
+
+ d = exif_mem_alloc (mem, sizeof (ExifMnoteDataCanon));
+ if (!d) return NULL;
+
+ exif_mnote_data_construct (d, mem);
+
+ /* Set up function pointers */
+ d->methods.free = exif_mnote_data_canon_free;
+ d->methods.set_byte_order = exif_mnote_data_canon_set_byte_order;
+ d->methods.set_offset = exif_mnote_data_canon_set_offset;
+ d->methods.load = exif_mnote_data_canon_load;
+ d->methods.save = exif_mnote_data_canon_save;
+ d->methods.count = exif_mnote_data_canon_count;
+ d->methods.get_id = exif_mnote_data_canon_get_id;
+ d->methods.get_name = exif_mnote_data_canon_get_name;
+ d->methods.get_title = exif_mnote_data_canon_get_title;
+ d->methods.get_description = exif_mnote_data_canon_get_description;
+ d->methods.get_value = exif_mnote_data_canon_get_value;
+
+ return d;
+}
diff --git a/src/libexif/canon/exif-mnote-data-canon.h b/src/libexif/canon/exif-mnote-data-canon.h
new file mode 100644
index 0000000..a476ca0
--- /dev/null
+++ b/src/libexif/canon/exif-mnote-data-canon.h
@@ -0,0 +1,45 @@
+/* exif-mnote-data-canon.h
+ *
+ * Copyright © 2002, 2003 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_MNOTE_DATA_CANON_H__
+#define __EXIF_MNOTE_DATA_CANON_H__
+
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-mnote-data.h>
+#include <libexif/exif-mnote-data-priv.h>
+#include <libexif/exif-mem.h>
+
+typedef struct _ExifMnoteDataCanon ExifMnoteDataCanon;
+
+#include <libexif/canon/mnote-canon-entry.h>
+
+struct _ExifMnoteDataCanon {
+ ExifMnoteData parent;
+
+ MnoteCanonEntry *entries;
+ unsigned int count;
+
+ ExifByteOrder order;
+ unsigned int offset;
+};
+
+ExifMnoteData *exif_mnote_data_canon_new (ExifMem *mem);
+
+#endif /* __EXIF_MNOTE_DATA_CANON_H__ */
diff --git a/src/libexif/canon/mnote-canon-entry.c b/src/libexif/canon/mnote-canon-entry.c
new file mode 100644
index 0000000..5fa4991
--- /dev/null
+++ b/src/libexif/canon/mnote-canon-entry.c
@@ -0,0 +1,590 @@
+/* mnote-canon-entry.c
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright © 2003 Matthieu Castet <mat-c@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "mnote-canon-entry.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libexif/exif-format.h>
+#include <libexif/exif-utils.h>
+#include <libexif/i18n.h>
+
+/* #define DEBUG */
+
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+#define CF(format,target,v,maxlen) \
+{ \
+ if (format != target) { \
+ snprintf (v, maxlen, \
+ _("Invalid format '%s', " \
+ "expected '%s'."), \
+ exif_format_get_name (format), \
+ exif_format_get_name (target)); \
+ break; \
+ } \
+}
+
+#define CC(number,target,v,maxlen) \
+{ \
+ if (number != target) { \
+ snprintf (v, maxlen, \
+ _("Invalid number of components (%i, " \
+ "expected %i)."), (int) number, (int) target); \
+ break; \
+ } \
+}
+#define CC2(number,t1,t2,v,maxlen) \
+{ \
+ if ((number != t1) && (number != t2)) { \
+ snprintf (v, maxlen, \
+ _("Invalid number of components (%i, " \
+ "expected %i or %i)."), (int) number, \
+ (int) t1, (int) t2); \
+ break; \
+ } \
+}
+
+char *
+mnote_canon_entry_get_value (const MnoteCanonEntry *entry, char *val, unsigned int maxlen)
+{
+ char buf[128];
+ ExifLong vl;
+ ExifShort vs, n;
+ int i;
+ unsigned char *data = entry->data;
+
+ if (!entry) return NULL;
+
+ memset (val, 0, maxlen);
+ maxlen--;
+
+ switch (entry->tag) {
+ case MNOTE_CANON_TAG_SETTINGS_1:
+ CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
+ n = exif_get_short (data, entry->order) / 2;
+ data += 2;
+ CC (entry->components, n, val, maxlen);
+ for (i = 1; i < n; i++) {
+ vs = exif_get_short (data, entry->order);
+ data += 2;
+ switch (i) {
+ case 1:
+ strncpy (val, _("Macro mode : "), maxlen);
+ switch (vs) {
+ case 1:
+ strncat (val, _("Macro"), maxlen - strlen(val));
+ break;
+ case 2:
+ strncat (val, _("Normal"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 2:
+ if (vs) {
+ snprintf (buf, sizeof (buf),
+ _(" / Self Timer : %i (ms)"), vs*100);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 4:
+ strncat (val, _(" / Flash mode : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0:
+ strncat (val, _("Flash not fired"), maxlen - strlen(val));
+ break;
+ case 1:
+ strncat (val, _("auto"), maxlen - strlen(val));
+ break;
+ case 2:
+ strncat (val, _("on"), maxlen - strlen(val));
+ break;
+ case 3:
+ strncat (val, _("red eyes reduction"), maxlen - strlen(val));
+ break;
+ case 4:
+ strncat (val, _("slow synchro"), maxlen - strlen(val));
+ break;
+ case 5:
+ strncat (val, _("auto + red eyes reduction"), maxlen - strlen(val));
+ break;
+ case 6:
+ strncat (val, _("on + red eyes reduction"), maxlen - strlen(val));
+ break;
+ case 16:
+ strncat (val, _("external"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 5:
+ strncat (val, _(" / Continuous drive mode : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0:
+ strncat (val, _("single or timer"), maxlen - strlen(val));
+ break;
+ case 1:
+ strncat (val, _("continuous"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 7:
+ strncat (val, _(" / Focus mode : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0:
+ strncat (val, _("One-Shot"), maxlen - strlen(val));
+ break;
+ case 1:
+ strncat (val, _("AI Servo"), maxlen - strlen(val));
+ break;
+ case 2:
+ strncat (val, _("AI Focus"), maxlen - strlen(val));
+ break;
+ case 3:
+ strncat (val, _("MF"), maxlen - strlen(val));
+ break;
+ case 4:
+ strncat (val, _("Single"), maxlen - strlen(val));
+ break;
+ case 5:
+ strncat (val, _("Continuous"), maxlen - strlen(val));
+ break;
+ case 6:
+ strncat (val, _("MF"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 10:
+ strncat (val, _(" / Image size : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0:
+ strncat (val, _("Large"), maxlen - strlen(val));
+ break;
+ case 1:
+ strncat (val, _("Medium"), maxlen - strlen(val));
+ break;
+ case 2:
+ strncat (val, _("Small"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 11:
+ strncat (val, _(" / Easy shooting mode : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0:
+ strncat (val, _("Full Auto"), maxlen - strlen(val));
+ break;
+ case 1:
+ strncat (val, _("Manual"), maxlen - strlen(val));
+ break;
+ case 2:
+ strncat (val, _("Landscape"), maxlen - strlen(val));
+ break;
+ case 3:
+ strncat (val, _("Fast Shutter"), maxlen - strlen(val));
+ break;
+ case 4:
+ strncat (val, _("Slow Shutter"), maxlen - strlen(val));
+ break;
+ case 5:
+ strncat (val, _("Night"), maxlen - strlen(val));
+ break;
+ case 6:
+ strncat (val, _("Black & White"), maxlen - strlen(val));
+ break;
+ case 7:
+ strncat (val, _("Sepia"), maxlen - strlen(val));
+ break;
+ case 8:
+ strncat (val, _("Portrait"), maxlen - strlen(val));
+ break;
+ case 9:
+ strncat (val, _("Sports"), maxlen - strlen(val));
+ break;
+ case 10:
+ strncat (val, _("Macro / Close-Up"), maxlen - strlen(val));
+ break;
+ case 11:
+ strncat (val, _("Pan Focus"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 13:
+ strncat (val, _(" / Contrast : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0xffff:
+ strncat (val, _("Low"), maxlen - strlen(val));
+ break;
+ case 0x0000:
+ strncat (val, _("Normal"), maxlen - strlen(val));
+ break;
+ case 0x0001:
+ strncat (val, _("High"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 14:
+ strncat (val, _(" / Saturation : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0xffff:
+ strncat (val, _("Low"), maxlen - strlen(val));
+ break;
+ case 0x0000:
+ strncat (val, _("Normal"), maxlen - strlen(val));
+ break;
+ case 0x0001:
+ strncat (val, _("High"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 15:
+ strncat (val, _(" / Sharpness : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0xffff:
+ strncat (val, _("Low"), maxlen - strlen(val));
+ break;
+ case 0x0000:
+ strncat (val, _("Normal"), maxlen - strlen(val));
+ break;
+ case 0x0001:
+ strncat (val, _("High"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 16:
+ if (vs) {
+ strncat (val, _(" / ISO : "), maxlen - strlen(val));
+ switch (vs) {
+ case 15:
+ strncat (val, _("auto"), maxlen - strlen(val));
+ break;
+ case 16:
+ strncat (val, _("50"), maxlen - strlen(val));
+ break;
+ case 17:
+ strncat (val, _("100"), maxlen - strlen(val));
+ break;
+ case 18:
+ strncat (val, _("200"), maxlen - strlen(val));
+ break;
+ case 19:
+ strncat (val, _("400"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ }
+ case 17:
+ strncat (val, _(" / Metering mode : "), maxlen - strlen(val));
+ switch (vs) {
+ case 3:
+ strncat (val, _("Evaluative"), maxlen - strlen(val));
+ break;
+ case 4:
+ strncat (val, _("Partial"), maxlen - strlen(val));
+ break;
+ case 5:
+ strncat (val, _("Center-weighted"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 19:
+ strncat (val, _(" / AF point selected : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0x3000:
+ strncat (val, _("none (MF)"), maxlen - strlen(val));
+ break;
+ case 0x3001:
+ strncat (val, _("auto-selected"), maxlen - strlen(val));
+ break;
+ case 0x3002:
+ strncat (val, _("right"), maxlen - strlen(val));
+ break;
+ case 0x3003:
+ strncat (val, _("center"), maxlen - strlen(val));
+ break;
+ case 0x3004:
+ strncat (val, _("left"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("0x%x???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 20:
+ strncat (val, _(" / Exposure mode : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0:
+ strncat (val, _("Easy shooting"), maxlen - strlen(val));
+ break;
+ case 1:
+ strncat (val, _("Program"), maxlen - strlen(val));
+ break;
+ case 2:
+ strncat (val, _("Tv-priority"), maxlen - strlen(val));
+ break;
+ case 3:
+ strncat (val, _("Av-priority"), maxlen - strlen(val));
+ break;
+ case 4:
+ strncat (val, _("Manual"), maxlen - strlen(val));
+ break;
+ case 5:
+ strncat (val, _("A-DEP"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 23:
+ snprintf (buf, sizeof (buf), _(" / long focal length of lens (in focal units) : %u"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ break;
+ case 24:
+ snprintf (buf, sizeof (buf), _(" / short focal length of lens (in focal units) : %u"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ break;
+ case 25:
+ snprintf (buf, sizeof (buf), _(" / focal units per mm : %u"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ break;
+ case 29:
+ strncat (val, _(" / Flash details : "), maxlen - strlen(val));
+ if ((vs>>14)&1)
+ strncat (val, _("External E-TTL"), maxlen - strlen(val));
+ if ((vs>>13)&1)
+ strncat (val, _("Internal flash"), maxlen - strlen(val));
+ if ((vs>>11)&1)
+ strncat (val, _("FP sync used"), maxlen - strlen(val));
+ if ((vs>>4)&1)
+ strncat (val, _("FP sync enabled"), maxlen - strlen(val));
+#ifdef DEBUG
+ printf ("Value29=0x%08x\n", vs);
+#endif
+ break;
+ case 32:
+ strncat (val, _(" / Focus mode2 : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0:
+ strncat (val, _("Single"), maxlen - strlen(val));
+ break;
+ case 1:
+ strncat (val, _("Continuous"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+#ifdef DEBUG
+ default:
+ printf ("Value%d=%d\n", i, vs);
+#endif
+ }
+ }
+
+ break;
+
+ case MNOTE_CANON_TAG_SETTINGS_2:
+ CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
+ n = exif_get_short (data, entry->order)/2;
+ data += 2;
+ CC (entry->components, n, val, maxlen);
+#ifdef DEBUG
+ printf ("Setting2 size %d %d\n",n,entry->size);
+#endif
+ for (i=1;i<n;i++)
+ {
+ vs = exif_get_short (data, entry->order);
+ data+=2;
+ switch(i) {
+ case 7:
+ strncpy (val, _("White balance : "), maxlen - strlen(val));
+ switch (vs) {
+ case 0:
+ strncat (val, _("Auto"), maxlen - strlen(val));
+ break;
+ case 1:
+ strncat (val, _("Sunny"), maxlen - strlen(val));
+ break;
+ case 2:
+ strncat (val, _("Cloudy"), maxlen - strlen(val));
+ break;
+ case 3:
+ strncat (val, _("Tungsten"), maxlen - strlen(val));
+ break;
+ case 4:
+ strncat (val, _("Flourescent"), maxlen - strlen(val));
+ break;
+ case 5:
+ strncat (val, _("Flash"), maxlen - strlen(val));
+ break;
+ case 6:
+ strncat (val, _("Custom"), maxlen - strlen(val));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%i???"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+ case 9:
+ snprintf (buf, sizeof (buf), _(" / Sequence number : %u"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ break;
+ case 14:
+ if (vs>>12)
+ {
+ strncat (val, _(" / AF point used : "), maxlen - strlen(val));
+ if (vs&1)
+ strncat (val, _("Right"), maxlen - strlen(val));
+ if ((vs>>1)&1)
+ strncat (val, _("Center"), maxlen - strlen(val));
+ if ((vs>>2)&1)
+ strncat (val, _("Left"), maxlen - strlen(val));
+ snprintf (buf, sizeof (buf), _(" (%u available focus point)"), vs>>12);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+#ifdef DEBUG
+ printf ("0x%08x\n", vs);
+#endif
+ break;
+ case 15:
+ snprintf (buf, sizeof (buf), _(" / Flash bias : %.2f EV"), vs/32.0);
+ strncat (val, buf, maxlen - strlen(val));
+
+ break;
+ case 19:
+ snprintf (buf, sizeof (buf), _(" / Subject Distance (mm) : %u"), vs);
+ strncat (val, buf, maxlen - strlen(val));
+ break;
+#ifdef DEBUG
+ default:
+ printf ("Value%d=%d\n", i, vs);
+#endif
+ }
+ }
+
+ break;
+
+ case MNOTE_CANON_TAG_IMAGE_TYPE:
+ case MNOTE_CANON_TAG_OWNER:
+ CF (entry->format, EXIF_FORMAT_ASCII, val, maxlen);
+ CC (entry->components, 32, val, maxlen);
+ strncpy (val, data, MIN (entry->size, maxlen));
+ break;
+
+ case MNOTE_CANON_TAG_FIRMWARE:
+ CF (entry->format, EXIF_FORMAT_ASCII, val, maxlen);
+ CC2 (entry->components, 24, 32, val, maxlen);
+ strncpy (val, data, MIN (entry->size, maxlen));
+ break;
+
+ case MNOTE_CANON_TAG_IMAGE_NUMBER:
+ CF (entry->format, EXIF_FORMAT_LONG, val, maxlen);
+ CC (entry->components, 1, val, maxlen);
+ vl = exif_get_long (data, entry->order);
+ snprintf (val, maxlen, "%03lu-%04lu",
+ (unsigned long) vl/10000,
+ (unsigned long) vl%10000);
+ break;
+
+ case MNOTE_CANON_TAG_SERIAL_NUMBER:
+ CF (entry->format, EXIF_FORMAT_LONG, val, maxlen);
+ CC (entry->components, 1, val, maxlen);
+ vl = exif_get_long (data, entry->order);
+ snprintf (val, maxlen, "%04X-%05d", (int)vl>>16,(int)vl&0xffff);
+ break;
+
+ case MNOTE_CANON_TAG_CUSTOM_FUNCS:
+ CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
+ n = exif_get_short (data, entry->order)/2;
+ data+=2;
+ CC (entry->components, n, val, maxlen);
+#ifdef DEBUG
+ printf ("Custom Function size %d %d\n",n,entry->size);
+#endif
+ for (i=1;i<n;i++)
+ {
+ vs = exif_get_short (data, entry->order);
+ data += 2;
+ snprintf (buf, sizeof(buf), _("C.F%d : %u"), i, vs);
+ strncat (val, buf, maxlen - strlen(val));
+ }
+ break;
+
+ default:
+#ifdef DEBUG
+ if (entry->format == EXIF_FORMAT_SHORT)
+ for(i=0;i<entry->components;i++) {
+ vs = exif_get_short (data, entry->order);
+ data+=2;
+ printf ("Value%d=%d\n", i, vs);
+ }
+ else if (entry->format == EXIF_FORMAT_LONG)
+ for(i=0;i<entry->components;i++) {
+ vl = exif_get_long (data, entry->order);
+ data+=4;
+ printf ("Value%d=%d\n", i, vs);
+ }
+ else if (entry->format == EXIF_FORMAT_ASCII)
+ strncpy (val, data, MIN (entry->size, maxlen));
+#endif
+ break;
+ }
+
+ return val;
+}
diff --git a/src/libexif/canon/mnote-canon-entry.h b/src/libexif/canon/mnote-canon-entry.h
new file mode 100644
index 0000000..62345d8
--- /dev/null
+++ b/src/libexif/canon/mnote-canon-entry.h
@@ -0,0 +1,43 @@
+/* mnote-canon-entry.h
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MNOTE_CANON_ENTRY_H__
+#define __MNOTE_CANON_ENTRY_H__
+
+#include <libexif/exif-format.h>
+#include <libexif/exif-byte-order.h>
+#include <libexif/canon/mnote-canon-tag.h>
+
+typedef struct _MnoteCanonEntry MnoteCanonEntry;
+
+struct _MnoteCanonEntry {
+ MnoteCanonTag tag;
+ ExifFormat format;
+ unsigned long components;
+
+ unsigned char *data;
+ unsigned int size;
+
+ ExifByteOrder order;
+};
+
+char *mnote_canon_entry_get_value (const MnoteCanonEntry *entry, char *val, unsigned int maxlen);
+
+#endif /* __MNOTE_CANON_ENTRY_H__ */
diff --git a/src/libexif/canon/mnote-canon-tag.c b/src/libexif/canon/mnote-canon-tag.c
new file mode 100644
index 0000000..890a5fc
--- /dev/null
+++ b/src/libexif/canon/mnote-canon-tag.c
@@ -0,0 +1,75 @@
+/* mnote-canon-tag.c
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "mnote-canon-tag.h"
+
+#include <stdlib.h>
+
+#include <libexif/i18n.h>
+
+static struct {
+ MnoteCanonTag tag;
+ const char *name;
+ const char *title;
+ const char *description;
+} table[] = {
+ {MNOTE_CANON_TAG_SETTINGS_1, "Settings1", N_("Settings (first part)"), ""},
+ {MNOTE_CANON_TAG_SETTINGS_2, "Settings2", N_("Settings (second part)"), ""},
+ {MNOTE_CANON_TAG_IMAGE_TYPE, "ImageType", N_("Image type"), ""},
+ {MNOTE_CANON_TAG_FIRMWARE, "FirmwareVersion", N_("Firmware version"), ""},
+ {MNOTE_CANON_TAG_IMAGE_NUMBER, "ImageNumber", N_("Image number"), ""},
+ {MNOTE_CANON_TAG_OWNER, "OwnerName", N_("Owner name"), ""},
+ {MNOTE_CANON_TAG_SERIAL_NUMBER, "SerialNumber", N_("Serial number"), ""},
+ {MNOTE_CANON_TAG_CUSTOM_FUNCS, "CustomFunctions", N_("Custom functions"), ""},
+ {0, NULL, NULL, NULL}
+};
+
+const char *
+mnote_canon_tag_get_name (MnoteCanonTag t)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ if (table[i].tag == t) return (_(table[i].name));
+ return NULL;
+}
+
+const char *
+mnote_canon_tag_get_title (MnoteCanonTag t)
+{
+ unsigned int i;
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ if (table[i].tag == t) return (_(table[i].title));
+ return NULL;
+}
+
+const char *
+mnote_canon_tag_get_description (MnoteCanonTag t)
+{
+ unsigned int i;
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ if (table[i].tag == t) return (_(table[i].description));
+ return NULL;
+}
diff --git a/src/libexif/canon/mnote-canon-tag.h b/src/libexif/canon/mnote-canon-tag.h
new file mode 100644
index 0000000..ce1a72e
--- /dev/null
+++ b/src/libexif/canon/mnote-canon-tag.h
@@ -0,0 +1,52 @@
+/* mnote-canon-tag.h
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MNOTE_CANON_TAG_H__
+#define __MNOTE_CANON_TAG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+enum _MnoteCanonTag {
+ MNOTE_CANON_TAG_UNKNOWN_0 = 0x0,
+ MNOTE_CANON_TAG_SETTINGS_1 = 0x1,
+ MNOTE_CANON_TAG_UNKNOWN_3 = 0x3,
+ MNOTE_CANON_TAG_SETTINGS_2 = 0x4,
+ MNOTE_CANON_TAG_IMAGE_TYPE = 0x6,
+ MNOTE_CANON_TAG_FIRMWARE = 0x7,
+ MNOTE_CANON_TAG_IMAGE_NUMBER = 0x8,
+ MNOTE_CANON_TAG_OWNER = 0x9,
+ MNOTE_CANON_TAG_UNKNOWN_10 = 0xa,
+ MNOTE_CANON_TAG_SERIAL_NUMBER = 0xc,
+ MNOTE_CANON_TAG_UNKNOWN_13 = 0xd,
+ MNOTE_CANON_TAG_CUSTOM_FUNCS = 0xf
+};
+typedef enum _MnoteCanonTag MnoteCanonTag;
+
+const char *mnote_canon_tag_get_name (MnoteCanonTag tag);
+const char *mnote_canon_tag_get_title (MnoteCanonTag tag);
+const char *mnote_canon_tag_get_description (MnoteCanonTag tag);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __MNOTE_CANON_TAG_H__ */
diff --git a/src/libexif/config.h b/src/libexif/config.h
new file mode 100644
index 0000000..54325e3
--- /dev/null
+++ b/src/libexif/config.h
@@ -0,0 +1,12 @@
+
+/* Define to 1 if translation of program messages to the user's native
+ language is requested. */
+/* #undef ENABLE_NLS */
+
+/* The gettext domain we're using */
+#define GETTEXT_PACKAGE "libexif-9"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
diff --git a/src/libexif/exif-byte-order.c b/src/libexif/exif-byte-order.c
new file mode 100644
index 0000000..1a4279f
--- /dev/null
+++ b/src/libexif/exif-byte-order.c
@@ -0,0 +1,39 @@
+/* exif-byte-order.c
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-byte-order.h>
+#include <libexif/i18n.h>
+
+#include <stdlib.h>
+
+const char *
+exif_byte_order_get_name (ExifByteOrder order)
+{
+ switch (order) {
+ case EXIF_BYTE_ORDER_MOTOROLA:
+ return (_("Motorola"));
+ case EXIF_BYTE_ORDER_INTEL:
+ return (_("Intel"));
+ default:
+ return NULL;
+ }
+}
diff --git a/src/libexif/exif-byte-order.h b/src/libexif/exif-byte-order.h
new file mode 100644
index 0000000..bd51d3c
--- /dev/null
+++ b/src/libexif/exif-byte-order.h
@@ -0,0 +1,39 @@
+/* exif-byte-order.h
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_BYTE_ORDER_H__
+#define __EXIF_BYTE_ORDER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+ EXIF_BYTE_ORDER_MOTOROLA,
+ EXIF_BYTE_ORDER_INTEL
+} ExifByteOrder;
+
+const char *exif_byte_order_get_name (ExifByteOrder order);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_BYTE_ORDER_H__ */
diff --git a/src/libexif/exif-content.c b/src/libexif/exif-content.c
new file mode 100644
index 0000000..39d73ad
--- /dev/null
+++ b/src/libexif/exif-content.c
@@ -0,0 +1,209 @@
+/* exif-content.c
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-content.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+
+struct _ExifContentPrivate
+{
+ unsigned int ref_count;
+
+ ExifMem *mem;
+ ExifLog *log;
+};
+
+ExifContent *
+exif_content_new (void)
+{
+ ExifMem *mem = exif_mem_new_default ();
+ ExifContent *content = exif_content_new_mem (mem);
+
+ exif_mem_unref (mem);
+
+ return content;
+}
+
+ExifContent *
+exif_content_new_mem (ExifMem *mem)
+{
+ ExifContent *content;
+
+ if (!mem) return NULL;
+
+ content = exif_mem_alloc (mem, (ExifLong) sizeof (ExifContent));
+ if (!content)
+ return NULL;
+ content->priv = exif_mem_alloc (mem,
+ (ExifLong) sizeof (ExifContentPrivate));
+ if (!content->priv) {
+ exif_mem_free (mem, content);
+ return NULL;
+ }
+
+ content->priv->ref_count = 1;
+
+ content->priv->mem = mem;
+ exif_mem_ref (mem);
+
+ return content;
+}
+
+void
+exif_content_ref (ExifContent *content)
+{
+ content->priv->ref_count++;
+}
+
+void
+exif_content_unref (ExifContent *content)
+{
+ content->priv->ref_count--;
+ if (!content->priv->ref_count)
+ exif_content_free (content);
+}
+
+void
+exif_content_free (ExifContent *content)
+{
+ ExifMem *mem = (content && content->priv) ? content->priv->mem : NULL;
+ unsigned int i;
+
+ if (!content) return;
+
+ for (i = 0; i < content->count; i++)
+ exif_entry_unref (content->entries[i]);
+ exif_mem_free (mem, content->entries);
+
+ if (content->priv) {
+ exif_log_unref (content->priv->log);
+ }
+
+ exif_mem_free (mem, content->priv);
+ exif_mem_free (mem, content);
+ exif_mem_unref (mem);
+}
+
+void
+exif_content_dump (ExifContent *content, unsigned int indent)
+{
+ char buf[1024];
+ unsigned int i;
+
+ for (i = 0; i < 2 * indent; i++)
+ buf[i] = ' ';
+ buf[i] = '\0';
+
+ if (!content)
+ return;
+
+ printf ("%sDumping exif content (%i entries)...\n", buf,
+ content->count);
+ for (i = 0; i < content->count; i++)
+ exif_entry_dump (content->entries[i], indent + 1);
+}
+
+void
+exif_content_add_entry (ExifContent *c, ExifEntry *entry)
+{
+ if (!c || !c->priv || !entry || entry->parent) return;
+
+ /* One tag can only be added once to an IFD. */
+ if (exif_content_get_entry (c, entry->tag)) {
+ exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "ExifContent",
+ "An attempt has been made to add "
+ "the tag '%s' twice to an IFD. This is against "
+ "specification.", exif_tag_get_name (entry->tag));
+ return;
+ }
+
+ entry->parent = c;
+ c->entries = exif_mem_realloc (c->priv->mem,
+ c->entries, sizeof (ExifEntry) * (c->count + 1));
+ if (!c->entries) return;
+ c->entries[c->count] = entry;
+ exif_entry_ref (entry);
+ c->count++;
+}
+
+void
+exif_content_remove_entry (ExifContent *c, ExifEntry *e)
+{
+ unsigned int i;
+
+ if (!c || !c->priv || !e || (e->parent != c)) return;
+
+ /* Search the entry */
+ for (i = 0; i < c->count; i++) if (c->entries[i] == e) break;
+ if (i == c->count) return;
+
+ /* Remove the entry */
+ memmove (&c->entries[i], &c->entries[i + 1],
+ sizeof (ExifEntry) * (c->count - i - 1));
+ c->count--;
+ e->parent = NULL;
+ exif_entry_unref (e);
+ c->entries = exif_mem_realloc (c->priv->mem, c->entries,
+ sizeof(ExifEntry) * c->count);
+}
+
+ExifEntry *
+exif_content_get_entry (ExifContent *content, ExifTag tag)
+{
+ unsigned int i;
+
+ if (!content)
+ return (NULL);
+
+ for (i = 0; i < content->count; i++)
+ if (content->entries[i]->tag == tag)
+ return (content->entries[i]);
+ return (NULL);
+}
+
+void
+exif_content_foreach_entry (ExifContent *content,
+ ExifContentForeachEntryFunc func, void *data)
+{
+ unsigned int i;
+
+ if (!content || !func)
+ return;
+
+ for (i = 0; i < content->count; i++)
+ func (content->entries[i], data);
+}
+
+void
+exif_content_log (ExifContent *content, ExifLog *log)
+{
+ if (!content || !content->priv || !log || content->priv->log == log)
+ return;
+
+ if (content->priv->log) exif_log_unref (content->priv->log);
+ content->priv->log = log;
+ exif_log_ref (log);
+}
diff --git a/src/libexif/exif-content.h b/src/libexif/exif-content.h
new file mode 100644
index 0000000..115f8ed
--- /dev/null
+++ b/src/libexif/exif-content.h
@@ -0,0 +1,76 @@
+/* exif-content.h
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_CONTENT_H__
+#define __EXIF_CONTENT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ExifContent ExifContent;
+typedef struct _ExifContentPrivate ExifContentPrivate;
+
+#include <libexif/exif-tag.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-data.h>
+#include <libexif/exif-log.h>
+#include <libexif/exif-mem.h>
+
+struct _ExifContent
+{
+ ExifEntry **entries;
+ unsigned int count;
+
+ /* Data containing this content */
+ ExifData *parent;
+
+ ExifContentPrivate *priv;
+};
+
+/* Lifecycle */
+ExifContent *exif_content_new (void);
+ExifContent *exif_content_new_mem (ExifMem *);
+void exif_content_ref (ExifContent *content);
+void exif_content_unref (ExifContent *content);
+void exif_content_free (ExifContent *content);
+
+void exif_content_add_entry (ExifContent *content, ExifEntry *e);
+void exif_content_remove_entry (ExifContent *content, ExifEntry *e);
+ExifEntry *exif_content_get_entry (ExifContent *content, ExifTag tag);
+
+typedef void (* ExifContentForeachEntryFunc) (ExifEntry *, void *user_data);
+void exif_content_foreach_entry (ExifContent *content,
+ ExifContentForeachEntryFunc func,
+ void *user_data);
+
+/* For your convenience */
+#define exif_content_get_value(c,t,v,m) \
+ (exif_content_get_entry (c,t) ? \
+ exif_entry_get_value (exif_content_get_entry (c,t),v,m) : NULL)
+
+void exif_content_dump (ExifContent *content, unsigned int indent);
+void exif_content_log (ExifContent *content, ExifLog *log);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_CONTENT_H__ */
diff --git a/src/libexif/exif-data.c b/src/libexif/exif-data.c
new file mode 100644
index 0000000..92e5857
--- /dev/null
+++ b/src/libexif/exif-data.c
@@ -0,0 +1,1039 @@
+/* exif-data.c
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-mnote-data.h>
+#include <libexif/exif-data.h>
+#include <libexif/exif-ifd.h>
+#include <libexif/exif-mnote-data-priv.h>
+#include <libexif/exif-utils.h>
+#include <libexif/exif-loader.h>
+#include <libexif/exif-log.h>
+#include <libexif/i18n.h>
+
+#include <libexif/olympus/exif-mnote-data-olympus.h>
+#include <libexif/canon/exif-mnote-data-canon.h>
+#include <libexif/pentax/exif-mnote-data-pentax.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#if defined(__WATCOMC__) || defined(_MSC_VER)
+# define strncasecmp strnicmp
+#endif
+
+#undef JPEG_MARKER_SOI
+#define JPEG_MARKER_SOI 0xd8
+#undef JPEG_MARKER_APP0
+#define JPEG_MARKER_APP0 0xe0
+#undef JPEG_MARKER_APP1
+#define JPEG_MARKER_APP1 0xe1
+
+static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+
+struct _ExifDataPrivate
+{
+ ExifByteOrder order;
+
+ ExifMnoteData *md;
+
+ ExifLog *log;
+ ExifMem *mem;
+
+ unsigned int ref_count;
+
+ /* Temporarily used while loading data */
+ unsigned int offset_mnote;
+};
+
+static void *
+exif_data_alloc (ExifData *data, unsigned int i)
+{
+ void *d;
+
+ if (!data || !i) return NULL;
+
+ d = exif_mem_alloc (data->priv->mem, i);
+ if (d) return d;
+
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", i);
+ return NULL;
+}
+
+ExifMnoteData *
+exif_data_get_mnote_data (ExifData *d)
+{
+ return (d && d->priv) ? d->priv->md : NULL;
+}
+
+ExifData *
+exif_data_new (void)
+{
+ ExifMem *mem = exif_mem_new_default ();
+ ExifData *d = exif_data_new_mem (mem);
+
+ exif_mem_unref (mem);
+
+ return d;
+}
+
+ExifData *
+exif_data_new_mem (ExifMem *mem)
+{
+ ExifData *data;
+ unsigned int i;
+
+ if (!mem) return NULL;
+
+ data = exif_mem_alloc (mem, sizeof (ExifData));
+ if (!data) return (NULL);
+ data->priv = exif_mem_alloc (mem, sizeof (ExifDataPrivate));
+ if (!data->priv) { exif_mem_free (mem, data); return (NULL); }
+ data->priv->ref_count = 1;
+
+ data->priv->mem = mem;
+ exif_mem_ref (mem);
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++) {
+ data->ifd[i] = exif_content_new_mem (data->priv->mem);
+ if (!data->ifd[i]) {
+ exif_data_free (data);
+ return (NULL);
+ }
+ data->ifd[i]->parent = data;
+ }
+
+ return (data);
+}
+
+ExifData *
+exif_data_new_from_data (const unsigned char *data, unsigned int size)
+{
+ ExifData *edata;
+
+ edata = exif_data_new ();
+ exif_data_load_data (edata, data, size);
+ return (edata);
+}
+
+static void
+exif_data_load_data_entry (ExifData *data, ExifEntry *entry,
+ const unsigned char *d,
+ unsigned int size, unsigned int offset)
+{
+ unsigned int s, doff;
+
+ entry->tag = exif_get_short (d + offset + 0, data->priv->order);
+ entry->format = exif_get_short (d + offset + 2, data->priv->order);
+ entry->components = exif_get_long (d + offset + 4, data->priv->order);
+
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Loading entry 0x%x ('%s')...", entry->tag,
+ exif_tag_get_name (entry->tag));
+
+ /*
+ * Size? If bigger than 4 bytes, the actual data is not
+ * in the entry but somewhere else (offset).
+ */
+ s = exif_format_get_size (entry->format) * entry->components;
+ if (!s)
+ return;
+ if (s > 4)
+ doff = exif_get_long (d + offset + 8, data->priv->order);
+ else
+ doff = offset + 8;
+
+ /* Sanity check */
+ if (size < doff + s)
+ return;
+
+ entry->data = exif_data_alloc (data, s);
+ if (entry->data) {
+ entry->size = s;
+ memcpy (entry->data, d + doff, s);
+ }
+
+ /* If this is the MakerNote, remember the offset */
+ if (entry->tag == EXIF_TAG_MAKER_NOTE) {
+ if (entry->size > 6) exif_log (data->priv->log,
+ EXIF_LOG_CODE_DEBUG, "ExifData",
+ "MakerNote found (%02x %02x %02x %02x "
+ "%02x %02x %02x...).",
+ entry->data[0], entry->data[1], entry->data[2],
+ entry->data[3], entry->data[4], entry->data[5],
+ entry->data[6]);
+ data->priv->offset_mnote = doff;
+ }
+
+ exif_entry_fix (entry);
+}
+
+static void
+exif_data_save_data_entry (ExifData *data, ExifEntry *e,
+ unsigned char **d, unsigned int *ds,
+ unsigned int offset)
+{
+ unsigned int doff, s;
+
+ if (!data || !data->priv) return;
+
+ /*
+ * Each entry is 12 bytes long. The memory for the entry has
+ * already been allocated.
+ */
+ exif_set_short (*d + 6 + offset + 0,
+ data->priv->order, (ExifShort) e->tag);
+ exif_set_short (*d + 6 + offset + 2,
+ data->priv->order, (ExifShort) e->format);
+
+#ifndef EXIF_DONT_CHANGE_MAKER_NOTE
+ /* If this is the maker note tag, update it. */
+ if ((e->tag == EXIF_TAG_MAKER_NOTE) && data->priv->md) {
+ exif_mem_free (data->priv->mem, e->data);
+ e->data = NULL;
+ e->size = 0;
+ exif_mnote_data_set_offset (data->priv->md, *ds - 6);
+ exif_mnote_data_save (data->priv->md, &e->data, &e->size);
+ e->components = e->size;
+ }
+#endif
+
+ exif_set_long (*d + 6 + offset + 4,
+ data->priv->order, e->components);
+
+ /*
+ * Size? If bigger than 4 bytes, the actual data is not in
+ * the entry but somewhere else.
+ */
+ s = exif_format_get_size (e->format) * e->components;
+ if (s > 4) {
+ doff = *ds - 6;
+ *ds += s;
+
+ /*
+ * According to the TIFF specification,
+ * the offset must be an even number. If we need to introduce
+ * a padding byte, we set it to 0.
+ */
+ if (s & 1) (*ds)++;
+ *d = exif_mem_realloc (data->priv->mem, *d, *ds);
+ if (!*d) {
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", *ds);
+ return;
+ }
+ exif_set_long (*d + 6 + offset + 8, data->priv->order, doff);
+ if (s & 1) *(*d + *ds - 1) = '\0';
+
+ } else
+ doff = offset + 8;
+
+ /* Write the data. Fill unneeded bytes with 0. */
+ memcpy (*d + 6 + doff, e->data, s);
+ if (s < 4) memset (*d + 6 + doff + s, 0, (4 - s));
+}
+
+static void
+exif_data_load_data_thumbnail (ExifData *data, const unsigned char *d,
+ unsigned int ds, ExifLong offset, ExifLong size)
+{
+ if (ds < offset + size) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Bogus thumbnail offset and size: %i < %i + %i.",
+ (int) ds, (int) offset, (int) size);
+ return;
+ }
+ if (data->data) exif_mem_free (data->priv->mem, data->data);
+ data->size = size;
+ data->data = exif_data_alloc (data, data->size);
+ if (!data->data) return;
+ memcpy (data->data, d + offset, data->size);
+}
+
+#undef CHECK_REC
+#define CHECK_REC(i) \
+if (data->ifd[(i)] == ifd) { \
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \
+ "ExifData", "Recursive entry in IFD " \
+ "'%s' detected. Skipping...", \
+ exif_ifd_get_name (i)); \
+ break; \
+} \
+if (data->ifd[(i)]->count) { \
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \
+ "ExifData", "Attemt to load IFD " \
+ "'%s' multiple times detected. " \
+ "Skipping...", \
+ exif_ifd_get_name (i)); \
+ break; \
+}
+
+static void
+exif_data_load_data_content (ExifData *data, ExifContent *ifd,
+ const unsigned char *d,
+ unsigned int ds, unsigned int offset)
+{
+ ExifLong o, thumbnail_offset = 0, thumbnail_length = 0;
+ ExifShort n;
+ ExifEntry *entry;
+ unsigned int i;
+ ExifTag tag;
+
+ if (!data || !data->priv) return;
+
+ /* Read the number of entries */
+ if (offset >= ds - 1) return;
+ n = exif_get_short (d + offset, data->priv->order);
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Loading %i entries...", n);
+ offset += 2;
+
+ /* Check if we have enough data. */
+ if (offset + 12 * n > ds) n = (ds - offset) / 12;
+
+ for (i = 0; i < n; i++) {
+
+ tag = exif_get_short (d + offset + 12 * i, data->priv->order);
+ switch (tag) {
+ case EXIF_TAG_EXIF_IFD_POINTER:
+ case EXIF_TAG_GPS_INFO_IFD_POINTER:
+ case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
+ o = exif_get_long (d + offset + 12 * i + 8,
+ data->priv->order);
+ switch (tag) {
+ case EXIF_TAG_EXIF_IFD_POINTER:
+ CHECK_REC (EXIF_IFD_EXIF);
+ exif_data_load_data_content (data,
+ data->ifd[EXIF_IFD_EXIF], d, ds, o);
+ break;
+ case EXIF_TAG_GPS_INFO_IFD_POINTER:
+ CHECK_REC (EXIF_IFD_GPS);
+ exif_data_load_data_content (data,
+ data->ifd[EXIF_IFD_GPS], d, ds, o);
+ break;
+ case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
+ CHECK_REC (EXIF_IFD_INTEROPERABILITY);
+ exif_data_load_data_content (data,
+ data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds, o);
+ break;
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
+ thumbnail_offset = o;
+ if (thumbnail_offset && thumbnail_length)
+ exif_data_load_data_thumbnail (data, d,
+ ds, thumbnail_offset,
+ thumbnail_length);
+ break;
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
+ thumbnail_length = o;
+ if (thumbnail_offset && thumbnail_length)
+ exif_data_load_data_thumbnail (data, d,
+ ds, thumbnail_offset,
+ thumbnail_length);
+ break;
+ default:
+ return;
+ }
+ break;
+ default:
+
+ /*
+ * If we don't know the tag, chances are high
+ * that the EXIF data does not follow the standard.
+ */
+ if (!exif_tag_get_name (tag)) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Unknown tag %x (entry %i)", tag, i);
+ return;
+ }
+ entry = exif_entry_new_mem (data->priv->mem);
+ exif_data_load_data_entry (data, entry, d, ds,
+ offset + 12 * i);
+ exif_content_add_entry (ifd, entry);
+ exif_entry_unref (entry);
+ break;
+ }
+ }
+}
+
+static int
+cmp_func (const unsigned char *p1, const unsigned char *p2, ExifByteOrder o)
+{
+ ExifShort tag1 = exif_get_short (p1, o);
+ ExifShort tag2 = exif_get_short (p2, o);
+
+ return (tag1 < tag2) ? -1 : (tag1 > tag2) ? 1 : 0;
+}
+
+static int
+cmp_func_intel (const void *elem1, const void *elem2)
+{
+ return cmp_func ((const unsigned char *) elem1,
+ (const unsigned char *) elem2, EXIF_BYTE_ORDER_INTEL);
+}
+
+static int
+cmp_func_motorola (const void *elem1, const void *elem2)
+{
+ return cmp_func ((const unsigned char *) elem1,
+ (const unsigned char *) elem2, EXIF_BYTE_ORDER_MOTOROLA);
+}
+
+static void
+exif_data_save_data_content (ExifData *data, ExifContent *ifd,
+ unsigned char **d, unsigned int *ds,
+ unsigned int offset)
+{
+ unsigned int j, n_ptr = 0, n_thumb = 0;
+ ExifIfd i;
+
+ if (!data || !data->priv || !ifd || !d || !ds) return;
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++)
+ if (ifd == data->ifd[i])
+ break;
+ if (i == EXIF_IFD_COUNT)
+ return;
+
+ /*
+ * Check if we need some extra entries for pointers or the thumbnail.
+ */
+ switch (i) {
+ case EXIF_IFD_0:
+
+ /*
+ * The pointer to IFD_EXIF is in IFD_0. The pointer to
+ * IFD_INTEROPERABILITY is in IFD_EXIF.
+ */
+ if (data->ifd[EXIF_IFD_EXIF]->count ||
+ data->ifd[EXIF_IFD_INTEROPERABILITY]->count)
+ n_ptr++;
+
+ /* The pointer to IFD_GPS is in IFD_0. */
+ if (data->ifd[EXIF_IFD_GPS]->count)
+ n_ptr++;
+
+ break;
+ case EXIF_IFD_1:
+ if (data->size)
+ n_thumb = 2;
+ break;
+ case EXIF_IFD_EXIF:
+ if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count)
+ n_ptr++;
+ default:
+ break;
+ }
+
+ /*
+ * Allocate enough memory for all entries
+ * and the number of entries.
+ */
+ *ds += (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4);
+ *d = exif_mem_realloc (data->priv->mem, *d, *ds);
+ if (!*d) {
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", *ds);
+ return;
+ }
+
+ /* Save the number of entries */
+ exif_set_short (*d + 6 + offset, data->priv->order,
+ (ExifShort) (ifd->count + n_ptr + n_thumb));
+ offset += 2;
+
+ /* Save each entry */
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Saving %i entries (IFD '%s', offset: %i)...",
+ ifd->count, exif_ifd_get_name (i), offset);
+ for (j = 0; j < ifd->count; j++)
+ exif_data_save_data_entry (data, ifd->entries[j], d, ds, offset + 12 * j);
+
+ offset += 12 * ifd->count;
+
+ /* Now save special entries. */
+ switch (i) {
+ case EXIF_IFD_0:
+
+ /*
+ * The pointer to IFD_EXIF is in IFD_0.
+ * However, the pointer to IFD_INTEROPERABILITY is in IFD_EXIF,
+ * therefore, if IFD_INTEROPERABILITY is not empty, we need
+ * IFD_EXIF even if latter is empty.
+ */
+ if (data->ifd[EXIF_IFD_EXIF]->count ||
+ data->ifd[EXIF_IFD_INTEROPERABILITY]->count) {
+ exif_set_short (*d + 6 + offset + 0, data->priv->order,
+ EXIF_TAG_EXIF_IFD_POINTER);
+ exif_set_short (*d + 6 + offset + 2, data->priv->order,
+ EXIF_FORMAT_LONG);
+ exif_set_long (*d + 6 + offset + 4, data->priv->order,
+ 1);
+ exif_set_long (*d + 6 + offset + 8, data->priv->order,
+ *ds - 6);
+ exif_data_save_data_content (data,
+ data->ifd[EXIF_IFD_EXIF], d, ds, *ds - 6);
+ offset += 12;
+ }
+
+ /* The pointer to IFD_GPS is in IFD_0, too. */
+ if (data->ifd[EXIF_IFD_GPS]->count) {
+ exif_set_short (*d + 6 + offset + 0, data->priv->order,
+ EXIF_TAG_GPS_INFO_IFD_POINTER);
+ exif_set_short (*d + 6 + offset + 2, data->priv->order,
+ EXIF_FORMAT_LONG);
+ exif_set_long (*d + 6 + offset + 4, data->priv->order,
+ 1);
+ exif_set_long (*d + 6 + offset + 8, data->priv->order,
+ *ds - 6);
+ exif_data_save_data_content (data,
+ data->ifd[EXIF_IFD_GPS], d, ds, *ds - 6);
+ offset += 12;
+ }
+
+ break;
+ case EXIF_IFD_EXIF:
+
+ /*
+ * The pointer to IFD_INTEROPERABILITY is in IFD_EXIF.
+ * See note above.
+ */
+ if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count) {
+ exif_set_short (*d + 6 + offset + 0, data->priv->order,
+ EXIF_TAG_INTEROPERABILITY_IFD_POINTER);
+ exif_set_short (*d + 6 + offset + 2, data->priv->order,
+ EXIF_FORMAT_LONG);
+ exif_set_long (*d + 6 + offset + 4, data->priv->order,
+ 1);
+ exif_set_long (*d + 6 + offset + 8, data->priv->order,
+ *ds - 6);
+ exif_data_save_data_content (data,
+ data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds,
+ *ds - 6);
+ offset += 12;
+ }
+
+ break;
+ case EXIF_IFD_1:
+
+ /*
+ * Information about the thumbnail (if any) is saved in
+ * IFD_1.
+ */
+ if (data->size) {
+
+ /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT */
+ exif_set_short (*d + 6 + offset + 0, data->priv->order,
+ EXIF_TAG_JPEG_INTERCHANGE_FORMAT);
+ exif_set_short (*d + 6 + offset + 2, data->priv->order,
+ EXIF_FORMAT_LONG);
+ exif_set_long (*d + 6 + offset + 4, data->priv->order,
+ 1);
+ exif_set_long (*d + 6 + offset + 8, data->priv->order,
+ *ds - 6);
+ *ds += data->size;
+ *d = exif_mem_realloc (data->priv->mem, *d, *ds);
+ if (!*d) {
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData",
+ *ds);
+ return;
+ }
+ memcpy (*d + *ds - data->size, data->data, data->size);
+ offset += 12;
+
+ /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH */
+ exif_set_short (*d + 6 + offset + 0, data->priv->order,
+ EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
+ exif_set_short (*d + 6 + offset + 2, data->priv->order,
+ EXIF_FORMAT_LONG);
+ exif_set_long (*d + 6 + offset + 4, data->priv->order,
+ 1);
+ exif_set_long (*d + 6 + offset + 8, data->priv->order,
+ data->size);
+ offset += 12;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ /* Sort the directory according to TIFF specification */
+ qsort (*d + 6 + offset - (ifd->count + n_ptr + n_thumb) * 12,
+ (ifd->count + n_ptr + n_thumb), 12,
+ data->priv->order == EXIF_BYTE_ORDER_INTEL ? cmp_func_intel : cmp_func_motorola);
+
+ /* Correctly terminate the directory */
+ if (i == EXIF_IFD_0 && (data->ifd[EXIF_IFD_1]->count ||
+ data->size)) {
+
+ /*
+ * We are saving IFD 0. Tell where IFD 1 starts and save
+ * IFD 1.
+ */
+ exif_set_long (*d + 6 + offset, data->priv->order, *ds - 6);
+ exif_data_save_data_content (data, data->ifd[EXIF_IFD_1], d, ds,
+ *ds - 6);
+ } else
+ exif_set_long (*d + 6 + offset, data->priv->order, 0);
+}
+
+typedef enum {
+ EXIF_DATA_TYPE_MAKER_NOTE_NONE = 0,
+ EXIF_DATA_TYPE_MAKER_NOTE_CANON = 1,
+ EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS = 2,
+ EXIF_DATA_TYPE_MAKER_NOTE_PENTAX = 3
+} ExifDataTypeMakerNote;
+
+static ExifDataTypeMakerNote
+exif_data_get_type_maker_note (ExifData *d)
+{
+ ExifEntry *e, *em;
+ char value[1024];
+
+ if (!d) return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
+
+ e = exif_data_get_entry (d, EXIF_TAG_MAKER_NOTE);
+ if (!e) return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
+
+ /* Olympus & Nikon */
+ if ((e->size >= 5) && (!memcmp (e->data, "OLYMP", 5) ||
+ !memcmp (e->data, "Nikon", 5)))
+ return EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS;
+
+ em = exif_data_get_entry (d, EXIF_TAG_MAKE);
+ if (!em) return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
+
+ /* Canon */
+ if (!strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon"))
+ return EXIF_DATA_TYPE_MAKER_NOTE_CANON;
+
+ /* Pentax & some variant of Nikon */
+ if ((e->size >= 2) && (e->data[0] == 0x00) && (e->data[1] == 0x1b)) {
+ if (!strncasecmp (
+ exif_entry_get_value (em, value, sizeof(value)),
+ "Nikon", 5))
+ return EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS;
+ else
+ return EXIF_DATA_TYPE_MAKER_NOTE_PENTAX;
+ }
+
+ return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
+}
+
+#define LOG_TOO_SMALL \
+exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", \
+ _("Size of data too small to allow for EXIF data."));
+
+void
+exif_data_load_data (ExifData *data, const unsigned char *d_orig,
+ unsigned int ds_orig)
+{
+ unsigned int l;
+ ExifLong offset;
+ ExifShort n;
+ const unsigned char *d = d_orig;
+ unsigned int ds = ds_orig, len;
+
+ if (!data || !data->priv || !d || !ds) return;
+
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Parsing %i byte(s) EXIF data...\n", ds);
+
+ /*
+ * It can be that the data starts with the EXIF header. If it does
+ * not, search the EXIF marker.
+ */
+ if (ds < 6) {
+ LOG_TOO_SMALL;
+ return;
+ }
+ if (!memcmp (d, ExifHeader, 6)) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Found EXIF header.");
+ } else {
+ while (1) {
+ while ((d[0] == 0xff) && ds) {
+ d++;
+ ds--;
+ }
+
+ /* JPEG_MARKER_SOI */
+ if (d[0] == JPEG_MARKER_SOI) {
+ d++;
+ ds--;
+ continue;
+ }
+
+ /* JPEG_MARKER_APP0 */
+ if (d[0] == JPEG_MARKER_APP0) {
+ d++;
+ ds--;
+ l = (d[0] << 8) | d[1];
+ if (l > ds)
+ return;
+ d += l;
+ ds -= l;
+ continue;
+ }
+
+ /* JPEG_MARKER_APP1 */
+ if (d[0] == JPEG_MARKER_APP1)
+ break;
+
+ /* Unknown marker or data. Give up. */
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifData", _("EXIF marker not found."));
+ return;
+ }
+ d++;
+ ds--;
+ if (ds < 2) {
+ LOG_TOO_SMALL;
+ return;
+ }
+ len = (d[0] << 8) | d[1];
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "We have to deal with %i byte(s) of EXIF data.",
+ len);
+ d += 2;
+ ds -= 2;
+ }
+
+ /*
+ * Verify the exif header
+ * (offset 2, length 6).
+ */
+ if (ds < 6) {
+ LOG_TOO_SMALL;
+ return;
+ }
+ if (memcmp (d, ExifHeader, 6)) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifData", _("EXIF header not found."));
+ return;
+ }
+
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Found EXIF header.");
+
+ /* Byte order (offset 6, length 2) */
+ if (ds < 14)
+ return;
+ if (!memcmp (d + 6, "II", 2))
+ data->priv->order = EXIF_BYTE_ORDER_INTEL;
+ else if (!memcmp (d + 6, "MM", 2))
+ data->priv->order = EXIF_BYTE_ORDER_MOTOROLA;
+ else {
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifData", _("Unknown encoding."));
+ return;
+ }
+
+ /* Fixed value */
+ if (exif_get_short (d + 8, data->priv->order) != 0x002a)
+ return;
+
+ /* IFD 0 offset */
+ offset = exif_get_long (d + 10, data->priv->order);
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "IFD 0 at %i.", (int) offset);
+
+ /* Parse the actual exif data (usually offset 14 from start) */
+ exif_data_load_data_content (data, data->ifd[EXIF_IFD_0], d + 6,
+ ds - 6, offset);
+
+ /* IFD 1 offset */
+ if (offset + 6 + 2 > ds) {
+ return;
+ }
+ n = exif_get_short (d + 6 + offset, data->priv->order);
+ if (offset + 6 + 2 + 12 * n + 4 > ds) {
+ return;
+ }
+ offset = exif_get_long (d + 6 + offset + 2 + 12 * n, data->priv->order);
+ if (offset) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "IFD 1 at %i.", (int) offset);
+
+ /* Sanity check. */
+ if (offset > ds - 6) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifData", "Bogus offset.");
+ return;
+ }
+
+ exif_data_load_data_content (data, data->ifd[EXIF_IFD_1], d + 6,
+ ds - 6, offset);
+ }
+
+ /*
+ * If we got an EXIF_TAG_MAKER_NOTE, try to interpret it. Some
+ * cameras use pointers in the maker note tag that point to the
+ * space between IFDs. Here is the only place where we have access
+ * to that data.
+ */
+ switch (exif_data_get_type_maker_note (data)) {
+ case EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS:
+ data->priv->md = exif_mnote_data_olympus_new (data->priv->mem);
+ break;
+ case EXIF_DATA_TYPE_MAKER_NOTE_PENTAX:
+ data->priv->md = exif_mnote_data_pentax_new (data->priv->mem);
+ break;
+ case EXIF_DATA_TYPE_MAKER_NOTE_CANON:
+ data->priv->md = exif_mnote_data_canon_new (data->priv->mem);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * If we are able to interpret the maker note, do so.
+ */
+ if (data->priv->md) {
+ exif_mnote_data_log (data->priv->md, data->priv->log);
+ exif_mnote_data_set_byte_order (data->priv->md,
+ data->priv->order);
+ exif_mnote_data_set_offset (data->priv->md,
+ data->priv->offset_mnote);
+ exif_mnote_data_load (data->priv->md, d, ds);
+ }
+}
+
+void
+exif_data_save_data (ExifData *data, unsigned char **d, unsigned int *ds)
+{
+ if (!data || !d || !ds)
+ return;
+
+ /* Header */
+ *ds = 14;
+ *d = exif_data_alloc (data, *ds);
+ if (!*d) return;
+ memcpy (*d, ExifHeader, 6);
+
+ /* Order (offset 6) */
+ if (data->priv->order == EXIF_BYTE_ORDER_INTEL) {
+ memcpy (*d + 6, "II", 2);
+ } else {
+ memcpy (*d + 6, "MM", 2);
+ }
+
+ /* Fixed value (2 bytes, offset 8) */
+ exif_set_short (*d + 8, data->priv->order, 0x002a);
+
+ /*
+ * IFD 0 offset (4 bytes, offset 10).
+ * We will start 8 bytes after the
+ * EXIF header (2 bytes for order, another 2 for the test, and
+ * 4 bytes for the IFD 0 offset make 8 bytes together).
+ */
+ exif_set_long (*d + 10, data->priv->order, 8);
+
+ /* Now save IFD 0. IFD 1 will be saved automatically. */
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Saving IFDs...");
+ exif_data_save_data_content (data, data->ifd[EXIF_IFD_0], d, ds,
+ *ds - 6);
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Saved %i byte(s) EXIF data.", *ds);
+}
+
+ExifData *
+exif_data_new_from_file (const char *path)
+{
+ ExifData *edata;
+ ExifLoader *loader;
+
+ loader = exif_loader_new ();
+ exif_loader_write_file (loader, path);
+ edata = exif_loader_get_data (loader);
+ exif_loader_unref (loader);
+
+ return (edata);
+}
+
+void
+exif_data_ref (ExifData *data)
+{
+ if (!data)
+ return;
+
+ data->priv->ref_count++;
+}
+
+void
+exif_data_unref (ExifData *data)
+{
+ if (!data) return;
+
+ data->priv->ref_count--;
+ if (!data->priv->ref_count) exif_data_free (data);
+}
+
+void
+exif_data_free (ExifData *data)
+{
+ unsigned int i;
+ ExifMem *mem = (data && data->priv) ? data->priv->mem : NULL;
+
+ if (!data) return;
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++) {
+ if (data->ifd[i]) {
+ exif_content_unref (data->ifd[i]);
+ data->ifd[i] = NULL;
+ }
+ }
+
+ if (data->data) {
+ exif_mem_free (mem, data->data);
+ data->data = NULL;
+ }
+
+ if (data->priv) {
+ if (data->priv->log) {
+ exif_log_unref (data->priv->log);
+ data->priv->log = NULL;
+ }
+ if (data->priv->md) {
+ exif_mnote_data_unref (data->priv->md);
+ data->priv->md = NULL;
+ }
+ exif_mem_free (mem, data->priv);
+ exif_mem_free (mem, data);
+ }
+
+ exif_mem_unref (mem);
+}
+
+void
+exif_data_dump (ExifData *data)
+{
+ unsigned int i;
+
+ if (!data)
+ return;
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++) {
+ if (data->ifd[i] && data->ifd[i]->count) {
+ printf ("Dumping IFD '%s'...\n",
+ exif_ifd_get_name (i));
+ exif_content_dump (data->ifd[i], 0);
+ }
+ }
+
+ if (data->data) {
+ printf ("%i byte(s) thumbnail data available.", data->size);
+ if (data->size >= 4) {
+ printf ("0x%02x 0x%02x ... 0x%02x 0x%02x\n",
+ data->data[0], data->data[1],
+ data->data[data->size - 2],
+ data->data[data->size - 1]);
+ }
+ }
+}
+
+ExifByteOrder
+exif_data_get_byte_order (ExifData *data)
+{
+ if (!data)
+ return (0);
+
+ return (data->priv->order);
+}
+
+void
+exif_data_foreach_content (ExifData *data, ExifDataForeachContentFunc func,
+ void *user_data)
+{
+ unsigned int i;
+
+ if (!data || !func)
+ return;
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++)
+ func (data->ifd[i], user_data);
+}
+
+typedef struct _ByteOrderChangeData ByteOrderChangeData;
+struct _ByteOrderChangeData {
+ ExifByteOrder old, new;
+};
+
+static void
+entry_set_byte_order (ExifEntry *e, void *data)
+{
+ ByteOrderChangeData *d = data;
+
+ if (!e)
+ return;
+
+ exif_array_set_byte_order (e->format, e->data, e->components, d->old, d->new);
+}
+
+static void
+content_set_byte_order (ExifContent *content, void *data)
+{
+ exif_content_foreach_entry (content, entry_set_byte_order, data);
+}
+
+void
+exif_data_set_byte_order (ExifData *data, ExifByteOrder order)
+{
+ ByteOrderChangeData d;
+
+ if (!data || (order == data->priv->order))
+ return;
+
+ d.old = data->priv->order;
+ d.new = order;
+ exif_data_foreach_content (data, content_set_byte_order, &d);
+ data->priv->order = order;
+ if (data->priv->md)
+ exif_mnote_data_set_byte_order (data->priv->md, order);
+}
+
+void
+exif_data_log (ExifData *data, ExifLog *log)
+{
+ unsigned int i;
+
+ if (!data || !data->priv) return;
+ exif_log_unref (data->priv->log);
+ data->priv->log = log;
+ exif_log_ref (log);
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++)
+ exif_content_log (data->ifd[i], log);
+}
+
+/* Used internally within libexif */
+ExifLog *exif_data_get_log (ExifData *);
+ExifLog *
+exif_data_get_log (ExifData *data)
+{
+ if (!data || !data->priv) return NULL;
+ return data->priv->log;
+}
diff --git a/src/libexif/exif-data.h b/src/libexif/exif-data.h
new file mode 100644
index 0000000..9ecad1d
--- /dev/null
+++ b/src/libexif/exif-data.h
@@ -0,0 +1,104 @@
+/*! \file exif-data.h
+ * \brief FIXME foo bar blah
+ *
+ * \author Lutz Müller <lutz@users.sourceforge.net>
+ * \date 2001-2005
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_DATA_H__
+#define __EXIF_DATA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-ifd.h>
+#include <libexif/exif-log.h>
+#include <libexif/exif-tag.h>
+
+typedef struct _ExifData ExifData;
+typedef struct _ExifDataPrivate ExifDataPrivate;
+
+#include <libexif/exif-content.h>
+#include <libexif/exif-mnote-data.h>
+#include <libexif/exif-mem.h>
+
+struct _ExifData
+{
+ ExifContent *ifd[EXIF_IFD_COUNT];
+
+ unsigned char *data;
+ unsigned int size;
+
+ ExifDataPrivate *priv;
+};
+
+ExifData *exif_data_new (void);
+ExifData *exif_data_new_mem (ExifMem *);
+
+/*! \brief load exif data from file
+ * \param[in] path filename including path
+ *
+ * Foo bar blah bleh baz.
+ */
+ExifData *exif_data_new_from_file (const char *path);
+ExifData *exif_data_new_from_data (const unsigned char *data,
+ unsigned int size);
+
+void exif_data_load_data (ExifData *data, const unsigned char *d,
+ unsigned int size);
+void exif_data_save_data (ExifData *data, unsigned char **d,
+ unsigned int *size);
+
+void exif_data_ref (ExifData *data);
+void exif_data_unref (ExifData *data);
+void exif_data_free (ExifData *data);
+
+ExifByteOrder exif_data_get_byte_order (ExifData *data);
+void exif_data_set_byte_order (ExifData *data, ExifByteOrder order);
+
+ExifMnoteData *exif_data_get_mnote_data (ExifData *);
+
+typedef void (* ExifDataForeachContentFunc) (ExifContent *, void *user_data);
+void exif_data_foreach_content (ExifData *data,
+ ExifDataForeachContentFunc func,
+ void *user_data);
+
+/* For debugging purposes and error reporting */
+void exif_data_dump (ExifData *data);
+void exif_data_log (ExifData *data, ExifLog *log);
+
+/* For your convenience */
+#define exif_data_get_entry(d,t) \
+ (exif_content_get_entry(d->ifd[EXIF_IFD_0],t) ? \
+ exif_content_get_entry(d->ifd[EXIF_IFD_0],t) : \
+ exif_content_get_entry(d->ifd[EXIF_IFD_1],t) ? \
+ exif_content_get_entry(d->ifd[EXIF_IFD_1],t) : \
+ exif_content_get_entry(d->ifd[EXIF_IFD_EXIF],t) ? \
+ exif_content_get_entry(d->ifd[EXIF_IFD_EXIF],t) : \
+ exif_content_get_entry(d->ifd[EXIF_IFD_GPS],t) ? \
+ exif_content_get_entry(d->ifd[EXIF_IFD_GPS],t) : \
+ exif_content_get_entry(d->ifd[EXIF_IFD_INTEROPERABILITY],t) ? \
+ exif_content_get_entry(d->ifd[EXIF_IFD_INTEROPERABILITY],t) : NULL)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_DATA_H__ */
diff --git a/src/libexif/exif-entry.c b/src/libexif/exif-entry.c
new file mode 100644
index 0000000..09d37e2
--- /dev/null
+++ b/src/libexif/exif-entry.c
@@ -0,0 +1,1383 @@
+/* exif-entry.c
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-entry.h>
+#include <libexif/exif-ifd.h>
+#include <libexif/exif-utils.h>
+#include <libexif/i18n.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+
+struct _ExifEntryPrivate
+{
+ unsigned int ref_count;
+
+ ExifMem *mem;
+};
+
+/* This function is hidden in exif-data.c */
+ExifLog *exif_data_get_log (ExifData *);
+
+static void
+exif_entry_log (ExifEntry *e, ExifLogCode code, const char *format, ...)
+{
+ va_list args;
+ ExifLog *l = NULL;
+
+ if (e && e->parent && e->parent->parent)
+ l = exif_data_get_log (e->parent->parent);
+ va_start (args, format);
+ exif_logv (l, code, "ExifEntry", format, args);
+ va_end (args);
+}
+
+static void *
+exif_entry_alloc (ExifEntry *e, unsigned int i)
+{
+ void *d;
+ ExifLog *l = NULL;
+
+ if (!e || !e->priv || !i) return NULL;
+
+ d = exif_mem_alloc (e->priv->mem, i);
+ if (d) return d;
+
+ if (e->parent && e->parent->parent)
+ l = exif_data_get_log (e->parent->parent);
+ EXIF_LOG_NO_MEMORY (l, "ExifEntry", i);
+ return NULL;
+}
+
+static void *
+exif_entry_realloc (ExifEntry *e, void *d_orig, unsigned int i)
+{
+ void *d;
+ ExifLog *l = NULL;
+
+ if (!e || !e->priv) return NULL;
+
+ if (!i) { exif_mem_free (e->priv->mem, d_orig); return NULL; }
+
+ d = exif_mem_realloc (e->priv->mem, d_orig, i);
+ if (d) return d;
+
+ if (e->parent && e->parent->parent)
+ l = exif_data_get_log (e->parent->parent);
+ EXIF_LOG_NO_MEMORY (l, "ExifEntry", i);
+ return NULL;
+}
+
+ExifEntry *
+exif_entry_new (void)
+{
+ ExifMem *mem = exif_mem_new_default ();
+ ExifEntry *e = exif_entry_new_mem (mem);
+
+ exif_mem_unref (mem);
+
+ return e;
+}
+
+ExifEntry *
+exif_entry_new_mem (ExifMem *mem)
+{
+ ExifEntry *e = NULL;
+
+ e = exif_mem_alloc (mem, sizeof (ExifEntry));
+ if (!e) return NULL;
+ e->priv = exif_mem_alloc (mem, sizeof (ExifEntryPrivate));
+ if (!e->priv) { exif_mem_free (mem, e); return NULL; }
+ e->priv->ref_count = 1;
+
+ e->priv->mem = mem;
+ exif_mem_ref (mem);
+
+ return e;
+}
+
+void
+exif_entry_ref (ExifEntry *e)
+{
+ if (!e) return;
+
+ e->priv->ref_count++;
+}
+
+void
+exif_entry_unref (ExifEntry *e)
+{
+ if (!e) return;
+
+ e->priv->ref_count--;
+ if (!e->priv->ref_count)
+ exif_entry_free (e);
+}
+
+void
+exif_entry_free (ExifEntry *e)
+{
+ if (!e) return;
+
+ if (e->priv) {
+ ExifMem *mem = e->priv->mem;
+ if (e->data)
+ exif_mem_free (mem, e->data);
+ exif_mem_free (mem, e->priv);
+ exif_mem_free (mem, e);
+ exif_mem_unref (mem);
+ }
+}
+
+void
+exif_entry_fix (ExifEntry *e)
+{
+ unsigned int i;
+ ExifByteOrder o;
+ ExifRational r;
+ ExifSRational sr;
+
+ if (!e || !e->priv) return;
+
+ switch (e->tag) {
+
+ /* These tags all need to be of format SHORT. */
+ case EXIF_TAG_YCBCR_SUB_SAMPLING:
+ case EXIF_TAG_SUBJECT_AREA:
+ case EXIF_TAG_COLOR_SPACE:
+ case EXIF_TAG_PLANAR_CONFIGURATION:
+ case EXIF_TAG_SENSING_METHOD:
+ case EXIF_TAG_ORIENTATION:
+ case EXIF_TAG_YCBCR_POSITIONING:
+ case EXIF_TAG_PHOTOMETRIC_INTERPRETATION:
+ case EXIF_TAG_CUSTOM_RENDERED:
+ case EXIF_TAG_EXPOSURE_MODE:
+ case EXIF_TAG_WHITE_BALANCE:
+ case EXIF_TAG_SCENE_CAPTURE_TYPE:
+ case EXIF_TAG_GAIN_CONTROL:
+ case EXIF_TAG_SATURATION:
+ case EXIF_TAG_CONTRAST:
+ case EXIF_TAG_SHARPNESS:
+ switch (e->format) {
+ case EXIF_FORMAT_LONG:
+ if (!e->parent || !e->parent->parent) break;
+ o = exif_data_get_byte_order (e->parent->parent);
+ for (i = 0; i < e->components; i++)
+ exif_set_short (
+ e->data + i *
+ exif_format_get_size (
+ EXIF_FORMAT_SHORT), o,
+ (ExifShort) exif_get_long (
+ e->data + i *
+ exif_format_get_size (
+ EXIF_FORMAT_LONG), o));
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = e->components *
+ exif_format_get_size (e->format);
+ e->data = exif_entry_realloc (e, e->data, e->size);
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ "Tag '%s' was of format '%s' (which is "
+ "against specification) and has been "
+ "changed to format '%s'.",
+ exif_tag_get_name (e->tag),
+ exif_format_get_name (EXIF_FORMAT_LONG),
+ exif_format_get_name (EXIF_FORMAT_SHORT));
+ break;
+ case EXIF_FORMAT_SHORT:
+ default:
+ break;
+ }
+ break;
+
+ /* All these tags need to be of format 'Rational'. */
+ case EXIF_TAG_FNUMBER:
+ case EXIF_TAG_APERTURE_VALUE:
+ case EXIF_TAG_EXPOSURE_TIME:
+ case EXIF_TAG_FOCAL_LENGTH:
+ switch (e->format) {
+ case EXIF_FORMAT_SRATIONAL:
+ if (!e->parent || !e->parent->parent) break;
+ o = exif_data_get_byte_order (e->parent->parent);
+ for (i = 0; i < e->components; i++) {
+ sr = exif_get_srational (e->data + i *
+ exif_format_get_size (
+ EXIF_FORMAT_SRATIONAL), o);
+ r.numerator = (ExifLong) sr.numerator;
+ r.denominator = (ExifLong) sr.denominator;
+ exif_set_rational (e->data + i *
+ exif_format_get_size (
+ EXIF_FORMAT_RATIONAL), o, r);
+ }
+ e->format = EXIF_FORMAT_RATIONAL;
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ "Tag '%s' was of format '%s' (which is "
+ "against specification) and has been "
+ "changed to format '%s'.",
+ exif_tag_get_name (e->tag),
+ exif_format_get_name (EXIF_FORMAT_SRATIONAL),
+ exif_format_get_name (EXIF_FORMAT_RATIONAL));
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case EXIF_TAG_USER_COMMENT:
+
+ /* Format needs to be UNDEFINED. */
+ if (e->format != EXIF_FORMAT_UNDEFINED) {
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ "Tag 'UserComment' had invalid format '%s'. "
+ "Format has been set to 'undefined'.",
+ exif_format_get_name (e->format));
+ e->format = EXIF_FORMAT_UNDEFINED;
+ }
+ /* Some packages like Canon ZoomBrowser EX 4.5 store
+ only one zero byte followed by 7 bytes of rubbish */
+ if ((e->size >= 8) && (e->data[0] == 0)) {
+ memcpy(e->data, "\0\0\0\0\0\0\0\0", 8);
+ }
+
+ /* Some cameras fill the tag with '\0' or ' '. */
+ for (i = 0; i < e->size &&
+ (!e->data[i] || (e->data[i] == ' ')); i++);
+ if (i && (i == e->size)) {
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ "Tag 'UserComment' contained unnecessary "
+ "data which has been removed.");
+ exif_mem_free (e->priv->mem, e->data);
+ e->data = NULL;
+ e->size = 0;
+ e->components = 0;
+ }
+
+ /* There need to be at least 8 bytes. */
+ if (e->size < 8) {
+ e->data = exif_entry_realloc (e, e->data, 8 + e->size);
+ if (!e->data) {
+ e->size = 0;
+ e->components = 0;
+ return;
+ }
+
+ /* Assume ASCII */
+ memmove (e->data + 8, e->data, e->size);
+ memcpy (e->data, "ASCII\0\0\0", 8);
+ e->size += 8;
+ e->components += 8;
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ "Tag 'UserComment' has been expanded to at "
+ "least 8 bytes in order to follow the "
+ "specification.");
+ break;
+ }
+
+ /*
+ * If the first 8 bytes are empty and real data starts
+ * afterwards, let's assume ASCII and claim the 8 first
+ * bytes for the format specifyer.
+ */
+ if (i >= 8) {
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ "Tag 'UserComment' did not start with "
+ "format identifyer. This has been fixed.");
+ memcpy (e->data, "ASCII\0\0\0", 8);
+ }
+
+ /* First 8 bytes need to follow the specification. */
+ if (memcmp (e->data, "ASCII\0\0\0" , 8) &&
+ memcmp (e->data, "UNICODE\0" , 8) &&
+ memcmp (e->data, "JIS\0\0\0\0\0" , 8) &&
+ memcmp (e->data, "\0\0\0\0\0\0\0\0", 8)) {
+ e->data = exif_entry_realloc (e, e->data, 8 + e->size);
+ if (!e->data) {
+ e->size = 0;
+ e->components = 0;
+ break;
+ }
+
+ /* Assume ASCII */
+ memmove (e->data + 8, e->data, e->size);
+ memcpy (e->data, "ASCII\0\0\0", 8);
+ e->size += 8;
+ e->components += 8;
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ "Tag 'UserComment' did not start with "
+ "format identifyer. This has been fixed.");
+ break;
+ }
+
+ break;
+ default:
+ break;
+ }
+}
+
+void
+exif_entry_dump (ExifEntry *e, unsigned int indent)
+{
+ char buf[1024];
+ char value[1024];
+ unsigned int i;
+
+ for (i = 0; i < 2 * indent; i++)
+ buf[i] = ' ';
+ buf[i] = '\0';
+
+ if (!e)
+ return;
+
+ printf ("%sTag: 0x%x ('%s')\n", buf, e->tag,
+ exif_tag_get_name (e->tag));
+ printf ("%s Format: %i ('%s')\n", buf, e->format,
+ exif_format_get_name (e->format));
+ printf ("%s Components: %i\n", buf, (int) e->components);
+ printf ("%s Size: %i\n", buf, e->size);
+ printf ("%s Value: %s\n", buf, exif_entry_get_value (e, value, sizeof(value)));
+}
+
+#define CF(entry,target,v,maxlen) \
+{ \
+ if (entry->format != target) { \
+ exif_entry_log (entry, EXIF_LOG_CODE_CORRUPT_DATA, \
+ _("The tag '%s' contains data of an invalid " \
+ "format ('%s', expected '%s')."), \
+ exif_tag_get_name (entry->tag), \
+ exif_format_get_name (entry->format), \
+ exif_format_get_name (target)); \
+ break; \
+ } \
+}
+
+#define CC(entry,target,v,maxlen) \
+{ \
+ if (entry->components != target) { \
+ exif_entry_log (entry, EXIF_LOG_CODE_CORRUPT_DATA, \
+ _("The tag '%s' contains an invalid number of " \
+ "components (%i, expected %i)."), \
+ exif_tag_get_name (entry->tag), \
+ (int) entry->components, (int) target); \
+ break; \
+ } \
+}
+
+static struct {
+ ExifTag tag;
+ const char *strings[10];
+} list[] = {
+ { EXIF_TAG_PLANAR_CONFIGURATION,
+ { N_("chunky format"), N_("planar format"), NULL}},
+ { EXIF_TAG_SENSING_METHOD,
+ { "", N_("Not defined"), N_("One-chip color area sensor"),
+ N_("Two-chip color area sensor"), N_("Three-chip color area sensor"),
+ N_("Color sequential area sensor"), "", N_("Trilinear sensor"),
+ N_("Color sequential linear sensor"), NULL}},
+ { EXIF_TAG_ORIENTATION,
+ { "", N_("top - left"), N_("top - right"), N_("bottom - right"),
+ N_("bottom - left"), N_("left - top"), N_("right - top"),
+ N_("right - bottom"), N_("left - bottom"), NULL}},
+ { EXIF_TAG_YCBCR_POSITIONING,
+ { "", N_("centered"), N_("co-sited"), NULL}},
+ { EXIF_TAG_PHOTOMETRIC_INTERPRETATION, {"", N_("RGB"), N_("YCbCr"), NULL}},
+ { EXIF_TAG_CUSTOM_RENDERED,
+ { N_("Normal process"), N_("Custom process"), NULL}},
+ { EXIF_TAG_EXPOSURE_MODE,
+ { N_("Auto exposure"), N_("Manual exposure"), N_("Auto bracket"), NULL}},
+ { EXIF_TAG_WHITE_BALANCE,
+ { N_("Auto white balance"), N_("Manual white balance"), NULL}},
+ { EXIF_TAG_SCENE_CAPTURE_TYPE,
+ { N_("Standard"), N_("Landscape"), N_("Portrait"),
+ N_("Night scene"), NULL}},
+ { EXIF_TAG_GAIN_CONTROL,
+ { N_("Normal"), N_("Low gain up"), N_("High gain up"),
+ N_("Low gain down"), N_("High gain down"), NULL}},
+ { EXIF_TAG_SATURATION,
+ { N_("Normal"), N_("Low saturation"), N_("High saturation"), NULL}},
+ { EXIF_TAG_CONTRAST , {N_("Normal"), N_("Soft"), N_("Hard"), NULL}},
+ { EXIF_TAG_SHARPNESS, {N_("Normal"), N_("Soft"), N_("Hard"), NULL}},
+ { 0, {NULL}}
+};
+
+static struct {
+ ExifTag tag;
+ struct {
+ int index;
+ const char *values[4];
+ } elem[25];
+} list2[] = {
+ { EXIF_TAG_METERING_MODE,
+ { { 0, {N_("Unknown"), NULL}},
+ { 1, {N_("Average"), N_("avg"), NULL}},
+ { 2, {N_("Center-Weighted Average"), N_("Center-Weight"), NULL}},
+ { 3, {N_("Spot"), NULL}},
+ { 4, {N_("Multi Spot"), NULL}},
+ { 5, {N_("Pattern"), NULL}},
+ { 6, {N_("Partial"), NULL}},
+ {255, {N_("Other"), NULL}},
+ { 0, {NULL}}}},
+ { EXIF_TAG_COMPRESSION,
+ { {1, {N_("Uncompressed"), NULL}},
+ {5, {N_("LZW compression"), NULL}},
+ {6, {N_("JPEG compression"), NULL}},
+ {0, {NULL}}}},
+ { EXIF_TAG_LIGHT_SOURCE,
+ { { 0, {N_("Unknown"), NULL}},
+ { 1, {N_("Daylight"), NULL}},
+ { 2, {N_("Fluorescent"), NULL}},
+ { 3, {N_("Tungsten incandescent light"), N_("Tungsten"), NULL}},
+ { 4, {N_("Flash"), NULL}},
+ { 9, {N_("Fine weather"), NULL}},
+ { 10, {N_("Cloudy weather"), N_("cloudy"), NULL}},
+ { 11, {N_("Shade"), NULL}},
+ { 12, {N_("Daylight fluorescent"), NULL}},
+ { 13, {N_("Day white fluorescent"), NULL}},
+ { 14, {N_("Cool white fluorescent"), NULL}},
+ { 15, {N_("White fluorescent"), NULL}},
+ { 17, {N_("Standard light A"), NULL}},
+ { 18, {N_("Standard light B"), NULL}},
+ { 19, {N_("Standard light C"), NULL}},
+ { 20, {N_("D55"), NULL}},
+ { 21, {N_("D65"), NULL}},
+ { 22, {N_("D75"), NULL}},
+ { 24, {N_("ISO studio tungsten"),NULL}},
+ {255, {N_("Other"), NULL}},
+ { 0, {NULL}}}},
+ { EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT,
+ { {2, {N_("Inch"), N_("in"), NULL}},
+ {3, {N_("Centimeter"), N_("cm"), NULL}},
+ {0, {NULL}}}},
+ { EXIF_TAG_RESOLUTION_UNIT,
+ { {2, {N_("Inch"), N_("in"), NULL}},
+ {3, {N_("Centimeter"), N_("cm"), NULL}},
+ {0, {NULL}}}},
+ { EXIF_TAG_EXPOSURE_PROGRAM,
+ { {0, {N_("Not defined"), NULL}},
+ {1, {N_("Manual"), NULL}},
+ {2, {N_("Normal program"), N_("Normal"), NULL}},
+ {3, {N_("Aperture priority"), N_("Aperture"), NULL}},
+ {4, {N_("Shutter priority"),N_("Shutter"), NULL}},
+ {5, {N_("Creative program (biased toward depth of field)"),
+ N_("Creative"), NULL}},
+ {6, {N_("Creative program (biased toward fast shutter speed"),
+ N_("Action"), NULL}},
+ {7, {N_("Portrait mode (for closeup photos with the background out "
+ "of focus)"), N_("Portrait"), NULL}},
+ {8, {N_("Landscape mode (for landscape photos with the background "
+ "in focus)"), N_("Landscape"), NULL}},
+ {0, {NULL}}}},
+ { EXIF_TAG_FLASH,
+ { {0x0000, {N_("Flash did not fire."), N_("no flash"), NULL}},
+ {0x0001, {N_("Flash fired."), N_("flash"), N_("Yes"), NULL}},
+ {0x0005, {N_("Strobe return light not detected."), N_("W/o strobe"),
+ NULL}},
+ {0x0007, {N_("Strobe return light detected."), N_("W. strobe"), NULL}},
+ {0x0009, {N_("Flash fired, compulsatory flash mode"), NULL}},
+ {0x000d, {N_("Flash fired, compulsatory flash mode, return light "
+ "not detected."), NULL}},
+ {0x000f, {N_("Flash fired, compulsatory flash mode, return light "
+ "detected."), NULL}},
+ {0x0010, {N_("Flash did not fire, compulsatory flash mode."), NULL}},
+ {0x0018, {N_("Flash did not fire, auto mode."), NULL}},
+ {0x0019, {N_("Flash fired, auto mode."), NULL}},
+ {0x001d, {N_("Flash fired, auto mode, return light not detected."),
+ NULL}},
+ {0x001f, {N_("Flash fired, auto mode, return light detected."), NULL}},
+ {0x0020, {N_("No flash function."),NULL}},
+ {0x0041, {N_("Flash fired, red-eye reduction mode."), NULL}},
+ {0x0045, {N_("Flash fired, red-eye reduction mode, return light "
+ "not detected."), NULL}},
+ {0x0047, {N_("Flash fired, red-eye reduction mode, return light "
+ "detected."), NULL}},
+ {0x0049, {N_("Flash fired, compulsory flash mode, red-eye reduction "
+ "mode."), NULL}},
+ {0x004d, {N_("Flash fired, compulsory flash mode, red-eye reduction "
+ "mode, return light not detected"), NULL}},
+ {0x004f, {N_("Flash fired, compulsory flash mode, red-eye reduction, "
+ "return light detected"), NULL}},
+ {0x0058, {N_("Flash did not fire, auto mode, red-eye reduction mode"), NULL}},
+ {0x0059, {N_("Flash fired, auto mode, red-eye reduction mode"), NULL}},
+ {0x005d, {N_("Flash fired, auto mode, return light not detected, "
+ "red-eye reduction mode."), NULL}},
+ {0x005f, {N_("Flash fired, auto mode, return light detected, "
+ "red-eye reduction mode."), NULL}},
+ {0x0000, {NULL}}}},
+ {EXIF_TAG_SUBJECT_DISTANCE_RANGE,
+ { {0, {N_("Unknown"), N_("?"), NULL}},
+ {1, {N_("Macro"), NULL}},
+ {2, {N_("Close view"), N_("close"), NULL}},
+ {3, {N_("Distant view"), N_("distant"), NULL}},
+ {0, {NULL}}}},
+ { EXIF_TAG_COLOR_SPACE,
+ { {1, {N_("sRGB"), NULL}},
+ {0xffff, {N_("Uncalibrated"), NULL}}}},
+ {0, }
+};
+
+const char *
+exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
+{
+ unsigned int i, j, k, l, ts;
+ const unsigned char *t;
+ ExifByte v_byte;
+ ExifShort v_short, v_short2, v_short3, v_short4;
+ ExifLong v_long;
+ ExifSLong v_slong;
+ ExifRational v_rat;
+ ExifSRational v_srat;
+ char b[64];
+ const char *c;
+ ExifByteOrder o;
+ double d;
+ ExifEntry *entry;
+ static struct {
+ char *label;
+ char major, minor;
+ } versions[] = {
+ {"0110", 1, 1},
+ {"0120", 1, 2},
+ {"0200", 2, 0},
+ {"0210", 2, 1},
+ {"0220", 2, 2},
+ {"0221", 2, 21},
+ {NULL , 0, 0}
+ };
+
+ /* FIXME: This belongs to somewhere else. */
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+
+ /* We need the byte order */
+ if (!e || !e->parent || !e->parent->parent)
+ return val;
+ o = exif_data_get_byte_order (e->parent->parent);
+
+ memset (val, 0, maxlen);
+ memset (b, 0, sizeof (b));
+ maxlen--;
+
+ /* Sanity check */
+ if (e->size != e->components * exif_format_get_size (e->format)) {
+ snprintf (val, maxlen, _("Invalid size of entry (%i, "
+ "expected %li x %i)."), e->size, e->components,
+ exif_format_get_size (e->format));
+ return val;
+ }
+
+ switch (e->tag) {
+ case EXIF_TAG_USER_COMMENT:
+
+ /*
+ * The specification says UNDEFINED, but some
+ * manufacturers don't care and use ASCII. If this is the
+ * case here, only refuse to read it if there is no chance
+ * of finding readable data.
+ */
+ if ((e->format != EXIF_FORMAT_ASCII) ||
+ (e->size <= 8) ||
+ ( memcmp (e->data, "ASCII\0\0\0" , 8) &&
+ memcmp (e->data, "UNICODE\0" , 8) &&
+ memcmp (e->data, "JIS\0\0\0\0\0", 8) &&
+ memcmp (e->data, "\0\0\0\0\0\0\0\0", 8)))
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+
+ /*
+ * Note that, according to the specification (V2.1, p 40),
+ * the user comment field does not have to be
+ * NULL terminated.
+ */
+ if ((e->size >= 8) && !memcmp (e->data, "ASCII\0\0\0", 8)) {
+ strncpy (val, (char *) e->data + 8, MIN (e->size - 8, maxlen));
+ break;
+ }
+ if ((e->size >= 8) && !memcmp (e->data, "UNICODE\0", 8)) {
+ strncpy (val, _("Unsupported UNICODE string"), maxlen);
+ break;
+ }
+ if ((e->size >= 8) && !memcmp (e->data, "JIS\0\0\0\0\0", 8)) {
+ strncpy (val, _("Unsupported JIS string"), maxlen);
+ break;
+ }
+
+ /* Check if there is really some information in the tag. */
+ for (i = 0; (i < e->size) &&
+ (!e->data[i] || (e->data[i] == ' ')); i++);
+ if (i == e->size) break;
+
+ /*
+ * If we reach this point, the tag does not
+ * comply with the standard and seems to contain data.
+ * Print as much as possible.
+ */
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ "Tag UserComment does not comply "
+ "with standard but contains data.");
+ for (; (i < e->size) && (strlen (val) < maxlen - 1); i++) {
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ "Byte at position %i: 0x%02x", i, e->data[i]);
+ val[strlen (val)] =
+ isprint (e->data[i]) ? e->data[i] : '.';
+ }
+ break;
+
+ case EXIF_TAG_EXIF_VERSION:
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (e, 4, val, maxlen);
+ strncpy (val, _("Unknown Exif Version"), maxlen);
+ for (i = 0; versions[i].label; i++) {
+ if (!memcmp (e->data, versions[i].label, 4)) {
+ snprintf (val, maxlen,
+ _("Exif Version %d.%d"),
+ versions[i].major,
+ versions[i].minor);
+ break;
+ }
+ }
+ break;
+ case EXIF_TAG_FLASH_PIX_VERSION:
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (e, 4, val, maxlen);
+ if (!memcmp (e->data, "0100", 4))
+ strncpy (val, _("FlashPix Version 1.0"), maxlen);
+ else if (!memcmp (e->data, "0101", 4))
+ strncpy (val, _("FlashPix Version 1.01"), maxlen);
+ else
+ strncpy (val, _("Unknown FlashPix Version"), maxlen);
+ break;
+ case EXIF_TAG_COPYRIGHT:
+ CF (e, EXIF_FORMAT_ASCII, val, maxlen);
+
+ /*
+ * First part: Photographer.
+ * Some cameras store a string like " " here. Ignore it.
+ */
+ if (e->size && e->data &&
+ (strspn (e->data, " ") != strlen ((char *) e->data)))
+ strncpy (val, (char *) e->data, MIN (maxlen, e->size));
+ else
+ strncpy (val, _("[None]"), maxlen);
+ strncat (val, " ", maxlen - strlen (val));
+ strncat (val, _("(Photographer)"), maxlen - strlen (val));
+
+ /* Second part: Editor. */
+ t = e->data + strlen ((char *) e->data) + 1;
+ ts = e->data + e->size - t;
+ strncat (val, " - ", maxlen - strlen (val));
+ if (e->size && e->data && (ts > 0) &&
+ (strspn (t, " ") != ts))
+ strncat (val, t, MIN (maxlen - strlen (val), ts));
+ else
+ strncat (val, _("[None]"), maxlen - strlen (val));
+ strncat (val, " ", maxlen - strlen (val));
+ strncat (val, _("(Editor)"), maxlen - strlen (val));
+
+ break;
+ case EXIF_TAG_FNUMBER:
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator) return val;
+ snprintf (val, maxlen, "f/%.01f", (float) v_rat.numerator /
+ (float) v_rat.denominator);
+ break;
+ case EXIF_TAG_APERTURE_VALUE:
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator) return val;
+ snprintf (val, maxlen, "f/%.01f",
+ pow (2 , ((float) v_rat.numerator /
+ (float) v_rat.denominator) / 2.));
+ break;
+ case EXIF_TAG_FOCAL_LENGTH:
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator) return val;
+
+ /*
+ * For calculation of the 35mm equivalent,
+ * Minolta cameras need a multiplier that depends on the
+ * camera model.
+ */
+ d = 0.;
+ entry = exif_content_get_entry (
+ e->parent->parent->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
+ if (entry && entry->data &&
+ !strncmp (entry->data, "Minolta", 7)) {
+ entry = exif_content_get_entry (
+ e->parent->parent->ifd[EXIF_IFD_0],
+ EXIF_TAG_MODEL);
+ if (entry && entry->data) {
+ if (!strncmp (entry->data, "DiMAGE 7", 8))
+ d = 3.9;
+ else if (!strncmp (entry->data, "DiMAGE 5", 8))
+ d = 4.9;
+ }
+ }
+ if (d)
+ snprintf (b, sizeof (b), _(" (35 equivalent: %d mm)"),
+ (int) (d * (double) v_rat.numerator /
+ (double) v_rat.denominator));
+
+ snprintf (val, maxlen, "%.1f mm",
+ (float) v_rat.numerator / (float) v_rat.denominator);
+ if (maxlen > strlen (val) + strlen (b))
+ strncat (val, b, maxlen - strlen (val) - 1);
+ break;
+ case EXIF_TAG_SUBJECT_DISTANCE:
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator) return val;
+ snprintf (val, maxlen, "%.1f m", (float) v_rat.numerator /
+ (float) v_rat.denominator);
+ break;
+ case EXIF_TAG_EXPOSURE_TIME:
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator) return val;
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ if (d < 1)
+ snprintf (val, maxlen, _("1/%d"),
+ (int) (1. / d));
+ else
+ snprintf (val, maxlen, _("%d"), (int) d);
+ if (maxlen > strlen (val) + strlen (_(" sec.")))
+ strncat (val, _(" sec."), maxlen - strlen (val) - 1);
+ break;
+ case EXIF_TAG_SHUTTER_SPEED_VALUE:
+ CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_srat = exif_get_srational (e->data, o);
+ if (!v_srat.denominator) return val;
+ snprintf (val, maxlen, "%.0f/%.0f", (float) v_srat.numerator,
+ (float) v_srat.denominator);
+ if (maxlen > strlen (val) + strlen (_(" sec.")))
+ strncat (val, _(" sec."), maxlen - strlen (val) - 1);
+ snprintf (b, sizeof (b), " (APEX: %i)",
+ (int) pow (sqrt(2), (float) v_srat.numerator /
+ (float) v_srat.denominator));
+ if (maxlen > strlen (val) + strlen (b))
+ strncat (val, b, maxlen - strlen (val) - 1);
+ break;
+ case EXIF_TAG_BRIGHTNESS_VALUE:
+ CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_srat = exif_get_srational (e->data, o);
+ snprintf (val, maxlen, "%i/%i", (int) v_srat.numerator,
+ (int) v_srat.denominator);
+ /* FIXME: How do I calculate the APEX value? */
+ break;
+ case EXIF_TAG_FILE_SOURCE:
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (e, 1, val, maxlen);
+ switch (e->data[0]) {
+ case 0x03: strncpy (val, _("DSC"), maxlen); break;
+ default: snprintf (val, maxlen, "0x%02x", e->data[0]); break;
+ }
+ break;
+ case EXIF_TAG_COMPONENTS_CONFIGURATION:
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (e, 4, val, maxlen);
+ for (i = 0; i < 4; i++) {
+ switch (e->data[i]) {
+ case 0: c = _("-"); break;
+ case 1: c = _("Y"); break;
+ case 2: c = _("Cb"); break;
+ case 3: c = _("Cr"); break;
+ case 4: c = _("R"); break;
+ case 5: c = _("G"); break;
+ case 6: c = _("B"); break;
+ default: c = _("reserved"); break;
+ }
+ strncat (val, c, maxlen - strlen (val));
+ if (i < 3) strncat (val, " ", maxlen - strlen (val));
+ }
+ break;
+ case EXIF_TAG_EXPOSURE_BIAS_VALUE:
+ CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_srat = exif_get_srational (e->data, o);
+ if (!v_srat.denominator) return val;
+ snprintf (val, maxlen, "%s%.01f",
+ v_srat.denominator * v_srat.numerator > 0 ? "+" : "",
+ (double) v_srat.numerator /
+ (double) v_srat.denominator);
+ break;
+ case EXIF_TAG_YCBCR_SUB_SAMPLING:
+ CF (e, EXIF_FORMAT_SHORT, val, maxlen);
+ CC (e, 2, val, maxlen);
+ v_short = exif_get_short (e->data, o);
+ v_short2 = exif_get_short (
+ e->data + exif_format_get_size (e->format),
+ o);
+ if ((v_short == 2) && (v_short2 == 1))
+ strncpy (val, _("YCbCr4:2:2"), maxlen);
+ else if ((v_short == 2) && (v_short2 == 2))
+ strncpy (val, _("YCbCr4:2:0"), maxlen);
+ else
+ snprintf (val, maxlen, "%i, %i", v_short, v_short2);
+ break;
+ case EXIF_TAG_MAKER_NOTE:
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ snprintf (val, maxlen, _("%i bytes unknown data"),
+ (int) e->components);
+ break;
+ case EXIF_TAG_SUBJECT_AREA:
+ CF (e, EXIF_FORMAT_SHORT, val, maxlen);
+ switch (e->components) {
+ case 2:
+ v_short = exif_get_short (e->data, o);
+ v_short2 = exif_get_short (e->data + 2, o);
+ snprintf (val, maxlen, "(x,y) = (%i,%i)",
+ v_short, v_short2);
+ break;
+ case 3:
+ v_short = exif_get_short (e->data, o);
+ v_short2 = exif_get_short (e->data + 2, o);
+ v_short3 = exif_get_short (e->data + 4, o);
+ snprintf (val, maxlen, _("Within distance %i of "
+ "(x,y) = (%i,%i)"), v_short3, v_short,
+ v_short2);
+ break;
+ case 4:
+ v_short = exif_get_short (e->data, o);
+ v_short2 = exif_get_short (e->data + 2, o);
+ v_short3 = exif_get_short (e->data + 4, o);
+ v_short4 = exif_get_short (e->data + 6, o);
+ snprintf (val, maxlen, _("Within rectangle "
+ "(width %i, height %i) around "
+ "(x,y) = (%i,%i)"), v_short3, v_short4,
+ v_short, v_short2);
+ break;
+ default:
+ snprintf (val, maxlen, _("Unexpected number "
+ "of components (%li, expected 2, 3, or 4)."),
+ e->components);
+ }
+ break;
+
+ case EXIF_TAG_METERING_MODE:
+ case EXIF_TAG_COMPRESSION:
+ case EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT:
+ case EXIF_TAG_RESOLUTION_UNIT:
+ case EXIF_TAG_EXPOSURE_PROGRAM:
+ case EXIF_TAG_FLASH:
+ case EXIF_TAG_SUBJECT_DISTANCE_RANGE:
+ case EXIF_TAG_COLOR_SPACE:
+ CF (e,EXIF_FORMAT_SHORT, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_short = exif_get_short (e->data, o);
+
+ /* Search the tag */
+ for (i = 0; list2[i].tag && (list2[i].tag != e->tag); i++);
+ if (!list2[i].tag) {
+ strncpy (val, "Internal error.", maxlen - 1);
+ break;
+ }
+
+ /* Find the value */
+ for (j = 0; list2[i].elem[j].values &&
+ (list2[i].elem[j].index < v_short); j++);
+ if (list2[i].elem[j].index != v_short) {
+ snprintf (val, maxlen, "Internal error (unknown "
+ "value %i).", v_short);
+ break;
+ }
+
+ /* Find a short enough value */
+ memset (val, 0, maxlen);
+ for (k = 0; list2[i].elem[j].values &&
+ list2[i].elem[j].values[k]; k++) {
+ l = strlen (_(list2[i].elem[j].values[k]));
+ if ((maxlen > l) && (strlen (val) < l))
+ strncpy (val, _(list2[i].elem[j].values[k]), maxlen - 1);
+ }
+ if (!strlen (val)) snprintf (val, maxlen, "%i", v_short);
+
+ break;
+ case EXIF_TAG_PLANAR_CONFIGURATION:
+ case EXIF_TAG_SENSING_METHOD:
+ case EXIF_TAG_ORIENTATION:
+ case EXIF_TAG_YCBCR_POSITIONING:
+ case EXIF_TAG_PHOTOMETRIC_INTERPRETATION:
+ case EXIF_TAG_CUSTOM_RENDERED:
+ case EXIF_TAG_EXPOSURE_MODE:
+ case EXIF_TAG_WHITE_BALANCE:
+ case EXIF_TAG_SCENE_CAPTURE_TYPE:
+ case EXIF_TAG_GAIN_CONTROL:
+ case EXIF_TAG_SATURATION:
+ case EXIF_TAG_CONTRAST:
+ case EXIF_TAG_SHARPNESS:
+ CF (e, EXIF_FORMAT_SHORT, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_short = exif_get_short (e->data, o);
+
+ /* Search the tag */
+ for (i = 0; list[i].tag && (list[i].tag != e->tag); i++);
+ if (!list[i].tag) {
+ strncpy (val, "Internal error.", maxlen - 1);
+ break;
+ }
+
+ /* Find the value */
+ for (j = 0; list[i].strings[j] && (j < v_short); j++);
+ if (!list[i].strings[j])
+ snprintf (val, maxlen, "%i", v_short);
+ else
+ strncpy (val, _(list[i].strings[j]), maxlen - 1);
+ break;
+ default:
+ if (!e->components) break;
+ switch (e->format) {
+ case EXIF_FORMAT_UNDEFINED:
+ break;
+ case EXIF_FORMAT_BYTE:
+ case EXIF_FORMAT_SBYTE:
+ v_byte = e->data[0];
+ snprintf (val, maxlen, "0x%02x", v_byte);
+ maxlen -= strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_byte = e->data[i];
+ snprintf (b, sizeof (b), ", 0x%02x", v_byte);
+ strncat (val, b, maxlen);
+ maxlen -= strlen (b);
+ if ((signed)maxlen <= 0) break;
+ }
+ break;
+ case EXIF_FORMAT_SHORT:
+ case EXIF_FORMAT_SSHORT:
+ v_short = exif_get_short (e->data, o);
+ snprintf (val, maxlen, "%i", v_short);
+ maxlen -= strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_short = exif_get_short (e->data +
+ exif_format_get_size (e->format) *
+ i, o);
+ snprintf (b, sizeof (b), ", %i", v_short);
+ strncat (val, b, maxlen);
+ maxlen -= strlen (b);
+ if ((signed)maxlen <= 0) break;
+ }
+ break;
+ case EXIF_FORMAT_LONG:
+ v_long = exif_get_long (e->data, o);
+ snprintf (val, maxlen, "%li", (long int) v_long);
+ maxlen -= strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_long = exif_get_long (e->data +
+ exif_format_get_size (e->format) *
+ i, o);
+ snprintf (b, sizeof (b), ", %li",
+ (long int) v_long);
+ strncat (val, b, maxlen);
+ maxlen -= strlen (b);
+ if ((signed)maxlen <= 0) break;
+ }
+ break;
+ case EXIF_FORMAT_SLONG:
+ v_slong = exif_get_slong (e->data, o);
+ snprintf (val, maxlen, "%li", (long int) v_slong);
+ maxlen -= strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_long = exif_get_slong (e->data +
+ exif_format_get_size (e->format) *
+ i, o);
+ snprintf (b, sizeof (b), ", %li",
+ (long int) v_long);
+ strncat (val, b, maxlen);
+ maxlen -= strlen (b);
+ if ((signed)maxlen <= 0) break;
+ }
+ break;
+ case EXIF_FORMAT_ASCII:
+ strncpy (val, (char *) e->data, MIN (maxlen, e->size));
+ break;
+ case EXIF_FORMAT_RATIONAL:
+ v_rat = exif_get_rational (e->data, o);
+ if (v_rat.denominator) {
+ snprintf (val, maxlen, "%2.2f", (double)v_rat.numerator / v_rat.denominator);
+ } else {
+ snprintf (val, maxlen, "%i/%i", v_rat.numerator, v_rat.denominator);
+ }
+ maxlen -= strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_rat = exif_get_rational (
+ e->data + 8 * i, o);
+ snprintf (b, sizeof (b), ", %2.2f",
+ (double)v_rat.numerator / v_rat.denominator);
+ strncat (val, b, maxlen);
+ maxlen -= strlen (b);
+ if ((signed)maxlen <= 0) break;
+ }
+ break;
+ case EXIF_FORMAT_SRATIONAL:
+ v_srat = exif_get_srational (e->data, o);
+ if (v_srat.denominator) {
+ snprintf (val, maxlen, "%2.2f", (double)v_srat.numerator / v_srat.denominator);
+ } else {
+ snprintf (val, maxlen, "%i/%i", v_srat.numerator, v_srat.denominator);
+ }
+ maxlen -= strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_srat = exif_get_srational (
+ e->data + 8 * i, o);
+ snprintf (b, sizeof (b), ", %2.2f",
+ (double)v_srat.numerator / v_srat.denominator);
+ strncat (val, b, maxlen);
+ maxlen -= strlen (b);
+ if ((signed) maxlen <= 0) break;
+ }
+ break;
+ case EXIF_FORMAT_DOUBLE:
+ case EXIF_FORMAT_FLOAT:
+ default:
+ /* What to do here? */
+ break;
+ }
+ }
+
+ return val;
+}
+
+void
+exif_entry_initialize (ExifEntry *e, ExifTag tag)
+{
+ time_t t;
+ struct tm *tm;
+ ExifRational r;
+ ExifByteOrder o;
+
+ /* We need the byte order */
+ if (!e || !e->parent || e->data || !e->parent->parent)
+ return;
+ o = exif_data_get_byte_order (e->parent->parent);
+
+ e->tag = tag;
+ switch (tag) {
+
+ /* LONG, 1 component, no default */
+ case EXIF_TAG_PIXEL_X_DIMENSION:
+ case EXIF_TAG_PIXEL_Y_DIMENSION:
+ case EXIF_TAG_EXIF_IFD_POINTER:
+ case EXIF_TAG_GPS_INFO_IFD_POINTER:
+ case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
+ e->components = 1;
+ e->format = EXIF_FORMAT_LONG;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ break;
+
+ /* SHORT, 1 component, no default */
+ case EXIF_TAG_SUBJECT_LOCATION:
+ case EXIF_TAG_SENSING_METHOD:
+ case EXIF_TAG_PHOTOMETRIC_INTERPRETATION:
+ case EXIF_TAG_COMPRESSION:
+ case EXIF_TAG_EXPOSURE_MODE:
+ case EXIF_TAG_WHITE_BALANCE:
+ case EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM:
+ case EXIF_TAG_GAIN_CONTROL:
+ case EXIF_TAG_SUBJECT_DISTANCE_RANGE:
+ case EXIF_TAG_FLASH:
+ case EXIF_TAG_COLOR_SPACE:
+
+ /* SHORT, 1 component, default 0 */
+ case EXIF_TAG_IMAGE_WIDTH:
+ case EXIF_TAG_IMAGE_LENGTH:
+ case EXIF_TAG_EXPOSURE_PROGRAM:
+ case EXIF_TAG_LIGHT_SOURCE:
+ case EXIF_TAG_METERING_MODE:
+ case EXIF_TAG_CUSTOM_RENDERED:
+ case EXIF_TAG_SCENE_CAPTURE_TYPE:
+ case EXIF_TAG_CONTRAST:
+ case EXIF_TAG_SATURATION:
+ case EXIF_TAG_SHARPNESS:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ exif_set_short (e->data, o, 0);
+ break;
+
+ /* SHORT, 1 component, default 1 */
+ case EXIF_TAG_ORIENTATION:
+ case EXIF_TAG_PLANAR_CONFIGURATION:
+ case EXIF_TAG_YCBCR_POSITIONING:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ exif_set_short (e->data, o, 1);
+ break;
+
+ /* SHORT, 1 component, default 2 */
+ case EXIF_TAG_RESOLUTION_UNIT:
+ case EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ exif_set_short (e->data, o, 2);
+ break;
+
+ /* SHORT, 1 component, default 3 */
+ case EXIF_TAG_SAMPLES_PER_PIXEL:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ exif_set_short (e->data, o, 3);
+ break;
+
+ case EXIF_TAG_BITS_PER_SAMPLE:
+ e->components = 3;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ exif_set_short (e->data, o, 8);
+ exif_set_short (
+ e->data + exif_format_get_size (e->format),
+ o, 8);
+ exif_set_short (
+ e->data + 2 * exif_format_get_size (e->format),
+ o, 8);
+ break;
+ case EXIF_TAG_YCBCR_SUB_SAMPLING:
+ e->components = 2;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ exif_set_short (e->data, o, 2);
+ exif_set_short (
+ e->data + exif_format_get_size (e->format),
+ o, 1);
+ break;
+
+ /* SHORT, any component, no default */
+ case EXIF_TAG_SUBJECT_AREA:
+ case EXIF_TAG_ISO_SPEED_RATINGS:
+ e->components = 0;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = 0;
+ e->data = 0;
+ break;
+
+ /* SRATIONAL, 1 component, no default */
+ case EXIF_TAG_EXPOSURE_BIAS_VALUE:
+ case EXIF_TAG_BRIGHTNESS_VALUE:
+ case EXIF_TAG_SHUTTER_SPEED_VALUE:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SRATIONAL;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ break;
+
+ /* RATIONAL, 1 component, no default */
+ case EXIF_TAG_EXPOSURE_TIME:
+ case EXIF_TAG_FOCAL_PLANE_X_RESOLUTION:
+ case EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION:
+ case EXIF_TAG_EXPOSURE_INDEX:
+ case EXIF_TAG_FLASH_ENERGY:
+ case EXIF_TAG_FNUMBER:
+ case EXIF_TAG_FOCAL_LENGTH:
+ case EXIF_TAG_SUBJECT_DISTANCE:
+ case EXIF_TAG_MAX_APERTURE_VALUE:
+ case EXIF_TAG_APERTURE_VALUE:
+ case EXIF_TAG_COMPRESSED_BITS_PER_PIXEL:
+ case EXIF_TAG_PRIMARY_CHROMATICITIES:
+ case EXIF_TAG_DIGITAL_ZOOM_RATIO:
+ e->components = 1;
+ e->format = EXIF_FORMAT_RATIONAL;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ break;
+
+ /* RATIONAL, 1 component, default 72/1 */
+ case EXIF_TAG_X_RESOLUTION:
+ case EXIF_TAG_Y_RESOLUTION:
+ e->components = 1;
+ e->format = EXIF_FORMAT_RATIONAL;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ r.numerator = 72;
+ r.denominator = 1;
+ exif_set_rational (e->data, o, r);
+ break;
+
+ /* RATIONAL, 2 components, no default */
+ case EXIF_TAG_WHITE_POINT:
+ e->components = 2;
+ e->format = EXIF_FORMAT_RATIONAL;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ break;
+
+ /* RATIONAL, 6 components */
+ case EXIF_TAG_REFERENCE_BLACK_WHITE:
+ e->components = 6;
+ e->format = EXIF_FORMAT_RATIONAL;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ r.denominator = 1;
+ r.numerator = 0;
+ exif_set_rational (e->data, o, r);
+ r.numerator = 255;
+ exif_set_rational (
+ e->data + exif_format_get_size (e->format), o, r);
+ r.numerator = 0;
+ exif_set_rational (
+ e->data + 2 * exif_format_get_size (e->format), o, r);
+ r.numerator = 255;
+ exif_set_rational (
+ e->data + 3 * exif_format_get_size (e->format), o, r);
+ r.numerator = 0;
+ exif_set_rational (
+ e->data + 4 * exif_format_get_size (e->format), o, r);
+ r.numerator = 255;
+ exif_set_rational (
+ e->data + 5 * exif_format_get_size (e->format), o, r);
+ break;
+
+ /* ASCII, 20 components, default current time */
+ case EXIF_TAG_DATE_TIME:
+ case EXIF_TAG_DATE_TIME_ORIGINAL:
+ case EXIF_TAG_DATE_TIME_DIGITIZED:
+ t = time (NULL);
+ tm = localtime (&t);
+ e->components = 20;
+ e->format = EXIF_FORMAT_ASCII;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ snprintf ((char *) e->data, e->size,
+ "%04i:%02i:%02i %02i:%02i:%02i",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ break;
+
+ /* EXIF_FORMAT_ASCII, 13 components */
+ case EXIF_TAG_RELATED_SOUND_FILE:
+ e->components = 13;
+ e->format = EXIF_FORMAT_ASCII;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ break;
+
+ case EXIF_TAG_IMAGE_UNIQUE_ID:
+ e->components = 33;
+ e->format = EXIF_FORMAT_ASCII;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ break;
+
+ /* ASCII, any components, no default */
+ case EXIF_TAG_SPECTRAL_SENSITIVITY:
+ case EXIF_TAG_SUB_SEC_TIME:
+ case EXIF_TAG_SUB_SEC_TIME_ORIGINAL:
+ case EXIF_TAG_SUB_SEC_TIME_DIGITIZED:
+ case EXIF_TAG_IMAGE_DESCRIPTION:
+ case EXIF_TAG_MAKE:
+ case EXIF_TAG_MODEL:
+ case EXIF_TAG_SOFTWARE:
+ case EXIF_TAG_ARTIST:
+ case EXIF_TAG_COPYRIGHT:
+ e->components = 0;
+ e->format = EXIF_FORMAT_ASCII;
+ e->size = 0;
+ e->data = NULL;
+ break;
+
+ /* UNDEFINED, no components, no default */
+ case EXIF_TAG_OECF:
+ case EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE:
+ case EXIF_TAG_NEW_CFA_PATTERN:
+ case EXIF_TAG_DEVICE_SETTING_DESCRIPTION:
+ case EXIF_TAG_MAKER_NOTE:
+ case EXIF_TAG_USER_COMMENT:
+ e->components = 0;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = 0;
+ e->data = NULL;
+ break;
+
+ /* UNDEFINED, 1 component, default 1 */
+ case EXIF_TAG_SCENE_TYPE:
+ e->components = 1;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ e->data[0] = 0x01;
+ break;
+
+ /* UNDEFINED, 1 component, default 3 */
+ case EXIF_TAG_FILE_SOURCE:
+ e->components = 1;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ e->data[0] = 0x03;
+ break;
+
+ /* UNDEFINED, 4 components, default 0 1 0 0 */
+ case EXIF_TAG_FLASH_PIX_VERSION:
+ e->components = 4;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ memcpy (e->data, "0100", 4);
+ break;
+
+ /* UNDEFINED, 4 components, default 0 2 1 0 */
+ case EXIF_TAG_EXIF_VERSION:
+ e->components = 4;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ memcpy (e->data, "0210", 4);
+ break;
+
+ /* UNDEFINED, 4 components, no default */
+ case EXIF_TAG_COMPONENTS_CONFIGURATION:
+ e->components = 4;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = malloc (e->size);
+ break;
+
+ default:
+ break;
+ }
+}
diff --git a/src/libexif/exif-entry.h b/src/libexif/exif-entry.h
new file mode 100644
index 0000000..072ee29
--- /dev/null
+++ b/src/libexif/exif-entry.h
@@ -0,0 +1,69 @@
+/* exif-entry.h
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_ENTRY_H__
+#define __EXIF_ENTRY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ExifEntry ExifEntry;
+typedef struct _ExifEntryPrivate ExifEntryPrivate;
+
+#include <libexif/exif-content.h>
+#include <libexif/exif-format.h>
+#include <libexif/exif-mem.h>
+
+struct _ExifEntry {
+ ExifTag tag;
+ ExifFormat format;
+ unsigned long components;
+
+ unsigned char *data;
+ unsigned int size;
+
+ /* Content containing this entry */
+ ExifContent *parent;
+
+ ExifEntryPrivate *priv;
+};
+
+/* Lifecycle */
+ExifEntry *exif_entry_new (void);
+ExifEntry *exif_entry_new_mem (ExifMem *);
+void exif_entry_ref (ExifEntry *entry);
+void exif_entry_unref (ExifEntry *entry);
+void exif_entry_free (ExifEntry *entry);
+
+void exif_entry_initialize (ExifEntry *entry, ExifTag tag);
+void exif_entry_fix (ExifEntry *entry);
+
+/* For your convenience */
+const char *exif_entry_get_value (ExifEntry *entry, char *val,
+ unsigned int maxlen);
+
+void exif_entry_dump (ExifEntry *entry, unsigned int indent);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_ENTRY_H__ */
diff --git a/src/libexif/exif-format.c b/src/libexif/exif-format.c
new file mode 100644
index 0000000..e0c3650
--- /dev/null
+++ b/src/libexif/exif-format.c
@@ -0,0 +1,72 @@
+/* exif-format.c
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-format.h>
+#include <libexif/i18n.h>
+
+#include <stdlib.h>
+
+static struct {
+ ExifFormat format;
+ const char *name;
+ unsigned char size;
+} ExifFormatTable[] = {
+ {EXIF_FORMAT_BYTE, N_("Byte"), 1},
+ {EXIF_FORMAT_ASCII, N_("Ascii"), 1},
+ {EXIF_FORMAT_SHORT, N_("Short"), 2},
+ {EXIF_FORMAT_LONG, N_("Long"), 4},
+ {EXIF_FORMAT_RATIONAL, N_("Rational"), 8},
+ {EXIF_FORMAT_SBYTE, N_("SByte"), 1},
+ {EXIF_FORMAT_SSHORT, N_("SShort"), 2},
+ {EXIF_FORMAT_SLONG, N_("SLong"), 4},
+ {EXIF_FORMAT_SRATIONAL, N_("SRational"), 8},
+ {EXIF_FORMAT_FLOAT, N_("Float"), 4},
+ {EXIF_FORMAT_DOUBLE, N_("Double"), 8},
+ {EXIF_FORMAT_UNDEFINED, N_("Undefined"), 1},
+ {0, NULL, 0}
+};
+
+const char *
+exif_format_get_name (ExifFormat format)
+{
+ unsigned int i;
+
+ /* FIXME: This belongs to somewhere else. */
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+
+ for (i = 0; ExifFormatTable[i].name; i++)
+ if (ExifFormatTable[i].format == format)
+ return _(ExifFormatTable[i].name);
+ return NULL;
+}
+
+unsigned char
+exif_format_get_size (ExifFormat format)
+{
+ unsigned int i;
+
+ for (i = 0; ExifFormatTable[i].size; i++)
+ if (ExifFormatTable[i].format == format)
+ return ExifFormatTable[i].size;
+ return 0;
+}
diff --git a/src/libexif/exif-format.h b/src/libexif/exif-format.h
new file mode 100644
index 0000000..0eae425
--- /dev/null
+++ b/src/libexif/exif-format.h
@@ -0,0 +1,50 @@
+/* exif-format.h
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_FORMAT_H__
+#define __EXIF_FORMAT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+ EXIF_FORMAT_BYTE = 1,
+ EXIF_FORMAT_ASCII = 2,
+ EXIF_FORMAT_SHORT = 3,
+ EXIF_FORMAT_LONG = 4,
+ EXIF_FORMAT_RATIONAL = 5,
+ EXIF_FORMAT_SBYTE = 6,
+ EXIF_FORMAT_UNDEFINED = 7,
+ EXIF_FORMAT_SSHORT = 8,
+ EXIF_FORMAT_SLONG = 9,
+ EXIF_FORMAT_SRATIONAL = 10,
+ EXIF_FORMAT_FLOAT = 11,
+ EXIF_FORMAT_DOUBLE = 12
+} ExifFormat;
+
+const char *exif_format_get_name (ExifFormat format);
+unsigned char exif_format_get_size (ExifFormat format);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_FORMAT_H__ */
diff --git a/src/libexif/exif-ifd.c b/src/libexif/exif-ifd.c
new file mode 100644
index 0000000..96de261
--- /dev/null
+++ b/src/libexif/exif-ifd.c
@@ -0,0 +1,49 @@
+/* exif-ifd.c
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-ifd.h>
+
+#include <stdlib.h>
+
+static struct {
+ ExifIfd ifd;
+ const char *name;
+} ExifIfdTable[] = {
+ {EXIF_IFD_0, "0"},
+ {EXIF_IFD_1, "1"},
+ {EXIF_IFD_EXIF, "EXIF"},
+ {EXIF_IFD_GPS, "GPS"},
+ {EXIF_IFD_INTEROPERABILITY, "Interoperability"},
+ {0, NULL}
+};
+
+const char *
+exif_ifd_get_name (ExifIfd ifd)
+{
+ unsigned int i;
+
+ for (i = 0; ExifIfdTable[i].name; i++)
+ if (ExifIfdTable[i].ifd == ifd)
+ break;
+
+ return (ExifIfdTable[i].name);
+}
diff --git a/src/libexif/exif-ifd.h b/src/libexif/exif-ifd.h
new file mode 100644
index 0000000..01f0019
--- /dev/null
+++ b/src/libexif/exif-ifd.h
@@ -0,0 +1,35 @@
+/* exif-ifd.h
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_IFD_H__
+#define __EXIF_IFD_H__
+
+typedef enum {
+ EXIF_IFD_0 = 0,
+ EXIF_IFD_1,
+ EXIF_IFD_EXIF,
+ EXIF_IFD_GPS,
+ EXIF_IFD_INTEROPERABILITY,
+ EXIF_IFD_COUNT
+} ExifIfd;
+
+const char *exif_ifd_get_name (ExifIfd ifd);
+
+#endif /* __EXIF_IFD_H__ */
diff --git a/src/libexif/exif-loader.c b/src/libexif/exif-loader.c
new file mode 100644
index 0000000..d6eba7d
--- /dev/null
+++ b/src/libexif/exif-loader.c
@@ -0,0 +1,349 @@
+#include <config.h>
+
+#include <libexif/exif-loader.h>
+#include <libexif/i18n.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#undef JPEG_MARKER_SOI
+#define JPEG_MARKER_SOI 0xd8
+#undef JPEG_MARKER_APP0
+#define JPEG_MARKER_APP0 0xe0
+#undef JPEG_MARKER_APP1
+#define JPEG_MARKER_APP1 0xe1
+#undef JPEG_MARKER_APP13
+#define JPEG_MARKER_APP13 0xed
+#undef JPEG_MARKER_COM
+#define JPEG_MARKER_COM 0xfe
+
+typedef enum {
+ EL_READ = 0,
+ EL_READ_SIZE_BYTE_24,
+ EL_READ_SIZE_BYTE_16,
+ EL_READ_SIZE_BYTE_08,
+ EL_READ_SIZE_BYTE_00,
+ EL_SKIP_BYTES,
+ EL_EXIF_FOUND,
+} ExifLoaderState;
+
+typedef enum {
+ EL_DATA_FORMAT_UNKNOWN,
+ EL_DATA_FORMAT_EXIF,
+ EL_DATA_FORMAT_JPEG,
+ EL_DATA_FORMAT_FUJI_RAW
+} ExifLoaderDataFormat;
+
+struct _ExifLoader {
+ ExifLoaderState state;
+ ExifLoaderDataFormat data_format;
+
+ /* Small buffer used for detection of format */
+ unsigned char b[12];
+ unsigned char b_len;
+
+ unsigned int size;
+ unsigned char *buf;
+ unsigned int bytes_read;
+
+ unsigned int ref_count;
+
+ ExifLog *log;
+ ExifMem *mem;
+};
+
+static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+
+static void *
+exif_loader_alloc (ExifLoader *l, unsigned int i)
+{
+ void *d;
+
+ if (!l || !i) return NULL;
+
+ d = exif_mem_alloc (l->mem, i);
+ if (d) return d;
+
+ EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i);
+ return NULL;
+}
+
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+void
+exif_loader_write_file (ExifLoader *l, const char *path)
+{
+ FILE *f;
+ int size;
+ unsigned char data[1024];
+
+ if (!l) return;
+
+ f = fopen (path, "rb");
+ if (!f) {
+ exif_log (l->log, EXIF_LOG_CODE_NONE, "ExifLoader",
+ _("The file '%s' could not be opened."), path);
+ return;
+ }
+ while (1) {
+ size = fread (data, 1, sizeof (data), f);
+ if (size <= 0) break;
+ if (!exif_loader_write (l, data, size)) break;
+ }
+ fclose (f);
+}
+
+static unsigned int
+exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len)
+{
+ if (!eld || (len && !buf) || (eld->bytes_read >= eld->size)) return 0;
+
+ /* If needed, allocate the buffer. */
+ if (!eld->buf) eld->buf = exif_loader_alloc (eld, eld->size);
+ if (!eld->buf) return 0;
+
+ /* Copy memory */
+ len = MIN (len, eld->size - eld->bytes_read);
+ memcpy (eld->buf + eld->bytes_read, buf, len);
+ eld->bytes_read += len;
+
+ return (eld->bytes_read >= eld->size) ? 0 : 1;
+}
+
+unsigned char
+exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
+{
+ unsigned int i;
+
+ if (!eld || (len && !buf)) return 0;
+
+ switch (eld->state) {
+ case EL_EXIF_FOUND:
+ return exif_loader_copy (eld, buf, len);
+ case EL_SKIP_BYTES:
+ if (eld->size > len) { eld->size -= len; return 1; }
+ len -= eld->size;
+ buf += eld->size;
+ eld->size = 0;
+ eld->b_len = 0;
+ switch (eld->data_format) {
+ case EL_DATA_FORMAT_FUJI_RAW:
+ eld->state = EL_READ_SIZE_BYTE_24;
+ break;
+ default:
+ eld->state = EL_READ;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
+ "Scanning %i byte(s) of data...", len);
+
+ /*
+ * First fill the small buffer. Only continue if the buffer
+ * is filled. Note that EXIF data contains at least 12 bytes.
+ */
+ i = MIN (len, sizeof (eld->b) - eld->b_len);
+ if (i) {
+ memcpy (&eld->b[eld->b_len], buf, i);
+ eld->b_len += i;
+ if (eld->b_len < sizeof (eld->b)) return 1;
+ buf += i;
+ len -= i;
+ }
+
+ switch (eld->data_format) {
+ case EL_DATA_FORMAT_UNKNOWN:
+
+ /* Check the small buffer against known formats. */
+ if (!memcmp (eld->b, "FUJIFILM", 8)) {
+
+ /* Skip to byte 84. There is another offset there. */
+ eld->data_format = EL_DATA_FORMAT_FUJI_RAW;
+ eld->size = 84;
+ eld->state = EL_SKIP_BYTES;
+ eld->size = 84;
+
+ } else if (!memcmp (eld->b + 2, ExifHeader, sizeof (ExifHeader))) {
+
+ /* Read the size (2 bytes). */
+ eld->data_format = EL_DATA_FORMAT_EXIF;
+ eld->state = EL_READ_SIZE_BYTE_08;
+ }
+ default:
+ break;
+ }
+
+ for (i = 0; i < sizeof (eld->b); i++)
+ switch (eld->state) {
+ case EL_EXIF_FOUND:
+ if (!exif_loader_copy (eld, eld->b + i,
+ sizeof (eld->b) - i)) return 0;
+ return exif_loader_copy (eld, buf, len);
+ case EL_SKIP_BYTES:
+ eld->size--;
+ if (!eld->size) eld->state = EL_READ;
+ break;
+
+ case EL_READ_SIZE_BYTE_24:
+ eld->size |= eld->b[i] << 24;
+ eld->state = EL_READ_SIZE_BYTE_16;
+ break;
+ case EL_READ_SIZE_BYTE_16:
+ eld->size |= eld->b[i] << 16;
+ eld->state = EL_READ_SIZE_BYTE_08;
+ break;
+ case EL_READ_SIZE_BYTE_08:
+ eld->size |= eld->b[i] << 8;
+ eld->state = EL_READ_SIZE_BYTE_00;
+ break;
+ case EL_READ_SIZE_BYTE_00:
+ eld->size |= eld->b[i] << 0;
+ switch (eld->data_format) {
+ case EL_DATA_FORMAT_JPEG:
+ eld->state = EL_SKIP_BYTES;
+ eld->size -= 2;
+ break;
+ case EL_DATA_FORMAT_FUJI_RAW:
+ eld->data_format = EL_DATA_FORMAT_EXIF;
+ eld->state = EL_SKIP_BYTES;
+ eld->size -= 86;
+ break;
+ case EL_DATA_FORMAT_EXIF:
+ eld->state = EL_EXIF_FOUND;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ switch (eld->b[i]) {
+ case JPEG_MARKER_APP1:
+ eld->data_format = EL_DATA_FORMAT_EXIF;
+ eld->size = 0;
+ eld->state = EL_READ_SIZE_BYTE_08;
+ break;
+ case JPEG_MARKER_APP0:
+ case JPEG_MARKER_APP13:
+ case JPEG_MARKER_COM:
+ eld->data_format = EL_DATA_FORMAT_JPEG;
+ eld->size = 0;
+ eld->state = EL_READ_SIZE_BYTE_08;
+ break;
+ case 0xff:
+ case JPEG_MARKER_SOI:
+ break;
+ default:
+ exif_log (eld->log,
+ EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifLoader", _("The data supplied "
+ "does not seem to contain "
+ "EXIF data."));
+ exif_loader_reset (eld);
+ return 0;
+ }
+ }
+
+ /*
+ * If we reach this point, the buffer has not been big enough
+ * to read all data we need. Fill it with new data.
+ */
+ eld->b_len = 0;
+ return exif_loader_write (eld, buf, len);
+}
+
+ExifLoader *
+exif_loader_new (void)
+{
+ ExifMem *mem = exif_mem_new_default ();
+ ExifLoader *l = exif_loader_new_mem (mem);
+
+ exif_mem_unref (mem);
+
+ return l;
+}
+
+ExifLoader *
+exif_loader_new_mem (ExifMem *mem)
+{
+ ExifLoader *loader;
+
+ if (!mem) return NULL;
+
+ loader = exif_mem_alloc (mem, sizeof (ExifLoader));
+ if (!loader) return NULL;
+ loader->ref_count = 1;
+
+ loader->mem = mem;
+ exif_mem_ref (mem);
+
+ return loader;
+}
+
+void
+exif_loader_ref (ExifLoader *loader)
+{
+ if (loader) loader->ref_count++;
+}
+
+static void
+exif_loader_free (ExifLoader *loader)
+{
+ ExifMem *mem;
+
+ if (!loader) return;
+
+ mem = loader->mem;
+ exif_loader_reset (loader);
+ exif_mem_free (mem, loader);
+ exif_mem_unref (mem);
+}
+
+void
+exif_loader_unref (ExifLoader *loader)
+{
+ if (!loader) return;
+ if (!--loader->ref_count)
+ exif_loader_free (loader);
+}
+
+void
+exif_loader_reset (ExifLoader *loader)
+{
+ if (!loader) return;
+ exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;
+ loader->size = 0;
+ loader->bytes_read = 0;
+ loader->state = 0;
+ loader->b_len = 0;
+ loader->data_format = EL_DATA_FORMAT_UNKNOWN;
+}
+
+ExifData *
+exif_loader_get_data (ExifLoader *loader)
+{
+ ExifData *ed;
+
+ if (!loader) return NULL;
+
+ ed = exif_data_new_mem (loader->mem);
+ exif_data_log (ed, loader->log);
+ exif_data_load_data (ed, loader->buf, loader->bytes_read);
+
+ return ed;
+}
+
+void
+exif_loader_log (ExifLoader *loader, ExifLog *log)
+{
+ if (!loader) return;
+ exif_log_unref (loader->log);
+ loader->log = log;
+ exif_log_ref (log);
+}
diff --git a/src/libexif/exif-loader.h b/src/libexif/exif-loader.h
new file mode 100644
index 0000000..cf900c8
--- /dev/null
+++ b/src/libexif/exif-loader.h
@@ -0,0 +1,57 @@
+/* exif-loader.h
+ *
+ * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_LOADER_H__
+#define __EXIF_LOADER_H__
+
+#include <libexif/exif-data.h>
+#include <libexif/exif-loader.h>
+#include <libexif/exif-log.h>
+#include <libexif/exif-mem.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ExifLoader ExifLoader;
+
+ExifLoader *exif_loader_new (void);
+ExifLoader *exif_loader_new_mem (ExifMem *);
+void exif_loader_ref (ExifLoader *);
+void exif_loader_unref (ExifLoader *);
+
+void exif_loader_write_file (ExifLoader *, const char *fname);
+
+/*
+ * Returns 1 while EXIF data is read (or while there is still
+ * hope that there will be EXIF data later on), 0 otherwise.
+ */
+unsigned char exif_loader_write (ExifLoader *, unsigned char *, unsigned int);
+
+void exif_loader_reset (ExifLoader *);
+ExifData *exif_loader_get_data (ExifLoader *);
+
+void exif_loader_log (ExifLoader *, ExifLog *);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_LOADER_H__ */
diff --git a/src/libexif/exif-log.c b/src/libexif/exif-log.c
new file mode 100644
index 0000000..5dde1ce
--- /dev/null
+++ b/src/libexif/exif-log.c
@@ -0,0 +1,148 @@
+/* exif-log.c
+ *
+ * Copyright © 2004 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-log.h>
+#include <libexif/i18n.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+struct _ExifLog {
+ unsigned int ref_count;
+
+ ExifLogFunc func;
+ void *data;
+
+ ExifMem *mem;
+};
+
+static struct {
+ ExifLogCode code;
+ const char *title;
+ const char *message;
+} codes[] = {
+ { EXIF_LOG_CODE_DEBUG, N_("Debugging information"),
+ N_("Debugging information is available.") },
+ { EXIF_LOG_CODE_NO_MEMORY, N_("Not enough memory"),
+ N_("The system cannot provide enough memory.") },
+ { EXIF_LOG_CODE_CORRUPT_DATA, N_("Corrupt data"),
+ N_("The data provided does not follow the specification.") },
+ { 0, NULL, NULL }
+};
+
+const char *
+exif_log_code_get_title (ExifLogCode code)
+{
+ unsigned int i;
+
+ for (i = 0; codes[i].title; i++) if (codes[i].code == code) break;
+ return _(codes[i].title);
+}
+
+const char *
+exif_log_code_get_message (ExifLogCode code)
+{
+ unsigned int i;
+
+ for (i = 0; codes[i].message; i++) if (codes[i].code == code) break;
+ return _(codes[i].message);
+}
+
+ExifLog *
+exif_log_new_mem (ExifMem *mem)
+{
+ ExifLog *log;
+
+ log = exif_mem_alloc (mem, sizeof (ExifLog));
+ if (!log) return NULL;
+ log->ref_count = 1;
+
+ log->mem = mem;
+ exif_mem_ref (mem);
+
+ return log;
+}
+
+ExifLog *
+exif_log_new (void)
+{
+ ExifMem *mem = exif_mem_new_default ();
+ ExifLog *log = exif_log_new_mem (mem);
+
+ exif_mem_unref (mem);
+
+ return log;
+}
+
+void
+exif_log_ref (ExifLog *log)
+{
+ if (!log) return;
+ log->ref_count++;
+}
+
+void
+exif_log_unref (ExifLog *log)
+{
+ if (!log) return;
+ if (log->ref_count > 0) log->ref_count--;
+ if (!log->ref_count) exif_log_free (log);
+}
+
+void
+exif_log_free (ExifLog *log)
+{
+ ExifMem *mem = log ? log->mem : NULL;
+
+ if (!log) return;
+
+ exif_mem_free (mem, log);
+ exif_mem_unref (mem);
+}
+
+void
+exif_log_set_func (ExifLog *log, ExifLogFunc func, void *data)
+{
+ if (!log) return;
+ log->func = func;
+ log->data = data;
+}
+
+void
+exif_log (ExifLog *log, ExifLogCode code, const char *domain,
+ const char *format, ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ exif_logv (log, code, domain, format, args);
+ va_end (args);
+}
+
+void
+exif_logv (ExifLog *log, ExifLogCode code, const char *domain,
+ const char *format, va_list args)
+{
+ if (!log) return;
+ if (!log->func) return;
+ log->func (log, code, domain, format, args, log->data);
+}
diff --git a/src/libexif/exif-log.h b/src/libexif/exif-log.h
new file mode 100644
index 0000000..01eed3f
--- /dev/null
+++ b/src/libexif/exif-log.h
@@ -0,0 +1,75 @@
+/*! \file exif-log.h
+ * \brief log message infrastructure
+ *
+ * Copyright © 2004 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_LOG_H__
+#define __EXIF_LOG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-mem.h>
+#include <stdarg.h>
+
+typedef struct _ExifLog ExifLog;
+
+ExifLog *exif_log_new (void);
+ExifLog *exif_log_new_mem (ExifMem *);
+void exif_log_ref (ExifLog *log);
+void exif_log_unref (ExifLog *log);
+void exif_log_free (ExifLog *log);
+
+typedef enum {
+ EXIF_LOG_CODE_NONE,
+ EXIF_LOG_CODE_DEBUG,
+ EXIF_LOG_CODE_NO_MEMORY,
+ EXIF_LOG_CODE_CORRUPT_DATA
+} ExifLogCode;
+const char *exif_log_code_get_title (ExifLogCode); /* Title for dialog */
+const char *exif_log_code_get_message (ExifLogCode); /* Message for dialog */
+
+/** Log callback function prototype.
+ */
+typedef void (* ExifLogFunc) (ExifLog *log, ExifLogCode, const char *domain,
+ const char *format, va_list args, void *data);
+
+/** Register log callback function.
+ */
+void exif_log_set_func (ExifLog *log, ExifLogFunc func, void *data);
+
+void exif_log (ExifLog *log, ExifLogCode, const char *domain,
+ const char *format, ...)
+#ifdef __GNUC__
+ __attribute__((__format__(printf,4,5)))
+#endif
+;
+
+void exif_logv (ExifLog *log, ExifLogCode, const char *domain,
+ const char *format, va_list args);
+
+/* For your convenience */
+#define EXIF_LOG_NO_MEMORY(l,d,s) exif_log (l, EXIF_LOG_CODE_NO_MEMORY, d, "Could not allocate %i byte(s).", s)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_LOG_H__ */
diff --git a/src/libexif/exif-mem.c b/src/libexif/exif-mem.c
new file mode 100644
index 0000000..12027d1
--- /dev/null
+++ b/src/libexif/exif-mem.c
@@ -0,0 +1,95 @@
+#include <libexif/exif-mem.h>
+
+#include <stdlib.h>
+
+struct _ExifMem {
+ unsigned int ref_count;
+ ExifMemAllocFunc alloc_func;
+ ExifMemReallocFunc realloc_func;
+ ExifMemFreeFunc free_func;
+};
+
+static void *
+exif_mem_alloc_func (ExifLong ds)
+{
+ return calloc ((size_t) ds, 1);
+}
+
+static void *
+exif_mem_realloc_func (void *d, ExifLong ds)
+{
+ return realloc (d, (size_t) ds);
+}
+
+static void
+exif_mem_free_func (void *d)
+{
+ free (d);
+}
+
+ExifMem *
+exif_mem_new (ExifMemAllocFunc alloc_func, ExifMemReallocFunc realloc_func,
+ ExifMemFreeFunc free_func)
+{
+ ExifMem *mem;
+
+ if (!alloc_func || !realloc_func) return NULL;
+ mem = alloc_func ? alloc_func (sizeof (ExifMem)) :
+ realloc_func (NULL, sizeof (ExifMem));
+ if (!mem) return NULL;
+ mem->ref_count = 1;
+
+ mem->alloc_func = alloc_func;
+ mem->realloc_func = realloc_func;
+ mem->free_func = free_func;
+
+ return mem;
+}
+
+void
+exif_mem_ref (ExifMem *mem)
+{
+ if (!mem) return;
+ mem->ref_count++;
+}
+
+void
+exif_mem_unref (ExifMem *mem)
+{
+ if (!mem) return;
+ if (!--mem->ref_count)
+ exif_mem_free (mem, mem);
+}
+
+void
+exif_mem_free (ExifMem *mem, void *d)
+{
+ if (!mem) return;
+ if (mem->free_func) {
+ mem->free_func (d);
+ return;
+ }
+}
+
+void *
+exif_mem_alloc (ExifMem *mem, ExifLong ds)
+{
+ if (!mem) return NULL;
+ if (mem->alloc_func || mem->realloc_func)
+ return mem->alloc_func ? mem->alloc_func (ds) :
+ mem->realloc_func (NULL, ds);
+ return NULL;
+}
+
+void *
+exif_mem_realloc (ExifMem *mem, void *d, ExifLong ds)
+{
+ return (mem && mem->realloc_func) ? mem->realloc_func (d, ds) : NULL;
+}
+
+ExifMem *
+exif_mem_new_default (void)
+{
+ return exif_mem_new (exif_mem_alloc_func, exif_mem_realloc_func,
+ exif_mem_free_func);
+}
diff --git a/src/libexif/exif-mem.h b/src/libexif/exif-mem.h
new file mode 100644
index 0000000..aa774c6
--- /dev/null
+++ b/src/libexif/exif-mem.h
@@ -0,0 +1,54 @@
+/* exif-mem.h
+ *
+ * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_MEM_H__
+#define __EXIF_MEM_H__
+
+#include <libexif/exif-utils.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Should work like calloc: Needs to return initialized memory. */
+typedef void * (* ExifMemAllocFunc) (ExifLong);
+
+typedef void * (* ExifMemReallocFunc) (void *, ExifLong);
+typedef void (* ExifMemFreeFunc) (void *);
+
+typedef struct _ExifMem ExifMem;
+
+ExifMem *exif_mem_new (ExifMemAllocFunc, ExifMemReallocFunc,
+ ExifMemFreeFunc);
+void exif_mem_ref (ExifMem *);
+void exif_mem_unref (ExifMem *);
+
+void *exif_mem_alloc (ExifMem *, ExifLong);
+void *exif_mem_realloc (ExifMem *, void *, ExifLong);
+void exif_mem_free (ExifMem *, void *);
+
+/* For your convenience */
+ExifMem *exif_mem_new_default (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_MEM_H__ */
diff --git a/src/libexif/exif-mnote-data-priv.h b/src/libexif/exif-mnote-data-priv.h
new file mode 100644
index 0000000..3a13883
--- /dev/null
+++ b/src/libexif/exif-mnote-data-priv.h
@@ -0,0 +1,76 @@
+/* exif-mnote-data-priv.h
+ *
+ * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_MNOTE_DATA_PRIV_H__
+#define __EXIF_MNOTE_DATA_PRIV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-mnote-data.h>
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-log.h>
+
+typedef struct _ExifMnoteDataMethods ExifMnoteDataMethods;
+struct _ExifMnoteDataMethods {
+
+ /* Live cycle */
+ void (* free) (ExifMnoteData *);
+
+ /* Modification */
+ void (* save) (ExifMnoteData *, unsigned char **, unsigned int *);
+ void (* load) (ExifMnoteData *, const unsigned char *, unsigned int);
+ void (* set_offset) (ExifMnoteData *, unsigned int);
+ void (* set_byte_order) (ExifMnoteData *, ExifByteOrder);
+
+ /* Query */
+ unsigned int (* count) (ExifMnoteData *);
+ unsigned int (* get_id) (ExifMnoteData *, unsigned int);
+ const char * (* get_name) (ExifMnoteData *, unsigned int);
+ const char * (* get_title) (ExifMnoteData *, unsigned int);
+ const char * (* get_description) (ExifMnoteData *, unsigned int);
+ char * (* get_value) (ExifMnoteData *, unsigned int, char *val, unsigned int maxlen);
+};
+
+typedef struct _ExifMnoteDataPriv ExifMnoteDataPriv;
+
+struct _ExifMnoteData
+{
+ ExifMnoteDataPriv *priv;
+
+ ExifMnoteDataMethods methods;
+
+ /* Logging */
+ ExifLog *log;
+
+ /* Memory management */
+ ExifMem *mem;
+};
+
+void exif_mnote_data_construct (ExifMnoteData *, ExifMem *mem);
+void exif_mnote_data_set_byte_order (ExifMnoteData *, ExifByteOrder);
+void exif_mnote_data_set_offset (ExifMnoteData *, unsigned int);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_MNOTE_PRIV_H__ */
diff --git a/src/libexif/exif-mnote-data.c b/src/libexif/exif-mnote-data.c
new file mode 100644
index 0000000..f55cdd4
--- /dev/null
+++ b/src/libexif/exif-mnote-data.c
@@ -0,0 +1,158 @@
+/* exif-mnote-data.c
+ *
+ * Copyright (C) 2003 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-mnote-data.h>
+#include <libexif/exif-mnote-data-priv.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+struct _ExifMnoteDataPriv
+{
+ unsigned int ref_count;
+};
+
+void
+exif_mnote_data_construct (ExifMnoteData *d, ExifMem *mem)
+{
+ if (!d || !mem) return;
+ if (d->priv) return;
+ d->priv = exif_mem_alloc (mem, sizeof (ExifMnoteDataPriv));
+ if (!d->priv) return;
+
+ d->priv->ref_count = 1;
+
+ d->mem = mem;
+ exif_mem_ref (mem);
+}
+
+void
+exif_mnote_data_ref (ExifMnoteData *d)
+{
+ if (d && d->priv) d->priv->ref_count++;
+}
+
+static void
+exif_mnote_data_free (ExifMnoteData *d)
+{
+ ExifMem *mem = d ? d->mem : NULL;
+
+ if (!d) return;
+ if (d->priv) {
+ if (d->methods.free) d->methods.free (d);
+ exif_mem_free (mem, d->priv);
+ d->priv = NULL;
+ }
+ exif_log_unref (d->log);
+ exif_mem_free (mem, d);
+ exif_mem_unref (mem);
+}
+
+void
+exif_mnote_data_unref (ExifMnoteData *d)
+{
+ if (!d || !d->priv) return;
+ if (d->priv->ref_count > 0) d->priv->ref_count--;
+ if (!d->priv->ref_count)
+ exif_mnote_data_free (d);
+}
+
+void
+exif_mnote_data_load (ExifMnoteData *d, const unsigned char *buf,
+ unsigned int buf_size)
+{
+ if (!d || !d->methods.load) return;
+ d->methods.load (d, buf, buf_size);
+}
+
+void
+exif_mnote_data_save (ExifMnoteData *d, unsigned char **buf,
+ unsigned int *buf_size)
+{
+ if (!d || !d->methods.save) return;
+ d->methods.save (d, buf, buf_size);
+}
+
+void
+exif_mnote_data_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
+{
+ if (!d || !d->methods.set_byte_order) return;
+ d->methods.set_byte_order (d, o);
+}
+
+void
+exif_mnote_data_set_offset (ExifMnoteData *d, unsigned int o)
+{
+ if (!d || !d->methods.set_offset) return;
+ d->methods.set_offset (d, o);
+}
+
+unsigned int
+exif_mnote_data_count (ExifMnoteData *d)
+{
+ if (!d || !d->methods.count) return 0;
+ return d->methods.count (d);
+}
+
+unsigned int
+exif_mnote_data_get_id (ExifMnoteData *d, unsigned int n)
+{
+ if (!d || !d->methods.get_id) return 0;
+ return d->methods.get_id (d, n);
+}
+
+const char *
+exif_mnote_data_get_name (ExifMnoteData *d, unsigned int n)
+{
+ if (!d || !d->methods.get_name) return NULL;
+ return d->methods.get_name (d, n);
+}
+
+const char *
+exif_mnote_data_get_title (ExifMnoteData *d, unsigned int n)
+{
+ if (!d || !d->methods.get_title) return NULL;
+ return d->methods.get_title (d, n);
+}
+
+const char *
+exif_mnote_data_get_description (ExifMnoteData *d, unsigned int n)
+{
+ if (!d || !d->methods.get_description) return NULL;
+ return d->methods.get_description (d, n);
+}
+
+char *
+exif_mnote_data_get_value (ExifMnoteData *d, unsigned int n, char *val, unsigned int maxlen)
+{
+ if (!d || !d->methods.get_value) return NULL;
+ return d->methods.get_value (d, n, val, maxlen);
+}
+
+void
+exif_mnote_data_log (ExifMnoteData *d, ExifLog *log)
+{
+ if (!d) return;
+ exif_log_unref (d->log);
+ d->log = log;
+ exif_log_ref (log);
+}
diff --git a/src/libexif/exif-mnote-data.h b/src/libexif/exif-mnote-data.h
new file mode 100644
index 0000000..015f2ae
--- /dev/null
+++ b/src/libexif/exif-mnote-data.h
@@ -0,0 +1,54 @@
+/* exif-mnote-data.h
+ *
+ * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_MNOTE_DATA_H__
+#define __EXIF_MNOTE_DATA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-log.h>
+
+typedef struct _ExifMnoteData ExifMnoteData;
+
+void exif_mnote_data_ref (ExifMnoteData *);
+void exif_mnote_data_unref (ExifMnoteData *);
+
+void exif_mnote_data_load (ExifMnoteData *, const unsigned char *,
+ unsigned int);
+void exif_mnote_data_save (ExifMnoteData *, unsigned char **, unsigned int *);
+
+unsigned int exif_mnote_data_count (ExifMnoteData *);
+unsigned int exif_mnote_data_get_id (ExifMnoteData *, unsigned int);
+const char *exif_mnote_data_get_name (ExifMnoteData *, unsigned int);
+const char *exif_mnote_data_get_title (ExifMnoteData *, unsigned int);
+const char *exif_mnote_data_get_description (ExifMnoteData *, unsigned int);
+
+/* Returns NULL or val */
+char *exif_mnote_data_get_value (ExifMnoteData *, unsigned int, char *val, unsigned int maxlen);
+
+void exif_mnote_data_log (ExifMnoteData *, ExifLog *);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_MNOTE_DATA_H__ */
diff --git a/src/libexif/exif-tag.c b/src/libexif/exif-tag.c
new file mode 100644
index 0000000..7781611
--- /dev/null
+++ b/src/libexif/exif-tag.c
@@ -0,0 +1,686 @@
+/* exif-tag.c
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-tag.h>
+#include <libexif/i18n.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+typedef enum {
+ ESL_MANDATORY = 1, /* Mandatory */
+ ESL_CMANDATORY = 2, /* Conditionally mandatory */
+ ESL_OPTIONAL = 3, /* Optional */
+ ESL_NOT_RECORDED = 4 /* Not recorded */
+} ExifSL; /* Exif Support Level */
+
+static struct {
+ ExifTag tag;
+ const char *name;
+ const char *title;
+ const char *description;
+ ExifSL esl_0[4], esl_1[4], esl_exif[4], esl_gps[4];
+} ExifTagTable[] = {
+ {EXIF_TAG_NEW_SUBFILE_TYPE, "NewSubfileType",
+ "New Subfile Type", N_("A general indication of the kind of data "
+ "contained in this subfile.")},
+ {EXIF_TAG_INTEROPERABILITY_INDEX, "InteroperabilityIndex",
+ "InteroperabilityIndex",
+ N_("Indicates the identification of the Interoperability rule. "
+ "Use \"R98\" for stating ExifR98 Rules. Four bytes used "
+ "including the termination code (NULL). see the separate "
+ "volume of Recommended Exif Interoperability Rules (ExifR98) "
+ "for other tags used for ExifR98.")},
+ {EXIF_TAG_INTEROPERABILITY_VERSION, "InteroperabilityVersion",
+ "InteroperabilityVersion", ""},
+ {EXIF_TAG_IMAGE_WIDTH, "ImageWidth", N_("Image Width"),
+ N_("The number of columns of image data, equal to the number of "
+ "pixels per row. In JPEG compressed data a JPEG marker is "
+ "used instead of this tag."),
+ {ESL_MANDATORY, ESL_MANDATORY, ESL_MANDATORY, ESL_NOT_RECORDED}},
+ {EXIF_TAG_IMAGE_LENGTH, "ImageLength", N_("Image Length"),
+ N_("The number of rows of image data. In JPEG compressed data a "
+ "JPEG marker is used instead of this tag."),
+ {ESL_MANDATORY, ESL_MANDATORY, ESL_MANDATORY, ESL_NOT_RECORDED}},
+ {EXIF_TAG_BITS_PER_SAMPLE, "BitsPerSample", N_("Bits per Sample"),
+ N_("The number of bits per image component. In this standard each "
+ "component of the image is 8 bits, so the value for this "
+ "tag is 9. See also <SamplesPerPixel>. In JPEG compressed data "
+ "a JPEG marker is used instead of this tag."),
+ {ESL_MANDATORY, ESL_MANDATORY, ESL_MANDATORY, ESL_NOT_RECORDED}},
+ {EXIF_TAG_COMPRESSION, "Compression", N_("Compression"),
+ N_("The compression scheme used for the image data. When a "
+ "primary image is JPEG compressed, this designation is "
+ "not necessary and is omitted. When thumbnails use JPEG "
+ "compression, this tag value is set to 6."),
+ {ESL_MANDATORY, ESL_MANDATORY, ESL_MANDATORY, ESL_NOT_RECORDED}},
+ {EXIF_TAG_PHOTOMETRIC_INTERPRETATION, "PhotometricInterpretation",
+ N_("Photometric Interpretation"),
+ N_("The pixel composition. In JPEG compressed data a JPEG "
+ "marker is used instead of this tag."),
+ {ESL_MANDATORY, ESL_MANDATORY, ESL_MANDATORY, ESL_NOT_RECORDED}},
+ {EXIF_TAG_FILL_ORDER, "FillOrder", N_("Fill Order"), ""},
+ {EXIF_TAG_DOCUMENT_NAME, "DocumentName", N_("Document Name"), ""},
+ {EXIF_TAG_IMAGE_DESCRIPTION, "ImageDescription",
+ N_("Image Description"),
+ N_("A character string giving the title of the image. It may be "
+ "a comment such as \"1988 company picnic\" or "
+ "the like. Two-bytes character codes cannot be used. "
+ "When a 2-bytes code is necessary, the Exif Private tag "
+ "<UserComment> is to be used."),
+ {ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY}},
+ {EXIF_TAG_MAKE, "Make", N_("Manufacturer"),
+ N_("The manufacturer of the recording "
+ "equipment. This is the manufacturer of the DSC, scanner, "
+ "video digitizer or other equipment that generated the "
+ "image. When the field is left blank, it is treated as "
+ "unknown."),
+ {ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY}},
+ {EXIF_TAG_MODEL, "Model", N_("Model"),
+ N_("The model name or model number of the equipment. This is the "
+ "model name or number of the DSC, scanner, video digitizer "
+ "or other equipment that generated the image. When the field "
+ "is left blank, it is treated as unknown."),
+ {ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY}},
+ {EXIF_TAG_STRIP_OFFSETS, "StripOffsets", N_("Strip Offsets"),
+ N_("For each strip, the byte offset of that strip. It is "
+ "recommended that this be selected so the number of strip "
+ "bytes does not exceed 64 Kbytes. With JPEG compressed "
+ "data this designation is not needed and is omitted. See also "
+ "<RowsPerStrip> and <StripByteCounts>."),
+ {ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY}},
+ {EXIF_TAG_ORIENTATION, "Orientation", N_("Orientation"),
+ N_("The image orientation viewed in terms of rows and columns."),
+ {ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY}},
+ {EXIF_TAG_SAMPLES_PER_PIXEL, "SamplesPerPixel",
+ N_("Samples per Pixel"),
+ N_("The number of components per pixel. Since this standard applies "
+ "to RGB and YCbCr images, the value set for this tag is 3. "
+ "In JPEG compressed data a JPEG marker is used instead of this "
+ "tag.")},
+ {EXIF_TAG_ROWS_PER_STRIP, "RowsPerStrip", N_("Rows per Strip"),
+ N_("The number of rows per strip. This is the number of rows "
+ "in the image of one strip when an image is divided into "
+ "strips. With JPEG compressed data this designation is not "
+ "needed and is omitted. See also <RowsPerStrip> and "
+ "<StripByteCounts>.")},
+ {EXIF_TAG_STRIP_BYTE_COUNTS, "StripByteCounts", N_("Strip Byte Count"),
+ N_("The total number of bytes in each strip. With JPEG compressed "
+ "data this designation is not needed and is omitted.")},
+ {EXIF_TAG_X_RESOLUTION, "XResolution", N_("x-Resolution"),
+ N_("The number of pixels per <ResolutionUnit> in the <ImageWidth> "
+ "direction. When the image resolution is unknown, 72 [dpi] "
+ "is designated.")},
+ {EXIF_TAG_Y_RESOLUTION, "YResolution", N_("y-Resolution"),
+ N_("The number of pixels per <ResolutionUnit> in the <ImageLength> "
+ "direction. The same value as <XResolution> is designated.")},
+ {EXIF_TAG_PLANAR_CONFIGURATION, "PlanarConfiguration",
+ N_("Planar Configuration"),
+ N_("Indicates whether pixel components are recorded in a chunky "
+ "or planar format. In JPEG compressed files a JPEG marker "
+ "is used instead of this tag. If this field does not exist, "
+ "the TIFF default of 1 (chunky) is assumed.")},
+ {EXIF_TAG_RESOLUTION_UNIT, "ResolutionUnit", N_("Resolution Unit"),
+ N_("The unit for measuring <XResolution> and <YResolution>. The same "
+ "unit is used for both <XResolution> and <YResolution>. If "
+ "the image resolution is unknown, 2 (inches) is designated.")},
+ {EXIF_TAG_TRANSFER_FUNCTION, "TransferFunction",
+ N_("Transfer Function"),
+ N_("A transfer function for the image, described in tabular style. "
+ "Normally this tag is not necessary, since color space is "
+ "specified in the color space information tag (<ColorSpace>).")},
+ {EXIF_TAG_SOFTWARE, "Software", N_("Software"),
+ N_("This tag records the name and version of the software or "
+ "firmware of the camera or image input device used to "
+ "generate the image. The detailed format is not specified, but "
+ "it is recommended that the example shown below be "
+ "followed. When the field is left blank, it is treated as "
+ "unknown.")},
+ {EXIF_TAG_DATE_TIME, "DateTime", N_("Date and Time"),
+ N_("The date and time of image creation. In this standard "
+ "(EXIF-2.1) it is the date and time the file was changed.")},
+ {EXIF_TAG_ARTIST, "Artist", N_("Artist"),
+ N_("This tag records the name of the camera owner, photographer or "
+ "image creator. The detailed format is not specified, but it is "
+ "recommended that the information be written as in the example "
+ "below for ease of Interoperability. When the field is "
+ "left blank, it is treated as unknown.")},
+ {EXIF_TAG_WHITE_POINT, "WhitePoint", N_("White Point"),
+ N_("The chromaticity of the white point of the image. Normally "
+ "this tag is not necessary, since color space is specified "
+ "in the colorspace information tag (<ColorSpace>).")},
+ {EXIF_TAG_PRIMARY_CHROMATICITIES, "PrimaryChromaticities",
+ N_("Primary Chromaticities"),
+ N_("The chromaticity of the three primary colors of the image. "
+ "Normally this tag is not necessary, since colorspace is "
+ "specified in the colorspace information tag (<ColorSpace>).")},
+ {EXIF_TAG_TRANSFER_RANGE, "TransferRange", N_("Transfer Range"), ""},
+ {EXIF_TAG_SUB_IFDS, "SubIFDs", "SubIFD Offsets", N_("Defined by Adobe Corporation "
+ "to enable TIFF Trees within a TIFF file.")},
+ {EXIF_TAG_JPEG_PROC, "JPEGProc", "JPEGProc", ""},
+ {EXIF_TAG_JPEG_INTERCHANGE_FORMAT, "JPEGInterchangeFormat",
+ N_("JPEG Interchange Format"),
+ N_("The offset to the start byte (SOI) of JPEG compressed "
+ "thumbnail data. This is not used for primary image "
+ "JPEG data.")},
+ {EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
+ "JPEGInterchangeFormatLength", N_("JPEG Interchange Format Length"),
+ N_("The number of bytes of JPEG compressed thumbnail data. This "
+ "is not used for primary image JPEG data. JPEG thumbnails "
+ "are not divided but are recorded as a continuous JPEG "
+ "bitstream from SOI to EOI. Appn and COM markers should "
+ "not be recorded. Compressed thumbnails must be recorded in no "
+ "more than 64 Kbytes, including all other data to be "
+ "recorded in APP1.")},
+ {EXIF_TAG_YCBCR_COEFFICIENTS, "YCbCrCoefficients",
+ N_("YCbCr Coefficients"),
+ N_("The matrix coefficients for transformation from RGB to YCbCr "
+ "image data. No default is given in TIFF; but here the "
+ "value given in Appendix E, \"Color Space Guidelines\", is used "
+ "as the default. The color space is declared in a "
+ "color space information tag, with the default being the value "
+ "that gives the optimal image characteristics "
+ "Interoperability this condition.")},
+ {EXIF_TAG_YCBCR_SUB_SAMPLING, "YCbCrSubSampling",
+ N_("YCbCr Sub-Sampling"),
+ N_("The sampling ratio of chrominance components in relation to the "
+ "luminance component. In JPEG compressed data a JPEG marker "
+ "is used instead of this tag.")},
+ {EXIF_TAG_YCBCR_POSITIONING, "YCbCrPositioning",
+ N_("YCbCr Positioning"),
+ N_("The position of chrominance components in relation to the "
+ "luminance component. This field is designated only for "
+ "JPEG compressed data or uncompressed YCbCr data. The TIFF "
+ "default is 1 (centered); but when Y:Cb:Cr = 4:2:2 it is "
+ "recommended in this standard that 2 (co-sited) be used to "
+ "record data, in order to improve the image quality when viewed "
+ "on TV systems. When this field does not exist, the reader shall "
+ "assume the TIFF default. In the case of Y:Cb:Cr = 4:2:0, the "
+ "TIFF default (centered) is recommended. If the reader "
+ "does not have the capability of supporting both kinds of "
+ "<YCbCrPositioning>, it shall follow the TIFF default regardless "
+ "of the value in this field. It is preferable that readers "
+ "be able to support both centered and co-sited positioning.")},
+ {EXIF_TAG_REFERENCE_BLACK_WHITE, "ReferenceBlackWhite",
+ N_("Reference Black/White"),
+ N_("The reference black point value and reference white point "
+ "value. No defaults are given in TIFF, but the values "
+ "below are given as defaults here. The color space is declared "
+ "in a color space information tag, with the default "
+ "being the value that gives the optimal image characteristics "
+ "Interoperability these conditions.")},
+ {EXIF_TAG_XML_PACKET, "XMLPacket", N_("XML Packet"), N_("XMP Metadata")},
+ {EXIF_TAG_RELATED_IMAGE_FILE_FORMAT, "RelatedImageFileFormat",
+ "RelatedImageFileFormat", ""},
+ {EXIF_TAG_RELATED_IMAGE_WIDTH, "RelatedImageWidth",
+ "RelatedImageWidth", ""},
+ {EXIF_TAG_RELATED_IMAGE_LENGTH, "RelatedImageLength",
+ "RelatedImageLength", ""},
+ {EXIF_TAG_CFA_REPEAT_PATTERN_DIM, "CFARepeatPatternDim",
+ "CFARepeatPatternDim", ""},
+ {EXIF_TAG_CFA_PATTERN, "CFAPattern",
+ N_("CFA Pattern"),
+ N_("Indicates the color filter array (CFA) geometric pattern of the "
+ "image sensor when a one-chip color area sensor is used. "
+ "It does not apply to all sensing methods.")},
+ {EXIF_TAG_BATTERY_LEVEL, "BatteryLevel", N_("Battery Level"), ""},
+ {EXIF_TAG_COPYRIGHT, "Copyright", N_("Copyright"),
+ N_("Copyright information. In this standard the tag is used to "
+ "indicate both the photographer and editor copyrights. It is "
+ "the copyright notice of the person or organization claiming "
+ "rights to the image. The Interoperability copyright "
+ "statement including date and rights should be written in this "
+ "field; e.g., \"Copyright, John Smith, 19xx. All rights "
+ "reserved.\". In this standard the field records both the "
+ "photographer and editor copyrights, with each recorded in a "
+ "separate part of the statement. When there is a clear "
+ "distinction between the photographer and editor copyrights, "
+ "these are to be written in the order of photographer followed "
+ "by editor copyright, separated by NULL (in this case, "
+ "since the statement also ends with a NULL, there are two NULL "
+ "codes) (see example 1). When only the photographer is given, "
+ "it is terminated by one NULL code (see example 2). When only "
+ "the editor copyright is given, "
+ "the photographer copyright part consists of one space followed "
+ "by a terminating NULL code, then the editor copyright is given "
+ "(see example 3). When the field is left blank, it is treated "
+ "as unknown.")},
+ {EXIF_TAG_EXPOSURE_TIME, "ExposureTime", N_("Exposure Time"),
+ N_("Exposure time, given in seconds (sec).")},
+ {EXIF_TAG_FNUMBER, "FNumber", N_("FNumber"),
+ N_("The F number.")},
+ {EXIF_TAG_IPTC_NAA, "IPTC/NAA", "IPTC/NAA", ""},
+ {EXIF_TAG_IMAGE_RESOURCES, "ImageResources", N_("Image Resources Block"), ""},
+ {EXIF_TAG_EXIF_IFD_POINTER, "ExifIFDPointer", "ExifIFDPointer",
+ N_("A pointer to the Exif IFD. Interoperability, Exif IFD has the "
+ "same structure as that of the IFD specified in TIFF. "
+ "ordinarily, however, it does not contain image data as in "
+ "the case of TIFF.")},
+ {EXIF_TAG_INTER_COLOR_PROFILE, "InterColorProfile",
+ "InterColorProfile", ""},
+ {EXIF_TAG_EXPOSURE_PROGRAM, "ExposureProgram", "ExposureProgram",
+ N_("The class of the program used by the camera to set exposure "
+ "when the picture is taken.")},
+ {EXIF_TAG_SPECTRAL_SENSITIVITY, "SpectralSensitivity",
+ N_("Spectral Sensitivity"),
+ N_("Indicates the spectral sensitivity of each channel of the "
+ "camera used. The tag value is an ASCII string compatible "
+ "with the standard developed by the ASTM Technical committee.")},
+ {EXIF_TAG_GPS_INFO_IFD_POINTER, "GPSInfoIFDPointer",
+ "GPSInfoIFDPointer",
+ N_("A pointer to the GPS Info IFD. The "
+ "Interoperability structure of the GPS Info IFD, like that of "
+ "Exif IFD, has no image data.")},
+#if 0
+ {EXIF_TAG_GPS_VERSION_ID, "GPSVersionID", "",
+ N_("Indicates the version of <GPSInfoIFD>. The version is given "
+ "as 2.0.0.0. This tag is mandatory when <GPSInfo> tag is "
+ "present. (Note: The <GPSVersionID tag is given in bytes, "
+ "unlike the <ExifVersion> tag. When the version is "
+ "2.0.0.0, the tag value is 02000000.H).")},
+ {EXIF_TAG_GPS_LATITUDE_REF, "GPSLatitudeRef", ""
+ N_("Indicates whether the latitude is north or south latitude. The "
+ "ASCII value 'N' indicates north latitude, and 'S' is south "
+ "latitude.")},
+ {EXIF_TAG_GPS_LATITUDE, "GPSLatitude", ""
+ N_("Indicates the latitude. The latitude is expressed as three "
+ "RATIONAL values giving the degrees, minutes, and seconds, "
+ "respectively. When degrees, minutes and seconds are expressed, "
+ "the format is dd/1,mm/1,ss/1. When degrees and minutes are used "
+ "and, for example, fractions of minutes are given up to two "
+ "two decimal places, the format is dd/1,mmmm/100,0/1.")},
+ {EXIF_TAG_GPS_LONGITUDE_REF, "GPSLongitudeRef", ""
+ N_("Indicates whether the longitude is east or west longitude. "
+ "ASCII 'E' indicates east longitude, and 'W' is west "
+ "longitude.")},
+ {EXIF_TAG_GPS_LONGITUDE, "GPSLongitude", ""
+ N_("Indicates the longitude. The longitude is expressed as three "
+ "RATIONAL values giving the degrees, minutes, and seconds, "
+ "respectively. When degrees, minutes and seconds are expressed, "
+ "the format is ddd/1,mm/1,ss/1. When degrees and minutes are "
+ "used and, for example, fractions of minutes are given up to "
+ "two decimal places, the format is ddd/1,mmmm/100,0/1.")},
+#endif
+ {EXIF_TAG_ISO_SPEED_RATINGS, "ISOSpeedRatings",
+ N_("ISO Speed Ratings"),
+ N_("Indicates the ISO Speed and ISO Latitude of the camera or "
+ "input device as specified in ISO 12232.")},
+ {EXIF_TAG_OECF, "OECF", "OECF",
+ N_("Indicates the Opto-Electoric Conversion Function (OECF) "
+ "specified in ISO 14524. <OECF> is the relationship between "
+ "the camera optical input and the image values.")},
+ {EXIF_TAG_EXIF_VERSION, "ExifVersion", N_("Exif Version"),
+ N_("The version of this standard supported. Nonexistence of this "
+ "field is taken to mean nonconformance to the standard.")},
+ {EXIF_TAG_DATE_TIME_ORIGINAL, "DateTimeOriginal",
+ N_("Date and Time (original)"),
+ N_("The date and time when the original image data was generated. "
+ "For a digital still camera "
+ "the date and time the picture was taken are recorded.")},
+ {EXIF_TAG_DATE_TIME_DIGITIZED, "DateTimeDigitized",
+ N_("Date and Time (digitized)"),
+ N_("The date and time when the image was stored as digital data. ")},
+ {EXIF_TAG_COMPONENTS_CONFIGURATION, "ComponentsConfiguration",
+ "ComponentsConfiguration",
+ N_("Information specific to compressed data. The channels of "
+ "each component are arranged in order from the 1st "
+ "component to the 4th. For uncompressed data the data "
+ "arrangement is given in the <PhotometricInterpretation> tag. "
+ "However, since <PhotometricInterpretation> can only "
+ "express the order of Y, Cb and Cr, this tag is provided "
+ "for cases when compressed data uses components other than "
+ "Y, Cb, and Cr and to enable support of other sequences.")},
+ {EXIF_TAG_COMPRESSED_BITS_PER_PIXEL, "CompressedBitsPerPixel",
+ N_("Compressed Bits per Pixel"),
+ N_("Information specific to compressed data. The compression mode "
+ "used for a compressed image is indicated in unit bits "
+ "per pixel.")},
+ {EXIF_TAG_SHUTTER_SPEED_VALUE, "ShutterSpeedValue", N_("Shutter speed"),
+ N_("Shutter speed. The unit is the APEX (Additive System of "
+ "Photographic Exposure) setting (see Appendix C).")},
+ {EXIF_TAG_APERTURE_VALUE, "ApertureValue", N_("Aperture"),
+ N_("The lens aperture. The unit is the APEX value.")},
+ {EXIF_TAG_BRIGHTNESS_VALUE, "BrightnessValue", N_("Brightness"),
+ N_("The value of brightness. The unit is the APEX value. "
+ "Ordinarily it is given in the range of -99.99 to 99.99.")},
+ {EXIF_TAG_EXPOSURE_BIAS_VALUE, "ExposureBiasValue",
+ N_("Exposure Bias"),
+ N_("The exposure bias. The units is the APEX value. Ordinarily "
+ "it is given in the range of -99.99 to 99.99.")},
+ {EXIF_TAG_MAX_APERTURE_VALUE, "MaxApertureValue", "MaxApertureValue",
+ N_("The smallest F number of the lens. The unit is the APEX value. "
+ "Ordinarily it is given in the range of 00.00 to 99.99, "
+ "but it is not limited to this range.")},
+ {EXIF_TAG_SUBJECT_DISTANCE, "SubjectDistance",
+ N_("Subject Distance"),
+ N_("The distance to the subject, given in meters.")},
+ {EXIF_TAG_METERING_MODE, "MeteringMode", N_("Metering Mode"),
+ N_("The metering mode.")},
+ {EXIF_TAG_LIGHT_SOURCE, "LightSource", N_("Light Source"),
+ N_("The kind of light source.")},
+ {EXIF_TAG_FLASH, "Flash", N_("Flash"),
+ N_("This tag is recorded when an image is taken using a strobe "
+ "light (flash).")},
+ {EXIF_TAG_FOCAL_LENGTH, "FocalLength", N_("Focal Length"),
+ N_("The actual focal length of the lens, in mm. Conversion is not "
+ "made to the focal length of a 35 mm film camera.")},
+ {EXIF_TAG_MAKER_NOTE, "MakerNote", N_("Maker Note"),
+ N_("A tag for manufacturers of Exif writers to record any desired "
+ "information. The contents are up to the manufacturer.")},
+ {EXIF_TAG_USER_COMMENT, "UserComment", N_("User Comment"),
+ N_("A tag for Exif users to write keywords or comments on the image "
+ "besides those in <ImageDescription>, and without the "
+ "character code limitations of the <ImageDescription> tag. The "
+ "character code used in the <UserComment> tag is identified "
+ "based on an ID code in a fixed 8-byte area at the start of "
+ "the tag data area. The unused portion of the area is padded "
+ "with NULL (\"00.h\"). ID codes are assigned by means of "
+ "registration. The designation method and references for each "
+ "character code are given in Table 6. The value of CountN "
+ "is determinated based on the 8 bytes in the character code "
+ "area and the number of bytes in the user comment part. Since "
+ "the TYPE is not ASCII, NULL termination is not necessary "
+ "(see Fig. 9). "
+ "The ID code for the <UserComment> area may be a Defined code "
+ "such as JIS or ASCII, or may be Undefined. The Undefined name "
+ "is UndefinedText, and the ID code is filled with 8 bytes of all "
+ "\"NULL\" (\"00.H\"). An Exif reader that reads the "
+ "<UserComment> tag must have a function for determining the "
+ "ID code. This function is not required in Exif readers that "
+ "do not use the <UserComment> tag (see Table 7). "
+ "When a <UserComment> area is set aside, it is recommended that "
+ "the ID code be ASCII and that the following user comment "
+ "part be filled with blank characters [20.H].")},
+ {EXIF_TAG_SUB_SEC_TIME, "SubsecTime", "SubsecTime",
+ N_("A tag used to record fractions of seconds for the "
+ "<DateTime> tag.")},
+ {EXIF_TAG_SUB_SEC_TIME_ORIGINAL, "SubSecTimeOriginal",
+ "SubSecTimeOriginal",
+ N_("A tag used to record fractions of seconds for the "
+ "<DateTimeOriginal> tag.")},
+ {EXIF_TAG_SUB_SEC_TIME_DIGITIZED, "SubSecTimeDigitized",
+ "SubSecTimeDigitized",
+ N_("A tag used to record fractions of seconds for the "
+ "<DateTimeDigitized> tag.")},
+ {EXIF_TAG_FLASH_PIX_VERSION, "FlashPixVersion", "FlashPixVersion",
+ N_("The FlashPix format version supported by a FPXR file.")},
+ {EXIF_TAG_COLOR_SPACE, "ColorSpace", N_("Color Space"),
+ N_("The color space information tag is always "
+ "recorded as the color space specifier. Normally sRGB (=1) "
+ "is used to define the color space based on the PC monitor "
+ "conditions and environment. If a color space other than "
+ "sRGB is used, Uncalibrated (=FFFF.H) is set. Image data "
+ "recorded as Uncalibrated can be treated as sRGB when it is "
+ "converted to FlashPix. On sRGB see Appendix E.")},
+ {EXIF_TAG_PIXEL_X_DIMENSION, "PixelXDimension", "PixelXDimension",
+ N_("Information specific to compressed data. When a "
+ "compressed file is recorded, the valid width of the "
+ "meaningful image must be recorded in this tag, whether or "
+ "not there is padding data or a restart marker. This tag "
+ "should not exist in an uncompressed file. For details see "
+ "section 2.8.1 and Appendix F.")},
+ {EXIF_TAG_PIXEL_Y_DIMENSION, "PixelYDimension", "PixelYDimension",
+ N_("Information specific to compressed data. When a compressed "
+ "file is recorded, the valid height of the meaningful image "
+ "must be recorded in this tag, whether or not there is padding "
+ "data or a restart marker. This tag should not exist in an "
+ "uncompressed file. For details see section 2.8.1 and Appendix "
+ "F. Since data padding is unnecessary in the vertical direction, "
+ "the number of lines recorded in this valid image height tag "
+ "will in fact be the same as that recorded in the SOF.")},
+ {EXIF_TAG_RELATED_SOUND_FILE, "RelatedSoundFile",
+ "RelatedSoundFile",
+ N_("This tag is used to record the name of an audio file related "
+ "to the image data. The only relational information "
+ "recorded here is the Exif audio file name and extension (an "
+ "ASCII string consisting of 8 characters + '.' + 3 "
+ "characters). The path is not recorded. Stipulations on audio "
+ "are given in section 3.6.3. File naming conventions are "
+ "given in section 3.7.1. "
+ "When using this tag, audio files must be recorded in "
+ "conformance to the Exif audio format. Writers are also allowed "
+ "to store the data such as Audio within APP2 as FlashPix "
+ "extension stream data. "
+ "Audio files must be recorded in conformance to the Exif audio "
+ "format. The mapping of Exif image files and audio files is done "
+ "in any of the three ways shown in Table 8. If multiple files "
+ "are mapped to one file as in [2] or [3] of this table, the above "
+ "format is used to record just one audio file name. If "
+ "there are multiple audio files, the first recorded file is "
+ "given. In the case of [3] in Table 8, for example, for the "
+ "Exif image file \"DSC00001.JPG\" only \"SND00001.WAV\" is "
+ "given as the related Exif audio file. When there are three "
+ "Exif audio files \"SND00001.WAV\", \"SND00002.WAV\" and "
+ "\"SND00003.WAV\", the Exif image file name for each of them, "
+ "\"DSC00001.JPG\", is indicated. By combining multiple "
+ "relational information, a variety of playback possibilities "
+ "can be supported. The method of using relational information "
+ "is left to the implementation on the playback side. Since this "
+ "information is an ASCII character string, it is terminated by "
+ "NULL. When this tag is used to map audio files, the relation "
+ "of the audio file to image data must also be indicated on the "
+ "audio file end.")},
+ {EXIF_TAG_INTEROPERABILITY_IFD_POINTER, "InteroperabilityIFDPointer",
+ "InteroperabilityIFDPointer",
+ N_("Interoperability IFD is composed of tags which stores the "
+ "information to ensure the Interoperability and pointed "
+ "by the following tag located in Exif IFD. "
+ "The Interoperability structure of Interoperability IFD is "
+ "the same as TIFF defined IFD structure "
+ "but does not contain the "
+ "image data characteristically compared with normal TIFF "
+ "IFD.")},
+ {EXIF_TAG_FLASH_ENERGY, "FlashEnergy", N_("Flash Energy"),
+ N_("Indicates the strobe energy at the time the image is "
+ "captured, as measured in Beam Candle Power Seconds (BCPS).")},
+ {EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE, "SpatialFrequencyResponse",
+ N_("Spatial Frequency Response"),
+ N_("This tag records the camera or input device spatial frequency "
+ "table and SFR values in the direction of image width, "
+ "image height, and diagonal direction, as specified in ISO "
+ "12233.")},
+ {EXIF_TAG_FOCAL_PLANE_X_RESOLUTION, "FocalPlaneXResolution",
+ N_("Focal Plane x-Resolution"),
+ N_("Indicates the number of pixels in the image width (X) direction "
+ "per <FocalPlaneResolutionUnit> on the camera focal plane.")},
+ {EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION, "FocalPlaneYResolution",
+ N_("Focal Plane y-Resolution"),
+ N_("Indicates the number of pixels in the image height (V) direction "
+ "per <FocalPlaneResolutionUnit> on the camera focal plane.")},
+ {EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT, "FocalPlaneResolutionUnit",
+ N_("Focal Plane Resolution Unit"),
+ N_("Indicates the unit for measuring <FocalPlaneXResolution> and "
+ "<FocalPlaneYResolution>. This value is the same as the "
+ "<ResolutionUnit>.")},
+ {EXIF_TAG_SUBJECT_LOCATION, "SubjectLocation",
+ N_("Subject Location"),
+ N_("Indicates the location of the main subject in the scene. The "
+ "value of this tag represents the pixel at the center of the "
+ "main subject relative to the left edge, prior to rotation "
+ "processing as per the <Rotation> tag. The first value "
+ "indicates the X column number and second indicates "
+ "the Y row number.")},
+ {EXIF_TAG_EXPOSURE_INDEX, "ExposureIndex", N_("Exposure index"),
+ N_("Indicates the exposure index selected on the camera or "
+ "input device at the time the image is captured.")},
+ {EXIF_TAG_SENSING_METHOD, "SensingMethod", N_("Sensing Method"),
+ N_("Indicates the image sensor type on the camera or input "
+ "device.")},
+ {EXIF_TAG_FILE_SOURCE, "FileSource", N_("File Source"),
+ N_("Indicates the image source. If a DSC recorded the image, "
+ "this tag value of this tag always be set to 3, indicating "
+ "that the image was recorded on a DSC.")},
+ {EXIF_TAG_SCENE_TYPE, "SceneType", N_("Scene Type"),
+ N_("Indicates the type of scene. If a DSC recorded the image, "
+ "this tag value must always be set to 1, indicating that the "
+ "image was directly photographed.")},
+ {EXIF_TAG_NEW_CFA_PATTERN, "CFAPattern",
+ N_("CFA Pattern"),
+ N_("Indicates the color filter array (CFA) geometric pattern of the "
+ "image sensor when a one-chip color area sensor is used. "
+ "It does not apply to all sensing methods.")},
+ {EXIF_TAG_SUBJECT_AREA, "SubjectArea", N_("Subject Area"),
+ N_("This tag indicates the location and area of the main subject "
+ "in the overall scene.")},
+ {EXIF_TAG_TIFF_EP_STANDARD_ID, "TIFF/EPStandardID", N_("TIFF/EP Standard ID"), ""},
+ {EXIF_TAG_CUSTOM_RENDERED, "CustomRendered", N_("Custom Rendered"),
+ N_("This tag indicates the use of special processing on image "
+ "data, such as rendering geared to output. When special "
+ "processing is performed, the reader is expected to disable "
+ "or minimize any further processing.")},
+ {EXIF_TAG_EXPOSURE_MODE, "ExposureMode", N_("Exposure Mode"),
+ N_("This tag indicates the exposure mode set when the image was "
+ "shot. In auto-bracketing mode, the camera shoots a series of "
+ "frames of the same scene at different exposure settings.")},
+ {EXIF_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance"),
+ N_("This tag indicates the white balance mode set when the image "
+ "was shot.")},
+ {EXIF_TAG_DIGITAL_ZOOM_RATIO, "DigitalZoomRatio",
+ N_("Digital Zoom Ratio"),
+ N_("This tag indicates the digital zoom ratio when the image was "
+ "shot. If the numerator of the recorded value is 0, this "
+ "indicates that digital zoom was not used.")},
+ {EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM, "FocalLengthIn35mmFilm",
+ N_("Focal Length In 35mm Film"),
+ N_("This tag indicates the equivalent focal length assuming a "
+ "35mm film camera, in mm. A value of 0 means the focal "
+ "length is unknown. Note that this tag differs from the "
+ "FocalLength tag.")},
+ {EXIF_TAG_SCENE_CAPTURE_TYPE, "SceneCaptureType",
+ N_("Scene Capture Type"),
+ N_("This tag indicates the type of scene that was shot. It can "
+ "also be used to record the mode in which the image was "
+ "shot. Note that this differs from the scene type "
+ "(SceneType) tag.")},
+ {EXIF_TAG_GAIN_CONTROL, "GainControl", N_("Gain Control"),
+ N_("This tag indicates the degree of overall image gain "
+ "adjustment.")},
+ {EXIF_TAG_CONTRAST, "Contrast", N_("Contrast"),
+ N_("This tag indicates the direction of contrast processing "
+ "applied by the camera when the image was shot.")},
+ {EXIF_TAG_SATURATION, "Saturation", N_("Saturation"),
+ N_("This tag indicates the direction of saturation processing "
+ "applied by the camera when the image was shot.")},
+ {EXIF_TAG_SHARPNESS, "Sharpness", N_("Sharpness"),
+ N_("This tag indicates the direction of sharpness processing "
+ "applied by the camera when the image was shot.")},
+ {EXIF_TAG_DEVICE_SETTING_DESCRIPTION, "DeviceSettingDescription",
+ N_("Device Setting Description"),
+ N_("This tag indicates information on the picture-taking "
+ "conditions of a particular camera model. The tag is used "
+ "only to indicate the picture-taking conditions in the "
+ "reader.")},
+ {EXIF_TAG_SUBJECT_DISTANCE_RANGE, "SubjectDistanceRange",
+ N_("Subject Distance Range"),
+ N_("This tag indicates the distance to the subject.")},
+ {EXIF_TAG_IMAGE_UNIQUE_ID, "ImageUniqueID", N_("Image Unique ID"),
+ N_("This tag indicates an identifier assigned uniquely to "
+ "each image. It is recorded as an ASCII string equivalent "
+ "to hexadecimal notation and 128-bit fixed length.")},
+ {0, NULL, NULL, NULL}
+};
+
+/* For now, do not use these functions. */
+ExifTag exif_tag_table_get_tag (unsigned int n);
+const char *exif_tag_table_get_name (unsigned int n);
+unsigned int exif_tag_table_count (void);
+
+ExifTag
+exif_tag_table_get_tag (unsigned int n)
+{
+ return (n < exif_tag_table_count ()) ? ExifTagTable[n].tag : 0;
+}
+
+const char *
+exif_tag_table_get_name (unsigned int n)
+{
+ return (n < exif_tag_table_count ()) ? ExifTagTable[n].name : NULL;
+}
+
+unsigned int
+exif_tag_table_count (void)
+{
+ return sizeof (ExifTagTable) / sizeof (ExifTagTable[0]);
+}
+
+const char *
+exif_tag_get_name (ExifTag tag)
+{
+ unsigned int i;
+
+ for (i = 0; ExifTagTable[i].name; i++)
+ if (ExifTagTable[i].tag == tag)
+ break;
+
+ return ExifTagTable[i].name;
+}
+
+const char *
+exif_tag_get_title (ExifTag tag)
+{
+ unsigned int i;
+
+ /* FIXME: This belongs to somewhere else. */
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+
+ for (i = 0; ExifTagTable[i].title; i++)
+ if (ExifTagTable[i].tag == tag) break;
+ return _(ExifTagTable[i].title);
+}
+
+const char *
+exif_tag_get_description (ExifTag tag)
+{
+ unsigned int i;
+
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+
+ for (i = 0; ExifTagTable[i].description; i++)
+ if (ExifTagTable[i].tag == tag) break;
+ return _(ExifTagTable[i].description);
+}
+
+ExifTag
+exif_tag_from_name (const char *name)
+{
+ unsigned int i;
+
+ if (!name) return 0;
+
+ for (i = 0; ExifTagTable[i].name; i++)
+ if (!strcmp (ExifTagTable[i].name, name)) break;
+ return ExifTagTable[i].tag;
+}
+
+const char *
+exif_tag_get_name_index (unsigned int i, ExifTag *tag)
+{
+ if (!ExifTagTable[i].name)
+ return NULL;
+
+ *tag = ExifTagTable[i].tag;
+
+ return (ExifTagTable[i].name);
+}
+
diff --git a/src/libexif/exif-tag.h b/src/libexif/exif-tag.h
new file mode 100644
index 0000000..f928374
--- /dev/null
+++ b/src/libexif/exif-tag.h
@@ -0,0 +1,148 @@
+/* exif-tag.h
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_TAG_H__
+#define __EXIF_TAG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+ EXIF_TAG_INTEROPERABILITY_INDEX = 0x0001,
+ EXIF_TAG_INTEROPERABILITY_VERSION = 0x0002,
+ EXIF_TAG_NEW_SUBFILE_TYPE = 0x00fe,
+ EXIF_TAG_IMAGE_WIDTH = 0x0100,
+ EXIF_TAG_IMAGE_LENGTH = 0x0101,
+ EXIF_TAG_BITS_PER_SAMPLE = 0x0102,
+ EXIF_TAG_COMPRESSION = 0x0103,
+ EXIF_TAG_PHOTOMETRIC_INTERPRETATION = 0x0106,
+ EXIF_TAG_FILL_ORDER = 0x010a,
+ EXIF_TAG_DOCUMENT_NAME = 0x010d,
+ EXIF_TAG_IMAGE_DESCRIPTION = 0x010e,
+ EXIF_TAG_MAKE = 0x010f,
+ EXIF_TAG_MODEL = 0x0110,
+ EXIF_TAG_STRIP_OFFSETS = 0x0111,
+ EXIF_TAG_ORIENTATION = 0x0112,
+ EXIF_TAG_SAMPLES_PER_PIXEL = 0x0115,
+ EXIF_TAG_ROWS_PER_STRIP = 0x0116,
+ EXIF_TAG_STRIP_BYTE_COUNTS = 0x0117,
+ EXIF_TAG_X_RESOLUTION = 0x011a,
+ EXIF_TAG_Y_RESOLUTION = 0x011b,
+ EXIF_TAG_PLANAR_CONFIGURATION = 0x011c,
+ EXIF_TAG_RESOLUTION_UNIT = 0x0128,
+ EXIF_TAG_TRANSFER_FUNCTION = 0x012d,
+ EXIF_TAG_SOFTWARE = 0x0131,
+ EXIF_TAG_DATE_TIME = 0x0132,
+ EXIF_TAG_ARTIST = 0x013b,
+ EXIF_TAG_WHITE_POINT = 0x013e,
+ EXIF_TAG_PRIMARY_CHROMATICITIES = 0x013f,
+ EXIF_TAG_TRANSFER_RANGE = 0x0156,
+ EXIF_TAG_SUB_IFDS = 0x014a,
+ EXIF_TAG_JPEG_PROC = 0x0200,
+ EXIF_TAG_JPEG_INTERCHANGE_FORMAT = 0x0201,
+ EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 0x0202,
+ EXIF_TAG_YCBCR_COEFFICIENTS = 0x0211,
+ EXIF_TAG_YCBCR_SUB_SAMPLING = 0x0212,
+ EXIF_TAG_YCBCR_POSITIONING = 0x0213,
+ EXIF_TAG_REFERENCE_BLACK_WHITE = 0x0214,
+ EXIF_TAG_XML_PACKET = 0x02bc,
+ EXIF_TAG_RELATED_IMAGE_FILE_FORMAT = 0x1000,
+ EXIF_TAG_RELATED_IMAGE_WIDTH = 0x1001,
+ EXIF_TAG_RELATED_IMAGE_LENGTH = 0x1002,
+ EXIF_TAG_CFA_REPEAT_PATTERN_DIM = 0x828d,
+ EXIF_TAG_CFA_PATTERN = 0x828e,
+ EXIF_TAG_BATTERY_LEVEL = 0x828f,
+ EXIF_TAG_COPYRIGHT = 0x8298,
+ EXIF_TAG_EXPOSURE_TIME = 0x829a,
+ EXIF_TAG_FNUMBER = 0x829d,
+ EXIF_TAG_IPTC_NAA = 0x83bb,
+ EXIF_TAG_IMAGE_RESOURCES = 0x8649,
+ EXIF_TAG_EXIF_IFD_POINTER = 0x8769,
+ EXIF_TAG_INTER_COLOR_PROFILE = 0x8773,
+ EXIF_TAG_EXPOSURE_PROGRAM = 0x8822,
+ EXIF_TAG_SPECTRAL_SENSITIVITY = 0x8824,
+ EXIF_TAG_GPS_INFO_IFD_POINTER = 0x8825,
+ EXIF_TAG_ISO_SPEED_RATINGS = 0x8827,
+ EXIF_TAG_OECF = 0x8828,
+ EXIF_TAG_EXIF_VERSION = 0x9000,
+ EXIF_TAG_DATE_TIME_ORIGINAL = 0x9003,
+ EXIF_TAG_DATE_TIME_DIGITIZED = 0x9004,
+ EXIF_TAG_COMPONENTS_CONFIGURATION = 0x9101,
+ EXIF_TAG_COMPRESSED_BITS_PER_PIXEL = 0x9102,
+ EXIF_TAG_SHUTTER_SPEED_VALUE = 0x9201,
+ EXIF_TAG_APERTURE_VALUE = 0x9202,
+ EXIF_TAG_BRIGHTNESS_VALUE = 0x9203,
+ EXIF_TAG_EXPOSURE_BIAS_VALUE = 0x9204,
+ EXIF_TAG_MAX_APERTURE_VALUE = 0x9205,
+ EXIF_TAG_SUBJECT_DISTANCE = 0x9206,
+ EXIF_TAG_METERING_MODE = 0x9207,
+ EXIF_TAG_LIGHT_SOURCE = 0x9208,
+ EXIF_TAG_FLASH = 0x9209,
+ EXIF_TAG_FOCAL_LENGTH = 0x920a,
+ EXIF_TAG_SUBJECT_AREA = 0x9214,
+ EXIF_TAG_TIFF_EP_STANDARD_ID = 0x9216,
+ EXIF_TAG_MAKER_NOTE = 0x927c,
+ EXIF_TAG_USER_COMMENT = 0x9286,
+ EXIF_TAG_SUB_SEC_TIME = 0x9290,
+ EXIF_TAG_SUB_SEC_TIME_ORIGINAL = 0x9291,
+ EXIF_TAG_SUB_SEC_TIME_DIGITIZED = 0x9292,
+ EXIF_TAG_FLASH_PIX_VERSION = 0xa000,
+ EXIF_TAG_COLOR_SPACE = 0xa001,
+ EXIF_TAG_PIXEL_X_DIMENSION = 0xa002,
+ EXIF_TAG_PIXEL_Y_DIMENSION = 0xa003,
+ EXIF_TAG_RELATED_SOUND_FILE = 0xa004,
+ EXIF_TAG_INTEROPERABILITY_IFD_POINTER = 0xa005,
+ EXIF_TAG_FLASH_ENERGY = 0xa20b,
+ EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE = 0xa20c,
+ EXIF_TAG_FOCAL_PLANE_X_RESOLUTION = 0xa20e,
+ EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION = 0xa20f,
+ EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT = 0xa210,
+ EXIF_TAG_SUBJECT_LOCATION = 0xa214,
+ EXIF_TAG_EXPOSURE_INDEX = 0xa215,
+ EXIF_TAG_SENSING_METHOD = 0xa217,
+ EXIF_TAG_FILE_SOURCE = 0xa300,
+ EXIF_TAG_SCENE_TYPE = 0xa301,
+ EXIF_TAG_NEW_CFA_PATTERN = 0xa302,
+ EXIF_TAG_CUSTOM_RENDERED = 0xa401,
+ EXIF_TAG_EXPOSURE_MODE = 0xa402,
+ EXIF_TAG_WHITE_BALANCE = 0xa403,
+ EXIF_TAG_DIGITAL_ZOOM_RATIO = 0xa404,
+ EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM = 0xa405,
+ EXIF_TAG_SCENE_CAPTURE_TYPE = 0xa406,
+ EXIF_TAG_GAIN_CONTROL = 0xa407,
+ EXIF_TAG_CONTRAST = 0xa408,
+ EXIF_TAG_SATURATION = 0xa409,
+ EXIF_TAG_SHARPNESS = 0xa40a,
+ EXIF_TAG_DEVICE_SETTING_DESCRIPTION = 0xa40b,
+ EXIF_TAG_SUBJECT_DISTANCE_RANGE = 0xa40c,
+ EXIF_TAG_IMAGE_UNIQUE_ID = 0xa420
+} ExifTag;
+
+ExifTag exif_tag_from_name (const char *);
+const char *exif_tag_get_name (ExifTag tag);
+const char *exif_tag_get_title (ExifTag tag);
+const char *exif_tag_get_description (ExifTag tag);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_TAG_H__ */
diff --git a/src/libexif/exif-utils.c b/src/libexif/exif-utils.c
new file mode 100644
index 0000000..9386012
--- /dev/null
+++ b/src/libexif/exif-utils.c
@@ -0,0 +1,214 @@
+/* exif-utils.c
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-utils.h>
+
+void
+exif_array_set_byte_order (ExifFormat f, unsigned char *b, unsigned int n,
+ ExifByteOrder o_orig, ExifByteOrder o_new)
+{
+ unsigned int j;
+ unsigned int fs = exif_format_get_size (f);
+ ExifShort s;
+ ExifSShort ss;
+ ExifLong l;
+ ExifSLong sl;
+ ExifRational r;
+ ExifSRational sr;
+
+ if (!b || !n || !fs) return;
+
+ switch (f) {
+ case EXIF_FORMAT_SHORT:
+ for (j = 0; j < n; j++) {
+ s = exif_get_short (b + j * fs, o_orig);
+ exif_set_short (b + j * fs, o_new, s);
+ }
+ break;
+ case EXIF_FORMAT_SSHORT:
+ for (j = 0; j < n; j++) {
+ ss = exif_get_sshort (b + j * fs, o_orig);
+ exif_set_sshort (b + j * fs, o_new, ss);
+ }
+ break;
+ case EXIF_FORMAT_LONG:
+ for (j = 0; j < n; j++) {
+ l = exif_get_long (b + j * fs, o_orig);
+ exif_set_long (b + j * fs, o_new, l);
+ }
+ break;
+ case EXIF_FORMAT_RATIONAL:
+ for (j = 0; j < n; j++) {
+ r = exif_get_rational (b + j * fs, o_orig);
+ exif_set_rational (b + j * fs, o_new, r);
+ }
+ break;
+ case EXIF_FORMAT_SLONG:
+ for (j = 0; j < n; j++) {
+ sl = exif_get_slong (b + j * fs, o_orig);
+ exif_set_slong (b + j * fs, o_new, sl);
+ }
+ break;
+ case EXIF_FORMAT_SRATIONAL:
+ for (j = 0; j < n; j++) {
+ sr = exif_get_srational (b + j * fs, o_orig);
+ exif_set_srational (b + j * fs, o_new, sr);
+ }
+ break;
+ case EXIF_FORMAT_UNDEFINED:
+ case EXIF_FORMAT_BYTE:
+ case EXIF_FORMAT_ASCII:
+ default:
+ /* Nothing here. */
+ break;
+ }
+}
+
+ExifSShort
+exif_get_sshort (const unsigned char *buf, ExifByteOrder order)
+{
+ if (!buf) return 0;
+ switch (order) {
+ case EXIF_BYTE_ORDER_MOTOROLA:
+ return ((buf[0] << 8) | buf[1]);
+ case EXIF_BYTE_ORDER_INTEL:
+ return ((buf[1] << 8) | buf[0]);
+ }
+
+ /* Won't be reached */
+ return (0);
+}
+
+ExifShort
+exif_get_short (const unsigned char *buf, ExifByteOrder order)
+{
+ return (exif_get_sshort (buf, order) & 0xffff);
+}
+
+void
+exif_set_sshort (unsigned char *b, ExifByteOrder order, ExifSShort value)
+{
+ if (!b) return;
+ switch (order) {
+ case EXIF_BYTE_ORDER_MOTOROLA:
+ b[0] = (unsigned char) (value >> 8);
+ b[1] = (unsigned char) value;
+ break;
+ case EXIF_BYTE_ORDER_INTEL:
+ b[0] = (unsigned char) value;
+ b[1] = (unsigned char) (value >> 8);
+ break;
+ }
+}
+
+void
+exif_set_short (unsigned char *b, ExifByteOrder order, ExifShort value)
+{
+ exif_set_sshort (b, order, value);
+}
+
+ExifSLong
+exif_get_slong (const unsigned char *b, ExifByteOrder order)
+{
+ if (!b) return 0;
+ switch (order) {
+ case EXIF_BYTE_ORDER_MOTOROLA:
+ return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]);
+ case EXIF_BYTE_ORDER_INTEL:
+ return ((b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]);
+ }
+
+ /* Won't be reached */
+ return (0);
+}
+
+void
+exif_set_slong (unsigned char *b, ExifByteOrder order, ExifSLong value)
+{
+ if (!b) return;
+ switch (order) {
+ case EXIF_BYTE_ORDER_MOTOROLA:
+ b[0] = (unsigned char) (value >> 24);
+ b[1] = (unsigned char) (value >> 16);
+ b[2] = (unsigned char) (value >> 8);
+ b[3] = (unsigned char) value;
+ break;
+ case EXIF_BYTE_ORDER_INTEL:
+ b[3] = (unsigned char) (value >> 24);
+ b[2] = (unsigned char) (value >> 16);
+ b[1] = (unsigned char) (value >> 8);
+ b[0] = (unsigned char) value;
+ break;
+ }
+}
+
+ExifLong
+exif_get_long (const unsigned char *buf, ExifByteOrder order)
+{
+ return (exif_get_slong (buf, order) & 0xffffffff);
+}
+
+void
+exif_set_long (unsigned char *b, ExifByteOrder order, ExifLong value)
+{
+ exif_set_slong (b, order, value);
+}
+
+ExifSRational
+exif_get_srational (const unsigned char *buf, ExifByteOrder order)
+{
+ ExifSRational r;
+
+ r.numerator = buf ? exif_get_slong (buf, order) : 0;
+ r.denominator = buf ? exif_get_slong (buf + 4, order) : 0;
+
+ return (r);
+}
+
+ExifRational
+exif_get_rational (const unsigned char *buf, ExifByteOrder order)
+{
+ ExifRational r;
+
+ r.numerator = buf ? exif_get_long (buf, order) : 0;
+ r.denominator = buf ? exif_get_long (buf + 4, order) : 0;
+
+ return (r);
+}
+
+void
+exif_set_rational (unsigned char *buf, ExifByteOrder order,
+ ExifRational value)
+{
+ if (!buf) return;
+ exif_set_long (buf, order, value.numerator);
+ exif_set_long (buf + 4, order, value.denominator);
+}
+
+void
+exif_set_srational (unsigned char *buf, ExifByteOrder order,
+ ExifSRational value)
+{
+ if (!buf) return;
+ exif_set_slong (buf, order, value.numerator);
+ exif_set_slong (buf + 4, order, value.denominator);
+}
diff --git a/src/libexif/exif-utils.h b/src/libexif/exif-utils.h
new file mode 100644
index 0000000..a75db0b
--- /dev/null
+++ b/src/libexif/exif-utils.h
@@ -0,0 +1,81 @@
+/* exif-utils.h
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_UTILS_H__
+#define __EXIF_UTILS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-format.h>
+#include <libexif/_stdint.h>
+
+
+/* If these definitions don't work for you, please let us fix the
+ * macro generating _stdint.h */
+
+typedef char ExifByte; /* 1 byte */
+typedef char * ExifAscii;
+typedef uint16_t ExifShort; /* 2 bytes */
+typedef int16_t ExifSShort; /* 2 bytes */
+typedef uint32_t ExifLong; /* 4 bytes */
+typedef struct {ExifLong numerator; ExifLong denominator;} ExifRational;
+typedef char ExifUndefined; /* 1 byte */
+typedef int32_t ExifSLong; /* 4 bytes */
+typedef struct {ExifSLong numerator; ExifSLong denominator;} ExifSRational;
+
+
+ExifShort exif_get_short (const unsigned char *b, ExifByteOrder order);
+ExifSShort exif_get_sshort (const unsigned char *b, ExifByteOrder order);
+ExifLong exif_get_long (const unsigned char *b, ExifByteOrder order);
+ExifSLong exif_get_slong (const unsigned char *b, ExifByteOrder order);
+ExifRational exif_get_rational (const unsigned char *b, ExifByteOrder order);
+ExifSRational exif_get_srational (const unsigned char *b, ExifByteOrder order);
+
+void exif_set_short (unsigned char *b, ExifByteOrder order,
+ ExifShort value);
+void exif_set_sshort (unsigned char *b, ExifByteOrder order,
+ ExifSShort value);
+void exif_set_long (unsigned char *b, ExifByteOrder order,
+ ExifLong value);
+void exif_set_slong (unsigned char *b, ExifByteOrder order,
+ ExifSLong value);
+void exif_set_rational (unsigned char *b, ExifByteOrder order,
+ ExifRational value);
+void exif_set_srational (unsigned char *b, ExifByteOrder order,
+ ExifSRational value);
+
+/* Please do not use this function outside of the library. */
+void exif_array_set_byte_order (ExifFormat, unsigned char *, unsigned int,
+ ExifByteOrder o_orig, ExifByteOrder o_new);
+
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/* For compatibility with older versions */
+#define EXIF_TAG_SUBSEC_TIME EXIF_TAG_SUB_SEC_TIME
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_UTILS_H__ */
diff --git a/src/libexif/exif.c b/src/libexif/exif.c
new file mode 100644
index 0000000..3be72a3
--- /dev/null
+++ b/src/libexif/exif.c
@@ -0,0 +1,1274 @@
+/*
+
+Copyright © 2000 Matthias Wandel, The PHP Group, Curtis Galloway
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <sys/time.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <math.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+#include <fcntl.h>
+
+#include "exif.h"
+
+typedef unsigned char uchar;
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+/*
+ This structure stores global state for an EXIF image file.
+*/
+typedef struct {
+ exif_data_t *d;
+ int MotorolaOrder;
+ const char *filename;
+
+ char *Thumbnail;
+ int ThumbnailSize;
+} ImageInfoType;
+
+void *(*exif_malloc_fn)(int);
+void *(*exif_realloc_fn)(void *, int);
+void (*exif_free_fn)(void *);
+
+static char *
+exif_strndup(char *str, int len)
+{
+ char *rval = (*exif_malloc_fn)(len+1);
+ strncpy(rval, str, len);
+ rval[len] = '\0';
+ return rval;
+}
+
+struct exif_data *
+exif_alloc(void)
+{
+ exif_data_t *d;
+
+ d = (*exif_malloc_fn)(sizeof(exif_data_t));
+ bzero(d, sizeof(*d));
+ return d;
+}
+
+static void
+exif_error(char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
+
+/* This structure is used to store a section of a Jpeg file. */
+typedef struct {
+ uchar *Data;
+ int Type;
+ unsigned Size;
+} Section_t;
+
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+
+
+/*
+ JPEG markers consist of one or more 0xFF bytes, followed by a marker
+ code byte (which is not an FF). Here are the marker codes of interest
+ in this program. (See jdmarker.c for a more complete list.)
+*/
+
+#define M_SOF0 0xC0 /* Start Of Frame N */
+#define M_SOF1 0xC1 /* N indicates which compression process */
+#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
+#define M_SOF3 0xC3
+#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
+#define M_SOF6 0xC6
+#define M_SOF7 0xC7
+#define M_SOF9 0xC9
+#define M_SOF10 0xCA
+#define M_SOF11 0xCB
+#define M_SOF13 0xCD
+#define M_SOF14 0xCE
+#define M_SOF15 0xCF
+#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
+#define M_EOI 0xD9 /* End Of Image (end of datastream) */
+#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
+#define M_EXIF 0xE1
+#define M_COM 0xFE /* COMment */
+
+
+#define PSEUDO_IMAGE_MARKER 0x123; /* Extra value. */
+
+#define EXIF_ALLOC_SIZE 16
+
+/*
+ * The name gets copied, so you can pass a static string;
+ * the data is not copied, so if it is a string,
+ * you must allocate it yourself.
+ */
+static int
+exif_append_data(exif_data_t **d_p,
+ char *name,
+ char rec_type,
+ int exif_format,
+ exif_rec_data_t *data)
+{
+ exif_data_t *d = *d_p;
+
+ if (rec_type == '\0')
+ return EXIT_FAILURE;
+
+ if (d->n_alloc <= d->n_recs) {
+ d->n_alloc += EXIF_ALLOC_SIZE;
+ d = (*exif_realloc_fn)(d, sizeof(exif_data_t) +
+ sizeof(exif_record_t) * d->n_alloc);
+ *d_p = d;
+ }
+ d->recs[d->n_recs].rec_type = rec_type;
+ bcopy(data, &d->recs[d->n_recs].rec_data, sizeof(exif_rec_data_t));
+ d->recs[d->n_recs].rec_name = (char*)strdup(name);
+ d->n_recs++;
+ return EXIT_SUCCESS;
+}
+
+/*
+ Get 16 bits motorola order (always) for jpeg header stuff.
+*/
+static int
+Get16m(void *Short)
+{
+ return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1];
+}
+
+
+/*
+ Process a COM marker.
+ We want to print out the marker contents as legible text;
+ we must guard against random junk and varying newline representations.
+*/
+static void
+process_COM (ImageInfoType *ImageInfo, uchar *Data, int length)
+{
+ int ch;
+ char *Comment;
+ int nch;
+ int a;
+ exif_rec_data_t rd;
+
+ nch = 0;
+ Comment = (*exif_malloc_fn)(length+1);
+
+ for (a=2;a<length;a++) {
+ ch = Data[a];
+
+ if (ch == '\r' && Data[a+1] == '\n') continue; /* Remove cr followed by lf. */
+
+ if (isprint(ch) || ch == '\n' || ch == '\t') {
+ Comment[nch++] = (char)ch;
+ } else {
+ Comment[nch++] = '?';
+ }
+ }
+
+ Comment[nch] = '\0'; /* Null terminate */
+
+ rd.s = Comment;
+ exif_append_data(&ImageInfo->d, "Comment", 's', EXIF_FMT_COMPUTED, &rd);
+}
+
+/* Process a SOFn marker. This is useful for the image dimensions. */
+static void
+process_SOFn (ImageInfoType *ImageInfo, uchar *Data, int marker)
+{
+ int data_precision, num_components;
+ const char *process;
+ exif_rec_data_t rd;
+
+ data_precision = Data[2];
+ rd.l = Get16m(Data+3);
+ exif_append_data(&ImageInfo->d,
+ "Height",
+ 'l',
+ EXIF_FMT_COMPUTED,
+ &rd);
+ rd.l = Get16m(Data+5);
+ exif_append_data(&ImageInfo->d,
+ "Width",
+ 'l',
+ EXIF_FMT_COMPUTED,
+ &rd);
+ num_components = Data[7];
+
+ if (num_components == 3) {
+ rd.l = 1;
+ } else {
+ rd.l = 0;
+ }
+ exif_append_data(&ImageInfo->d, "IsColor", 'l', EXIF_FMT_COMPUTED, &rd);
+
+ switch (marker) {
+ case M_SOF0: process = "Baseline"; break;
+ case M_SOF1: process = "Extended sequential"; break;
+ case M_SOF2: process = "Progressive"; break;
+ case M_SOF3: process = "Lossless"; break;
+ case M_SOF5: process = "Differential sequential"; break;
+ case M_SOF6: process = "Differential progressive"; break;
+ case M_SOF7: process = "Differential lossless"; break;
+ case M_SOF9: process = "Extended sequential, arithmetic coding"; break;
+ case M_SOF10: process = "Progressive, arithmetic coding"; break;
+ case M_SOF11: process = "Lossless, arithmetic coding"; break;
+ case M_SOF13: process = "Differential sequential, arithmetic coding"; break;
+ case M_SOF14: process = "Differential progressive, arithmetic coding"; break;
+ case M_SOF15: process = "Differential lossless, arithmetic coding"; break;
+ default: process = "Unknown"; break;
+ }
+}
+
+/*
+ Describes format descriptor
+*/
+static int ExifBytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
+#define NUM_FORMATS EXIF_FMT_DOUBLE
+
+/*
+ Describes tag values
+*/
+
+#define TAG_EXIF_OFFSET 0x8769
+#define TAG_INTEROP_OFFSET 0xa005
+
+#define TAG_COMPRESSION 0x0103
+
+#define TAG_MAKE 0x010F
+#define TAG_MODEL 0x0110
+#define TAG_ORIENTATION 0x0112
+
+#define TAG_SOFTWARE 0x0131
+
+/* Olympus specific tags */
+#define TAG_SPECIALMODE 0x0200
+#define TAG_JPEGQUAL 0x0201
+#define TAG_MACRO 0x0202
+#define TAG_DIGIZOOM 0x0204
+#define TAG_SOFTWARERELEASE 0x0207
+#define TAG_PICTINFO 0x0208
+#define TAG_CAMERAID 0x0209
+/* end Olympus specific tags */
+
+#define TAG_COPYRIGHT 0x8298
+
+#define TAG_EXPOSURETIME 0x829A
+#define TAG_FNUMBER 0x829D
+
+#define TAG_GPSINFO 0x8825
+#define TAG_ISOSPEED 0x8827
+#define TAG_EXIFVERSION 0x9000
+
+#define TAG_SHUTTERSPEED 0x9201
+#define TAG_APERTURE 0x9202
+#define TAG_MAXAPERTURE 0x9205
+#define TAG_FOCALLENGTH 0x920A
+
+#define TAG_DATETIME_ORIGINAL 0x9003
+#define TAG_USERCOMMENT 0x9286
+
+#define TAG_SUBJECT_DISTANCE 0x9206
+#define TAG_LIGHT_SOURCE 0x9208
+#define TAG_FLASH 0x9209
+
+#define TAG_FOCALPLANEXRES 0xa20E
+#define TAG_FOCALPLANEUNITS 0xa210
+#define TAG_IMAGEWIDTH 0xA002
+
+struct ExifTag {
+ unsigned short Tag;
+ char *Desc;
+ void (*Func)();
+};
+
+
+
+/* Convert a 16 bit unsigned value from file's native byte order */
+static int
+Get16u(void *Short, int MotorolaOrder)
+{
+ if (MotorolaOrder) {
+ return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1];
+ } else {
+ return (((uchar *)Short)[1] << 8) | ((uchar *)Short)[0];
+ }
+}
+
+/* Convert a 32 bit signed value from file's native byte order */
+static int
+Get32s(void *Long, int MotorolaOrder)
+{
+ if (MotorolaOrder) {
+ return ((( char *)Long)[0] << 24) | (((uchar *)Long)[1] << 16)
+ | (((uchar *)Long)[2] << 8 ) | (((uchar *)Long)[3] << 0 );
+ } else {
+ return ((( char *)Long)[3] << 24) | (((uchar *)Long)[2] << 16)
+ | (((uchar *)Long)[1] << 8 ) | (((uchar *)Long)[0] << 0 );
+ }
+}
+
+/* Convert a 32 bit unsigned value from file's native byte order */
+static unsigned
+Get32u(void *Long, int MotorolaOrder)
+{
+ return (unsigned)Get32s(Long, MotorolaOrder) & 0xffffffff;
+}
+
+
+/* Evaluate number, be it int, rational, or float from directory. */
+static double
+ConvertAnyFormat(void *ValuePtr, int Format, int MotorolaOrder)
+{
+ double Value;
+ Value = 0;
+
+ switch(Format) {
+ case EXIF_FMT_SBYTE: Value = *(signed char *)ValuePtr; break;
+ case EXIF_FMT_BYTE: Value = *(uchar *)ValuePtr; break;
+
+ case EXIF_FMT_USHORT: Value = Get16u(ValuePtr,MotorolaOrder); break;
+ case EXIF_FMT_ULONG: Value = Get32u(ValuePtr,MotorolaOrder); break;
+
+ case EXIF_FMT_URATIONAL:
+ case EXIF_FMT_SRATIONAL:
+ {
+ int Num,Den;
+ Num = Get32s(ValuePtr,MotorolaOrder);
+ Den = Get32s(4+(char *)ValuePtr,MotorolaOrder);
+ if (Den == 0) {
+ Value = 0;
+ } else {
+ Value = (double)Num/Den;
+ }
+ break;
+ }
+
+ case EXIF_FMT_SSHORT: Value = (signed short)Get16u(ValuePtr,MotorolaOrder); break;
+ case EXIF_FMT_SLONG: Value = Get32s(ValuePtr,MotorolaOrder); break;
+
+ /* Not sure if this is correct (never seen float used in Exif format) */
+ case EXIF_FMT_SINGLE: Value = (double)*(float *)ValuePtr; break;
+ case EXIF_FMT_DOUBLE: Value = *(double *)ValuePtr; break;
+ }
+ return Value;
+}
+
+/* Evaluate number, be it int, rational, or float from directory. */
+static char
+ConvertAnyFormat2(void *ValuePtr, int ByteCount, int Format, int MotorolaOrder, exif_rec_data_t *data_p)
+{
+ char *str, *p;
+ char r_type;
+ unsigned char c;
+ static char hexdigits[] = "0123456789ABCDEF";
+
+ switch(Format) {
+ case EXIF_FMT_STRING:
+ data_p->s = exif_strndup(ValuePtr, ByteCount);
+ r_type = 's';
+ break;
+
+ case EXIF_FMT_SBYTE:
+ data_p->l = (long)*(signed char *)ValuePtr;
+ r_type = 'l';
+ break;
+
+ case EXIF_FMT_BYTE:
+ data_p->l = (long)*(uchar *)ValuePtr;
+ r_type = 'l';
+ break;
+
+ case EXIF_FMT_USHORT:
+ data_p->l = (long)Get16u(ValuePtr,MotorolaOrder);
+ r_type = 'l';
+ break;
+ case EXIF_FMT_ULONG:
+ data_p->l = (long)Get32u(ValuePtr,MotorolaOrder);
+ r_type = 'l';
+ break;
+
+ case EXIF_FMT_URATIONAL:
+ case EXIF_FMT_SRATIONAL:
+ {
+ int Num,Den;
+ data_p->r.num = Get32s(ValuePtr,MotorolaOrder);
+ data_p->r.denom = Get32s(4+(char *)ValuePtr,MotorolaOrder);
+ r_type = 'r';
+ break;
+ }
+
+ case EXIF_FMT_SSHORT:
+ data_p->l = (signed short)Get16u(ValuePtr,MotorolaOrder);
+ r_type = 'l';
+ break;
+ case EXIF_FMT_SLONG:
+ data_p->l = (long)Get32s(ValuePtr,MotorolaOrder);
+ r_type = 'l';
+ break;
+
+ /* Not sure if this is correct (never seen float used in Exif format) */
+ case EXIF_FMT_SINGLE:
+ data_p->f = *(float *)ValuePtr;
+ r_type = 'f';
+ break;
+
+ case EXIF_FMT_DOUBLE:
+ data_p->g = *(double *)ValuePtr;
+ r_type = 'f';
+ break;
+
+ default:
+ /* unknown type */
+ p = str = (*exif_malloc_fn)(ByteCount*2 + 1);
+ while (ByteCount--) {
+ c = *(unsigned char *)ValuePtr++;
+ *p++ = hexdigits[c / 16];
+ *p++ = hexdigits[c % 16];
+ }
+ *p++ = '\0';
+ data_p->s = str;
+ r_type = 's';
+ break;
+ }
+ return r_type;
+}
+
+
+static void
+ProcessFocalPlaneUnits(ImageInfoType *ImageInfo,
+ void *ValuePtr,
+ int ByteCount,
+ int Format,
+ struct ExifTag *tag_p)
+{
+ exif_rec_data_t rd;
+ float FocalPlaneUnits;
+
+ switch((int)ConvertAnyFormat(ValuePtr, Format, ImageInfo->MotorolaOrder)) {
+ case 1:
+ FocalPlaneUnits = 25.4;
+ break; /* inch */
+ case 2:
+ /* According to the information I was using, 2 means meters.
+ But looking at the Canon PowerShot's files, inches is the only
+ sensible value. */
+ FocalPlaneUnits = 25.4;
+ break;
+
+ case 3:
+ FocalPlaneUnits = 10;
+ break; /* centimeter */
+ case 4:
+ FocalPlaneUnits = 1;
+ break; /* milimeter */
+ case 5:
+ FocalPlaneUnits = .001;
+ break; /* micrometer */
+ }
+
+ rd.f = FocalPlaneUnits;
+ exif_append_data(&ImageInfo->d,
+ "FocalPlaneUnits",
+ 'f',
+ Format,
+ &rd);
+}
+
+static void
+ProcessVersion(ImageInfoType *ImageInfo,
+ void *ValuePtr,
+ int ByteCount,
+ int Format,
+ struct ExifTag *tag_p)
+{
+ exif_rec_data_t rd;
+ rd.s = exif_strndup(ValuePtr, ByteCount);
+ exif_append_data(&ImageInfo->d,
+ tag_p->Desc,
+ 's',
+ Format,
+ &rd);
+}
+
+static void
+ProcessUserComment(ImageInfoType *ImageInfo,
+ void *_ValuePtr,
+ int ByteCount,
+ int Format,
+ struct ExifTag *tag_p)
+{
+ char *ValuePtr = (char *)_ValuePtr;
+ exif_rec_data_t rd;
+ int a;
+
+ /* Olympus has this padded with trailing spaces. Remove these first. */
+ for (a=ByteCount;;) {
+ a--;
+ if ((ValuePtr)[a] == ' ') {
+ (ValuePtr)[a] = '\0';
+ } else {
+ break;
+ }
+ if (a == 0) break;
+ }
+
+ /* Copy the comment */
+ if (memcmp(ValuePtr, "ASCII",5) == 0) {
+ for (a=5;a<10;a++) {
+ int c;
+ c = (ValuePtr)[a];
+ if (c != '\0' && c != ' ') {
+ rd.s = exif_strndup(a+ValuePtr, ByteCount - a);
+ exif_append_data(&ImageInfo->d,
+ "UserComment",
+ 's',
+ Format,
+ &rd);
+ break;
+ }
+ }
+
+ } else {
+ rd.s = exif_strndup(ValuePtr, ByteCount);
+ exif_append_data(&ImageInfo->d,
+ "UserComment",
+ 's',
+ Format,
+ &rd);
+ }
+}
+
+static void
+ProcessShutterSpeed(ImageInfoType *ImageInfo,
+ void *ValuePtr,
+ int ByteCount,
+ int Format,
+ struct ExifTag *tag_p)
+{
+ exif_rec_data_t rd;
+ char rec_type;
+
+ rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format,
+ ImageInfo->MotorolaOrder,
+ &rd);
+ exif_append_data(&ImageInfo->d,
+ tag_p->Desc,
+ rec_type,
+ Format,
+ &rd);
+
+ /* Convert shutter speed value to shutter speed;
+ * shutter speed is 1/(2**ShutterSpeedValue)
+ */
+ rd.r.denom = (int)pow(2.0, ((double)rd.r.num)/((double)rd.r.denom));
+ rd.r.num = 1;
+ exif_append_data(&ImageInfo->d,
+ "ShutterSpeed",
+ 'r',
+ EXIF_FMT_COMPUTED,
+ &rd);
+
+}
+
+static void
+ProcessAperture(ImageInfoType *ImageInfo,
+ void *ValuePtr,
+ int ByteCount,
+ int Format,
+ struct ExifTag *tag_p)
+{
+ exif_rec_data_t rd;
+ char rec_type;
+ double fstop;
+ char label[32];
+
+ rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format,
+ ImageInfo->MotorolaOrder,
+ &rd);
+ exif_append_data(&ImageInfo->d,
+ tag_p->Desc,
+ rec_type,
+ Format,
+ &rd);
+
+ if (exif_find_record(ImageInfo->d, "FNumber") == NULL) {
+ /* Convert aperture to F-stop. */
+ fstop = pow(sqrt(2), ((double)rd.r.num)/((double)rd.r.denom));
+ sprintf(label, "f%.1g", fstop);
+ rd.s = (char*)strdup(label);
+ exif_append_data(&ImageInfo->d,
+ "FNumber",
+ 's',
+ EXIF_FMT_COMPUTED,
+ &rd);
+ }
+}
+
+static void
+ProcessCanonMakerNote(ImageInfoType *ImageInfo,
+ void *ValuePtr,
+ int ByteCount,
+ int Format,
+ struct ExifTag *tag_p,
+ char *OffsetBase)
+{
+
+ /* This is for the Canon MakerNote. */
+ /* XXX - go by value of Maker tag. */
+ exif_rec_data_t rd;
+ char rec_type;
+ unsigned long n_dir, tag, format, components, offset;
+ char label[32];
+ void *OffsetPtr;
+
+ n_dir = Get16u(ValuePtr, ImageInfo->MotorolaOrder);
+ ValuePtr += 2;
+ while (n_dir--) {
+ tag = Get16u(ValuePtr, ImageInfo->MotorolaOrder);
+ ValuePtr += 2;
+ format = Get16u(ValuePtr, ImageInfo->MotorolaOrder);
+ ValuePtr += 2;
+ components = Get32u(ValuePtr, ImageInfo->MotorolaOrder);
+ ValuePtr += 4;
+ offset = Get32u(ValuePtr, ImageInfo->MotorolaOrder);
+ ByteCount = components * ExifBytesPerFormat[format];
+ if (ByteCount > 4) {
+ OffsetPtr = OffsetBase + offset;
+ } else {
+ OffsetPtr = ValuePtr;
+ }
+ ValuePtr += 4;
+ rec_type = ConvertAnyFormat2(OffsetPtr, ByteCount, format,
+ ImageInfo->MotorolaOrder,
+ &rd);
+ sprintf(label, "MakerNote%04x", tag);
+ exif_append_data(&ImageInfo->d,
+ label,
+ rec_type,
+ format,
+ &rd);
+
+ }
+}
+
+
+struct MakerNote {
+ char *Make;
+ void (*Func)();
+};
+
+static struct MakerNote
+MakerProcessors[] = {
+ {"Canon", ProcessCanonMakerNote},
+ {NULL, NULL}
+};
+
+static void
+ProcessMakerNote(ImageInfoType *ImageInfo,
+ void *ValuePtr,
+ int ByteCount,
+ int Format,
+ struct ExifTag *tag_p,
+ char *OffsetBase)
+{
+ struct MakerNote *mn_p;
+ exif_record_t *rec_p;
+
+ rec_p = exif_find_record(ImageInfo->d, "Make");
+ if (rec_p == NULL) {
+ return;
+ }
+
+ for(mn_p = &MakerProcessors[0]; mn_p->Make != NULL; mn_p++) {
+ if (strcmp(mn_p->Make, rec_p->rec_data.s) == 0) {
+ (*mn_p->Func)(ImageInfo, ValuePtr, ByteCount, Format, tag_p, OffsetBase);
+ break;
+ }
+ }
+}
+
+static struct ExifTag
+TagTable[] = {
+ { 0x0001, "InteroperabilityIndex"},
+ { 0x0002, "InteroperabilityVersion", ProcessVersion},
+ { 0x0100, "ImageWidth"},
+ { 0x0101, "ImageLength"},
+ { 0x0102, "BitsPerSample"},
+ { 0x0103, "Compression"},
+ { 0x0106, "PhotometricInterpretation"},
+ { 0x010A, "FillOrder"},
+ { 0x010D, "DocumentName"},
+ { 0x010E, "ImageDescription"},
+ { 0x010F, "Make"},
+ { 0x0110, "Model"},
+ { 0x0111, "StripOffsets"},
+ { 0x0112, "Orientation"},
+ { 0x0115, "SamplesPerPixel"},
+ { 0x0116, "RowsPerStrip"},
+ { 0x0117, "StripByteCounts"},
+ { 0x011A, "XResolution"},
+ { 0x011B, "YResolution"},
+ { 0x011C, "PlanarConfiguration"},
+ { 0x0128, "ResolutionUnit"},
+ { 0x012D, "TransferFunction"},
+ { 0x0131, "Software"},
+ { 0x0132, "DateTime"},
+ { 0x013B, "Artist"},
+ { 0x013E, "WhitePoint"},
+ { 0x013F, "PrimaryChromaticities"},
+ { 0x0156, "TransferRange"},
+ { 0x0200, "JPEGProc"},
+ { 0x0201, "JPEGInterchangeFormat"},
+ { 0x0202, "JPEGInterchangeFormatLength"},
+ { 0x0211, "YCbCrCoefficients"},
+ { 0x0212, "YCbCrSubSampling"},
+ { 0x0213, "YCbCrPositioning"},
+ { 0x0214, "ReferenceBlackWhite"},
+ { 0x1000, "RelatedImageFileFormat"},
+ { 0x1001, "RelatedImageWidth"},
+ { 0x1002, "RelatedImageLength"},
+ { 0x828D, "CFARepeatPatternDim"},
+ { 0x828E, "CFAPattern"},
+ { 0x828F, "BatteryLevel"},
+ { 0x8298, "Copyright"},
+ { 0x829A, "ExposureTime"},
+ { 0x829D, "FNumber"},
+ { 0x83BB, "IPTC/NAA"},
+ { 0x8769, "ExifOffset"},
+ { 0x8773, "InterColorProfile"},
+ { 0x8822, "ExposureProgram"},
+ { 0x8824, "SpectralSensitivity"},
+ { 0x8825, "GPSInfo"},
+ { 0x8827, "ISOSpeedRatings"},
+ { 0x8828, "OECF"},
+ { 0x9000, "ExifVersion", ProcessVersion},
+ { 0x9003, "DateTimeOriginal"},
+ { 0x9004, "DateTimeDigitized"},
+ { 0x9101, "ComponentsConfiguration"},
+ { 0x9102, "CompressedBitsPerPixel"},
+ { 0x9201, "ShutterSpeedValue", ProcessShutterSpeed},
+ { 0x9202, "ApertureValue", ProcessAperture},
+ { 0x9203, "BrightnessValue"},
+ { 0x9204, "ExposureBiasValue"},
+ { 0x9205, "MaxApertureValue", ProcessAperture},
+ { 0x9206, "SubjectDistance"},
+ { 0x9207, "MeteringMode"},
+ { 0x9208, "LightSource"},
+ { 0x9209, "Flash"},
+ { 0x920A, "FocalLength"},
+ { 0x927C, "MakerNote", ProcessMakerNote},
+ { 0x9286, "UserComment", ProcessUserComment},
+ { 0x9290, "SubSecTime"},
+ { 0x9291, "SubSecTimeOriginal"},
+ { 0x9292, "SubSecTimeDigitized"},
+ { 0xA000, "FlashPixVersion", ProcessVersion},
+ { 0xA001, "ColorSpace"},
+ { 0xA002, "ExifImageWidth"},
+ { 0xA003, "ExifImageLength"},
+ { 0xA005, "InteroperabilityOffset"},
+ { 0xA20B, "FlashEnergy"}, /* 0x920B in TIFF/EP */
+ { 0xA20C, "SpatialFrequencyResponse"}, /* 0x920C - - */
+ { 0xA20E, "FocalPlaneXResolution"}, /* 0x920E - - */
+ { 0xA20F, "FocalPlaneYResolution"}, /* 0x920F - - */
+ { 0xA210, "FocalPlaneResolutionUnit", ProcessFocalPlaneUnits},
+ /* 0x9210 - - */
+ { 0xA214, "SubjectLocation"}, /* 0x9214 - - */
+ { 0xA215, "ExposureIndex"}, /* 0x9215 - - */
+ { 0xA217, "SensingMethod"}, /* 0x9217 - - */
+ { 0xA300, "FileSource"},
+ { 0xA301, "SceneType"},
+ { 0, NULL}
+} ;
+
+
+
+/* Process one of the nested EXIF directories. */
+static int
+ProcessExifDir(ImageInfoType *ImageInfo, char *DirStart, char *OffsetBase, unsigned ExifLength, char *LastExifRefd)
+{
+ int de;
+ int a;
+ int NumDirEntries;
+ exif_rec_data_t rd;
+ char rec_type;
+ char label[32];
+
+ NumDirEntries = Get16u(DirStart, ImageInfo->MotorolaOrder);
+
+ if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength)) {
+ exif_error("Illegally sized directory");
+ return FALSE;
+ }
+
+
+ for (de=0;de<NumDirEntries;de++) {
+ int Tag, Format, Components;
+ char *ValuePtr;
+ int ByteCount;
+ char *DirEntry;
+ struct ExifTag *tag_p;
+
+ DirEntry = DirStart+2+12*de;
+
+ Tag = Get16u(DirEntry, ImageInfo->MotorolaOrder);
+ Format = Get16u(DirEntry+2, ImageInfo->MotorolaOrder);
+ Components = Get32u(DirEntry+4, ImageInfo->MotorolaOrder);
+
+ if ((Format-1) >= NUM_FORMATS) {
+ /* (-1) catches illegal zero case as unsigned underflows to positive large. */
+ exif_error("Illegal format code in EXIF dir");
+ return FALSE;
+ }
+
+ ByteCount = Components * ExifBytesPerFormat[Format];
+
+ if (ByteCount > 4) {
+ unsigned OffsetVal;
+ OffsetVal = Get32u(DirEntry+8, ImageInfo->MotorolaOrder);
+ /* If its bigger than 4 bytes, the dir entry contains an offset. */
+ if (OffsetVal+ByteCount > ExifLength) {
+ /* Bogus pointer offset and / or bytecount value */
+ /* printf("Offset %d bytes %d ExifLen %d\n",OffsetVal, ByteCount, ExifLength); */
+
+ exif_error("Illegal pointer offset value in EXIF");
+ return FALSE;
+ }
+ ValuePtr = OffsetBase+OffsetVal;
+ } else {
+ /* 4 bytes or less and value is in the dir entry itself */
+ ValuePtr = DirEntry+8;
+ }
+
+ if (LastExifRefd < ValuePtr+ByteCount) {
+ /*
+ Keep track of last byte in the exif header that was actually referenced.
+ That way, we know where the discardable thumbnail data begins.
+ */
+ LastExifRefd = ValuePtr+ByteCount;
+ }
+
+ if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET) {
+ char *SubdirStart;
+ SubdirStart = OffsetBase + Get32u(ValuePtr, ImageInfo->MotorolaOrder);
+ if (SubdirStart < OffsetBase || SubdirStart > OffsetBase+ExifLength) {
+ exif_error("Illegal subdirectory link");
+ return FALSE;
+ }
+ ProcessExifDir(ImageInfo, SubdirStart, OffsetBase, ExifLength, LastExifRefd);
+ continue;
+ }
+
+ /* Search through tag table */
+ for (tag_p = &TagTable[0]; tag_p->Desc != NULL; tag_p++) {
+ if (tag_p->Tag == Tag) {
+ if (tag_p->Func != NULL) {
+ (*tag_p->Func)(ImageInfo, ValuePtr, ByteCount, Format, tag_p, OffsetBase);
+ } else {
+ rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format,
+ ImageInfo->MotorolaOrder,
+ &rd);
+ exif_append_data(&ImageInfo->d,
+ tag_p->Desc,
+ rec_type,
+ Format,
+ &rd);
+ }
+ break;
+ }
+ }
+ if (tag_p->Desc == NULL) {
+ rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format,
+ ImageInfo->MotorolaOrder,
+ &rd);
+ sprintf(label, "0x%04x", Tag);
+ exif_append_data(&ImageInfo->d,
+ label,
+ rec_type,
+ Format,
+ &rd);
+ }
+ }
+ return TRUE;
+}
+
+/*
+ Process an EXIF marker
+ Describes all the drivel that most digital cameras include...
+*/
+static int
+process_EXIF (ImageInfoType *ImageInfo, char *CharBuf, unsigned int length, char *LastExifRefd)
+{
+ int cc;
+ exif_rec_data_t rd;
+ LastExifRefd = CharBuf;
+
+ { /* Check the EXIF header component */
+ static const uchar ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+ if (memcmp(CharBuf+2, ExifHeader,6)) {
+ exif_error("Incorrect Exif header");
+ return FALSE;
+ }
+ }
+
+ if (memcmp(CharBuf+8,"II",2) == 0) {
+ ImageInfo->MotorolaOrder = 0;
+ } else {
+ if (memcmp(CharBuf+8,"MM",2) == 0) {
+ ImageInfo->MotorolaOrder = 1;
+ } else {
+ exif_error("Invalid Exif alignment marker.");
+ return FALSE;
+ }
+ }
+
+ /* Check the next two values for correctness. */
+ if (Get16u(CharBuf+10,ImageInfo->MotorolaOrder) != 0x2a
+ || Get32u(CharBuf+12,ImageInfo->MotorolaOrder) != 0x08) {
+ exif_error("Invalid Exif start (1, NULL)");
+ return FALSE;
+ }
+
+ /* First directory starts 16 bytes in. Offsets start at 8 bytes in. */
+ cc = ProcessExifDir(ImageInfo, CharBuf+16, CharBuf+8, length-6, LastExifRefd);
+ if (cc != TRUE) {
+ return cc;
+ }
+ return TRUE;
+}
+
+/* Parse the marker stream until SOS or EOI is seen; */
+static int
+scan_JPEG_header (ImageInfoType *ImageInfo, FILE *infile, Section_t *Sections, int *SectionsRead, int ReadAll, char *LastExifRefd)
+{
+ int a;
+ int HaveCom = FALSE;
+
+ a = fgetc(infile);
+ if (a != 0xff || fgetc(infile) != M_SOI) {
+ return FALSE;
+ }
+
+ for(*SectionsRead=0;*SectionsRead < 19;) {
+ int itemlen;
+ int marker = 0;
+ int ll,lh, got;
+ uchar *Data;
+
+ for (a=0;a<7;a++) {
+ marker = fgetc(infile);
+ if (marker != 0xff) break;
+ }
+ if (marker == 0xff) {
+ /* 0xff is legal padding, but if we get that many, something's wrong. */
+ exif_error("too many padding bytes!");
+ return FALSE;
+ }
+
+ Sections[*SectionsRead].Type = marker;
+
+ /* Read the length of the section. */
+ lh = fgetc(infile);
+ ll = fgetc(infile);
+
+ itemlen = (lh << 8) | ll;
+
+ if (itemlen < 2) {
+ exif_error("invalid marker");
+ return FALSE;
+ }
+
+ Sections[*SectionsRead].Size = itemlen;
+
+ Data = (uchar *)(*exif_malloc_fn)(itemlen+1); /* Add 1 to allow sticking a 0 at the end. */
+ Sections[*SectionsRead].Data = Data;
+
+ /* Store first two pre-read bytes. */
+ Data[0] = (uchar)lh;
+ Data[1] = (uchar)ll;
+
+ got = fread(Data+2, 1, itemlen-2, infile); /* Read the whole section. */
+ if (got != itemlen-2) {
+ exif_error("reading from file");
+ return FALSE;
+ }
+ *SectionsRead += 1;
+
+ switch(marker) {
+ case M_SOS: /* stop before hitting compressed data */
+ /* If reading entire image is requested, read the rest of the data. */
+ if (ReadAll) {
+ int cp, ep, size;
+ /* Determine how much file is left. */
+ cp = ftell(infile);
+ fseek(infile, 0, SEEK_END);
+ ep = ftell(infile);
+ fseek(infile, cp, SEEK_SET);
+
+ size = ep-cp;
+ Data = (uchar *)(*exif_malloc_fn)(size);
+ if (Data == NULL) {
+ exif_error("could not allocate data for entire image");
+ return FALSE;
+ }
+
+ got = fread(Data, 1, size, infile);
+ if (got != size) {
+ exif_error("could not read the rest of the image");
+ return FALSE;
+ }
+
+ Sections[*SectionsRead].Data = Data;
+ Sections[*SectionsRead].Size = size;
+ Sections[*SectionsRead].Type = PSEUDO_IMAGE_MARKER;
+ (*SectionsRead)++;
+ /*
+ *HaveAll = 1;
+ */
+ }
+ return TRUE;
+
+ case M_EOI: /* in case it's a tables-only JPEG stream */
+ exif_error("No image in jpeg!");
+ return FALSE;
+
+ case M_COM: /* Comment section */
+ if (HaveCom) {
+ (*SectionsRead) -= 1;
+ (*exif_free_fn)(Sections[*SectionsRead].Data);
+ } else {
+ process_COM(ImageInfo, Data, itemlen);
+ HaveCom = TRUE;
+ }
+ break;
+
+ case M_EXIF:
+ if (*SectionsRead <= 2) {
+ /* Seen files from some 'U-lead' software with Vivitar scanner
+ that uses marker 31 later in the file (no clue what for!) */
+ process_EXIF(ImageInfo, (char *)Data, itemlen, LastExifRefd);
+ }
+ break;
+
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ process_SOFn(ImageInfo, Data, marker);
+ break;
+ default:
+ /* skip any other marker silently. */
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ Discard read data.
+*/
+static void
+DiscardData(Section_t *Sections, int *SectionsRead)
+{
+ int a;
+ for (a=0;a<*SectionsRead-1;a++) {
+ (*exif_free_fn)(Sections[a].Data);
+ }
+ *SectionsRead = 0;
+}
+
+/*
+ Read image data.
+*/
+static int
+ReadJpegFile(ImageInfoType *ImageInfo, Section_t *Sections,
+ int *SectionsRead, int fd,
+ int ReadAll, char *LastExifRefd)
+{
+ FILE *infile;
+ int ret;
+ char *tmp;
+ char **p_argv;
+ int p_argc;
+
+ infile = fdopen(fd, "rb"); /* Unix ignores 'b', windows needs it. */
+
+ if (infile == NULL) {
+ exif_error("Unable to open '%s'", ImageInfo->filename);
+ return FALSE;
+ }
+
+ /* Start with an empty image information structure. */
+ memset(ImageInfo, 0, sizeof(*ImageInfo));
+ memset(Sections, 0, sizeof(*Sections));
+
+ ImageInfo->d = exif_alloc();
+
+ /* Scan the JPEG headers. */
+ ret = scan_JPEG_header(ImageInfo, infile, Sections, SectionsRead, ReadAll, LastExifRefd);
+ if (!ret) {
+ exif_error("Invalid Jpeg file: '%s'",ImageInfo->filename);
+ return FALSE;
+ }
+
+ fclose(infile);
+
+ return ret;
+}
+
+static int
+read_jpeg_exif(ImageInfoType *ImageInfo, int fd, int ReadAll)
+{
+ Section_t Sections[20];
+ int SectionsRead;
+ char *LastExifRefd=NULL;
+ int ret;
+ int thumbsize=0;
+
+ ret = ReadJpegFile(ImageInfo, Sections, &SectionsRead, fd, ReadAll, LastExifRefd);
+#if 0
+ /*
+ * Thought this might pick out the embedded thumbnail, but it doesn't work. -RL
+ */
+ for (i=0;i<SectionsRead-1;i++) {
+ if (Sections[i].Type == M_EXIF) {
+ thumbsize = Sections[i].Size;
+ if(thumbsize>0) {
+ ImageInfo->Thumbnail = (*exif_malloc_fn)(thumbsize+5);
+ ImageInfo->ThumbnailSize = thumbsize;
+ ImageInfo->Thumbnail[0] = 0xff;
+ ImageInfo->Thumbnail[1] = 0xd8;
+ ImageInfo->Thumbnail[2] = 0xff;
+ memcpy(ImageInfo->Thumbnail+4, Sections[i].Data, thumbsize+4);
+ }
+ }
+ }
+#endif
+ if (ret != FALSE) {
+ DiscardData(Sections, &SectionsRead);
+ }
+ return(ret);
+}
+
+exif_data_t *
+exif_parse_fd(int fd)
+{
+ ImageInfoType ImageInfo;
+
+ ImageInfo.filename = "<file stream>";
+ if (read_jpeg_exif(&ImageInfo, fd, 1) != TRUE) {
+ return NULL;
+ }
+ return ImageInfo.d;
+}
+
+exif_data_t *
+exif_parse_file(const char *filename)
+{
+ ImageInfoType ImageInfo;
+ int fd;
+
+ ImageInfo.filename = filename;
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ return NULL;
+ }
+
+ if (read_jpeg_exif(&ImageInfo, fd, 1) != TRUE) {
+ return NULL;
+ }
+ return ImageInfo.d;
+}
+
+void
+exif_free_data(struct exif_data *d)
+{
+ int i;
+ for (i=0; i<d->n_recs; i++) {
+ (*exif_free_fn)(d->recs[i].rec_name);
+ if (d->recs[i].rec_type == 's') {
+ (*exif_free_fn)(d->recs[i].rec_data.s);
+ }
+ }
+ (*exif_free_fn)(d);
+}
+
+void
+exif_init(void *(*malloc_fn)(int),
+ void (*free_fn)(void *),
+ void *(*realloc_fn)(void *, int))
+{
+ if (malloc_fn == NULL) {
+ malloc_fn = (void *(*)(int))malloc;
+ }
+ exif_malloc_fn = malloc_fn;
+ if (free_fn == NULL) {
+ free_fn = (void (*)(void *))free;
+ }
+ exif_free_fn = free_fn;
+ if (realloc_fn == NULL) {
+ realloc_fn = (void *(*)(void *, int))realloc;
+ }
+ exif_realloc_fn = realloc_fn;
+}
+
+extern exif_record_t *
+exif_find_record(exif_data_t *d, const char *rec_name)
+{
+ int i;
+ for (i=0; i<d->n_recs; i++) {
+ if (strcmp(d->recs[i].rec_name, rec_name) == 0) {
+ return &d->recs[i];
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+
+
diff --git a/src/libexif/exif.h b/src/libexif/exif.h
new file mode 100644
index 0000000..32f0a6d
--- /dev/null
+++ b/src/libexif/exif.h
@@ -0,0 +1,86 @@
+/*
+
+Copyright © 2000 Curtis Galloway
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+typedef struct exif_rational {
+ int num;
+ unsigned denom;
+} exif_rational_t;
+
+typedef union {
+ long l;
+ float f;
+ double g;
+ char * s;
+ exif_rational_t r;
+} exif_rec_data_t;
+
+typedef struct exif_record {
+ char * rec_name;
+ char rec_type;
+ int exif_format;
+ exif_rec_data_t rec_data;
+} exif_record_t;
+
+typedef struct exif_data {
+ int n_recs;
+ int n_alloc;
+ exif_record_t recs[0];
+} exif_data_t;
+
+
+/* EXIF data formats */
+
+#define EXIF_FMT_COMPUTED -1 /* Not in raw data */
+#define EXIF_FMT_BYTE 1
+#define EXIF_FMT_STRING 2
+#define EXIF_FMT_USHORT 3
+#define EXIF_FMT_ULONG 4
+#define EXIF_FMT_URATIONAL 5
+#define EXIF_FMT_SBYTE 6
+#define EXIF_FMT_UNDEFINED 7
+#define EXIF_FMT_SSHORT 8
+#define EXIF_FMT_SLONG 9
+#define EXIF_FMT_SRATIONAL 10
+#define EXIF_FMT_SINGLE 11
+#define EXIF_FMT_DOUBLE 12
+
+extern void
+exif_init(void *(*malloc_fn)(int),
+ void (*free_fn)(void *),
+ void *(*realloc_fn)(void *, int));
+
+extern exif_data_t *
+exif_parse_fd(int fd);
+
+extern exif_data_t *
+exif_parse_file(const char *filename);
+
+extern void
+exif_free_data(exif_data_t *d);
+
+extern exif_record_t *
+exif_find_record(exif_data_t *d, const char *rec_name);
+
+
diff --git a/src/libexif/i18n.h b/src/libexif/i18n.h
new file mode 100644
index 0000000..6d08e3c
--- /dev/null
+++ b/src/libexif/i18n.h
@@ -0,0 +1,51 @@
+/* i18n.h
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __I18N_H__
+#define __I18N_H__
+
+#include "config.h"
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# undef _
+# define _(String) dgettext (GETTEXT_PACKAGE, String)
+# ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+# else
+# define N_(String) (String)
+# endif
+#else
+# define textdomain(String) (String)
+# define gettext(String) (String)
+# define dgettext(Domain,Message) (Message)
+# define dcgettext(Domain,Message,Type) (Message)
+#ifdef __WATCOMC__
+# define bind_textdomain_codeset(Domain,Codeset)
+# define bindtextdomain(Domain,Directory)
+#else
+# define bind_textdomain_codeset(Domain,Codeset) (Codeset)
+# define bindtextdomain(Domain,Directory) (Domain)
+#endif
+# define _(String) (String)
+# define N_(String) (String)
+#endif
+
+#endif /* __I18N_H__ */
diff --git a/src/libexif/olympus/exif-mnote-data-olympus.c b/src/libexif/olympus/exif-mnote-data-olympus.c
new file mode 100644
index 0000000..02794c5
--- /dev/null
+++ b/src/libexif/olympus/exif-mnote-data-olympus.c
@@ -0,0 +1,403 @@
+/* exif-mnote-data-olympus.c
+ *
+ * Copyright © 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "exif-mnote-data-olympus.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <libexif/exif-utils.h>
+#include <libexif/exif-data.h>
+
+#define DEBUG
+
+static void
+exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n)
+{
+ ExifMnoteData *d = (ExifMnoteData *) n;
+ unsigned int i;
+
+ if (!n) return;
+
+ if (n->entries) {
+ for (i = 0; i < n->count; i++)
+ if (n->entries[i].data) {
+ exif_mem_free (d->mem, n->entries[i].data);
+ n->entries[i].data = NULL;
+ }
+ exif_mem_free (d->mem, n->entries);
+ n->entries = NULL;
+ n->count = 0;
+ }
+}
+
+static void
+exif_mnote_data_olympus_free (ExifMnoteData *n)
+{
+ if (!n) return;
+
+ exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n);
+}
+
+static char *
+exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
+{
+ ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
+
+ if (!d || !val) return NULL;
+ if (i > n->count -1) return NULL;
+ exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
+ "Querying value for tag '%s'...",
+ mnote_olympus_tag_get_name (n->entries[i].tag));
+ return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
+}
+
+static void
+exif_mnote_data_olympus_save (ExifMnoteData *ne,
+ unsigned char **buf, unsigned int *buf_size)
+{
+ ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
+ unsigned int i, o, s, doff, base = 0, o2 = 6;
+ int datao = 0;
+
+ if (!n || !buf || !buf_size) return;
+
+ /*
+ * Allocate enough memory for all entries and the number of entries.
+ */
+ *buf_size = 6 + 2 + 2 + n->count * 12;
+ switch (n->version) {
+ case 0: /* Olympus */
+ *buf = exif_mem_alloc (ne->mem, *buf_size);
+ if (!*buf) return;
+
+ /* Write the header and the number of entries. */
+ strcpy (*buf, "OLYMP");
+ o2 += 2;
+ datao = n->offset;
+ break;
+ case 1: /* Nikon v1 */
+ base = MNOTE_NIKON1_TAG_BASE;
+ *buf_size -= 8;
+ /* Fall through */
+ case 2: /* Nikon v2 */
+ *buf_size += 8;
+ *buf = exif_mem_alloc (ne->mem, *buf_size);
+ if (!*buf) return;
+
+ /* Write the header and the number of entries. */
+ strcpy (*buf, "Nikon");
+ (*buf)[6] = n->version;
+ o2 += 2; *buf_size += 2;
+ if (n->version == 2) {
+ exif_set_short (*buf + 10, n->order, (ExifShort) (
+ (n->order == EXIF_BYTE_ORDER_INTEL) ?
+ ('I' << 8) | 'I' :
+ ('M' << 8) | 'M'));
+ exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
+ exif_set_long (*buf + 14, n->order, (ExifShort) 8);
+ o2 += 2 + 8;
+ }
+ datao = -10;
+ break;
+ }
+
+ exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
+ o2 += 2;
+
+ /* Save each entry */
+ for (i = 0; i < n->count; i++) {
+ o = o2 + i * 12;
+ exif_set_short (*buf + o + 0, n->order,
+ (ExifShort) (n->entries[i].tag - base));
+ exif_set_short (*buf + o + 2, n->order,
+ (ExifShort) n->entries[i].format);
+ exif_set_long (*buf + o + 4, n->order,
+ n->entries[i].components);
+ o += 8;
+ s = exif_format_get_size (n->entries[i].format) *
+ n->entries[i].components;
+ if (s > 4) {
+ doff = *buf_size;
+ *buf_size += s;
+ *buf = exif_mem_realloc (ne->mem, *buf,
+ sizeof (char) * *buf_size);
+ if (!*buf) return;
+ exif_set_long (*buf + o, n->order, datao + doff);
+ } else
+ doff = o;
+
+ /* Write the data. */
+ if (n->entries[i].data) {
+ memcpy (*buf + doff, n->entries[i].data, s);
+ } else {
+ /* Most certainly damaged input file */
+ memset (*buf + doff, 0, s);
+ }
+ }
+}
+
+static void
+exif_mnote_data_olympus_load (ExifMnoteData *en,
+ const unsigned char *buf, unsigned int buf_size)
+{
+ ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
+ ExifShort c;
+ unsigned int i, s, o, o2 = 0, datao = 6, base = 0;
+
+ if (!n || !buf) return;
+
+ /* Start of interesting data */
+ o2 = 6 + n->offset;
+
+ /*
+ * Olympus headers start with "OLYMP" and need to have at least
+ * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
+ * number of entries, and 12 for one entry.
+ *
+ * Nikon headers start with "Nikon" (6 bytes including '\0'),
+ * version number (1 or 2).
+ *
+ * Version 1 continues with 0, 1, 0, number_of_tags,
+ * or just with number_of_tags (models D1H, D1X...).
+ *
+ * Version 2 continues with an unknown byte (0 or 10),
+ * two unknown bytes (0), "MM" or "II", another byte 0 and
+ * lastly 0x2A.
+ */
+ if (buf_size - n->offset < 22) return;
+ if (!memcmp (buf + o2, "OLYMP", 5)) {
+ exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
+ "Parsing Olympus maker note...");
+
+ /* The number of entries is at position 8. */
+ n->version = 0;
+ o2 += 8;
+
+ } else if (!memcmp (buf + o2, "Nikon", 6)) {
+ o2 += 6;
+ exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
+ "Parsing Nikon maker note (0x%02x, %02x, %02x, "
+ "%02x, %02x, %02x, %02x, %02x)...",
+ buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
+ buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
+
+ /* The first byte is the version. */
+ if (o2 >= buf_size) return;
+ n->version = buf[o2];
+ o2 += 1;
+
+ /* Skip an unknown byte (00 or 0A). */
+ o2 += 1;
+
+ switch (n->version) {
+ case 1:
+
+ base = MNOTE_NIKON1_TAG_BASE;
+ break;
+
+ case 2:
+
+ /* Skip 2 unknown bytes (00 00). */
+ o2 += 2;
+
+ /*
+ * Byte order. From here the data offset
+ * gets calculated.
+ */
+ datao = o2;
+ if (o2 >= buf_size) return;
+ if (!strncmp (&buf[o2], "II", 2))
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ else if (!strncmp (&buf[o2], "MM", 2))
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
+ else {
+ exif_log (en->log, EXIF_LOG_CODE_DEBUG,
+ "ExifMnoteDatalympus", "Unknown "
+ "byte order '%c%c'", buf[o2],
+ buf[o2 + 1]);
+ return;
+ }
+ o2 += 2;
+
+ /* Skip 2 unknown bytes (00 2A). */
+ o2 += 2;
+
+ /* Go to where the number of entries is. */
+ if (o2 >= buf_size) return;
+ o2 = datao + exif_get_long (buf + o2, n->order);
+ break;
+
+ default:
+ exif_log (en->log, EXIF_LOG_CODE_DEBUG,
+ "ExifMnoteDataOlympus", "Unknown version "
+ "number %i.", n->version);
+ return;
+ }
+ } else if (!memcmp (buf + o2, "\0\x1b", 2)) {
+ n->version = 2;
+ } else {
+ return;
+ }
+
+ /* Number of entries */
+ if (o2 >= buf_size) return;
+ c = exif_get_short (buf + o2, n->order);
+ o2 += 2;
+
+ /* Read the number of entries and remove old ones. */
+ exif_mnote_data_olympus_clear (n);
+
+ n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
+ if (!n->entries) return;
+
+ /* Parse the entries */
+ for (i = 0; i < c; i++) {
+ o = o2 + 12 * i;
+ if (o + 12 > buf_size) return;
+
+ n->count = i + 1;
+ n->entries[i].tag = exif_get_short (buf + o, n->order) + base;
+ n->entries[i].format = exif_get_short (buf + o + 2, n->order);
+ n->entries[i].components = exif_get_long (buf + o + 4, n->order);
+ n->entries[i].order = n->order;
+
+ exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
+ "Loading entry 0x%x ('%s')...", n->entries[i].tag,
+ mnote_olympus_tag_get_name (n->entries[i].tag));
+
+ /*
+ * Size? If bigger than 4 bytes, the actual data is not
+ * in the entry but somewhere else (offset).
+ */
+ s = exif_format_get_size (n->entries[i].format) *
+ n->entries[i].components;
+ if (!s) continue;
+ o += 8;
+ if (s > 4) o = exif_get_long (buf + o, n->order) + datao;
+ if (o + s > buf_size) continue;
+
+ /* Sanity check */
+ n->entries[i].data = exif_mem_alloc (en->mem, s);
+ if (!n->entries[i].data) continue;
+ n->entries[i].size = s;
+ memcpy (n->entries[i].data, buf + o, s);
+ }
+}
+
+static unsigned int
+exif_mnote_data_olympus_count (ExifMnoteData *n)
+{
+ return n ? ((ExifMnoteDataOlympus *) n)->count : 0;
+}
+
+static unsigned int
+exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n)
+{
+ ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d;
+
+ if (!note) return 0;
+ if (note->count <= n) return 0;
+ return note->entries[n].tag;
+}
+
+static const char *
+exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i)
+{
+ ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
+
+ if (!n) return NULL;
+ if (i >= n->count) return NULL;
+ return mnote_olympus_tag_get_name (n->entries[i].tag);
+}
+
+static const char *
+exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i)
+{
+ ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
+
+ if (!n) return NULL;
+ if (i >= n->count) return NULL;
+ return mnote_olympus_tag_get_title (n->entries[i].tag);
+}
+
+static const char *
+exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
+{
+ ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
+
+ if (!n) return NULL;
+ if (i >= n->count) return NULL;
+ return mnote_olympus_tag_get_title (n->entries[i].tag);
+}
+
+static void
+exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
+{
+ ExifByteOrder o_orig;
+ ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
+ unsigned int i;
+
+ if (!n) return;
+
+ o_orig = n->order;
+ n->order = o;
+ for (i = 0; i < n->count; i++) {
+ n->entries[i].order = o;
+ exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
+ n->entries[i].components, o_orig, o);
+ }
+}
+
+static void
+exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
+{
+ if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
+}
+
+ExifMnoteData *
+exif_mnote_data_olympus_new (ExifMem *mem)
+{
+ ExifMnoteData *d;
+
+ if (!mem) return NULL;
+
+ d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus));
+ if (!d) return NULL;
+
+ exif_mnote_data_construct (d, mem);
+
+ /* Set up function pointers */
+ d->methods.free = exif_mnote_data_olympus_free;
+ d->methods.set_byte_order = exif_mnote_data_olympus_set_byte_order;
+ d->methods.set_offset = exif_mnote_data_olympus_set_offset;
+ d->methods.load = exif_mnote_data_olympus_load;
+ d->methods.save = exif_mnote_data_olympus_save;
+ d->methods.count = exif_mnote_data_olympus_count;
+ d->methods.get_id = exif_mnote_data_olympus_get_id;
+ d->methods.get_name = exif_mnote_data_olympus_get_name;
+ d->methods.get_title = exif_mnote_data_olympus_get_title;
+ d->methods.get_description = exif_mnote_data_olympus_get_description;
+ d->methods.get_value = exif_mnote_data_olympus_get_value;
+
+ return d;
+}
diff --git a/src/libexif/olympus/exif-mnote-data-olympus.h b/src/libexif/olympus/exif-mnote-data-olympus.h
new file mode 100644
index 0000000..b9b4209
--- /dev/null
+++ b/src/libexif/olympus/exif-mnote-data-olympus.h
@@ -0,0 +1,45 @@
+/* mnote-olympus-data.h
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MNOTE_OLYMPUS_CONTENT_H__
+#define __MNOTE_OLYMPUS_CONTENT_H__
+
+#include <libexif/exif-mnote-data-priv.h>
+#include <libexif/olympus/mnote-olympus-entry.h>
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-mem.h>
+
+typedef struct _ExifMnoteDataOlympus ExifMnoteDataOlympus;
+
+struct _ExifMnoteDataOlympus {
+ ExifMnoteData parent;
+
+ MnoteOlympusEntry *entries;
+ unsigned int count;
+
+ ExifByteOrder order;
+ unsigned int offset;
+ /* 0: Olympus; 1: Nikon v1; 2: Nikon v2 */
+ int version;
+};
+
+ExifMnoteData *exif_mnote_data_olympus_new (ExifMem *);
+
+#endif /* __MNOTE_OLYMPUS_CONTENT_H__ */
diff --git a/src/libexif/olympus/mnote-olympus-entry.c b/src/libexif/olympus/mnote-olympus-entry.c
new file mode 100644
index 0000000..1eff6fe
--- /dev/null
+++ b/src/libexif/olympus/mnote-olympus-entry.c
@@ -0,0 +1,540 @@
+/* mnote-olympus-entry.c
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "mnote-olympus-entry.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libexif/exif-format.h>
+#include <libexif/exif-utils.h>
+#include <libexif/exif-entry.h>
+#include <libexif/i18n.h>
+
+#define CF(format,target,v,maxlen) \
+{ \
+ if (format != target) { \
+ snprintf (v, maxlen, \
+ _("Invalid format '%s', " \
+ "expected '%s'."), \
+ exif_format_get_name (format), \
+ exif_format_get_name (target)); \
+ break; \
+ } \
+}
+
+#define CC(number,target,v,maxlen) \
+{ \
+ if (number != target) { \
+ snprintf (v, maxlen, \
+ _("Invalid number of components (%i, " \
+ "expected %i)."), (int) number, (int) target); \
+ break; \
+ } \
+}
+
+#define CC2(number,t1,t2,v,maxlen) \
+{ \
+ if ((number != t1) && (number != t2)) { \
+ snprintf (v, maxlen, \
+ _("Invalid number of components (%i, " \
+ "expected %i or %i)."), (int) number, \
+ (int) t1, (int) t2); \
+ break; \
+ } \
+}
+
+static struct {
+ ExifTag tag;
+ ExifFormat fmt;
+ struct {
+ int index;
+ const char *string;
+ } elem[10];
+} items[] = {
+ { MNOTE_NIKON_TAG_LENSTYPE, EXIF_FORMAT_BYTE,
+ { {0, N_("AF non D Lens")},
+ {1, N_("Manual")},
+ {2, N_("AF-D or AF-S Lens")},
+ {6, N_("AF-D G Lens")},
+ {10, N_("AF-D VR Lens")},
+ {0, NULL}}},
+ { MNOTE_NIKON_TAG_FLASHUSED, EXIF_FORMAT_BYTE,
+ { {0, N_("Flash did not fire")},
+ {4, N_("Flash unit unknown")},
+ {7, N_("Flash is external")},
+ {9, N_("Flash is on Camera")},
+ {0, NULL}}},
+ { MNOTE_NIKON1_TAG_QUALITY, EXIF_FORMAT_SHORT,
+ { {1, N_("VGA Basic")},
+ {2, N_("VGA Normal")},
+ {3, N_("VGA Fine")},
+ {4, N_("SXGA Basic")},
+ {5, N_("SXGA Normal")},
+ {6, N_("SXGA Fine")},
+ {10, N_("2 MPixel Basic")},
+ {11, N_("2 MPixel Normal")},
+ {12, N_("2 MPixel Fine")},
+ {0, NULL}}},
+ { MNOTE_NIKON1_TAG_COLORMODE, EXIF_FORMAT_SHORT,
+ { {1, N_("Color")},
+ {2, N_("Monochrome")},
+ {0, NULL}}},
+ { MNOTE_NIKON1_TAG_IMAGEADJUSTMENT, EXIF_FORMAT_SHORT,
+ { {0, N_("Normal")},
+ {1, N_("Bright+")},
+ {2, N_("Bright-")},
+ {3, N_("Contrast+")},
+ {4, N_("Contrast-")},
+ {0, NULL}}},
+ { MNOTE_NIKON1_TAG_CCDSENSITIVITY, EXIF_FORMAT_SHORT,
+ { {0, N_("ISO80")},
+ {2, N_("ISO160")},
+ {4, N_("ISO320")},
+ {5, N_("ISO100")},
+ {0, NULL}}},
+ { MNOTE_NIKON1_TAG_WHITEBALANCE, EXIF_FORMAT_SHORT,
+ { {0, N_("Auto")},
+ {1, N_("Preset")},
+ {2, N_("Daylight")},
+ {3, N_("Incandescense")},
+ {4, N_("Fluorescence")},
+ {5, N_("Cloudy")},
+ {6, N_("SpeedLight")},
+ {0, NULL}}},
+ { MNOTE_NIKON1_TAG_CONVERTER, EXIF_FORMAT_SHORT,
+ { {0, N_("No Fisheye")},
+ {1, N_("Fisheye On")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_QUALITY, EXIF_FORMAT_SHORT,
+ { {1, N_("SQ")},
+ {2, N_("HQ")},
+ {3, N_("SHQ")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_MACRO, EXIF_FORMAT_SHORT,
+ { {0, N_("No")},
+ {1, N_("Yes")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_DIGIZOOM, EXIF_FORMAT_SHORT,
+ { {0, N_("1x")},
+ {2, N_("2x")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_FLASHMODE, EXIF_FORMAT_SHORT,
+ { {0, N_("Auto")},
+ {1, N_("Red-eye reduction")},
+ {2, N_("Fill")},
+ {3, N_("Off")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_SHARPNESS, EXIF_FORMAT_SHORT,
+ { {0, N_("Normal")},
+ {1, N_("Hard")},
+ {2, N_("Soft")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_CONTRAST, EXIF_FORMAT_SHORT,
+ { {0, N_("Hard")},
+ {1, N_("Normal")},
+ {2, N_("Soft")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_MANFOCUS, EXIF_FORMAT_SHORT,
+ { {0, N_("No")},
+ {1, N_("Yes")},
+ {0, NULL}}},
+ { 0, }
+};
+
+char *
+mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int maxlen)
+{
+ char buf[30];
+ ExifLong vl;
+ ExifShort vs = 0;
+ ExifRational vr;
+ int i, j;
+ double r, b;
+
+ if (!entry)
+ return (NULL);
+
+ memset (v, 0, maxlen);
+ maxlen--;
+
+ if ((!entry->data) && (entry->components > 0)) return (v);
+
+ switch (entry->tag) {
+
+ /* Nikon */
+ case MNOTE_NIKON_TAG_FIRMWARE:
+ CF (entry->format, EXIF_FORMAT_UNDEFINED, v, maxlen);
+ CC (entry->components, 4, v, maxlen);
+ vl = exif_get_long (entry->data, entry->order);
+ if ((vl & 0xF0F0F0F0) == 0x30303030) {
+ memcpy (v, entry->data, MIN (maxlen, 4));
+ } else {
+ snprintf (v, maxlen, "%04lx", (long unsigned int) vl);
+ }
+ break;
+ case MNOTE_NIKON_TAG_ISO:
+ CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen);
+ CC (entry->components, 2, v, maxlen);
+ //vs = exif_get_short (entry->data, entry->order);
+ vs = exif_get_short (entry->data + 2, entry->order);
+ snprintf (v, maxlen, "ISO %hd", vs);
+ break;
+ case MNOTE_NIKON_TAG_ISO2:
+ CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen);
+ CC (entry->components, 2, v, maxlen);
+ //vs = exif_get_short (entry->data, entry->order);
+ vs = exif_get_short (entry->data + 2, entry->order);
+ snprintf (v, maxlen, "ISO2 %hd", vs);
+ break;
+ case MNOTE_NIKON_TAG_QUALITY:
+ CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen);
+ //CC (entry->components, 8, v, maxlen);
+ //vl = exif_get_long (entry->data , entry->order);
+ //printf("-> 0x%04x\n",entry->data);
+ //printf("-> 0x%s<\n",entry->data - 0);
+ memcpy(v, entry->data ,entry->components);
+ //snprintf (v, maxlen, "%s<", ( entry->data - 9 );
+ break;
+ case MNOTE_NIKON_TAG_COLORMODE:
+ case MNOTE_NIKON_TAG_COLORMODE1:
+ case MNOTE_NIKON_TAG_WHITEBALANCE:
+ case MNOTE_NIKON_TAG_SHARPENING:
+ case MNOTE_NIKON_TAG_FOCUSMODE:
+ case MNOTE_NIKON_TAG_FLASHSETTING:
+ case MNOTE_NIKON_TAG_ISOSELECTION:
+ case MNOTE_NIKON_TAG_FLASHMODE:
+ case MNOTE_NIKON_TAG_IMAGEADJUSTMENT:
+ case MNOTE_NIKON_TAG_ADAPTER:
+ CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen);
+ memcpy(v, entry->data, MIN (maxlen, entry->components));
+ break;
+ case MNOTE_NIKON_TAG_TOTALPICTURES:
+ CF (entry->format, EXIF_FORMAT_LONG, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ vl = exif_get_long (entry->data, entry->order);
+ snprintf (v, maxlen, "%lu", (long unsigned int) vl );
+ break;
+ case MNOTE_NIKON_TAG_WHITEBALANCEFINE:
+ CF (entry->format, EXIF_FORMAT_SSHORT, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ vs = exif_get_short (entry->data, entry->order);
+ snprintf (v, maxlen, "%hd", vs);
+ break;
+ case MNOTE_NIKON_TAG_WHITEBALANCERB:
+ CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);
+ CC (entry->components, 4, v, maxlen);
+ vr = exif_get_rational (entry->data, entry->order);
+ r = (double)vr.numerator / vr.denominator;
+ vr = exif_get_rational (entry->data+8, entry->order);
+ b = (double)vr.numerator / vr.denominator;
+ //printf("numerator %li, denominator %li\n", vr.numerator, vr.denominator);
+ snprintf (v, maxlen, "Red Correction %f, Blue Correction %f", r,b);
+ break;
+ case MNOTE_NIKON_TAG_MANUALFOCUSDISTANCE:
+ CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ vr = exif_get_rational (entry->data, entry->order);
+ if (vr.numerator) {
+ r = (double)vr.numerator / vr.denominator;
+ snprintf (v, maxlen, "%2.2f meters", r);
+ } else {
+ strncpy (v, _("No manual focus selection"), maxlen);
+ }
+ break;
+ case MNOTE_NIKON_TAG_DIGITALZOOM:
+ case MNOTE_NIKON1_TAG_DIGITALZOOM:
+ CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ vr = exif_get_rational (entry->data, entry->order);
+ r = (double)vr.numerator / vr.denominator;
+ snprintf (v, maxlen, "%2.2f", r);
+ break;
+ case MNOTE_NIKON_TAG_AFFOCUSPOSITION:
+ CF (entry->format, EXIF_FORMAT_UNDEFINED, v, maxlen);
+ CC (entry->components, 4, v, maxlen);
+ switch ( *( entry->data+1) ) {
+ case 0: strncpy (v, "AF Position: Center", maxlen); break;
+ case 1: strncpy (v, "AF Position: Top", maxlen); break;
+ case 2: strncpy (v, "AF Position: Bottom", maxlen); break;
+ case 3: strncpy (v, "AF Position: Left", maxlen); break;
+ case 4: strncpy (v, "AF Position: Right", maxlen); break;
+ default: strncpy (v, "Unknown AF Position", maxlen);
+ }
+ break;
+ case MNOTE_OLYMPUS_TAG_DIGIZOOM:
+ if (entry->format == EXIF_FORMAT_RATIONAL) {
+ CC (entry->components, 1, v, maxlen);
+ vr = exif_get_rational (entry->data, entry->order);
+ r = (double)vr.numerator / vr.denominator;
+ if (!vr.numerator) {
+ strncpy (v, _("None"), maxlen);
+ } else {
+ snprintf (v, maxlen, "%2.2f", r);
+ }
+ break;
+ }
+ /* fall through to handle SHORT version of this tag */
+ case MNOTE_NIKON_TAG_LENSTYPE:
+ case MNOTE_NIKON_TAG_FLASHUSED:
+ case MNOTE_NIKON1_TAG_QUALITY:
+ case MNOTE_NIKON1_TAG_COLORMODE:
+ case MNOTE_NIKON1_TAG_IMAGEADJUSTMENT:
+ case MNOTE_NIKON1_TAG_CCDSENSITIVITY:
+ case MNOTE_NIKON1_TAG_WHITEBALANCE:
+ case MNOTE_NIKON1_TAG_CONVERTER:
+ case MNOTE_OLYMPUS_TAG_QUALITY:
+ case MNOTE_OLYMPUS_TAG_MACRO:
+ case MNOTE_OLYMPUS_TAG_FLASHMODE:
+ case MNOTE_OLYMPUS_TAG_SHARPNESS:
+ case MNOTE_OLYMPUS_TAG_CONTRAST:
+ case MNOTE_OLYMPUS_TAG_MANFOCUS:
+ /* search the tag */
+ for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++);
+ if (!items[i].tag) {
+ strncpy (v, "Internal error", maxlen);
+ break;
+ }
+ CF (entry->format, items[i].fmt, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ switch (entry->format) {
+ case EXIF_FORMAT_BYTE:
+ case EXIF_FORMAT_UNDEFINED:
+ vs = entry->data[0];
+ break;
+ case EXIF_FORMAT_SHORT:
+ vs = exif_get_short(entry->data, entry->order);
+ break;
+ default:
+ vs = 0;
+ break;
+ }
+ /* find the value */
+ for (j = 0; items[i].elem[j].string &&
+ (items[i].elem[j].index < vs); j++);
+ if (items[i].elem[j].index != vs) {
+ snprintf (v, maxlen, "Unknown value %hi", vs);
+ break;
+ }
+ strncpy (v, items[i].elem[j].string, maxlen);
+ break;
+
+ case MNOTE_NIKON_TAG_LENS:
+ CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);
+ CC (entry->components, 4, v, maxlen);
+ {
+ double c,d;
+ unsigned long a,b;
+ vr = exif_get_rational (entry->data, entry->order);
+ a = vr.numerator / vr.denominator;
+ vr = exif_get_rational (entry->data+8, entry->order);
+ b = vr.numerator / vr.denominator;
+ vr = exif_get_rational (entry->data+16, entry->order);
+ c = (double)vr.numerator / vr.denominator;
+ vr = exif_get_rational (entry->data+24, entry->order);
+ d = (double)vr.numerator / vr.denominator;
+ //printf("numerator %li, denominator %li\n", vr.numerator, vr.denominator);
+ snprintf (v, maxlen, "%ld-%ldmm 1:%3.1f - %3.1f",a,b,c,d);
+ }
+ break;
+ case MNOTE_NIKON1_TAG_FOCUS:
+ CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ vr = exif_get_rational (entry->data, entry->order);
+ if (!vr.denominator) {
+ strncpy (v, _("Infinite"), maxlen);
+ } else {
+ r = (double)vr.numerator / vr.denominator;
+ snprintf (v, maxlen, "%2.2f", r);
+ }
+ break;
+
+ /* Olympus */
+ case MNOTE_OLYMPUS_TAG_MODE:
+ CF (entry->format, EXIF_FORMAT_LONG, v, maxlen);
+ CC (entry->components, 3, v, maxlen);
+ vl = exif_get_long (entry->data, entry->order);
+ switch (vl) {
+ case 0:
+ strncpy (v, _("normal"), maxlen);
+ break;
+ case 1:
+ strncpy (v, _("unknown"), maxlen);
+ break;
+ case 2:
+ strncpy (v, _("fast"), maxlen);
+ break;
+ case 3:
+ strncpy (v, _("panorama"), maxlen);
+ break;
+ default:
+ snprintf (v, maxlen, _("%li"), (long int) vl);
+ }
+ vl = exif_get_long (entry->data + 4, entry->order);
+ snprintf (buf, sizeof (buf), "/%li/", (long int) vl);
+ strncat (v, buf, maxlen - strlen (v));
+ vl = exif_get_long (entry->data + 4, entry->order);
+ switch (vl) {
+ case 1:
+ strncat (v, _("left to right"), maxlen - strlen (v));
+ break;
+ case 2:
+ strncat (v, _("right to left"), maxlen - strlen (v));
+ break;
+ case 3:
+ strncat (v, _("bottom to top"), maxlen - strlen (v));
+ break;
+ case 4:
+ strncat (v, _("top to bottom"), maxlen - strlen (v));
+ break;
+ default:
+ snprintf (buf, sizeof (buf), _("%li"),
+ (long int) vl);
+ strncat (v, buf, maxlen - strlen (v));
+ }
+ break;
+ case MNOTE_OLYMPUS_TAG_UNKNOWN_1:
+ CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ strncpy (v, _("Unknown tag."), maxlen);
+ break;
+ case MNOTE_OLYMPUS_TAG_UNKNOWN_2:
+ CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ break;
+ case MNOTE_OLYMPUS_TAG_UNKNOWN_3:
+ CF (entry->format, EXIF_FORMAT_SSHORT, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ break;
+ case MNOTE_OLYMPUS_TAG_VERSION:
+ CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen);
+ CC2 (entry->components, 5, 8, v, maxlen);
+ strncpy (v, entry->data, MIN (maxlen, entry->size));
+ break;
+ case MNOTE_OLYMPUS_TAG_INFO:
+ CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen);
+ CC2 (entry->components, 52, 53, v, maxlen);
+ strncpy (v, entry->data, MIN (maxlen, entry->size));
+ break;
+ case MNOTE_OLYMPUS_TAG_ID:
+ CF (entry->format, EXIF_FORMAT_UNDEFINED, v, maxlen);
+ CC (entry->components, 32, v, maxlen);
+ strncpy (v, entry->data, MIN (maxlen, entry->size));
+ break;
+ case MNOTE_OLYMPUS_TAG_UNKNOWN_4:
+ CF (entry->format, EXIF_FORMAT_LONG, v, maxlen);
+ CC (entry->components, 30, v, maxlen);
+ break;
+ case MNOTE_OLYMPUS_TAG_FOCUSDIST:
+ CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ vr = exif_get_rational (entry->data, entry->order);
+ if (vr.numerator == 0) {
+ strncpy (v, _("Unknown"), maxlen);
+ }
+ else {
+ unsigned long tmp = vr.numerator / vr.denominator;
+ /* printf("numerator %li, denominator %li\n", vr.numerator, vr.denominator); */
+ snprintf (v, maxlen, "%li mm", tmp);
+ }
+ break;
+ case MNOTE_OLYMPUS_TAG_WBALANCE:
+ CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen);
+ CC (entry->components, 2, v, maxlen);
+ vs = exif_get_short (entry->data, entry->order);
+ switch (vs) {
+ case 1:
+ strncpy (v, _("Automatic"), maxlen);
+ break;
+ case 2:
+ {
+ ExifShort v2 = exif_get_short (entry->data + 2, entry->order);
+ unsigned long colorTemp = 0;
+ switch (v2) {
+ case 2:
+ colorTemp = 3000;
+ break;
+ case 3:
+ colorTemp = 3700;
+ break;
+ case 4:
+ colorTemp = 4000;
+ break;
+ case 5:
+ colorTemp = 4500;
+ break;
+ case 6:
+ colorTemp = 5500;
+ break;
+ case 7:
+ colorTemp = 6500;
+ break;
+ case 9:
+ colorTemp = 7500;
+ break;
+ }
+ if (colorTemp) {
+ snprintf (v, maxlen, "Manual: %liK", colorTemp);
+ }
+ else {
+ strncpy (v, _("Manual: Unknown"), maxlen);
+ }
+
+ }
+ break;
+ case 3:
+ strncpy (v, _("One-touch"), maxlen);
+ break;
+ default:
+ strncpy (v, _("Unknown"), maxlen);
+ break;
+ }
+ break;
+ default:
+ switch (entry->format) {
+ case EXIF_FORMAT_ASCII:
+ strncpy (v, entry->data,
+ MIN (maxlen, entry->components));
+ break;
+ case EXIF_FORMAT_SHORT:
+ vs = exif_get_short (entry->data, entry->order);
+ snprintf (v, maxlen, "%hi", vs);
+ break;
+ case EXIF_FORMAT_LONG:
+ vl = exif_get_long (entry->data, entry->order);
+ snprintf (v, maxlen, "%li", (long int) vl);
+ break;
+ case EXIF_FORMAT_UNDEFINED:
+ default:
+ snprintf (v, maxlen, _("%li bytes unknown data: "),
+ (long int) entry->size);
+ for (i = 0; i < (int)entry->size; i++) {
+ sprintf (buf, "%02x", entry->data[i]);
+ strncat (v, buf, maxlen - strlen (v));
+ }
+ break;
+ }
+ break;
+ }
+
+ return (v);
+}
diff --git a/src/libexif/olympus/mnote-olympus-entry.h b/src/libexif/olympus/mnote-olympus-entry.h
new file mode 100644
index 0000000..a725228
--- /dev/null
+++ b/src/libexif/olympus/mnote-olympus-entry.h
@@ -0,0 +1,43 @@
+/* mnote-olympus-entry.h
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MNOTE_OLYMPUS_ENTRY_H__
+#define __MNOTE_OLYMPUS_ENTRY_H__
+
+#include <libexif/exif-format.h>
+#include <libexif/exif-byte-order.h>
+#include <libexif/olympus/mnote-olympus-tag.h>
+
+typedef struct _MnoteOlympusEntry MnoteOlympusEntry;
+
+struct _MnoteOlympusEntry {
+ MnoteOlympusTag tag;
+ ExifFormat format;
+ unsigned long components;
+
+ unsigned char *data;
+ unsigned int size;
+
+ ExifByteOrder order;
+};
+
+char *mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *val, unsigned int maxlen);
+
+#endif /* __MNOTE_OLYMPUS_ENTRY_H__ */
diff --git a/src/libexif/olympus/mnote-olympus-tag.c b/src/libexif/olympus/mnote-olympus-tag.c
new file mode 100644
index 0000000..b7beacd
--- /dev/null
+++ b/src/libexif/olympus/mnote-olympus-tag.c
@@ -0,0 +1,155 @@
+/* mnote-olympus-tag.c:
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "mnote-olympus-tag.h"
+
+#include <libexif/i18n.h>
+#include <libexif/exif-utils.h>
+
+#include <stdlib.h>
+
+static struct {
+ MnoteOlympusTag tag;
+ const char *name;
+ const char *title;
+ const char *description;
+} table[] = {
+
+ /* Nikon v2 */
+ {MNOTE_NIKON_TAG_FIRMWARE, "Firmware", N_("Firmware Version"), NULL},
+ {MNOTE_NIKON_TAG_ISO, "ISO", N_("ISO Setting"), NULL},
+ {MNOTE_NIKON_TAG_COLORMODE1, "COLORMODE1", N_("Colormode (?)"), NULL},
+ {MNOTE_NIKON_TAG_QUALITY, "QUALITY", N_("Quality"), NULL},
+ {MNOTE_NIKON_TAG_WHITEBALANCE, "WHITEBALANCE", N_("Whitebalance"), NULL},
+ {MNOTE_NIKON_TAG_SHARPENING, "SHARPENING", N_("Image Sharpening"), NULL},
+ {MNOTE_NIKON_TAG_FOCUSMODE, "FOCUSMODE", N_("Focus Mode"), NULL},
+ {MNOTE_NIKON_TAG_FLASHSETTING, "FLASHSETTING", N_("Flash Setting"), NULL},
+ {MNOTE_NIKON_TAG_FLASHMODE, "FLASHMODE", N_("Flash Mode"), NULL},
+ {MNOTE_NIKON_TAG_WHITEBALANCEFINE,"WHITEBALANCEFINE",N_("Whitebalance fine ajustment"), NULL},
+ {MNOTE_NIKON_TAG_WHITEBALANCERB, "WHITEBALANCERB", N_("Whitebalance RB"), NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X000D, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_ISOSELECTION, "ISOSELECTION", N_("Isoselection"), NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0011, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_EXPOSUREDIFF, "EXPOSUREDIFF", N_("Exposurediff ?"), NULL},
+ {MNOTE_NIKON_TAG_FLASHCOMPENSATION, "FLASHCOMPENSATION", N_("Flashcompensation ?"), NULL},
+ {MNOTE_NIKON_TAG_ISO2, "ISO", N_("ISO Setting"), NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0016, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0017, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0018, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0019, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_IMAGEADJUSTMENT, "ImageAdjustment", N_("Image Adjustment"), NULL},
+ {MNOTE_NIKON_TAG_TONECOMPENSATION, "TONECOMPENSATION", N_("Tonecompensation"), NULL},
+ {MNOTE_NIKON_TAG_ADAPTER, "Adapter", N_("Adapter"), NULL},
+ {MNOTE_NIKON_TAG_LENSTYPE, "LENSTYPE", N_("Lenstype"), NULL},
+ {MNOTE_NIKON_TAG_LENS, "LENS", N_("Lens"), NULL},
+ {MNOTE_NIKON_TAG_MANUALFOCUSDISTANCE, "MANUALFOCUSDISTANCE", N_("Manual Focus Distance"), NULL},
+ {MNOTE_NIKON_TAG_DIGITALZOOM, "DigitalZoom", N_("Digital Zoom"), NULL},
+ {MNOTE_NIKON_TAG_FLASHUSED, "FLASHUSED", N_("Flash used"), NULL},
+ {MNOTE_NIKON_TAG_AFFOCUSPOSITION, "AFFOCUSPOSITION", N_("AF Focus position"), NULL},
+ {MNOTE_NIKON_TAG_BRACKETING, "BRACKETING", N_("Bracketing"), NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X008A, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X008B, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_CURVE, "CURVE,", N_("Contrast curve"), NULL},
+ {MNOTE_NIKON_TAG_COLORMODE, "COLORMODE,", N_("Colormode"), NULL},
+ {MNOTE_NIKON_TAG_LIGHTYPE, "LIGHTYPE,", N_("Lightype"), NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0091, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_HUE, "Hue,", N_("Hue Adjustment"), NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0094, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_NOISEREDUCTION, "NOISEREDUCTION,", N_("Noisereduction"), NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0097, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0098, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X009A, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X009B, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X00A0, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X00A2, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X00A3, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_TOTALPICTURES, "TOTALPICTURES,", N_("Total number of pictures taken"), NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X00A8, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_OPTIMIZATION, "OPTIMIZATION,", N_("Optimize Image"), NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X00AA, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X00AB, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_CAPTUREEDITORDATA, "CAPTUREEDITORDATA", N_("Capture Editor Data"), NULL},
+ {MNOTE_NIKON_TAG_CAPTUREEDITORVER, "CAPTUREEDITORVER", N_("Capture Editor Version"), NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0E0E, NULL, NULL, NULL},
+ {MNOTE_NIKON_TAG_UNKNOWN_0X0E10, NULL, NULL, NULL},
+ {MNOTE_NIKON1_TAG_UNKNOWN_0X0002, NULL, NULL, NULL},
+ {MNOTE_NIKON1_TAG_QUALITY, "QUALITY", N_("Quality"), NULL},
+ {MNOTE_NIKON1_TAG_COLORMODE, "COLORMODE,", N_("Colormode"), NULL},
+ {MNOTE_NIKON1_TAG_IMAGEADJUSTMENT, "ImageAdjustment", N_("Image Adjustment"), NULL},
+ {MNOTE_NIKON1_TAG_CCDSENSITIVITY, "CCDSensitivity", N_("CCD Sensitivity"), NULL},
+ {MNOTE_NIKON1_TAG_WHITEBALANCE, "WhiteBalance", N_("Whitebalance"), NULL},
+ {MNOTE_NIKON1_TAG_FOCUS, "Focus", N_("Focus"), NULL},
+ {MNOTE_NIKON1_TAG_UNKNOWN_0X0009, NULL, NULL, NULL},
+ {MNOTE_NIKON1_TAG_DIGITALZOOM, "DigitalZoom", N_("Digital Zoom"), NULL},
+ {MNOTE_NIKON1_TAG_CONVERTER, "Converter", N_("Converter"), NULL},
+
+ /* Olympus */
+ {MNOTE_OLYMPUS_TAG_MODE, "Mode", N_("Speed/Sequence/Panorama direction"), NULL},
+ {MNOTE_OLYMPUS_TAG_QUALITY, "Quality", N_("Quality"), NULL},
+ {MNOTE_OLYMPUS_TAG_MACRO, "Macro", N_("Macro"), NULL},
+ {MNOTE_OLYMPUS_TAG_UNKNOWN_1, NULL, NULL, NULL},
+ {MNOTE_OLYMPUS_TAG_DIGIZOOM, "DigiZoom", N_("Digital Zoom"), NULL},
+ {MNOTE_OLYMPUS_TAG_UNKNOWN_2, NULL, NULL, NULL},
+ {MNOTE_OLYMPUS_TAG_UNKNOWN_3, NULL, NULL, NULL},
+ {MNOTE_OLYMPUS_TAG_VERSION, "FirmwareVersion", N_("Firmware version"), NULL},
+ {MNOTE_OLYMPUS_TAG_INFO, "Info", N_("Info"), NULL},
+ {MNOTE_OLYMPUS_TAG_ID, "CameraID", N_("Camera ID"), NULL},
+ {MNOTE_OLYMPUS_TAG_UNKNOWN_4, NULL, NULL, NULL},
+ {MNOTE_OLYMPUS_TAG_FLASHMODE, "FlashMode", N_("Flash Mode"), NULL},
+ {MNOTE_OLYMPUS_TAG_FOCUSDIST, "ManualFocusDistance", N_("Manual Focus Distance"), NULL},
+ {MNOTE_OLYMPUS_TAG_SHARPNESS, "Sharpness", N_("Sharpness Setting"), NULL},
+ {MNOTE_OLYMPUS_TAG_WBALANCE, "WhiteBalance", N_("White Balance Setting"), NULL},
+ {MNOTE_OLYMPUS_TAG_CONTRAST, "Contrast", N_("Contrast Setting"), NULL},
+ {MNOTE_OLYMPUS_TAG_MANFOCUS, "ManualFocus", N_("Manual Focus"), NULL},
+ {0, NULL, NULL, NULL}
+};
+
+const char *
+mnote_olympus_tag_get_name (MnoteOlympusTag t)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ if (table[i].tag == t) return (table[i].name);
+ return NULL;
+}
+
+const char *
+mnote_olympus_tag_get_title (MnoteOlympusTag t)
+{
+ unsigned int i;
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ if (table[i].tag == t) return (_(table[i].title));
+ return NULL;
+}
+
+const char *
+mnote_olympus_tag_get_description (MnoteOlympusTag t)
+{
+ unsigned int i;
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ if (table[i].tag == t) return (_(table[i].description));
+ return NULL;
+}
diff --git a/src/libexif/olympus/mnote-olympus-tag.h b/src/libexif/olympus/mnote-olympus-tag.h
new file mode 100644
index 0000000..22278ac
--- /dev/null
+++ b/src/libexif/olympus/mnote-olympus-tag.h
@@ -0,0 +1,130 @@
+/* mnote-olympus-tag.h
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MNOTE_OLYMPUS_TAG_H__
+#define __MNOTE_OLYMPUS_TAG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+enum _MnoteOlympusTag {
+
+ /* Nikon v.2 */
+ MNOTE_NIKON_TAG_FIRMWARE = 0x0001,
+ MNOTE_NIKON_TAG_ISO = 0x0002,
+ MNOTE_NIKON_TAG_COLORMODE1 = 0x0003,
+ MNOTE_NIKON_TAG_QUALITY = 0x0004,
+ MNOTE_NIKON_TAG_WHITEBALANCE = 0x0005,
+ MNOTE_NIKON_TAG_SHARPENING = 0x0006,
+ MNOTE_NIKON_TAG_FOCUSMODE = 0x0007,
+ MNOTE_NIKON_TAG_FLASHSETTING = 0x0008,
+ MNOTE_NIKON_TAG_FLASHMODE = 0x0009,
+ MNOTE_NIKON_TAG_WHITEBALANCEFINE = 0x000b,
+ MNOTE_NIKON_TAG_WHITEBALANCERB = 0x000c,
+ MNOTE_NIKON_TAG_UNKNOWN_0X000D = 0x000d,
+ MNOTE_NIKON_TAG_EXPOSUREDIFF = 0x000e,
+ MNOTE_NIKON_TAG_ISOSELECTION = 0x000f,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0011 = 0x0011,
+ MNOTE_NIKON_TAG_FLASHCOMPENSATION = 0x0012,
+ MNOTE_NIKON_TAG_ISO2 = 0x0013,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0016 = 0x0016,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0017 = 0x0017,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0018 = 0x0018,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0019 = 0x0019,
+ MNOTE_NIKON_TAG_IMAGEADJUSTMENT = 0x0080,
+ MNOTE_NIKON_TAG_TONECOMPENSATION = 0x0081,
+ MNOTE_NIKON_TAG_ADAPTER = 0x0082,
+ MNOTE_NIKON_TAG_LENSTYPE = 0x0083,
+ MNOTE_NIKON_TAG_LENS = 0x0084,
+ MNOTE_NIKON_TAG_MANUALFOCUSDISTANCE = 0x0085,
+ MNOTE_NIKON_TAG_DIGITALZOOM = 0x0086,
+ MNOTE_NIKON_TAG_FLASHUSED = 0x0087,
+ MNOTE_NIKON_TAG_AFFOCUSPOSITION = 0x0088,
+ MNOTE_NIKON_TAG_BRACKETING = 0x0089,
+ MNOTE_NIKON_TAG_UNKNOWN_0X008A = 0x008a,
+ MNOTE_NIKON_TAG_UNKNOWN_0X008B = 0x008b,
+ MNOTE_NIKON_TAG_CURVE = 0x008c,
+ MNOTE_NIKON_TAG_COLORMODE = 0x008d,
+ MNOTE_NIKON_TAG_LIGHTYPE = 0x0090,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0091 = 0x0091,
+ MNOTE_NIKON_TAG_HUE = 0x0092,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0094 = 0x0094,
+ MNOTE_NIKON_TAG_NOISEREDUCTION = 0x0095,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0097 = 0x0097,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0098 = 0x0098,
+ MNOTE_NIKON_TAG_UNKNOWN_0X009A = 0x009a,
+ MNOTE_NIKON_TAG_UNKNOWN_0X009B = 0x009b,
+ MNOTE_NIKON_TAG_UNKNOWN_0X00A0 = 0x00a0,
+ MNOTE_NIKON_TAG_UNKNOWN_0X00A2 = 0x00a2,
+ MNOTE_NIKON_TAG_UNKNOWN_0X00A3 = 0x00a3,
+ MNOTE_NIKON_TAG_TOTALPICTURES = 0x00a7,
+ MNOTE_NIKON_TAG_UNKNOWN_0X00A8 = 0x00a8,
+ MNOTE_NIKON_TAG_OPTIMIZATION = 0x00a9,
+ MNOTE_NIKON_TAG_UNKNOWN_0X00AA = 0x00aa,
+ MNOTE_NIKON_TAG_UNKNOWN_0X00AB = 0x00ab,
+ MNOTE_NIKON_TAG_CAPTUREEDITORDATA = 0x0e01,
+ MNOTE_NIKON_TAG_CAPTUREEDITORVER = 0x0e09,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0E0E = 0x0e0e,
+ MNOTE_NIKON_TAG_UNKNOWN_0X0E10 = 0x0e10,
+
+ /* Nikon v1: real values + our proprietary base to distinguish from v2 */
+ MNOTE_NIKON1_TAG_BASE = 0x8000,
+ MNOTE_NIKON1_TAG_UNKNOWN_0X0002 = 0x0002 + MNOTE_NIKON1_TAG_BASE,
+ MNOTE_NIKON1_TAG_QUALITY = 0x0003 + MNOTE_NIKON1_TAG_BASE,
+ MNOTE_NIKON1_TAG_COLORMODE = 0x0004 + MNOTE_NIKON1_TAG_BASE,
+ MNOTE_NIKON1_TAG_IMAGEADJUSTMENT = 0x0005 + MNOTE_NIKON1_TAG_BASE,
+ MNOTE_NIKON1_TAG_CCDSENSITIVITY = 0x0006 + MNOTE_NIKON1_TAG_BASE,
+ MNOTE_NIKON1_TAG_WHITEBALANCE = 0x0007 + MNOTE_NIKON1_TAG_BASE,
+ MNOTE_NIKON1_TAG_FOCUS = 0x0008 + MNOTE_NIKON1_TAG_BASE,
+ MNOTE_NIKON1_TAG_UNKNOWN_0X0009 = 0x0009 + MNOTE_NIKON1_TAG_BASE,
+ MNOTE_NIKON1_TAG_DIGITALZOOM = 0x000a + MNOTE_NIKON1_TAG_BASE,
+ MNOTE_NIKON1_TAG_CONVERTER = 0x000b + MNOTE_NIKON1_TAG_BASE,
+
+ /* Olympus */
+ MNOTE_OLYMPUS_TAG_MODE = 0x0200,
+ MNOTE_OLYMPUS_TAG_QUALITY = 0x0201,
+ MNOTE_OLYMPUS_TAG_MACRO = 0x0202,
+ MNOTE_OLYMPUS_TAG_UNKNOWN_1 = 0x0203,
+ MNOTE_OLYMPUS_TAG_DIGIZOOM = 0x0204,
+ MNOTE_OLYMPUS_TAG_UNKNOWN_2 = 0x0205,
+ MNOTE_OLYMPUS_TAG_UNKNOWN_3 = 0x0206,
+ MNOTE_OLYMPUS_TAG_VERSION = 0x0207,
+ MNOTE_OLYMPUS_TAG_INFO = 0x0208,
+ MNOTE_OLYMPUS_TAG_ID = 0x0209,
+ MNOTE_OLYMPUS_TAG_UNKNOWN_4 = 0x0f04,
+ MNOTE_OLYMPUS_TAG_FLASHMODE = 0x1004,
+ MNOTE_OLYMPUS_TAG_MANFOCUS = 0x100b,
+ MNOTE_OLYMPUS_TAG_FOCUSDIST = 0x100c,
+ MNOTE_OLYMPUS_TAG_SHARPNESS = 0x100f,
+ MNOTE_OLYMPUS_TAG_WBALANCE = 0x1015,
+ MNOTE_OLYMPUS_TAG_CONTRAST = 0x1029
+};
+typedef enum _MnoteOlympusTag MnoteOlympusTag;
+
+const char *mnote_olympus_tag_get_name (MnoteOlympusTag tag);
+const char *mnote_olympus_tag_get_title (MnoteOlympusTag tag);
+const char *mnote_olympus_tag_get_description (MnoteOlympusTag tag);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __MNOTE_OLYMPUS_TAG_H__ */
diff --git a/src/libexif/pentax/exif-mnote-data-pentax.c b/src/libexif/pentax/exif-mnote-data-pentax.c
new file mode 100644
index 0000000..cc2cc12
--- /dev/null
+++ b/src/libexif/pentax/exif-mnote-data-pentax.c
@@ -0,0 +1,209 @@
+/* exif-mnote-data-pentax.c
+ *
+ * Copyright © 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "exif-mnote-data-pentax.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-utils.h>
+
+/* #define DEBUG */
+
+static void
+exif_mnote_data_pentax_clear (ExifMnoteDataPentax *n)
+{
+ ExifMnoteData *d = (ExifMnoteData *) n;
+ unsigned int i;
+
+ if (!n) return;
+
+ if (n->entries) {
+ for (i = 0; i < n->count; i++)
+ if (n->entries[i].data) {
+ exif_mem_free (d->mem, n->entries[i].data);
+ n->entries[i].data = NULL;
+ }
+ exif_mem_free (d->mem, n->entries);
+ n->entries = NULL;
+ n->count = 0;
+ }
+}
+
+static void
+exif_mnote_data_pentax_free (ExifMnoteData *n)
+{
+ if (!n) return;
+
+ exif_mnote_data_pentax_clear ((ExifMnoteDataPentax *) n);
+}
+
+static char *
+exif_mnote_data_pentax_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
+{
+ ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) d;
+
+ if (!n) return NULL;
+ if (n->count <= i) return NULL;
+ return mnote_pentax_entry_get_value (&n->entries[i], val, maxlen);
+}
+
+static void
+exif_mnote_data_pentax_load (ExifMnoteData *en,
+ const unsigned char *buf, unsigned int buf_size)
+{
+ ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) en;
+ unsigned int i, o, s;
+ ExifShort c;
+
+ /* Number of entries */
+ if (buf_size < 2) return;
+ c = exif_get_short (buf + 6 + n->offset, n->order);
+ n->entries = exif_mem_alloc (en->mem, sizeof (MnotePentaxEntry) * c);
+ if (!n->entries) return;
+
+ for (i = 0; i < c; i++) {
+ o = 6 + 2 + n->offset + 12 * i;
+ if (o + 8 > buf_size) return;
+
+ n->count = i + 1;
+ n->entries[i].tag = exif_get_short (buf + o + 0, n->order);
+ n->entries[i].format = exif_get_short (buf + o + 2, n->order);
+ n->entries[i].components = exif_get_long (buf + o + 4, n->order);
+ n->entries[i].order = n->order;
+
+ /*
+ * Size? If bigger than 4 bytes, the actual data is not
+ * in the entry but somewhere else (offset).
+ */
+ s = exif_format_get_size (n->entries[i].format) *
+ n->entries[i].components;
+ if (!s) return;
+ o += 8;
+ if (s > 4) o = exif_get_long (buf + o, n->order) + 6;
+ if (o + s > buf_size) return;
+
+ /* Sanity check */
+ n->entries[i].data = exif_mem_alloc (en->mem, sizeof (char) * s);
+ if (!n->entries[i].data) return;
+ n->entries[i].size = s;
+ memcpy (n->entries[i].data, buf + o, s);
+ }
+}
+
+static unsigned int
+exif_mnote_data_pentax_count (ExifMnoteData *n)
+{
+ return n ? ((ExifMnoteDataPentax *) n)->count : 0;
+}
+
+static unsigned int
+exif_mnote_data_pentax_get_id (ExifMnoteData *d, unsigned int n)
+{
+ ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d;
+
+ if (!note) return 0;
+ if (note->count <= n) return 0;
+ return note->entries[n].tag;
+}
+
+static const char *
+exif_mnote_data_pentax_get_name (ExifMnoteData *d, unsigned int n)
+{
+ ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d;
+
+ if (!note) return NULL;
+ if (note->count <= n) return NULL;
+ return mnote_pentax_tag_get_name (note->entries[n].tag);
+}
+
+static const char *
+exif_mnote_data_pentax_get_title (ExifMnoteData *d, unsigned int n)
+{
+ ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d;
+
+ if (!note) return NULL;
+ if (note->count <= n) return NULL;
+ return mnote_pentax_tag_get_title (note->entries[n].tag);
+}
+
+static const char *
+exif_mnote_data_pentax_get_description (ExifMnoteData *d, unsigned int n)
+{
+ ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d;
+
+ if (!note) return NULL;
+ if (note->count <= n) return NULL;
+ return mnote_pentax_tag_get_description (note->entries[n].tag);
+}
+
+static void
+exif_mnote_data_pentax_set_offset (ExifMnoteData *d, unsigned int o)
+{
+ if (d) ((ExifMnoteDataPentax *) d)->offset = o;
+}
+
+static void
+exif_mnote_data_pentax_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
+{
+ ExifByteOrder o_orig;
+ ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) d;
+ unsigned int i;
+
+ if (!n) return;
+
+ o_orig = n->order;
+ n->order = o;
+ for (i = 0; i < n->count; i++) {
+ n->entries[i].order = o;
+ exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
+ n->entries[i].components, o_orig, o);
+ }
+}
+
+ExifMnoteData *
+exif_mnote_data_pentax_new (ExifMem *mem)
+{
+ ExifMnoteData *d;
+
+ if (!mem) return NULL;
+
+ d = exif_mem_alloc (mem, sizeof (ExifMnoteDataPentax));
+ if (!d) return NULL;
+
+ exif_mnote_data_construct (d, mem);
+
+ /* Set up function pointers */
+ d->methods.free = exif_mnote_data_pentax_free;
+ d->methods.set_byte_order = exif_mnote_data_pentax_set_byte_order;
+ d->methods.set_offset = exif_mnote_data_pentax_set_offset;
+ d->methods.load = exif_mnote_data_pentax_load;
+ d->methods.count = exif_mnote_data_pentax_count;
+ d->methods.get_id = exif_mnote_data_pentax_get_id;
+ d->methods.get_name = exif_mnote_data_pentax_get_name;
+ d->methods.get_title = exif_mnote_data_pentax_get_title;
+ d->methods.get_description = exif_mnote_data_pentax_get_description;
+ d->methods.get_value = exif_mnote_data_pentax_get_value;
+
+ return d;
+}
diff --git a/src/libexif/pentax/exif-mnote-data-pentax.h b/src/libexif/pentax/exif-mnote-data-pentax.h
new file mode 100644
index 0000000..c04bc41
--- /dev/null
+++ b/src/libexif/pentax/exif-mnote-data-pentax.h
@@ -0,0 +1,44 @@
+/* exif-mnote-data-pentax.h
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EXIF_MNOTE_DATA_PENTAX_H__
+#define __EXIF_MNOTE_DATA_PENTAX_H__
+
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-mnote-data.h>
+#include <libexif/exif-mnote-data-priv.h>
+#include <libexif/pentax/mnote-pentax-entry.h>
+#include <libexif/exif-mem.h>
+
+typedef struct _ExifMnoteDataPentax ExifMnoteDataPentax;
+
+struct _ExifMnoteDataPentax {
+ ExifMnoteData parent;
+
+ MnotePentaxEntry *entries;
+ unsigned int count;
+
+ ExifByteOrder order;
+ unsigned int offset;
+};
+
+ExifMnoteData *exif_mnote_data_pentax_new (ExifMem *);
+
+#endif /* __EXIF_MNOTE_DATA_PENTAX_H__ */
diff --git a/src/libexif/pentax/mnote-pentax-entry.c b/src/libexif/pentax/mnote-pentax-entry.c
new file mode 100644
index 0000000..3469f22
--- /dev/null
+++ b/src/libexif/pentax/mnote-pentax-entry.c
@@ -0,0 +1,210 @@
+/* mnote-pentax-entry.c
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "mnote-pentax-entry.h"
+
+#include <libexif/i18n.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libexif/exif-format.h>
+#include <libexif/exif-utils.h>
+#include <libexif/exif-entry.h>
+
+
+#define CF(format,target,v,maxlen) \
+{ \
+ if (format != target) { \
+ snprintf (v, maxlen, \
+ _("Invalid format '%s', " \
+ "expected '%s'."), \
+ exif_format_get_name (format), \
+ exif_format_get_name (target)); \
+ break; \
+ } \
+}
+
+#define CC(number,target,v,maxlen) \
+{ \
+ if (number != target) { \
+ snprintf (v, maxlen, \
+ _("Invalid number of components (%i, " \
+ "expected %i)."), (int) number, (int) target); \
+ break; \
+ } \
+}
+
+static struct {
+ ExifTag tag;
+ struct {
+ int index;
+ const char *string;
+ } elem[7];
+} items[] = {
+ { MNOTE_PENTAX_TAG_MODE,
+ { {0, N_("Auto")},
+ {1, N_("Night-scene")},
+ {2, N_("Manual")},
+ {0, NULL}}},
+ { MNOTE_PENTAX_TAG_QUALITY,
+ { {0, N_("Good")},
+ {1, N_("Better")},
+ {2, N_("Best")},{0,NULL}}},
+ { MNOTE_PENTAX_TAG_FOCUS,
+ { {2, N_("Custom")},
+ {3, N_("Auto")},
+ {0, NULL}}},
+ { MNOTE_PENTAX_TAG_FLASH,
+ { {1, N_("Auto")},
+ {2, N_("Flash on")},
+ {4, N_("Flash off")},
+ {6, N_("Red-eye Reduction")},
+ {0, NULL}}},
+ { MNOTE_PENTAX_TAG_WHITE_BALANCE,
+ { {0, N_("Auto")},
+ {1, N_("Daylight")},
+ {2, N_("Shade")},
+ {3, N_("Tungsten")},
+ {4, N_("Fluorescent")},
+ {5, N_("Manual")},
+ {0, NULL}}},
+ { MNOTE_PENTAX_TAG_SHARPNESS,
+ { {0, N_("Normal")},
+ {1, N_("Soft")},
+ {2, N_("Hard")},
+ {0, NULL}}},
+ { MNOTE_PENTAX_TAG_CONTRAST,
+ { {0, N_("Normal")},
+ {1, N_("Low")},
+ {2, N_("High")},
+ {0, NULL}}},
+ { MNOTE_PENTAX_TAG_SATURATION,
+ { {0, N_("Normal")},
+ {1, N_("Low")},
+ {2, N_("High")},
+ {0, NULL}}},
+ { MNOTE_PENTAX_TAG_ISO_SPEED,
+ { {10, N_("100")},
+ {16, N_("200")},
+ {100, N_("100")},
+ {200, N_("200")},
+ { 0, NULL}}},
+ { MNOTE_PENTAX_TAG_COLOR,
+ { {1, N_("Full")},
+ {2, N_("Black & White")},
+ {3, N_("Sepia")},
+ {0, NULL}}},
+};
+
+char *
+mnote_pentax_entry_get_value (MnotePentaxEntry *entry,
+ char *val, unsigned int maxlen)
+{
+ ExifLong vl;
+ ExifShort vs;
+ int i = 0, j = 0;
+
+ if (!entry) return (NULL);
+
+ memset (val, 0, maxlen);
+ maxlen--;
+
+ switch (entry->tag) {
+ case MNOTE_PENTAX_TAG_MODE:
+ case MNOTE_PENTAX_TAG_QUALITY:
+ case MNOTE_PENTAX_TAG_FOCUS:
+ case MNOTE_PENTAX_TAG_FLASH:
+ case MNOTE_PENTAX_TAG_WHITE_BALANCE:
+ case MNOTE_PENTAX_TAG_SHARPNESS:
+ case MNOTE_PENTAX_TAG_CONTRAST:
+ case MNOTE_PENTAX_TAG_SATURATION:
+ case MNOTE_PENTAX_TAG_ISO_SPEED:
+ case MNOTE_PENTAX_TAG_COLOR:
+ CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
+ CC (entry->components, 1, val, maxlen);
+ vs = exif_get_short (entry->data, entry->order);
+
+ /* search the tag */
+ for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++);
+ if (!items[i].tag) {
+ strncpy (val, "Internal error", maxlen);
+ break;
+ }
+
+ /* find the value */
+ for (j = 0; items[i].elem[j].string &&
+ (items[i].elem[j].index < vs); j++);
+ if (items[i].elem[j].index != vs) {
+ snprintf (val, maxlen,
+ "Internal error (unknown value %i)", vs);
+ break;
+ }
+ snprintf (val, maxlen, "%s", items[i].elem[j].string);
+ break;
+
+ case MNOTE_PENTAX_TAG_ZOOM:
+ CF (entry->format, EXIF_FORMAT_LONG, val, maxlen);
+ CC (entry->components, 1, val, maxlen);
+ vl = exif_get_long (entry->data, entry->order);
+ snprintf (val, maxlen, "%li", (long int) vl);
+ break;
+ case MNOTE_PENTAX_TAG_PRINTIM:
+ CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (entry->components, 124, val, maxlen);
+ snprintf (val, maxlen, "%li bytes unknown data",
+ entry->components);
+ break;
+ case MNOTE_PENTAX_TAG_TZ_CITY:
+ CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (entry->components, 4, val, maxlen);
+ snprintf (val, entry->components, "%s", entry->data);
+ break;
+ case MNOTE_PENTAX_TAG_TZ_DST:
+ CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (entry->components, 4, val, maxlen);
+ snprintf (val, entry->components, "%s", entry->data);
+ break;
+ default:
+ switch (entry->format) {
+ case EXIF_FORMAT_ASCII:
+ strncpy (val, entry->data, MIN(maxlen, entry->components));
+ break;
+ case EXIF_FORMAT_SHORT:
+ vs = exif_get_short (entry->data, entry->order);
+ snprintf (val, maxlen, "%i", vs);
+ break;
+ case EXIF_FORMAT_LONG:
+ vl = exif_get_long (entry->data, entry->order);
+ snprintf (val, maxlen, "%li", (long int) vl);
+ break;
+ case EXIF_FORMAT_UNDEFINED:
+ default:
+ snprintf (val, maxlen, "%li bytes unknown data",
+ entry->components);
+ break;
+ }
+ break;
+ }
+
+ return (val);
+}
diff --git a/src/libexif/pentax/mnote-pentax-entry.h b/src/libexif/pentax/mnote-pentax-entry.h
new file mode 100644
index 0000000..628d5dd
--- /dev/null
+++ b/src/libexif/pentax/mnote-pentax-entry.h
@@ -0,0 +1,43 @@
+/* mnote-pentax-entry.h
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MNOTE_PENTAX_ENTRY_H__
+#define __MNOTE_PENTAX_ENTRY_H__
+
+#include <libexif/exif-format.h>
+#include <libexif/exif-byte-order.h>
+#include <libexif/pentax/mnote-pentax-tag.h>
+
+typedef struct _MnotePentaxEntry MnotePentaxEntry;
+
+struct _MnotePentaxEntry {
+ MnotePentaxTag tag;
+ ExifFormat format;
+ unsigned long components;
+
+ unsigned char *data;
+ unsigned int size;
+
+ ExifByteOrder order;
+};
+
+char *mnote_pentax_entry_get_value (MnotePentaxEntry *entry, char *val, unsigned int maxlen);
+
+#endif /* __MNOTE_PENTAX_ENTRY_H__ */
diff --git a/src/libexif/pentax/mnote-pentax-tag.c b/src/libexif/pentax/mnote-pentax-tag.c
new file mode 100644
index 0000000..76823a4
--- /dev/null
+++ b/src/libexif/pentax/mnote-pentax-tag.c
@@ -0,0 +1,94 @@
+/* mnote-pentax-tag.c:
+ *
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "mnote-pentax-tag.h"
+
+#include <stdlib.h>
+
+#include <libexif/i18n.h>
+
+static struct {
+ MnotePentaxTag tag;
+ const char *name;
+ const char *title;
+ const char *description;
+} table[] = {
+ {MNOTE_PENTAX_TAG_MODE, "Mode", N_("Capture Mode"), NULL},
+ {MNOTE_PENTAX_TAG_QUALITY, "Quality", N_("Quality Level"), NULL},
+ {MNOTE_PENTAX_TAG_FOCUS, "Focus", N_("Focus Mode"), NULL},
+ {MNOTE_PENTAX_TAG_FLASH, "Flash", N_("Flash Mode"), NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_05, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_06, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance"), NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_08, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_09, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_ZOOM, "Zoom", N_("Zoom"), NULL},
+ {MNOTE_PENTAX_TAG_SHARPNESS, "Sharpness", N_("Sharpness"), NULL},
+ {MNOTE_PENTAX_TAG_CONTRAST, "Contrast", N_("Contrast"), NULL},
+ {MNOTE_PENTAX_TAG_SATURATION, "Saturation", N_("Saturation"), NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_14, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_15, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_16, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_17, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_18, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_19, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_ISO_SPEED, "ISOSpeed", N_("ISOSpeed"), NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_21, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_COLOR, "Color", N_("Color"), NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_24, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_UNKNOWN_25, NULL, NULL, NULL},
+ {MNOTE_PENTAX_TAG_PRINTIM, "PrintIM", N_("PrintIM Settings"), NULL},
+ {MNOTE_PENTAX_TAG_TZ_CITY, "TimeZone", N_("TimeZone"), NULL},
+ {MNOTE_PENTAX_TAG_TZ_DST, "DaylightSavings", N_("DaylightSavings"), NULL},
+ {0, NULL, NULL, NULL}
+};
+
+const char *
+mnote_pentax_tag_get_name (MnotePentaxTag t)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ if (table[i].tag == t) return (table[i].name);
+ return NULL;
+}
+
+const char *
+mnote_pentax_tag_get_title (MnotePentaxTag t)
+{
+ unsigned int i;
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ if (table[i].tag == t) return (_(table[i].title));
+ return NULL;
+}
+
+const char *
+mnote_pentax_tag_get_description (MnotePentaxTag t)
+{
+ unsigned int i;
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ if (table[i].tag == t) return (_(table[i].description));
+ return NULL;
+}
diff --git a/src/libexif/pentax/mnote-pentax-tag.h b/src/libexif/pentax/mnote-pentax-tag.h
new file mode 100644
index 0000000..a261102
--- /dev/null
+++ b/src/libexif/pentax/mnote-pentax-tag.h
@@ -0,0 +1,74 @@
+/* mnote-pentax-tag.h
+ *
+ * Copyright © 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MNOTE_PENTAX_TAG_H__
+#define __MNOTE_PENTAX_TAG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * Missing features which are probably in the unknowns somewhere ...
+ * 1/ AF Area (Wide, Spot, Free)
+ * 2/ AE Metering (Multi segment, Centre-weighted, Spot)
+ * 3/
+ */
+
+enum _MnotePentaxTag {
+ MNOTE_PENTAX_TAG_MODE = 0x0001,
+ MNOTE_PENTAX_TAG_QUALITY = 0x0002,
+ MNOTE_PENTAX_TAG_FOCUS = 0x0003,
+ MNOTE_PENTAX_TAG_FLASH = 0x0004,
+ MNOTE_PENTAX_TAG_UNKNOWN_05 = 0x0005,
+ MNOTE_PENTAX_TAG_UNKNOWN_06 = 0x0006,
+ MNOTE_PENTAX_TAG_WHITE_BALANCE = 0x0007,
+ MNOTE_PENTAX_TAG_UNKNOWN_08 = 0x0008,
+ MNOTE_PENTAX_TAG_UNKNOWN_09 = 0x0009,
+ MNOTE_PENTAX_TAG_ZOOM = 0x000a,
+ MNOTE_PENTAX_TAG_SHARPNESS = 0x000b,
+ MNOTE_PENTAX_TAG_CONTRAST = 0x000c,
+ MNOTE_PENTAX_TAG_SATURATION = 0x000d,
+ MNOTE_PENTAX_TAG_UNKNOWN_14 = 0x000e,
+ MNOTE_PENTAX_TAG_UNKNOWN_15 = 0x000f,
+ MNOTE_PENTAX_TAG_UNKNOWN_16 = 0x0010,
+ MNOTE_PENTAX_TAG_UNKNOWN_17 = 0x0011,
+ MNOTE_PENTAX_TAG_UNKNOWN_18 = 0x0012,
+ MNOTE_PENTAX_TAG_UNKNOWN_19 = 0x0013,
+ MNOTE_PENTAX_TAG_ISO_SPEED = 0x0014,
+ MNOTE_PENTAX_TAG_UNKNOWN_21 = 0x0015,
+ MNOTE_PENTAX_TAG_COLOR = 0x0017,
+ MNOTE_PENTAX_TAG_UNKNOWN_24 = 0x0018,
+ MNOTE_PENTAX_TAG_UNKNOWN_25 = 0x0019,
+ MNOTE_PENTAX_TAG_PRINTIM = 0x0e00,
+ MNOTE_PENTAX_TAG_TZ_CITY = 0x1000,
+ MNOTE_PENTAX_TAG_TZ_DST = 0x1001
+};
+typedef enum _MnotePentaxTag MnotePentaxTag;
+
+const char *mnote_pentax_tag_get_name (MnotePentaxTag tag);
+const char *mnote_pentax_tag_get_title (MnotePentaxTag tag);
+const char *mnote_pentax_tag_get_description (MnotePentaxTag tag);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __MNOTE_PENTAX_TAG_H__ */