summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.mak1
-rw-r--r--src/libexif/canon/exif-mnote-data-canon.c168
-rw-r--r--src/libexif/canon/exif-mnote-data-canon.h7
-rw-r--r--src/libexif/canon/mnote-canon-entry.c1061
-rw-r--r--src/libexif/canon/mnote-canon-entry.h5
-rw-r--r--src/libexif/canon/mnote-canon-tag.c134
-rw-r--r--src/libexif/canon/mnote-canon-tag.h17
-rw-r--r--src/libexif/exif-byte-order.c2
-rw-r--r--src/libexif/exif-byte-order.h2
-rw-r--r--src/libexif/exif-content.c111
-rw-r--r--src/libexif/exif-content.h10
-rw-r--r--src/libexif/exif-data-type.h40
-rw-r--r--src/libexif/exif-data.c480
-rw-r--r--src/libexif/exif-data.h24
-rw-r--r--src/libexif/exif-entry.c379
-rw-r--r--src/libexif/exif-entry.h29
-rw-r--r--src/libexif/exif-format.c11
-rw-r--r--src/libexif/exif-format.h2
-rw-r--r--src/libexif/exif-ifd.c4
-rw-r--r--src/libexif/exif-ifd.h14
-rw-r--r--src/libexif/exif-loader.c106
-rw-r--r--src/libexif/exif-loader.h56
-rw-r--r--src/libexif/exif-log.c8
-rw-r--r--src/libexif/exif-log.h14
-rw-r--r--src/libexif/exif-mem.c3
-rw-r--r--src/libexif/exif-mem.h52
-rw-r--r--src/libexif/exif-mnote-data-priv.h2
-rw-r--r--src/libexif/exif-mnote-data.c2
-rw-r--r--src/libexif/exif-mnote-data.h2
-rw-r--r--src/libexif/exif-system.h31
-rw-r--r--src/libexif/exif-tag.c412
-rw-r--r--src/libexif/exif-tag.h66
-rw-r--r--src/libexif/exif-utils.c39
-rw-r--r--src/libexif/exif-utils.h15
-rw-r--r--src/libexif/exif.c1274
-rw-r--r--src/libexif/exif.h86
-rw-r--r--src/libexif/fuji/exif-mnote-data-fuji.c297
-rw-r--r--src/libexif/fuji/exif-mnote-data-fuji.h43
-rw-r--r--src/libexif/fuji/mnote-fuji-entry.c306
-rw-r--r--src/libexif/fuji/mnote-fuji-entry.h45
-rw-r--r--src/libexif/fuji/mnote-fuji-tag.c105
-rw-r--r--src/libexif/fuji/mnote-fuji-tag.h92
-rw-r--r--src/libexif/i18n.h1
-rw-r--r--src/libexif/olympus/exif-mnote-data-olympus.c152
-rw-r--r--src/libexif/olympus/exif-mnote-data-olympus.h5
-rw-r--r--src/libexif/olympus/mnote-olympus-entry.c385
-rw-r--r--src/libexif/olympus/mnote-olympus-entry.h2
-rw-r--r--src/libexif/olympus/mnote-olympus-tag.c216
-rw-r--r--src/libexif/olympus/mnote-olympus-tag.h132
-rw-r--r--src/libexif/pentax/exif-mnote-data-pentax.c80
-rw-r--r--src/libexif/pentax/exif-mnote-data-pentax.h6
-rw-r--r--src/libexif/pentax/mnote-pentax-entry.c305
-rw-r--r--src/libexif/pentax/mnote-pentax-entry.h2
-rw-r--r--src/libexif/pentax/mnote-pentax-tag.c50
-rw-r--r--src/libexif/pentax/mnote-pentax-tag.h83
55 files changed, 4298 insertions, 2678 deletions
diff --git a/src/config.mak b/src/config.mak
index d2c3c0d..059eb74 100644
--- a/src/config.mak
+++ b/src/config.mak
@@ -55,6 +55,7 @@ SRCZLIB := $(addprefix zlib/, $(SRCZLIB))
INCLUDES += zlib
SRCEXIF = \
+ fuji/exif-mnote-data-fuji.c fuji/mnote-fuji-entry.c fuji/mnote-fuji-tag.c \
canon/exif-mnote-data-canon.c canon/mnote-canon-entry.c canon/mnote-canon-tag.c \
olympus/exif-mnote-data-olympus.c olympus/mnote-olympus-entry.c olympus/mnote-olympus-tag.c \
pentax/exif-mnote-data-pentax.c pentax/mnote-pentax-entry.c pentax/mnote-pentax-tag.c \
diff --git a/src/libexif/canon/exif-mnote-data-canon.c b/src/libexif/canon/exif-mnote-data-canon.c
index b1c5dab..2783d15 100644
--- a/src/libexif/canon/exif-mnote-data-canon.c
+++ b/src/libexif/canon/exif-mnote-data-canon.c
@@ -1,7 +1,7 @@
/* exif-mnote-data-canon.c
*
- * Copyright © 2002, 2003 Lutz Müller <lutz@users.sourceforge.net>
- * Copyright © 2003 Matthieu Castet <mat-c@users.sourceforge.net>
+ * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ * Copyright (c) 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
@@ -60,14 +60,33 @@ exif_mnote_data_canon_free (ExifMnoteData *n)
exif_mnote_data_canon_clear ((ExifMnoteDataCanon *) n);
}
+static void
+exif_mnote_data_canon_get_tags (ExifMnoteDataCanon *dc, unsigned int n,
+ unsigned int *m, unsigned int *s)
+{
+ unsigned int from = 0, to;
+
+ if (!dc || !m) return;
+ for (*m = 0; *m < dc->count; (*m)++) {
+ to = from + mnote_canon_entry_count_values (&dc->entries[*m]);
+ if (to > n) {
+ if (s) *s = n - from;
+ break;
+ }
+ from = to;
+ }
+}
+
static char *
exif_mnote_data_canon_get_value (ExifMnoteData *note, unsigned int n, char *val, unsigned int maxlen)
{
- ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note;
+ ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
+ unsigned int m, s;
- if (!note) return NULL;
- if (cnote->count <= n) return NULL;
- return mnote_canon_entry_get_value (&cnote->entries[n], val, maxlen);
+ if (!dc) return NULL;
+ exif_mnote_data_canon_get_tags (dc, n, &m, &s);
+ if (m >= dc->count) return NULL;
+ return mnote_canon_entry_get_value (&dc->entries[m], s, val, maxlen);
}
static void
@@ -99,7 +118,9 @@ exif_mnote_data_canon_save (ExifMnoteData *ne,
unsigned char **buf, unsigned int *buf_size)
{
ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
- unsigned int i, o, s, doff;
+ size_t i, o, s, doff;
+ unsigned char *t;
+ size_t ts;
if (!n || !buf || !buf_size) return;
@@ -124,14 +145,22 @@ exif_mnote_data_canon_save (ExifMnoteData *ne,
o += 8;
s = exif_format_get_size (n->entries[i].format) *
n->entries[i].components;
+ if (s > 65536) {
+ /* Corrupt data: EXIF data size is limited to the
+ * maximum size of a JPEG segment (64 kb).
+ */
+ continue;
+ }
if (s > 4) {
- *buf_size += s;
+ ts = *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;
+ if (s & 1) ts += 1;
+ t = exif_mem_realloc (ne->mem, *buf,
+ sizeof (char) * ts);
+ if (!t) return;
+ *buf = t;
+ *buf_size = ts;
doff = *buf_size - s;
if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
exif_set_long (*buf + o, n->order, n->offset + doff);
@@ -166,7 +195,8 @@ exif_mnote_data_canon_load (ExifMnoteData *ne,
{
ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
ExifShort c;
- unsigned int i, o, s;
+ size_t i, o, s;
+ MnoteCanonEntry *t;
if (!n || !buf || !buf_size || (buf_size < 6 + n->offset + 2)) return;
@@ -176,86 +206,102 @@ exif_mnote_data_canon_load (ExifMnoteData *ne,
/* 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);
+ o = 6 + 2 + n->offset + 12 * i;
+ if (o + 8 > buf_size) return;
+
+ t = exif_mem_realloc (ne->mem, n->entries,
+ sizeof (MnoteCanonEntry) * (i + 1));
+ if (!t) return;
+ n->count = i + 1;
+ n->entries = t;
+ 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;
+ ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) n;
+ unsigned int i, c;
+
+ for (i = c = 0; dc && (i < dc->count); i++)
+ c += mnote_canon_entry_count_values (&dc->entries[i]);
+ return c;
}
static unsigned int
-exif_mnote_data_canon_get_id (ExifMnoteData *d, unsigned int n)
+exif_mnote_data_canon_get_id (ExifMnoteData *d, unsigned int i)
{
- ExifMnoteDataCanon *note = (ExifMnoteDataCanon *) d;
+ ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) d;
+ unsigned int m;
- if (!note) return 0;
- if (note->count <= n) return 0;
- return note->entries[n].tag;
+ if (!dc) return 0;
+ exif_mnote_data_canon_get_tags (dc, i, &m, NULL);
+ if (m >= dc->count) return 0;
+ return dc->entries[m].tag;
}
static const char *
exif_mnote_data_canon_get_name (ExifMnoteData *note, unsigned int i)
{
- ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note;
+ ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
+ unsigned int m, s;
- if (!note) return NULL;
- if (i >= cnote->count) return NULL;
- return mnote_canon_tag_get_name (cnote->entries[i].tag);
+ if (!dc) return NULL;
+ exif_mnote_data_canon_get_tags (dc, i, &m, &s);
+ if (m >= dc->count) return NULL;
+ return mnote_canon_tag_get_name_sub (dc->entries[m].tag, s, dc->options);
}
static const char *
exif_mnote_data_canon_get_title (ExifMnoteData *note, unsigned int i)
{
- ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note;
+ ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
+ unsigned int m, s;
- if (!note) return NULL;
- if (i >= cnote->count) return NULL;
- return mnote_canon_tag_get_title (cnote->entries[i].tag);
+ if (!dc) return NULL;
+ exif_mnote_data_canon_get_tags (dc, i, &m, &s);
+ if (m >= dc->count) return NULL;
+ return mnote_canon_tag_get_title_sub (dc->entries[m].tag, s, dc->options);
}
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);
+ ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
+ unsigned int m;
+
+ if (!dc) return NULL;
+ exif_mnote_data_canon_get_tags (dc, i, &m, NULL);
+ if (m >= dc->count) return NULL;
+ return mnote_canon_tag_get_description (dc->entries[m].tag);
}
ExifMnoteData *
-exif_mnote_data_canon_new (ExifMem *mem)
+exif_mnote_data_canon_new (ExifMem *mem, ExifDataOption o)
{
ExifMnoteData *d;
+ ExifMnoteDataCanon *dc;
if (!mem) return NULL;
@@ -277,5 +323,7 @@ exif_mnote_data_canon_new (ExifMem *mem)
d->methods.get_description = exif_mnote_data_canon_get_description;
d->methods.get_value = exif_mnote_data_canon_get_value;
+ dc = (ExifMnoteDataCanon*)d;
+ dc->options = o;
return d;
}
diff --git a/src/libexif/canon/exif-mnote-data-canon.h b/src/libexif/canon/exif-mnote-data-canon.h
index a476ca0..6d46432 100644
--- a/src/libexif/canon/exif-mnote-data-canon.h
+++ b/src/libexif/canon/exif-mnote-data-canon.h
@@ -1,6 +1,6 @@
/* exif-mnote-data-canon.h
*
- * Copyright © 2002, 2003 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 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
@@ -25,6 +25,7 @@
#include <libexif/exif-mnote-data.h>
#include <libexif/exif-mnote-data-priv.h>
#include <libexif/exif-mem.h>
+#include <libexif/exif-data.h>
typedef struct _ExifMnoteDataCanon ExifMnoteDataCanon;
@@ -38,8 +39,10 @@ struct _ExifMnoteDataCanon {
ExifByteOrder order;
unsigned int offset;
+
+ ExifDataOption options;
};
-ExifMnoteData *exif_mnote_data_canon_new (ExifMem *mem);
+ExifMnoteData *exif_mnote_data_canon_new (ExifMem *mem, ExifDataOption o);
#endif /* __EXIF_MNOTE_DATA_CANON_H__ */
diff --git a/src/libexif/canon/mnote-canon-entry.c b/src/libexif/canon/mnote-canon-entry.c
index 5fa4991..2a206de 100644
--- a/src/libexif/canon/mnote-canon-entry.c
+++ b/src/libexif/canon/mnote-canon-entry.c
@@ -1,7 +1,7 @@
/* mnote-canon-entry.c
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
- * Copyright © 2003 Matthieu Castet <mat-c@users.sourceforge.net>
+ * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>
+ * Copyright (c) 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
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include <libexif/exif-format.h>
#include <libexif/exif-utils.h>
@@ -32,9 +33,6 @@
/* #define DEBUG */
-#undef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-
#define CF(format,target,v,maxlen) \
{ \
if (format != target) { \
@@ -67,470 +65,637 @@
} \
}
+#define UNDEFINED 0xFF
+
+static const struct canon_entry_table_t {
+ unsigned int subtag;
+ ExifShort value;
+ const char *name;
+} entries_settings_1 [] = {
+#ifndef NO_VERBOSE_TAG_DATA
+ { 0, 1, N_("Macro")},
+ { 0, 2, N_("Normal")},
+ { 2, 1, N_("Economy")},
+ { 2, 2, N_("Normal")},
+ { 2, 3, N_("Fine")},
+ { 2, 4, N_("RAW")},
+ { 2, 5, N_("Superfine")},
+ { 3, 0, N_("Off")},
+ { 3, 1, N_("Auto")},
+ { 3, 2, N_("On")},
+ { 3, 3, N_("Red-eye reduction")},
+ { 3, 4, N_("Slow synchro")},
+ { 3, 5, N_("Auto + Red-eye reduction")},
+ { 3, 6, N_("On + Red-eye reduction")},
+ { 3, 16, N_("External flash")},
+ { 4, 0, N_("Single")},
+ { 4, 1, N_("Continuous")},
+ { 4, 2, N_("Movie")},
+ { 4, 3, N_("Continuous, speed priority")},
+ { 4, 4, N_("Continuous, low")},
+ { 4, 5, N_("Continuous, high")},
+ { 6, 0, N_("One-shot AF")},
+ { 6, 1, N_("AI servo AF")},
+ { 6, 2, N_("AI focus AF")},
+ { 6, 3, N_("Manual focus")},
+ { 6, 4, N_("Single")},
+ { 6, 5, N_("Continuous")},
+ { 6, 6, N_("Manual focus")},
+ { 6, 16, N_("Pan focus")},
+ { 8, 1, N_("JPEG")},
+ { 8, 2, N_("CRW+THM")},
+ { 8, 3, N_("AVI+THM")},
+ { 8, 4, N_("TIF")},
+ { 8, 5, N_("TIF+JPEG")},
+ { 8, 6, N_("CR2")},
+ { 8, 7, N_("CR2+JPEG")},
+ { 9, 0, N_("Large")},
+ { 9, 1, N_("Medium")},
+ { 9, 2, N_("Small")},
+ { 9, 5, N_("Medium 1")},
+ { 9, 6, N_("Medium 2")},
+ { 9, 7, N_("Medium 3")},
+ { 9, 8, N_("Postcard")},
+ { 9, 9, N_("Widescreen")},
+ {10, 0, N_("Full auto")},
+ {10, 1, N_("Manual")},
+ {10, 2, N_("Landscape")},
+ {10, 3, N_("Fast shutter")},
+ {10, 4, N_("Slow shutter")},
+ {10, 5, N_("Night")},
+ {10, 6, N_("Grayscale")},
+ {10, 7, N_("Sepia")},
+ {10, 8, N_("Portrait")},
+ {10, 9, N_("Sports")},
+ {10, 10, N_("Macro")},
+ {10, 11, N_("Black & white")},
+ {10, 12, N_("Pan focus")},
+ {10, 13, N_("Vivid")},
+ {10, 14, N_("Neutral")},
+ {10, 15, N_("Flash off")},
+ {10, 16, N_("Long shutter")},
+ {10, 17, N_("Super macro")},
+ {10, 18, N_("Foliage")},
+ {10, 19, N_("Indoor")},
+ {10, 20, N_("Fireworks")},
+ {10, 21, N_("Beach")},
+ {10, 22, N_("Underwater")},
+ {10, 23, N_("Snow")},
+ {10, 24, N_("Kids & pets")},
+ {10, 25, N_("Night snapshot")},
+ {10, 26, N_("Digital macro")},
+ {10, 27, N_("My colors")},
+ {10, 28, N_("Still image")},
+ {10, 30, N_("Color accent")},
+ {10, 31, N_("Color swap")},
+ {10, 32, N_("Aquarium")},
+ {10, 33, N_("ISO 3200")},
+ {11, 0, N_("None")},
+ {11, 1, N_("2x")},
+ {11, 2, N_("4x")},
+ {11, 3, N_("Other")},
+ {12, 0x0000, N_("Normal")},
+ {12, 0x0001, N_("High")},
+ {12, 0xffff, N_("Low")},
+ {13, 0x0000, N_("Normal")},
+ {13, 0x0001, N_("High")},
+ {13, 0xffff, N_("Low")},
+ {14, 0x0000, N_("Normal")},
+ {14, 0x0001, N_("High")},
+ {14, 0xffff, N_("Low")},
+ {15, 14, N_("Auto high")},
+ {15, 15, N_("Auto")},
+ {15, 16, N_("50")},
+ {15, 17, N_("100")},
+ {15, 18, N_("200")},
+ {15, 19, N_("400")},
+ {15, 20, N_("800")},
+ {16, 0, N_("Default")},
+ {16, 1, N_("Spot")},
+ {16, 2, N_("Average")},
+ {16, 3, N_("Evaluative")},
+ {16, 4, N_("Partial")},
+ {16, 5, N_("Center-weighted average")},
+ {17, 0, N_("Manual")},
+ {17, 1, N_("Auto")},
+ {17, 2, N_("Not known")},
+ {17, 3, N_("Macro")},
+ {17, 4, N_("Very close")},
+ {17, 5, N_("Close")},
+ {17, 6, N_("Middle range")},
+ {17, 7, N_("Far range")},
+ {17, 8, N_("Pan focus")},
+ {17, 9, N_("Super macro")},
+ {17, 10, N_("Infinity")},
+ {18, 0x2005, N_("Manual AF point selection")},
+ {18, 0x3000, N_("None (MF)")},
+ {18, 0x3001, N_("Auto-selected")},
+ {18, 0x3002, N_("Right")},
+ {18, 0x3003, N_("Center")},
+ {18, 0x3004, N_("Left")},
+ {18, 0x4001, N_("Auto AF point selection")},
+ {19, 0, N_("Easy shooting")},
+ {19, 1, N_("Program")},
+ {19, 2, N_("Tv-priority")},
+ {19, 3, N_("Av-priority")},
+ {19, 4, N_("Manual")},
+ {19, 5, N_("A-DEP")},
+ {19, 6, N_("M-DEP")},
+ {21, 1, N_("Canon EF 50mm f/1.8")},
+ {21, 2, N_("Canon EF 28mm f/2.8")},
+ {21, 4, N_("Sigma UC Zoom 35-135mm f/4-5.6")},
+ {21, 6, N_("Tokina AF193-2 19-35mm f/3.5-4.5")},
+ {21, 7, N_("Canon EF 100-300mm F5.6L")},
+ {21, 10, N_("Sigma 50mm f/2.8 EX or 28mm f/1.8")},
+ {21, 11, N_("Canon EF 35mm f/2")},
+ {21, 13, N_("Canon EF 15mm f/2.8")},
+ {21, 21, N_("Canon EF 80-200mm f/2.8L")},
+ {21, 22, N_("Tokina AT-X280AF PRO 28-80mm F2.8 ASPHERICAL")},
+ {21, 26, N_("Cosina 100mm f/3.5 Macro AF")},
+ {21, 28, N_("Tamron AF Aspherical 28-200mm f/3.8-5.6")},
+ {21, 29, N_("Canon EF 50mm f/1.8 MkII")},
+ {21, 31, N_("Tamron SP AF 300mm f/2.8 LD IF")},
+ {21, 32, N_("Canon EF 24mm f/2.8 or Sigma 15mm f/2.8 EX Fisheye")},
+ {21, 39, N_("Canon EF 75-300mm f/4-5.6")},
+ {21, 40, N_("Canon EF 28-80mm f/3.5-5.6")},
+ {21, 43, N_("Canon EF 28-105mm f/4-5.6")},
+ {21, 45, N_("Canon EF-S 18-55mm f/3.5-5.6")},
+ {21, 124, N_("Canon MP-E 65mm f/2.8 1-5x Macro Photo")},
+ {21, 125, N_("Canon TS-E 24mm f/3.5L")},
+ {21, 126, N_("Canon TS-E 45mm f/2.8")},
+ {21, 127, N_("Canon TS-E 90mm f/2.8")},
+ {21, 130, N_("Canon EF 50mm f/1.0L")},
+ {21, 131, N_("Sigma 17-35mm f2.8-4 EX Aspherical HSM")},
+ {21, 134, N_("Canon EF 600mm f/4L IS")},
+ {21, 135, N_("Canon EF 200mm f/1.8L")},
+ {21, 136, N_("Canon EF 300mm f/2.8L")},
+ {21, 137, N_("Canon EF 85mm f/1.2L")},
+ {21, 139, N_("Canon EF 400mm f/2.8L")},
+ {21, 141, N_("Canon EF 500mm f/4.5L")},
+ {21, 142, N_("Canon EF 300mm f/2.8L IS")},
+ {21, 143, N_("Canon EF 500mm f/4L IS")},
+ {21, 149, N_("Canon EF 100mm f/2")},
+ {21, 150, N_("Sigma 20mm EX f/1.8")},
+ {21, 151, N_("Canon EF 200mm f/2.8L")},
+ {21, 152, N_("Sigma 10-20mm F4-5.6 or 12-24mm f/4.5-5.6 or 14mm f/2.8")},
+ {21, 153, N_("Canon EF 35-350mm f/3.5-5.6L")},
+ {21, 155, N_("Canon EF 85mm f/1.8 USM")},
+ {21, 156, N_("Canon EF 28-105mm f/3.5-4.5 USM")},
+ {21, 160, N_("Canon EF 20-35mm f/3.5-4.5 USM")},
+ {21, 161, N_("Canon EF 28-70mm f/2.8L or Sigma 24-70mm EX f/2.8")},
+ {21, 165, N_("Canon EF 70-200mm f/2.8 L")},
+ {21, 166, N_("Canon EF 70-200mm f/2.8 L + x1.4")},
+ {21, 167, N_("Canon EF 70-200mm f/2.8 L + x2")},
+ {21, 168, N_("Canon EF 28mm f/1.8 USM")},
+ {21, 169, N_("Sigma 15-30mm f/3.5-4.5 EX DG Aspherical")},
+ {21, 170, N_("Canon EF 200mm f/2.8L II")},
+ {21, 173, N_("Canon EF 180mm Macro f/3.5L or Sigma 180mm EX HSM Macro f/3.5")},
+ {21, 174, N_("Canon EF 135mm f/2L")},
+ {21, 176, N_("Canon EF 24-85mm f/3.5-4.5 USM")},
+ {21, 177, N_("Canon EF 300mm f/4L IS")},
+ {21, 178, N_("Canon EF 28-135mm f/3.5-5.6 IS")},
+ {21, 180, N_("Canon EF 35mm f/1.4L")},
+ {21, 181, N_("Canon EF 100-400mm f/4.5-5.6L IS + x1.4")},
+ {21, 182, N_("Canon EF 100-400mm f/4.5-5.6L IS + x2")},
+ {21, 183, N_("Canon EF 100-400mm f/4.5-5.6L IS")},
+ {21, 184, N_("Canon EF 400mm f/2.8L + x2")},
+ {21, 186, N_("Canon EF 70-200mm f/4L")},
+ {21, 190, N_("Canon EF 100mm f/2.8 Macro")},
+ {21, 191, N_("Canon EF 400mm f/4 DO IS")},
+ {21, 197, N_("Canon EF 75-300mm f/4-5.6 IS")},
+ {21, 198, N_("Canon EF 50mm f/1.4")},
+ {21, 202, N_("Canon EF 28-80 f/3.5-5.6 USM IV")},
+ {21, 211, N_("Canon EF 28-200mm f/3.5-5.6")},
+ {21, 213, N_("Canon EF 90-300mm f/4.5-5.6")},
+ {21, 214, N_("Canon EF-S 18-55mm f/3.5-4.5 USM")},
+ {21, 224, N_("Canon EF 70-200mm f/2.8L IS USM")},
+ {21, 225, N_("Canon EF 70-200mm f/2.8L IS USM + x1.4")},
+ {21, 226, N_("Canon EF 70-200mm f/2.8L IS USM + x2")},
+ {21, 229, N_("Canon EF 16-35mm f/2.8L")},
+ {21, 230, N_("Canon EF 24-70mm f/2.8L")},
+ {21, 231, N_("Canon EF 17-40mm f/4L")},
+ {21, 232, N_("Canon EF 70-300mm f/4.5-5.6 DO IS USM")},
+ {21, 234, N_("Canon EF-S 17-85mm f4-5.6 IS USM")},
+ {21, 235, N_("Canon EF-S10-22mm F3.5-4.5 USM")},
+ {21, 236, N_("Canon EF-S60mm F2.8 Macro USM")},
+ {21, 237, N_("Canon EF 24-105mm f/4L IS")},
+ {21, 238, N_("Canon EF 70-300mm F4-5.6 IS USM")},
+ {21, 241, N_("Canon EF 50mm F1.2L USM")},
+ {21, 242, N_("Canon EF 70-200mm f/4L IS USM")},
+ {28, 0, N_("Manual")},
+ {28, 1, N_("TTL")},
+ {28, 2, N_("A-TTL")},
+ {28, 3, N_("E-TTL")},
+ {28, 4, N_("FP sync enabled")},
+ {28, 7, N_("2nd-curtain sync used")},
+ {28, 11, N_("FP sync used")},
+ {28, 13, N_("Internal")},
+ {28, 14, N_("External")},
+ {31, 0, N_("Single")},
+ {31, 1, N_("Continuous")},
+ {32, 0, N_("Normal AE")},
+ {32, 1, N_("Exposure compensation")},
+ {32, 2, N_("AE lock")},
+ {32, 3, N_("AE lock + Exposure compensation")},
+ {32, 4, N_("No AE")},
+ {33, 0, N_("Off")},
+ {33, 1, N_("On")},
+ {33, 2, N_("On, shot only")},
+ {39, 0, N_("Off")},
+ {39, 1, N_("Vivid")},
+ {39, 2, N_("Neutral")},
+ {39, 3, N_("Smooth")},
+ {39, 4, N_("Sepia")},
+ {39, 5, N_("Black & white")},
+ {39, 6, N_("Custom")},
+ {39, 100, N_("My color data")},
+ {40, 0, N_("Off")},
+ {40, 0x0500, N_("Full")},
+ {40, 0x0502, N_("2/3")},
+ {40, 0x0504, N_("1/3")},
+#endif
+ { 0, 0, NULL}
+},
+entries_focal_length [] = {
+#ifndef NO_VERBOSE_TAG_DATA
+ {0, 1, N_("Fixed")},
+ {0, 2, N_("Zoom")},
+#endif
+ {0, 0, NULL}
+},
+entries_settings_2 [] = {
+#ifndef NO_VERBOSE_TAG_DATA
+ { 6, 0, N_("Auto")},
+ { 6, 1, N_("Sunny")},
+ { 6, 2, N_("Cloudy")},
+ { 6, 3, N_("Tungsten")},
+ { 6, 4, N_("Fluorescent")},
+ { 6, 5, N_("Flash")},
+ { 6, 6, N_("Custom")},
+ { 6, 7, N_("Black & white")},
+ { 6, 8, N_("Shade")},
+ { 6, 9, N_("Manual temperature (Kelvin)")},
+ { 6, 10, N_("PC set 1")},
+ { 6, 11, N_("PC set 2")},
+ { 6, 12, N_("PC set 3")},
+ { 6, 14, N_("Daylight fluorescent")},
+ { 6, 15, N_("Custom 1")},
+ { 6, 16, N_("Custom 2")},
+ { 6, 17, N_("Underwater")},
+ { 7, 0, N_("Off")},
+ { 7, 1, N_("Night scene")},
+ { 7, 2, N_("On")},
+ { 7, 3, N_("None")},
+ { 13, 0x3000, N_("None (MF)")},
+ { 13, 0x3001, N_("Right")},
+ { 13, 0x3002, N_("Center")},
+ { 13, 0x3003, N_("Center + Right")},
+ { 13, 0x3004, N_("Left")},
+ { 13, 0x3005, N_("Left + Right")},
+ { 13, 0x3006, N_("Left + Center")},
+ { 13, 0x3007, N_("All")},
+ { 15, 0, N_("Off")},
+ { 15, 1, N_("On (shot 1)")},
+ { 15, 2, N_("On (shot 2)")},
+ { 15, 3, N_("On (shot 3)")},
+ { 15, 0xffff, N_("On")},
+ { 25, 248, N_("EOS high-end")},
+ { 25, 250, N_("Compact")},
+ { 25, 252, N_("EOS mid-range")},
+ { 26, 0, N_("None")},
+ { 26, 1, N_("Rotate 90 CW")},
+ { 26, 2, N_("Rotate 180")},
+ { 26, 3, N_("Rotate 270 CW")},
+ { 26, 0xffff, N_("Rotated by software")},
+ { 27, 0, N_("Off")},
+ { 27, 1, N_("On")},
+ { 32, 0, N_("Off")},
+ { 32, 0x0014, N_("1/3")},
+ { 32, 0x008c, N_("2/3")},
+ { 32, 0x07d0, N_("Full")},
+#endif
+ {0, 0, NULL}
+},
+entries_panorama [] = {
+#ifndef NO_VERBOSE_TAG_DATA
+ {0, 0, N_("Left to right")},
+ {0, 1, N_("Right to left")},
+ {0, 2, N_("Bottom to top")},
+ {0, 3, N_("Top to bottom")},
+ {0, 4, N_("2x2 matrix (clockwise)")},
+#endif
+ {0, 0, NULL}
+},
+color_information [] = {
+#ifndef NO_VERBOSE_TAG_DATA
+ {0, 0, N_("Standard")},
+ {0, 1, N_("Manual")},
+ {0, 2, N_("Custom")},
+ {2, 0, N_("N/A")},
+ {2, 1, N_("Lowest")},
+ {2, 2, N_("Low")},
+ {2, 3, N_("Standard")},
+ {2, 4, N_("High")},
+ {2, 5, N_("Highest")},
+ {7, 0, N_("Auto")},
+ {7, 1, N_("Daylight")},
+ {7, 2, N_("Cloudy")},
+ {7, 3, N_("Tungsten")},
+ {7, 4, N_("Fluorescent")},
+ {7, 5, N_("Flash")},
+ {7, 6, N_("Custom")},
+ {7, 7, N_("Black & White")},
+ {7, 8, N_("Shade")},
+ {7, 9, N_("Manual Temperature (Kelvin)")},
+ {7, 10, N_("PC Set1")},
+ {7, 11, N_("PC Set2")},
+ {7, 12, N_("PC Set3")},
+ {7, 14, N_("Daylight Fluorescent")},
+ {7, 15, N_("Custom 1")},
+ {7, 16, N_("Custom 2")},
+ {7, 17, N_("Underwater")},
+ {9, 0x00, N_("None")},
+ {9, 0x01, N_("Standard")},
+ {9, 0x02, N_("Set 1")},
+ {9, 0x03, N_("Set 2")},
+ {9, 0x04, N_("Set 3")},
+ {9, 0x21, N_("User Def. 1")},
+ {9, 0x22, N_("User Def. 2")},
+ {9, 0x23, N_("User Def. 3")},
+ {9, 0x41, N_("External 1")},
+ {9, 0x42, N_("External 2")},
+ {9, 0x43, N_("External 3")},
+ {9, 0x81, N_("Standard")},
+ {9, 0x82, N_("Portrait")},
+ {9, 0x83, N_("Landscape")},
+ {9, 0x84, N_("Neutral")},
+ {9, 0x85, N_("Faithful")},
+ {9, 0x86, N_("Monochrome")},
+#endif
+ {0, 0, NULL}
+};
+
+static void
+canon_search_table_value (const struct canon_entry_table_t table[],
+ unsigned int t, ExifShort vs, char *val, unsigned int maxlen)
+{
+ unsigned int j;
+
+ /* Search the table for the first matching subtag and value. */
+ for (j = 0; table[j].name && ((table[j].subtag < t) ||
+ ((table[j].subtag == t) && table[j].value <= vs)); j++) {
+ if ((table[j].subtag == t) && (table[j].value == vs)) {
+ break;
+ }
+ }
+ if ((table[j].subtag == t) && (table[j].value == vs) && table[j].name) {
+ /* Matching subtag and value found. */
+ strncpy (val, _(table[j].name), maxlen);
+ } else {
+ /* No matching subtag and/or value found. */
+ snprintf (val, maxlen, "0x%04x", vs);
+ }
+}
+
+static void
+canon_search_table_bitfield (const struct canon_entry_table_t table[],
+ unsigned int t, ExifShort vs, char *val, unsigned int maxlen)
+{
+ unsigned int j;
+
+ /* Search the table for the first matching subtag. */
+ for (j = 0; table[j].name && (table[j].subtag <= t); j++) {
+ if (table[j].subtag == t) {
+ break;
+ }
+ }
+ if ((table[j].subtag == t) && table[j].name) {
+ unsigned int i, bit, lastbit = 0;
+
+ /*
+ * Search the table for the last matching bit, because
+ * that one needs no additional comma appended.
+ */
+ for (i = j; table[i].name && (table[i].subtag == t); i++) {
+ bit = table[i].value;
+ if ((vs >> bit) & 1) {
+ lastbit = bit;
+ }
+ }
+ /* Search the table for all matching bits. */
+ for (i = j; table[i].name && (table[i].subtag == t); i++) {
+ bit = table[i].value;
+ if ((vs >> bit) & 1) {
+ strncat(val, table[i].name, maxlen - strlen (val));
+ if (bit != lastbit)
+ strncat (val, N_(", "), maxlen - strlen (val));
+ }
+ }
+ } else {
+ /* No matching subtag found. */
+ snprintf (val, maxlen, "0x%04x", vs);
+ }
+}
+
+unsigned int
+mnote_canon_entry_count_values (const MnoteCanonEntry *entry)
+{
+ unsigned int val;
+
+ if (!entry) return 0;
+
+ switch (entry->tag) {
+ case MNOTE_CANON_TAG_FOCAL_LENGTH:
+ case MNOTE_CANON_TAG_PANORAMA:
+ return entry->components;
+ case MNOTE_CANON_TAG_SETTINGS_1:
+ case MNOTE_CANON_TAG_SETTINGS_2:
+ case MNOTE_CANON_TAG_CUSTOM_FUNCS:
+ case MNOTE_CANON_TAG_COLOR_INFORMATION:
+ if (entry->format != EXIF_FORMAT_SHORT) return 0;
+
+ val = exif_get_short (entry->data, entry->order);
+ /* val is buffer size, i.e. # of values plus 1 */
+ return MIN (entry->size - 2, val) / 2;
+ default:
+ return 1;
+ }
+}
+
+/*
+ * For reference, see Exif 2.1 specification (Appendix C),
+ * or http://en.wikipedia.org/wiki/APEX_system
+ */
+static double
+apex_value_to_aperture (double x)
+{
+ return pow (2, x / 2.);
+}
+
+static double
+apex_value_to_shutter_speed(double x)
+{
+ return 1.0 / pow (2, x);
+}
+
+static double
+apex_value_to_iso_speed (double x)
+{
+ return 3.125 * pow (2, x);
+}
+
char *
-mnote_canon_entry_get_value (const MnoteCanonEntry *entry, char *val, unsigned int maxlen)
+mnote_canon_entry_get_value (const MnoteCanonEntry *entry, unsigned int t, char *val, unsigned int maxlen)
{
- char buf[128];
- ExifLong vl;
- ExifShort vs, n;
- int i;
- unsigned char *data = entry->data;
+ char buf[128];
+ ExifLong vl;
+ ExifShort vs, n;
+ unsigned char *data;
+ double d;
- if (!entry) return NULL;
+ if (!entry)
+ return NULL;
- memset (val, 0, maxlen);
- maxlen--;
+ data = entry->data;
+
+ 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;
+ if (t >= n) return NULL;
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));
+ vs = exif_get_short (data + 2 + t * 2, entry->order);
+ switch (t) {
+ case 1:
+ if (!vs) {
+ strncpy(val, _("Off"), maxlen);
+ break;
}
+ snprintf (val, maxlen, _("%i (ms)"), vs * 100);
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));
+ case 15:
+ if (((vs & 0xC000) == 0x4000) && (vs != 0x7FFF)) {
+ /* Canon S3 IS - directly specified value */
+ snprintf (val, maxlen, _("%i"), vs & ~0x4000);
+ } else {
+ /* Standard Canon - index into lookup table */
+ canon_search_table_value (entries_settings_1, t, vs, val, maxlen);
}
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));
- }
+ case 22:
+ case 23:
+ case 24:
+ snprintf (val, maxlen, "%u", vs);
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));
- }
+ case 25:
+ case 26:
+ snprintf (val, maxlen, "%.2f", apex_value_to_aperture (vs / 32.0));
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));
- }
+ case 28:
+ canon_search_table_bitfield(entries_settings_1, t, vs, val, maxlen);
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));
- }
+ case 34:
+ snprintf (val, maxlen, "%.2f", vs / 10.0);
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));
- }
+ case 35:
+ case 36:
+ snprintf (val, maxlen, "%u", vs);
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));
- }
+ default:
+ canon_search_table_value (entries_settings_1, t, vs, val, maxlen);
+ }
+ break;
+
+ case MNOTE_CANON_TAG_FOCAL_LENGTH:
+ CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
+ vs = exif_get_short (data + t * 2, entry->order);
+ switch (t) {
+ case 1:
+ snprintf (val, maxlen, "%u", vs);
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));
- }
+ case 2:
+ case 3:
+ snprintf (val, maxlen, _("%.2f mm"), vs * 25.4 / 1000);
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
- }
+ default:
+ canon_search_table_value (entries_focal_length, t, vs, val, maxlen);
}
-
- break;
+ 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;
+ n = exif_get_short (data, entry->order) / 2;
+ if (t >= n) return NULL;
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));
+ vs = exif_get_short (data + 2 + t * 2, entry->order);
+ switch (t) {
+ case 0:
+ snprintf (val, maxlen, "%.3f", pow (2, (ExifSShort)vs / 32.0));
+ break;
+ case 1:
+ snprintf (val, maxlen, "%.0f", apex_value_to_iso_speed ((ExifSShort)vs / 32.0));
+ break;
+ case 2:
+ case 5:
+ case 14:
+ case 16:
+ snprintf (val, maxlen, _("%.2f EV"), vs / 32.0);
+ break;
+ case 3:
+ case 20:
+ snprintf (val, maxlen, "%.2f", apex_value_to_aperture (vs / 32.0));
+ break;
+ case 4:
+ case 21:
+ d = apex_value_to_shutter_speed ((ExifSShort)vs / 32.0);
+ if (d < 1)
+ snprintf (val, maxlen, _("1/%d"),(int)(1.0 / d));
+ else
+ snprintf (val, maxlen, _("%d"), (int) d);
+ break;
+ case 8:
+ snprintf (val, maxlen, "%u", vs);
+ break;
+ case 12:
+ snprintf (val, maxlen, "%.2f", vs / 32.0);
+ break;
+ case 18:
+ case 19:
+ snprintf (val, maxlen, _("%u mm"), vs);
+ break;
+ case 28:
+ if ((ExifSShort)vs <= 0) {
+ strncpy(val, _("Off"), maxlen);
break;
-#ifdef DEBUG
- default:
- printf ("Value%d=%d\n", i, vs);
-#endif
}
+ snprintf (val, maxlen, _("%i (ms)"), vs * 100);
+ break;
+ default:
+ canon_search_table_value (entries_settings_2, t, vs, val, maxlen);
}
+ break;
+ case MNOTE_CANON_TAG_PANORAMA:
+ CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
+ vs = exif_get_short (data + t * 2, entry->order);
+ canon_search_table_value (entries_panorama, t, vs, val, maxlen);
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));
+ /* Fall through; ImageType can have many sizes */
+ case MNOTE_CANON_TAG_IMAGE_TYPE:
+ CF (entry->format, EXIF_FORMAT_ASCII, val, maxlen);
+ strncpy (val, (char *)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));
+/* CC2 (entry->components, 24, 32, val, maxlen); Can also be 22 */
+ strncpy (val, (char *)data, MIN (entry->size, maxlen));
break;
case MNOTE_CANON_TAG_IMAGE_NUMBER:
@@ -551,23 +716,27 @@ mnote_canon_entry_get_value (const MnoteCanonEntry *entry, char *val, unsigned i
case MNOTE_CANON_TAG_CUSTOM_FUNCS:
CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
- n = exif_get_short (data, entry->order)/2;
- data+=2;
+ n = exif_get_short (data, entry->order) / 2;
+ if (t >= n) return NULL;
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));
- }
+ vs = exif_get_short (data + 2 + t * 2, entry->order);
+ snprintf (buf, sizeof (buf), "%u", vs);
+ strncat (val, buf, maxlen - strlen (val));
+ break;
+
+ case MNOTE_CANON_TAG_COLOR_INFORMATION:
+ CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
+ n = exif_get_short (data, entry->order) / 2;
+ if (t >= n) return NULL;
+ CC (entry->components, n, val, maxlen);
+ vs = exif_get_short (data + 2 + t * 2, entry->order);
+ canon_search_table_value (color_information, t, vs, val, maxlen);
break;
default:
#ifdef DEBUG
+ {
+ int i;
if (entry->format == EXIF_FORMAT_SHORT)
for(i=0;i<entry->components;i++) {
vs = exif_get_short (data, entry->order);
@@ -582,9 +751,9 @@ mnote_canon_entry_get_value (const MnoteCanonEntry *entry, char *val, unsigned i
}
else if (entry->format == EXIF_FORMAT_ASCII)
strncpy (val, data, MIN (entry->size, maxlen));
+ }
#endif
break;
- }
-
- return val;
+ }
+ return val;
}
diff --git a/src/libexif/canon/mnote-canon-entry.h b/src/libexif/canon/mnote-canon-entry.h
index 62345d8..e78c639 100644
--- a/src/libexif/canon/mnote-canon-entry.h
+++ b/src/libexif/canon/mnote-canon-entry.h
@@ -1,6 +1,6 @@
/* mnote-canon-entry.h
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -38,6 +38,7 @@ struct _MnoteCanonEntry {
ExifByteOrder order;
};
-char *mnote_canon_entry_get_value (const MnoteCanonEntry *entry, char *val, unsigned int maxlen);
+unsigned int mnote_canon_entry_count_values (const MnoteCanonEntry *);
+char *mnote_canon_entry_get_value (const MnoteCanonEntry *, unsigned int t, 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
index 890a5fc..447caab 100644
--- a/src/libexif/canon/mnote-canon-tag.c
+++ b/src/libexif/canon/mnote-canon-tag.c
@@ -1,6 +1,6 @@
/* mnote-canon-tag.c
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -25,34 +25,137 @@
#include <libexif/i18n.h>
-static struct {
+static const struct {
MnoteCanonTag tag;
const char *name;
const char *title;
const char *description;
} table[] = {
+#ifndef NO_VERBOSE_TAG_STRINGS
{MNOTE_CANON_TAG_SETTINGS_1, "Settings1", N_("Settings (first part)"), ""},
+ {MNOTE_CANON_TAG_FOCAL_LENGTH, "FocalLength", N_("Focal length"), ""},
{MNOTE_CANON_TAG_SETTINGS_2, "Settings2", N_("Settings (second part)"), ""},
+ {MNOTE_CANON_TAG_PANORAMA, "Panorama", N_("Panorama"), ""},
{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_COLOR_INFORMATION, "ColorInformation", N_("Color information"), ""},
{MNOTE_CANON_TAG_SERIAL_NUMBER, "SerialNumber", N_("Serial number"), ""},
{MNOTE_CANON_TAG_CUSTOM_FUNCS, "CustomFunctions", N_("Custom functions"), ""},
+#endif
{0, NULL, NULL, NULL}
};
+static const struct {
+ MnoteCanonTag tag;
+ unsigned int subtag;
+ const char *name;
+} table_sub[] = {
+#ifndef NO_VERBOSE_TAG_STRINGS
+ {MNOTE_CANON_TAG_SETTINGS_1, 0, N_("Macro mode")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 1, N_("Self-timer")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 2, N_("Quality")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 3, N_("Flash mode")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 4, N_("Drive mode")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 6, N_("Focus mode")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 8, N_("Record mode")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 9, N_("Image size")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 10, N_("Easy shooting mode")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 11, N_("Digital zoom")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 12, N_("Contrast")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 13, N_("Saturation")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 14, N_("Sharpness")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 15, N_("ISO")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 16, N_("Metering mode")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 17, N_("Focus range")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 18, N_("AF point")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 19, N_("Exposure mode")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 21, N_("Lens type")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 22, N_("Long focal length of lens")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 23, N_("Short focal length of lens")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 24, N_("Focal units per mm")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 25, N_("Maximal aperture")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 26, N_("Minimal aperture")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 27, N_("Flash activity")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 28, N_("Flash details")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 31, N_("Focus mode")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 32, N_("AE setting")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 33, N_("Image stabilization")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 34, N_("Display aperture")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 35, N_("Zoom source width")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 36, N_("Zoom target width")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 39, N_("Photo effect")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 40, N_("Manual flash output")},
+ {MNOTE_CANON_TAG_SETTINGS_1, 41, N_("Color tone")},
+ {MNOTE_CANON_TAG_FOCAL_LENGTH, 0, N_("Focal type")},
+ {MNOTE_CANON_TAG_FOCAL_LENGTH, 1, N_("Focal length")},
+ {MNOTE_CANON_TAG_FOCAL_LENGTH, 2, N_("Focal plane x size")},
+ {MNOTE_CANON_TAG_FOCAL_LENGTH, 3, N_("Focal plane y size")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 0, N_("Auto ISO")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 1, N_("Shot ISO")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 2, N_("Measured EV")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 3, N_("Target aperture")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 4, N_("Target exposure time")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 5, N_("Exposure compensation")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 6, N_("White balance")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 7, N_("Slow shutter")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 8, N_("Sequence number")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 12, N_("Flash guide number")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 13, N_("AF point")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 14, N_("Flash exposure compensation")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 15, N_("AE bracketing")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 16, N_("AE bracket value")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 18, N_("Focus distance upper")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 19, N_("Focus distance lower")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 20, N_("FNumber")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 21, N_("Exposure time")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 23, N_("Bulb duration")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 25, N_("Camera type")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 26, N_("Auto rotate")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 27, N_("ND filter")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 28, N_("Self-timer")},
+ {MNOTE_CANON_TAG_SETTINGS_2, 32, N_("Manual flash output")},
+ {MNOTE_CANON_TAG_PANORAMA, 2, N_("Panorama frame")},
+ {MNOTE_CANON_TAG_PANORAMA, 5, N_("Panorama direction")},
+ {MNOTE_CANON_TAG_COLOR_INFORMATION, 0, N_("Tone curve")},
+ {MNOTE_CANON_TAG_COLOR_INFORMATION, 2, N_("Sharpness frequency")},
+ {MNOTE_CANON_TAG_COLOR_INFORMATION, 7, N_("White balance")},
+ {MNOTE_CANON_TAG_COLOR_INFORMATION, 9, N_("Picture style")},
+#endif
+ {0, 0, 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));
+ if (table[i].tag == t) return table[i].name; /* do not translate */
return NULL;
}
const char *
+mnote_canon_tag_get_name_sub (MnoteCanonTag t, unsigned int s, ExifDataOption o)
+{
+ unsigned int i;
+ int tag_found = 0;
+
+ for (i = 0; i < sizeof (table_sub) / sizeof (table_sub[0]); i++) {
+ if (table_sub[i].tag == t) {
+ if (table_sub[i].subtag == s)
+ return table_sub[i].name;
+ tag_found = 1;
+ }
+ }
+ if (!tag_found || !(o & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS))
+ return mnote_canon_tag_get_name (t);
+ else
+ return NULL;
+}
+
+const char *
mnote_canon_tag_get_title (MnoteCanonTag t)
{
unsigned int i;
@@ -64,12 +167,35 @@ mnote_canon_tag_get_title (MnoteCanonTag t)
}
const char *
+mnote_canon_tag_get_title_sub (MnoteCanonTag t, unsigned int s, ExifDataOption o)
+{
+ unsigned int i;
+ int tag_found = 0;
+
+ for (i = 0; i < sizeof (table_sub) / sizeof (table_sub[0]); i++) {
+ if (table_sub[i].tag == t) {
+ if (table_sub[i].subtag == s)
+ return _(table_sub[i].name);
+ tag_found = 1;
+ }
+ }
+ if (!tag_found || !(o & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS))
+ return mnote_canon_tag_get_title (t);
+ else
+ 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));
+ if (table[i].tag == t) {
+ if (!*table[i].description)
+ return "";
+ return (_(table[i].description));
+ }
return NULL;
}
diff --git a/src/libexif/canon/mnote-canon-tag.h b/src/libexif/canon/mnote-canon-tag.h
index ce1a72e..aead76e 100644
--- a/src/libexif/canon/mnote-canon-tag.h
+++ b/src/libexif/canon/mnote-canon-tag.h
@@ -1,6 +1,6 @@
/* mnote-canon-tag.h
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -21,6 +21,8 @@
#ifndef __MNOTE_CANON_TAG_H__
#define __MNOTE_CANON_TAG_H__
+#include <libexif/exif-data.h>
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -28,8 +30,10 @@ extern "C" {
enum _MnoteCanonTag {
MNOTE_CANON_TAG_UNKNOWN_0 = 0x0,
MNOTE_CANON_TAG_SETTINGS_1 = 0x1,
+ MNOTE_CANON_TAG_FOCAL_LENGTH = 0x2,
MNOTE_CANON_TAG_UNKNOWN_3 = 0x3,
MNOTE_CANON_TAG_SETTINGS_2 = 0x4,
+ MNOTE_CANON_TAG_PANORAMA = 0x5,
MNOTE_CANON_TAG_IMAGE_TYPE = 0x6,
MNOTE_CANON_TAG_FIRMWARE = 0x7,
MNOTE_CANON_TAG_IMAGE_NUMBER = 0x8,
@@ -37,13 +41,16 @@ enum _MnoteCanonTag {
MNOTE_CANON_TAG_UNKNOWN_10 = 0xa,
MNOTE_CANON_TAG_SERIAL_NUMBER = 0xc,
MNOTE_CANON_TAG_UNKNOWN_13 = 0xd,
- MNOTE_CANON_TAG_CUSTOM_FUNCS = 0xf
+ MNOTE_CANON_TAG_CUSTOM_FUNCS = 0xf,
+ MNOTE_CANON_TAG_COLOR_INFORMATION = 0xa0
};
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);
+const char *mnote_canon_tag_get_name (MnoteCanonTag);
+const char *mnote_canon_tag_get_name_sub (MnoteCanonTag, unsigned int, ExifDataOption);
+const char *mnote_canon_tag_get_title (MnoteCanonTag);
+const char *mnote_canon_tag_get_title_sub (MnoteCanonTag, unsigned int, ExifDataOption);
+const char *mnote_canon_tag_get_description (MnoteCanonTag);
#ifdef __cplusplus
}
diff --git a/src/libexif/exif-byte-order.c b/src/libexif/exif-byte-order.c
index 1a4279f..444fece 100644
--- a/src/libexif/exif-byte-order.c
+++ b/src/libexif/exif-byte-order.c
@@ -1,6 +1,6 @@
/* exif-byte-order.c
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
diff --git a/src/libexif/exif-byte-order.h b/src/libexif/exif-byte-order.h
index bd51d3c..a7c98c9 100644
--- a/src/libexif/exif-byte-order.h
+++ b/src/libexif/exif-byte-order.h
@@ -1,6 +1,6 @@
/* exif-byte-order.h
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
diff --git a/src/libexif/exif-content.c b/src/libexif/exif-content.c
index 39d73ad..c763751 100644
--- a/src/libexif/exif-content.c
+++ b/src/libexif/exif-content.c
@@ -1,6 +1,6 @@
/* exif-content.c
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
@@ -21,12 +21,15 @@
#include <config.h>
#include <libexif/exif-content.h>
+#include <libexif/exif-system.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+/* unused constant
+ * static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+ */
struct _ExifContentPrivate
{
@@ -120,7 +123,7 @@ exif_content_dump (ExifContent *content, unsigned int indent)
if (!content)
return;
- printf ("%sDumping exif content (%i entries)...\n", buf,
+ printf ("%sDumping exif content (%u entries)...\n", buf,
content->count);
for (i = 0; i < content->count; i++)
exif_entry_dump (content->entries[i], indent + 1);
@@ -129,6 +132,7 @@ exif_content_dump (ExifContent *content, unsigned int indent)
void
exif_content_add_entry (ExifContent *c, ExifEntry *entry)
{
+ ExifEntry **entries;
if (!c || !c->priv || !entry || entry->parent) return;
/* One tag can only be added once to an IFD. */
@@ -140,19 +144,20 @@ exif_content_add_entry (ExifContent *c, ExifEntry *entry)
return;
}
+ entries = exif_mem_realloc (c->priv->mem,
+ c->entries, sizeof (ExifEntry*) * (c->count + 1));
+ if (!entries) 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;
+ entries[c->count++] = entry;
+ c->entries = entries;
exif_entry_ref (entry);
- c->count++;
}
void
exif_content_remove_entry (ExifContent *c, ExifEntry *e)
{
unsigned int i;
+ ExifEntry **t, *temp;
if (!c || !c->priv || !e || (e->parent != c)) return;
@@ -161,13 +166,26 @@ exif_content_remove_entry (ExifContent *c, ExifEntry *e)
if (i == c->count) return;
/* Remove the entry */
- memmove (&c->entries[i], &c->entries[i + 1],
- sizeof (ExifEntry) * (c->count - i - 1));
- c->count--;
+ temp = c->entries[c->count-1];
+ if (c->count > 1) {
+ t = exif_mem_realloc (c->priv->mem, c->entries,
+ sizeof(ExifEntry*) * (c->count - 1));
+ if (!t) {
+ return;
+ }
+ c->entries = t;
+ c->count--;
+ if (i != c->count) { /* we deallocated the last slot already */
+ memmove (&t[i], &t[i + 1], sizeof (ExifEntry*) * (c->count - i - 1));
+ t[c->count-1] = temp;
+ }
+ } else {
+ exif_mem_free (c->priv->mem, c->entries);
+ c->entries = NULL;
+ c->count = 0;
+ }
e->parent = NULL;
exif_entry_unref (e);
- c->entries = exif_mem_realloc (c->priv->mem, c->entries,
- sizeof(ExifEntry) * c->count);
}
ExifEntry *
@@ -207,3 +225,70 @@ exif_content_log (ExifContent *content, ExifLog *log)
content->priv->log = log;
exif_log_ref (log);
}
+
+ExifIfd
+exif_content_get_ifd (ExifContent *c)
+{
+ if (!c || !c->parent) return EXIF_IFD_COUNT;
+
+ return
+ ((c)->parent->ifd[EXIF_IFD_0] == (c)) ? EXIF_IFD_0 :
+ ((c)->parent->ifd[EXIF_IFD_1] == (c)) ? EXIF_IFD_1 :
+ ((c)->parent->ifd[EXIF_IFD_EXIF] == (c)) ? EXIF_IFD_EXIF :
+ ((c)->parent->ifd[EXIF_IFD_GPS] == (c)) ? EXIF_IFD_GPS :
+ ((c)->parent->ifd[EXIF_IFD_INTEROPERABILITY] == (c)) ? EXIF_IFD_INTEROPERABILITY :
+ EXIF_IFD_COUNT;
+}
+
+static void
+fix_func (ExifEntry *e, void *UNUSED(data))
+{
+ exif_entry_fix (e);
+}
+
+void
+exif_content_fix (ExifContent *c)
+{
+ ExifIfd ifd = exif_content_get_ifd (c);
+ ExifDataType dt;
+ ExifTag t;
+ ExifEntry *e;
+
+ if (!c) return;
+
+ dt = exif_data_get_data_type (c->parent);
+
+ /* First of all, fix all existing entries. */
+ exif_content_foreach_entry (c, fix_func, NULL);
+
+ /*
+ * Then check for existing tags that are not allowed and for
+ * non-existing mandatory tags.
+ */
+ for (t = 0; t <= 0xffff; t++) {
+ switch (exif_tag_get_support_level_in_ifd (t, ifd, dt)) {
+ case EXIF_SUPPORT_LEVEL_MANDATORY:
+ if (exif_content_get_entry (c, t)) break;
+ exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
+ "Tag '%s' is mandatory in IFD '%s' and has therefore been added.",
+ exif_tag_get_name_in_ifd (t, ifd), exif_ifd_get_name (ifd));
+ e = exif_entry_new ();
+ exif_content_add_entry (c, e);
+ exif_entry_initialize (e, t);
+ exif_entry_unref (e);
+ break;
+ case EXIF_SUPPORT_LEVEL_NOT_RECORDED:
+ e = exif_content_get_entry (c, t);
+ if (!e) break;
+ exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
+ "Tag '%s' is not recorded in IFD '%s' and has therefore been "
+ "removed.", exif_tag_get_name_in_ifd (t, ifd),
+ exif_ifd_get_name (ifd));
+ exif_content_remove_entry (c, e);
+ break;
+ case EXIF_SUPPORT_LEVEL_OPTIONAL:
+ default:
+ break;
+ }
+ }
+}
diff --git a/src/libexif/exif-content.h b/src/libexif/exif-content.h
index 115f8ed..ade2e01 100644
--- a/src/libexif/exif-content.h
+++ b/src/libexif/exif-content.h
@@ -1,6 +1,6 @@
/* exif-content.h
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
@@ -52,9 +52,10 @@ 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);
+void exif_content_add_entry (ExifContent *, ExifEntry *);
+void exif_content_remove_entry (ExifContent *, ExifEntry *);
+ExifEntry *exif_content_get_entry (ExifContent *, ExifTag);
+void exif_content_fix (ExifContent *);
typedef void (* ExifContentForeachEntryFunc) (ExifEntry *, void *user_data);
void exif_content_foreach_entry (ExifContent *content,
@@ -62,6 +63,7 @@ void exif_content_foreach_entry (ExifContent *content,
void *user_data);
/* For your convenience */
+ExifIfd exif_content_get_ifd (ExifContent *);
#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)
diff --git a/src/libexif/exif-data-type.h b/src/libexif/exif-data-type.h
new file mode 100644
index 0000000..271a2f2
--- /dev/null
+++ b/src/libexif/exif-data-type.h
@@ -0,0 +1,40 @@
+/* exif-data-tag.h
+ *
+ * Copyright (c) 2005 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 __EXIF_DATA_TYPE_H__
+#define __EXIF_DATA_TYPE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+ EXIF_DATA_TYPE_UNCOMPRESSED_CHUNKY = 0,
+ EXIF_DATA_TYPE_UNCOMPRESSED_PLANAR,
+ EXIF_DATA_TYPE_UNCOMPRESSED_YCC,
+ EXIF_DATA_TYPE_COMPRESSED,
+ EXIF_DATA_TYPE_COUNT
+} ExifDataType;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_TAG_H__ */
diff --git a/src/libexif/exif-data.c b/src/libexif/exif-data.c
index 92e5857..314fd8b 100644
--- a/src/libexif/exif-data.c
+++ b/src/libexif/exif-data.c
@@ -1,6 +1,6 @@
/* exif-data.c
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
@@ -28,18 +28,17 @@
#include <libexif/exif-loader.h>
#include <libexif/exif-log.h>
#include <libexif/i18n.h>
+#include <libexif/exif-system.h>
-#include <libexif/olympus/exif-mnote-data-olympus.h>
#include <libexif/canon/exif-mnote-data-canon.h>
+#include <libexif/fuji/exif-mnote-data-fuji.h>
+#include <libexif/olympus/exif-mnote-data-olympus.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
@@ -66,6 +65,9 @@ struct _ExifDataPrivate
/* Temporarily used while loading data */
unsigned int offset_mnote;
+
+ ExifDataOption options;
+ ExifDataType data_type;
};
static void *
@@ -73,10 +75,12 @@ exif_data_alloc (ExifData *data, unsigned int i)
{
void *d;
- if (!data || !i) return NULL;
+ if (!data || !i)
+ return NULL;
d = exif_mem_alloc (data->priv->mem, i);
- if (d) return d;
+ if (d)
+ return d;
EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", i);
return NULL;
@@ -105,12 +109,17 @@ exif_data_new_mem (ExifMem *mem)
ExifData *data;
unsigned int i;
- if (!mem) return NULL;
+ if (!mem)
+ return NULL;
data = exif_mem_alloc (mem, sizeof (ExifData));
- if (!data) return (NULL);
+ if (!data)
+ return (NULL);
data->priv = exif_mem_alloc (mem, sizeof (ExifDataPrivate));
- if (!data->priv) { exif_mem_free (mem, data); return (NULL); }
+ if (!data->priv) {
+ exif_mem_free (mem, data);
+ return (NULL);
+ }
data->priv->ref_count = 1;
data->priv->mem = mem;
@@ -125,6 +134,19 @@ exif_data_new_mem (ExifMem *mem)
data->ifd[i]->parent = data;
}
+ /* Default options */
+#ifndef NO_VERBOSE_TAG_STRINGS
+ /*
+ * When the tag list is compiled away, setting this option prevents
+ * any tags from being loaded
+ */
+ exif_data_set_option (data, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS);
+#endif
+ exif_data_set_option (data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
+
+ /* Default data type: none */
+ exif_data_set_data_type (data, EXIF_DATA_TYPE_COUNT);
+
return (data);
}
@@ -138,7 +160,7 @@ exif_data_new_from_data (const unsigned char *data, unsigned int size)
return (edata);
}
-static void
+static int
exif_data_load_data_entry (ExifData *data, ExifEntry *entry,
const unsigned char *d,
unsigned int size, unsigned int offset)
@@ -153,41 +175,56 @@ exif_data_load_data_entry (ExifData *data, ExifEntry *entry,
"Loading entry 0x%x ('%s')...", entry->tag,
exif_tag_get_name (entry->tag));
+ /* {0,1,2,4,8} x { 0x00000000 .. 0xffffffff }
+ * -> { 0x000000000 .. 0x7fffffff8 } */
+ s = exif_format_get_size(entry->format) * entry->components;
+ if (s < entry->components) {
+ return 0;
+ }
+ if (0 == s)
+ return 0;
/*
* 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 */
+ /* Sanity checks */
+ if ((doff + s < doff) || (doff + s < s))
+ return 0;
if (size < doff + s)
- return;
+ return 0;
entry->data = exif_data_alloc (data, s);
if (entry->data) {
entry->size = s;
memcpy (entry->data, d + doff, s);
+ } else {
+ /* FIXME: What do our callers do if (entry->data == NULL)? */
+ EXIF_LOG_NO_MEMORY(data->priv->log, "ExifData", 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]);
+ if (!entry->data) {
+ exif_log (data->priv->log,
+ EXIF_LOG_CODE_DEBUG, "ExifData",
+ "MakerNote found with NULL data");
+ } else 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);
+ return 1;
}
static void
@@ -196,8 +233,11 @@ exif_data_save_data_entry (ExifData *data, ExifEntry *e,
unsigned int offset)
{
unsigned int doff, s;
+ unsigned char *t;
+ unsigned int ts;
- if (!data || !data->priv) return;
+ if (!data || !data->priv)
+ return;
/*
* Each entry is 12 bytes long. The memory for the entry has
@@ -208,17 +248,17 @@ exif_data_save_data_entry (ExifData *data, ExifEntry *e,
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;
+ if (!(data->priv->options & EXIF_DATA_OPTION_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);
@@ -230,50 +270,62 @@ exif_data_save_data_entry (ExifData *data, ExifEntry *e,
s = exif_format_get_size (e->format) * e->components;
if (s > 4) {
doff = *ds - 6;
- *ds += s;
+ ts = *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);
+ if (s & 1)
+ ts++;
+ t = exif_mem_realloc (data->priv->mem, *d, ts);
+ if (!t) {
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts);
return;
}
+ *d = t;
+ *ds = ts;
exif_set_long (*d + 6 + offset + 8, data->priv->order, doff);
- if (s & 1) *(*d + *ds - 1) = '\0';
+ 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));
+ /* Write the data. Fill unneeded bytes with 0. Do not crash with
+ * e->data is NULL */
+ if (e->data) {
+ memcpy (*d + 6 + doff, e->data, s);
+ } else {
+ memset (*d + 6 + doff, 0, 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) {
+ if ((ds < offset + size) || (offset > ds)) {
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
- "Bogus thumbnail offset and size: %i < %i + %i.",
- (int) ds, (int) offset, (int) size);
+ "Bogus thumbnail offset (%u) or size (%u).",
+ offset, size);
return;
}
- if (data->data) exif_mem_free (data->priv->mem, data->data);
+ 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;
+ if (!data->data)
+ return;
memcpy (data->data, d + offset, data->size);
}
#undef CHECK_REC
#define CHECK_REC(i) \
-if (data->ifd[(i)] == ifd) { \
+if ((i) == ifd) { \
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \
"ExifData", "Recursive entry in IFD " \
"'%s' detected. Skipping...", \
@@ -282,7 +334,7 @@ if (data->ifd[(i)] == ifd) { \
} \
if (data->ifd[(i)]->count) { \
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \
- "ExifData", "Attemt to load IFD " \
+ "ExifData", "Attempt to load IFD " \
"'%s' multiple times detected. " \
"Skipping...", \
exif_ifd_get_name (i)); \
@@ -290,9 +342,9 @@ if (data->ifd[(i)]->count) { \
}
static void
-exif_data_load_data_content (ExifData *data, ExifContent *ifd,
+exif_data_load_data_content (ExifData *data, ExifIfd ifd,
const unsigned char *d,
- unsigned int ds, unsigned int offset)
+ unsigned int ds, unsigned int offset, unsigned int recursion_depth)
{
ExifLong o, thumbnail_offset = 0, thumbnail_length = 0;
ExifShort n;
@@ -300,17 +352,30 @@ exif_data_load_data_content (ExifData *data, ExifContent *ifd,
unsigned int i;
ExifTag tag;
- if (!data || !data->priv) return;
+ if (!data || !data->priv)
+ return;
+
+ /* check for valid ExifIfd enum range */
+ if (( ((int)ifd) < 0) || ( ((int)ifd) >= EXIF_IFD_COUNT))
+ return;
+
+ if (recursion_depth > 150) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData",
+ "Deep recursion detected!");
+ return;
+ }
/* Read the number of entries */
- if (offset >= ds - 1) return;
+ 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;
+ if (offset + 12 * n > ds)
+ n = (ds - offset) / 12;
for (i = 0; i < n; i++) {
@@ -326,32 +391,29 @@ exif_data_load_data_content (ExifData *data, ExifContent *ifd,
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);
+ exif_data_load_data_content (data, EXIF_IFD_EXIF, d, ds, o, recursion_depth + 1);
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);
+ exif_data_load_data_content (data, EXIF_IFD_GPS, d, ds, o, recursion_depth + 1);
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);
+ exif_data_load_data_content (data, EXIF_IFD_INTEROPERABILITY, d, ds, o, recursion_depth + 1);
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);
+ 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);
+ ds, thumbnail_offset,
+ thumbnail_length);
break;
default:
return;
@@ -360,18 +422,33 @@ exif_data_load_data_content (ExifData *data, ExifContent *ifd,
default:
/*
- * If we don't know the tag, chances are high
- * that the EXIF data does not follow the standard.
+ * If we don't know the tag, don't fail. It could be that new
+ * versions of the standard have defined additional tags. Note that
+ * 0 is a valid tag in the GPS IFD.
*/
- if (!exif_tag_get_name (tag)) {
+ if (!exif_tag_get_name_in_ifd (tag, ifd)) {
+
+ /*
+ * Special case: Tag and format 0. That's against specification.
+ * At least up to 2.2. But Photoshop writes it anyways.
+ */
+ if (!memcmp (d + offset + 12 * i, "\0\0\0\0", 4)) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Skipping empty entry at position %i in '%s'.", i,
+ exif_ifd_get_name (ifd));
+ break;
+ }
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
- "Unknown tag %x (entry %i)", tag, i);
- return;
+ "Unknown tag 0x%04x (entry %i in '%s'). Please report this tag "
+ "to <libexif-devel@lists.sourceforge.net>.", tag, i,
+ exif_ifd_get_name (ifd));
+ if (data->priv->options & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS)
+ break;
}
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);
+ if (exif_data_load_data_entry (data, entry, d, ds,
+ offset + 12 * i))
+ exif_content_add_entry (data->ifd[ifd], entry);
exif_entry_unref (entry);
break;
}
@@ -391,14 +468,14 @@ 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);
+ (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);
+ (const unsigned char *) elem2, EXIF_BYTE_ORDER_MOTOROLA);
}
static void
@@ -408,8 +485,11 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,
{
unsigned int j, n_ptr = 0, n_thumb = 0;
ExifIfd i;
+ unsigned char *t;
+ unsigned int ts;
- if (!data || !data->priv || !ifd || !d || !ds) return;
+ if (!data || !data->priv || !ifd || !d || !ds)
+ return;
for (i = 0; i < EXIF_IFD_COUNT; i++)
if (ifd == data->ifd[i])
@@ -451,24 +531,33 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,
* 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);
+ ts = *ds + (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4);
+ t = exif_mem_realloc (data->priv->mem, *d, ts);
+ if (!t) {
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts);
return;
}
+ *d = t;
+ *ds = ts;
/* 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 */
+ /*
+ * Save each entry. Make sure that no memcpys from NULL pointers are
+ * performed
+ */
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);
+ for (j = 0; j < ifd->count; j++) {
+ if (ifd->entries[j]) {
+ exif_data_save_data_entry (data, ifd->entries[j], d, ds,
+ offset + 12 * j);
+ }
+ }
offset += 12 * ifd->count;
@@ -493,7 +582,7 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,
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);
+ data->ifd[EXIF_IFD_EXIF], d, ds, *ds - 6);
offset += 12;
}
@@ -508,7 +597,7 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,
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);
+ data->ifd[EXIF_IFD_GPS], d, ds, *ds - 6);
offset += 12;
}
@@ -529,8 +618,8 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,
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);
+ data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds,
+ *ds - 6);
offset += 12;
}
@@ -552,19 +641,21 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,
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) {
+ ts = *ds + data->size;
+ t = exif_mem_realloc (data->priv->mem, *d, ts);
+ if (!t) {
EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData",
- *ds);
+ ts);
return;
}
+ *d = t;
+ *ds = ts;
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_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,
@@ -581,12 +672,12 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,
/* 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);
+ (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)) {
+ data->size)) {
/*
* We are saving IFD 0. Tell where IFD 1 starts and save
@@ -603,7 +694,10 @@ 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
+ EXIF_DATA_TYPE_MAKER_NOTE_PENTAX = 3,
+ EXIF_DATA_TYPE_MAKER_NOTE_NIKON = 4,
+ EXIF_DATA_TYPE_MAKER_NOTE_CASIO = 5,
+ EXIF_DATA_TYPE_MAKER_NOTE_FUJI = 6
} ExifDataTypeMakerNote;
static ExifDataTypeMakerNote
@@ -612,18 +706,23 @@ exif_data_get_type_maker_note (ExifData *d)
ExifEntry *e, *em;
char value[1024];
- if (!d) return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
+ 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)))
+ if (!e)
+ return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
+
+ /* Olympus & Nikon & Sanyo */
+ if ((e->size >= 8) && ( !memcmp (e->data, "OLYMP", 6) ||
+ !memcmp (e->data, "OLYMPUS", 8) ||
+ !memcmp (e->data, "SANYO", 6) ||
+ !memcmp (e->data, "Nikon", 6)))
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;
+ if (!em)
+ return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
/* Canon */
if (!strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon"))
@@ -632,12 +731,21 @@ exif_data_get_type_maker_note (ExifData *d)
/* 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;
+ exif_entry_get_value (em, value, sizeof(value)),
+ "Nikon", 5))
+ return EXIF_DATA_TYPE_MAKER_NOTE_NIKON;
else
return EXIF_DATA_TYPE_MAKER_NOTE_PENTAX;
}
+ if ((e->size >= 8) && !memcmp (e->data, "AOC", 4)) {
+ return EXIF_DATA_TYPE_MAKER_NOTE_PENTAX;
+ }
+ if ((e->size >= 8) && !memcmp (e->data, "QVC", 4)) {
+ return EXIF_DATA_TYPE_MAKER_NOTE_CASIO;
+ }
+ if ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8)) {
+ return EXIF_DATA_TYPE_MAKER_NOTE_FUJI;
+ }
return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
}
@@ -656,7 +764,8 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,
const unsigned char *d = d_orig;
unsigned int ds = ds_orig, len;
- if (!data || !data->priv || !d || !ds) return;
+ 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);
@@ -731,7 +840,7 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,
}
if (memcmp (d, ExifHeader, 6)) {
exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
- "ExifData", _("EXIF header not found."));
+ "ExifData", _("EXIF header not found."));
return;
}
@@ -747,7 +856,7 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,
data->priv->order = EXIF_BYTE_ORDER_MOTOROLA;
else {
exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
- "ExifData", _("Unknown encoding."));
+ "ExifData", _("Unknown encoding."));
return;
}
@@ -761,8 +870,7 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,
"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);
+ exif_data_load_data_content (data, EXIF_IFD_0, d + 6, ds - 6, offset, 0);
/* IFD 1 offset */
if (offset + 6 + 2 > ds) {
@@ -780,12 +888,10 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,
/* Sanity check. */
if (offset > ds - 6) {
exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
- "ExifData", "Bogus offset.");
- return;
+ "ExifData", "Bogus offset of IFD1.");
+ } else {
+ exif_data_load_data_content (data, EXIF_IFD_1, d + 6, ds - 6, offset, 0);
}
-
- exif_data_load_data_content (data, data->ifd[EXIF_IFD_1], d + 6,
- ds - 6, offset);
}
/*
@@ -796,13 +902,18 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,
*/
switch (exif_data_get_type_maker_note (data)) {
case EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS:
+ case EXIF_DATA_TYPE_MAKER_NOTE_NIKON:
data->priv->md = exif_mnote_data_olympus_new (data->priv->mem);
break;
case EXIF_DATA_TYPE_MAKER_NOTE_PENTAX:
+ case EXIF_DATA_TYPE_MAKER_NOTE_CASIO:
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);
+ data->priv->md = exif_mnote_data_canon_new (data->priv->mem, data->priv->options);
+ break;
+ case EXIF_DATA_TYPE_MAKER_NOTE_FUJI:
+ data->priv->md = exif_mnote_data_fuji_new (data->priv->mem);
break;
default:
break;
@@ -819,18 +930,27 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,
data->priv->offset_mnote);
exif_mnote_data_load (data->priv->md, d, ds);
}
+
+ if (data->priv->options & EXIF_DATA_OPTION_FOLLOW_SPECIFICATION)
+ exif_data_fix (data);
}
void
exif_data_save_data (ExifData *data, unsigned char **d, unsigned int *ds)
{
+ if (ds)
+ *ds = 0; /* This means something went wrong */
+
if (!data || !d || !ds)
return;
/* Header */
*ds = 14;
*d = exif_data_alloc (data, *ds);
- if (!*d) return;
+ if (!*d) {
+ *ds = 0;
+ return;
+ }
memcpy (*d, ExifHeader, 6);
/* Order (offset 6) */
@@ -886,10 +1006,12 @@ exif_data_ref (ExifData *data)
void
exif_data_unref (ExifData *data)
{
- if (!data) return;
+ if (!data)
+ return;
data->priv->ref_count--;
- if (!data->priv->ref_count) exif_data_free (data);
+ if (!data->priv->ref_count)
+ exif_data_free (data);
}
void
@@ -898,7 +1020,8 @@ exif_data_free (ExifData *data)
unsigned int i;
ExifMem *mem = (data && data->priv) ? data->priv->mem : NULL;
- if (!data) return;
+ if (!data)
+ return;
for (i = 0; i < EXIF_IFD_COUNT; i++) {
if (data->ifd[i]) {
@@ -1020,7 +1143,8 @@ exif_data_log (ExifData *data, ExifLog *log)
{
unsigned int i;
- if (!data || !data->priv) return;
+ if (!data || !data->priv)
+ return;
exif_log_unref (data->priv->log);
data->priv->log = log;
exif_log_ref (log);
@@ -1034,6 +1158,112 @@ ExifLog *exif_data_get_log (ExifData *);
ExifLog *
exif_data_get_log (ExifData *data)
{
- if (!data || !data->priv) return NULL;
+ if (!data || !data->priv)
+ return NULL;
return data->priv->log;
}
+
+static const struct {
+ ExifDataOption option;
+ const char *name;
+ const char *description;
+} exif_data_option[] = {
+ {EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS, N_("Ignore unknown tags"),
+ N_("Ignore unknown tags when loading EXIF data.")},
+ {EXIF_DATA_OPTION_FOLLOW_SPECIFICATION, N_("Follow specification"),
+ N_("Add, correct and remove entries to get EXIF data that follows "
+ "the specification.")},
+ {EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE, N_("Do not change maker note"),
+ N_("When loading and resaving Exif data, save the maker note unmodified."
+ " Be aware that the maker note can get corrupted.")},
+ {0, NULL, NULL}
+};
+
+const char *
+exif_data_option_get_name (ExifDataOption o)
+{
+ unsigned int i;
+
+ for (i = 0; exif_data_option[i].name; i++)
+ if (exif_data_option[i].option == o)
+ break;
+ return _(exif_data_option[i].name);
+}
+
+const char *
+exif_data_option_get_description (ExifDataOption o)
+{
+ unsigned int i;
+
+ for (i = 0; exif_data_option[i].description; i++)
+ if (exif_data_option[i].option == o)
+ break;
+ return _(exif_data_option[i].description);
+}
+
+void
+exif_data_set_option (ExifData *d, ExifDataOption o)
+{
+ if (!d)
+ return;
+
+ d->priv->options |= o;
+}
+
+void
+exif_data_unset_option (ExifData *d, ExifDataOption o)
+{
+ if (!d)
+ return;
+
+ d->priv->options &= ~o;
+}
+
+static void
+fix_func (ExifContent *c, void *UNUSED(data))
+{
+ switch (exif_content_get_ifd (c)) {
+ case EXIF_IFD_1:
+ if (c->parent->data)
+ exif_content_fix (c);
+ else {
+ exif_log (c->parent->priv->log, EXIF_LOG_CODE_DEBUG, "exif-data",
+ "No thumbnail but entries on thumbnail. These entries have been "
+ "removed.");
+ while (c->count) {
+ unsigned int cnt = c->count;
+ exif_content_remove_entry (c, c->entries[c->count - 1]);
+ if (cnt == c->count) {
+ /* safety net */
+ exif_log (c->parent->priv->log, EXIF_LOG_CODE_DEBUG, "exif-data",
+ "failed to remove last entry from entries.");
+ c->count--;
+ }
+ }
+ }
+ break;
+ default:
+ exif_content_fix (c);
+ }
+}
+
+void
+exif_data_fix (ExifData *d)
+{
+ exif_data_foreach_content (d, fix_func, NULL);
+}
+
+void
+exif_data_set_data_type (ExifData *d, ExifDataType dt)
+{
+ if (!d || !d->priv)
+ return;
+
+ d->priv->data_type = dt;
+}
+
+ExifDataType
+exif_data_get_data_type (ExifData *d)
+{
+ return (d && d->priv) ? d->priv->data_type : EXIF_DATA_TYPE_COUNT;
+}
diff --git a/src/libexif/exif-data.h b/src/libexif/exif-data.h
index 9ecad1d..3b99412 100644
--- a/src/libexif/exif-data.h
+++ b/src/libexif/exif-data.h
@@ -1,7 +1,7 @@
/*! \file exif-data.h
- * \brief FIXME foo bar blah
+ * \brief Defines the ExifData type and the associated functions.
*
- * \author Lutz Müller <lutz@users.sourceforge.net>
+ * \author Lutz Mueller <lutz@users.sourceforge.net>
* \date 2001-2005
*
* This library is free software; you can redistribute it and/or
@@ -28,6 +28,7 @@ extern "C" {
#endif /* __cplusplus */
#include <libexif/exif-byte-order.h>
+#include <libexif/exif-data-type.h>
#include <libexif/exif-ifd.h>
#include <libexif/exif-log.h>
#include <libexif/exif-tag.h>
@@ -54,8 +55,6 @@ 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,
@@ -74,17 +73,32 @@ 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 *);
+void exif_data_fix (ExifData *);
typedef void (* ExifDataForeachContentFunc) (ExifContent *, void *user_data);
void exif_data_foreach_content (ExifData *data,
ExifDataForeachContentFunc func,
void *user_data);
+typedef enum {
+ EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS = 1 << 0,
+ EXIF_DATA_OPTION_FOLLOW_SPECIFICATION = 1 << 1,
+ EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE = 1 << 2
+} ExifDataOption;
+
+const char *exif_data_option_get_name (ExifDataOption);
+const char *exif_data_option_get_description (ExifDataOption);
+void exif_data_set_option (ExifData *, ExifDataOption);
+void exif_data_unset_option (ExifData *, ExifDataOption);
+
+void exif_data_set_data_type (ExifData *, ExifDataType);
+ExifDataType exif_data_get_data_type (ExifData *);
+
/* For debugging purposes and error reporting */
void exif_data_dump (ExifData *data);
void exif_data_log (ExifData *data, ExifLog *log);
-/* For your convenience */
+/** convenience macro. */
#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) : \
diff --git a/src/libexif/exif-entry.c b/src/libexif/exif-entry.c
index 09d37e2..02ec510 100644
--- a/src/libexif/exif-entry.c
+++ b/src/libexif/exif-entry.c
@@ -1,6 +1,6 @@
/* exif-entry.c
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
@@ -30,6 +30,7 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
+#define _USE_MATH_DEFINES /* required by MS compilers to define M_PI */
#include <math.h>
struct _ExifEntryPrivate
@@ -42,6 +43,7 @@ struct _ExifEntryPrivate
/* This function is hidden in exif-data.c */
ExifLog *exif_data_get_log (ExifData *);
+#ifndef NO_VERBOSE_TAG_STRINGS
static void
exif_entry_log (ExifEntry *e, ExifLogCode code, const char *format, ...)
{
@@ -54,6 +56,15 @@ exif_entry_log (ExifEntry *e, ExifLogCode code, const char *format, ...)
exif_logv (l, code, "ExifEntry", format, args);
va_end (args);
}
+#else
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define exif_entry_log(...) do { } while (0)
+#elif defined(__GNUC__)
+#define exif_entry_log(x...) do { } while (0)
+#else
+#define exif_entry_log (void)
+#endif
+#endif
static void *
exif_entry_alloc (ExifEntry *e, unsigned int i)
@@ -199,9 +210,9 @@ exif_entry_fix (ExifEntry *e)
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 "
+ _("Tag '%s' was of format '%s' (which is "
"against specification) and has been "
- "changed to format '%s'.",
+ "changed to format '%s'."),
exif_tag_get_name (e->tag),
exif_format_get_name (EXIF_FORMAT_LONG),
exif_format_get_name (EXIF_FORMAT_SHORT));
@@ -233,9 +244,9 @@ exif_entry_fix (ExifEntry *e)
}
e->format = EXIF_FORMAT_RATIONAL;
exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
- "Tag '%s' was of format '%s' (which is "
+ _("Tag '%s' was of format '%s' (which is "
"against specification) and has been "
- "changed to format '%s'.",
+ "changed to format '%s'."),
exif_tag_get_name (e->tag),
exif_format_get_name (EXIF_FORMAT_SRATIONAL),
exif_format_get_name (EXIF_FORMAT_RATIONAL));
@@ -250,30 +261,18 @@ exif_entry_fix (ExifEntry *e)
/* 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'.",
+ _("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);
@@ -289,9 +288,9 @@ exif_entry_fix (ExifEntry *e)
e->size += 8;
e->components += 8;
exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
- "Tag 'UserComment' has been expanded to at "
+ _("Tag 'UserComment' has been expanded to at "
"least 8 bytes in order to follow the "
- "specification.");
+ "specification."));
break;
}
@@ -300,14 +299,20 @@ exif_entry_fix (ExifEntry *e)
* afterwards, let's assume ASCII and claim the 8 first
* bytes for the format specifyer.
*/
- if (i >= 8) {
+ for (i = 0; (i < e->size) && !e->data[i]; i++);
+ if (!i) for ( ; (i < e->size) && (e->data[i] == ' '); i++);
+ if ((i >= 8) && (i < e->size)) {
exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
- "Tag 'UserComment' did not start with "
+ "Tag 'UserComment' is not empty but does not start with "
"format identifyer. This has been fixed.");
memcpy (e->data, "ASCII\0\0\0", 8);
+ break;
}
- /* First 8 bytes need to follow the specification. */
+ /*
+ * First 8 bytes need to follow the specification. If they don't,
+ * assume ASCII.
+ */
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) &&
@@ -325,8 +330,8 @@ exif_entry_fix (ExifEntry *e)
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.");
+ _("Tag 'UserComment' did not start with "
+ "format identifier. This has been fixed."));
break;
}
@@ -384,10 +389,11 @@ exif_entry_dump (ExifEntry *e, unsigned int indent)
} \
}
-static struct {
+static const struct {
ExifTag tag;
const char *strings[10];
} list[] = {
+#ifndef NO_VERBOSE_TAG_DATA
{ EXIF_TAG_PLANAR_CONFIGURATION,
{ N_("chunky format"), N_("planar format"), NULL}},
{ EXIF_TAG_SENSING_METHOD,
@@ -401,7 +407,9 @@ static struct {
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_PHOTOMETRIC_INTERPRETATION,
+ {N_("Reversed mono"), N_("Normal mono"), N_("RGB"), N_("Palette"), "",
+ N_("CMYK"), N_("YCbCr"), "", N_("CieLAB"), NULL}},
{ EXIF_TAG_CUSTOM_RENDERED,
{ N_("Normal process"), N_("Custom process"), NULL}},
{ EXIF_TAG_EXPOSURE_MODE,
@@ -418,16 +426,18 @@ static struct {
{ 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}},
+#endif
{ 0, {NULL}}
};
-static struct {
+static const struct {
ExifTag tag;
struct {
int index;
const char *values[4];
} elem[25];
} list2[] = {
+#ifndef NO_VERBOSE_TAG_DATA
{ EXIF_TAG_METERING_MODE,
{ { 0, {N_("Unknown"), NULL}},
{ 1, {N_("Average"), N_("avg"), NULL}},
@@ -442,6 +452,9 @@ static struct {
{ {1, {N_("Uncompressed"), NULL}},
{5, {N_("LZW compression"), NULL}},
{6, {N_("JPEG compression"), NULL}},
+ {7, {N_("JPEG compression"), NULL}},
+ {8, {N_("Deflate/ZIP compression"), NULL}},
+ {32773, {N_("PackBits compression"), NULL}},
{0, {NULL}}}},
{ EXIF_TAG_LIGHT_SOURCE,
{ { 0, {N_("Unknown"), NULL}},
@@ -450,7 +463,7 @@ static struct {
{ 3, {N_("Tungsten incandescent light"), N_("Tungsten"), NULL}},
{ 4, {N_("Flash"), NULL}},
{ 9, {N_("Fine weather"), NULL}},
- { 10, {N_("Cloudy weather"), N_("cloudy"), NULL}},
+ { 10, {N_("Cloudy weather"), N_("Cloudy"), NULL}},
{ 11, {N_("Shade"), NULL}},
{ 12, {N_("Daylight fluorescent"), NULL}},
{ 13, {N_("Day white fluorescent"), NULL}},
@@ -481,7 +494,7 @@ static struct {
{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"),
+ {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}},
@@ -494,12 +507,13 @@ static struct {
{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 "
+ {0x0008, {N_("Flash did not fire."), NULL}}, /* Olympus E-330 */
+ {0x0009, {N_("Flash fired, compulsory flash mode."), NULL}},
+ {0x000d, {N_("Flash fired, compulsory flash mode, return light "
"not detected."), NULL}},
- {0x000f, {N_("Flash fired, compulsatory flash mode, return light "
+ {0x000f, {N_("Flash fired, compulsory flash mode, return light "
"detected."), NULL}},
- {0x0010, {N_("Flash did not fire, compulsatory flash mode."), NULL}},
+ {0x0010, {N_("Flash did not fire, compulsory 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."),
@@ -514,11 +528,11 @@ static struct {
{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}},
+ "mode, return light not detected."), NULL}},
+ {0x004f, {N_("Flash fired, compulsory flash mode, red-eye reduction mode, "
+ "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, "
@@ -527,13 +541,16 @@ static struct {
{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}},
+ {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, }
+ {2, {N_("Adobe RGB"), NULL}},
+ {0xffff, {N_("Uncalibrated"), NULL}},
+ {0x0000, {NULL}}}},
+#endif
+ {0, { { 0, {NULL}}} }
};
const char *
@@ -552,8 +569,8 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
ExifByteOrder o;
double d;
ExifEntry *entry;
- static struct {
- char *label;
+ static const struct {
+ const char *label;
char major, minor;
} versions[] = {
{"0110", 1, 1},
@@ -566,18 +583,24 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
};
/* FIXME: This belongs to somewhere else. */
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ /* libexif should use the default system locale.
+ * If an application specifically requires UTF-8, then we
+ * must give the application a way to tell libexif that.
+ *
+ * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ */
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ /* make sure the returned string is zero terminated */
+ memset (val, 0, maxlen);
+ maxlen--;
+ memset (b, 0, sizeof (b));
+
/* 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, "
@@ -632,11 +655,11 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
* Print as much as possible.
*/
exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
- "Tag UserComment does not comply "
- "with standard but contains data.");
+ _("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]);
+ _("Byte at position %i: 0x%02x"), i, e->data[i]);
val[strlen (val)] =
isprint (e->data[i]) ? e->data[i] : '.';
}
@@ -674,7 +697,7 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
* Some cameras store a string like " " here. Ignore it.
*/
if (e->size && e->data &&
- (strspn (e->data, " ") != strlen ((char *) e->data)))
+ (strspn ((char *)e->data, " ") != strlen ((char *) e->data)))
strncpy (val, (char *) e->data, MIN (maxlen, e->size));
else
strncpy (val, _("[None]"), maxlen);
@@ -682,14 +705,15 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
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
+ if (e->size && e->data) {
+ t = e->data + strlen ((char *) e->data) + 1;
+ ts = e->data + e->size - t;
+ if ((ts > 0) && (strspn ((char *)t, " ") != ts))
+ strncat (val, (char *)t, MIN (maxlen - strlen (val), ts));
+ } else {
strncat (val, _("[None]"), maxlen - strlen (val));
+ }
strncat (val, " ", maxlen - strlen (val));
strncat (val, _("(Editor)"), maxlen - strlen (val));
@@ -699,17 +723,20 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int 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);
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ snprintf (val, maxlen, "f/%.01lf", d);
break;
case EXIF_TAG_APERTURE_VALUE:
+ case EXIF_TAG_MAX_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.));
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ snprintf (val, maxlen, _("%.02lf EV"), d);
+ snprintf (b, sizeof (b), _(" (f/%.01f)"), pow (2, d / 2.));
+ if (maxlen > strlen (val) + strlen (b))
+ strncat (val, b, maxlen - strlen (val) - 1);
break;
case EXIF_TAG_FOCAL_LENGTH:
CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
@@ -726,14 +753,14 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
entry = exif_content_get_entry (
e->parent->parent->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
if (entry && entry->data &&
- !strncmp (entry->data, "Minolta", 7)) {
+ !strncmp ((char *)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))
+ if (!strncmp ((char *)entry->data, "DiMAGE 7", 8))
d = 3.9;
- else if (!strncmp (entry->data, "DiMAGE 5", 8))
+ else if (!strncmp ((char *)entry->data, "DiMAGE 5", 8))
d = 4.9;
}
}
@@ -742,8 +769,8 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
(int) (d * (double) v_rat.numerator /
(double) v_rat.denominator));
- snprintf (val, maxlen, "%.1f mm",
- (float) v_rat.numerator / (float) v_rat.denominator);
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ snprintf (val, maxlen, "%.1lf mm", d);
if (maxlen > strlen (val) + strlen (b))
strncat (val, b, maxlen - strlen (val) - 1);
break;
@@ -752,8 +779,8 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int 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);
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ snprintf (val, maxlen, "%.1lf m", d);
break;
case EXIF_TAG_EXPOSURE_TIME:
CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
@@ -762,8 +789,7 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
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));
+ snprintf (val, maxlen, _("1/%d"), (int) (0.5 + 1. / d));
else
snprintf (val, maxlen, _("%d"), (int) d);
if (maxlen > strlen (val) + strlen (_(" sec.")))
@@ -774,23 +800,32 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int 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));
+ d = (double) v_srat.numerator / (double) v_srat.denominator;
+ snprintf (val, maxlen, _("%.02f EV"), d);
+ snprintf (b, sizeof (b), " (APEX: %i)", (int) pow (sqrt(2), d));
if (maxlen > strlen (val) + strlen (b))
strncat (val, b, maxlen - strlen (val) - 1);
+ d = 1. / pow (2, d);
+ if (d < 1)
+ snprintf (b, sizeof (b), _(" 1/%d sec.)"), (int) (1. / d));
+ else
+ snprintf (b, sizeof (b), _(" %d sec.)"), (int) d);
+ if (maxlen > strlen (val) + strlen (b)) {
+ val[strlen (val) - 1] = ',';
+ 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? */
+ if (!v_srat.denominator) return val;
+ d = (double) v_srat.numerator / (double) v_srat.denominator;
+ snprintf (val, maxlen, _("%.02f EV"), d);
+ snprintf (b, sizeof (b), _(" (%.02f cd/m^2)"),
+ 1. / (M_PI * 0.3048 * 0.3048) * pow (2, d));
+ if (maxlen > strlen (val) + strlen (b))
+ strncat (val, b, maxlen - strlen (val) - 1);
break;
case EXIF_TAG_FILE_SOURCE:
CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
@@ -823,10 +858,8 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int 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);
+ d = (double) v_srat.numerator / (double) v_srat.denominator;
+ snprintf (val, maxlen, _("%.02f EV"), d);
break;
case EXIF_TAG_YCBCR_SUB_SAMPLING:
CF (e, EXIF_FORMAT_SHORT, val, maxlen);
@@ -842,11 +875,6 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int 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) {
@@ -896,26 +924,26 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
/* 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);
+ snprintf (val, maxlen, _("Internal error (unknown "
+ "value %i)"), v_short);
break;
}
/* Find the value */
- for (j = 0; list2[i].elem[j].values &&
+ for (j = 0; list2[i].elem[j].values[0] &&
(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);
+ 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++) {
+ for (k = 0; 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);
+ strncpy (val, _(list2[i].elem[j].values[k]), maxlen);
}
if (!strlen (val)) snprintf (val, maxlen, "%i", v_short);
@@ -940,7 +968,8 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
/* 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);
+ snprintf (val, maxlen, _("Internal error (unknown "
+ "value %i)"), v_short);
break;
}
@@ -948,13 +977,35 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
for (j = 0; list[i].strings[j] && (j < v_short); j++);
if (!list[i].strings[j])
snprintf (val, maxlen, "%i", v_short);
+ else if (!*list[i].strings[j])
+ val[0] = 0;
else
- strncpy (val, _(list[i].strings[j]), maxlen - 1);
- break;
+ strncpy (val, _(list[i].strings[j]), maxlen);
+ break;
+ case EXIF_TAG_XP_TITLE:
+ case EXIF_TAG_XP_COMMENT:
+ case EXIF_TAG_XP_AUTHOR:
+ case EXIF_TAG_XP_KEYWORDS:
+ case EXIF_TAG_XP_SUBJECT:
+ /* Warning! The texts are converted from UTF16 to UTF8 */
+ exif_convert_utf16_to_utf8(val, (unsigned short*)e->data, MIN(maxlen, e->size));
+ break;
+ case EXIF_TAG_INTEROPERABILITY_VERSION:
+ if (e->format == EXIF_FORMAT_UNDEFINED) {
+ strncpy (val, (char *) e->data, MIN (maxlen, e->size));
+ break;
+ }
+ /* Fall through - EXIF_TAG_GPS_LATITUDE is same as INTEROPERABILITY_VERSION */
default:
- if (!e->components) break;
+ if (!e->size) break;
switch (e->format) {
case EXIF_FORMAT_UNDEFINED:
+ if ((e->tag == EXIF_TAG_SCENE_TYPE) && (e->size == 1)) {
+ snprintf (val, maxlen, "%i", e->data[0]);
+ } else {
+ snprintf (val, maxlen, _("%i bytes undefined data"),
+ e->size);
+ }
break;
case EXIF_FORMAT_BYTE:
case EXIF_FORMAT_SBYTE:
@@ -1019,20 +1070,29 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
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);
- }
+ if (v_rat.denominator)
+ snprintf (val, maxlen, "%2.2lf",
+ (double) v_rat.numerator /
+ (double) v_rat.denominator);
+ else
+ snprintf (val, maxlen, "%2.2lf/%2.2lf",
+ (double) v_rat.numerator,
+ (double) 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);
+ if (v_rat.denominator)
+ snprintf (b, sizeof (b), ", %2.2lf",
+ (double) v_rat.numerator /
+ (double) v_rat.denominator);
+ else
+ snprintf (b, sizeof (b), ", %2.2lf/%2.2lf",
+ (double) v_rat.numerator,
+ (double) v_rat.denominator);
strncat (val, b, maxlen);
maxlen -= strlen (b);
- if ((signed)maxlen <= 0) break;
+ if ((signed) maxlen <= 0) break;
}
break;
case EXIF_FORMAT_SRATIONAL:
@@ -1064,6 +1124,10 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
return val;
}
+
+/**
+ * \bug Log and report failed exif_mem_malloc() calls.
+ */
void
exif_entry_initialize (ExifEntry *e, ExifTag tag)
{
@@ -1092,6 +1156,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
e->format = EXIF_FORMAT_LONG;
e->size = exif_format_get_size (e->format) * e->components;
e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
break;
/* SHORT, 1 component, no default */
@@ -1104,8 +1169,8 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
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:
+ case EXIF_TAG_FLASH:
/* SHORT, 1 component, default 0 */
case EXIF_TAG_IMAGE_WIDTH:
@@ -1122,36 +1187,40 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
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, 0);
break;
/* SHORT, 1 component, default 1 */
- case EXIF_TAG_ORIENTATION:
- case EXIF_TAG_PLANAR_CONFIGURATION:
- case EXIF_TAG_YCBCR_POSITIONING:
+ 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);
+ if (!e->data) break;
exif_set_short (e->data, o, 1);
break;
/* SHORT, 1 component, default 2 */
- case EXIF_TAG_RESOLUTION_UNIT:
+ 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);
+ if (!e->data) break;
exif_set_short (e->data, o, 2);
break;
/* SHORT, 1 component, default 3 */
- case EXIF_TAG_SAMPLES_PER_PIXEL:
+ 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);
+ if (!e->data) break;
exif_set_short (e->data, o, 3);
break;
@@ -1198,6 +1267,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
e->format = EXIF_FORMAT_SRATIONAL;
e->size = exif_format_get_size (e->format) * e->components;
e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
break;
/* RATIONAL, 1 component, no default */
@@ -1218,6 +1288,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
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;
break;
/* RATIONAL, 1 component, default 72/1 */
@@ -1227,6 +1298,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
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.numerator = 72;
r.denominator = 1;
exif_set_rational (e->data, o, r);
@@ -1238,6 +1310,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
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;
break;
/* RATIONAL, 6 components */
@@ -1267,6 +1340,21 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
e->data + 5 * exif_format_get_size (e->format), o, r);
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, 20 components, default current time */
case EXIF_TAG_DATE_TIME:
case EXIF_TAG_DATE_TIME_ORIGINAL:
@@ -1284,21 +1372,6 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
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:
@@ -1317,12 +1390,14 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
break;
/* UNDEFINED, no components, no default */
+ /* Use this if the tag is otherwise unsupported */
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:
+ default:
e->components = 0;
e->format = EXIF_FORMAT_UNDEFINED;
e->size = 0;
@@ -1350,24 +1425,24 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
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);
+ 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);
+ 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;
+ memcpy (e->data, "0210", 4);
+ break;
/* UNDEFINED, 4 components, no default */
case EXIF_TAG_COMPONENTS_CONFIGURATION:
@@ -1377,7 +1452,5 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
e->data = malloc (e->size);
break;
- default:
- break;
}
}
diff --git a/src/libexif/exif-entry.h b/src/libexif/exif-entry.h
index 072ee29..23731fe 100644
--- a/src/libexif/exif-entry.h
+++ b/src/libexif/exif-entry.h
@@ -1,6 +1,7 @@
-/* exif-entry.h
+/*! \file exif-entry.h
+ * \brief Handling EXIF entries
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
@@ -32,6 +33,7 @@ typedef struct _ExifEntryPrivate ExifEntryPrivate;
#include <libexif/exif-format.h>
#include <libexif/exif-mem.h>
+/*! */
struct _ExifEntry {
ExifTag tag;
ExifFormat format;
@@ -47,21 +49,44 @@ struct _ExifEntry {
};
/* Lifecycle */
+
+/*! Reserve memory for and initialize new #ExifEntry* */
ExifEntry *exif_entry_new (void);
+
ExifEntry *exif_entry_new_mem (ExifMem *);
+
+/*! Increase reference counter for #ExifEntry* */
void exif_entry_ref (ExifEntry *entry);
+
+/*! Decrease reference counter for #ExifEntry* */
void exif_entry_unref (ExifEntry *entry);
+
+/*! Actually free the #ExifEntry*
+ *
+ * \deprecated Should not be called directly. Use exif_entry_ref() and
+ * exif_entry_unref() instead.
+ */
void exif_entry_free (ExifEntry *entry);
void exif_entry_initialize (ExifEntry *entry, ExifTag tag);
void exif_entry_fix (ExifEntry *entry);
/* For your convenience */
+
+/*! Return the value of the EXIF entry
+ *
+ * CAUTION: The character set of the returned string is not defined.
+ * It may be UTF-8, latin1, the native encoding of the
+ * computer, or the native encoding of the camera.
+ */
const char *exif_entry_get_value (ExifEntry *entry, char *val,
unsigned int maxlen);
+/*! Dump text representation of #ExifEntry to stdout */
void exif_entry_dump (ExifEntry *entry, unsigned int indent);
+#define exif_entry_get_ifd(e) ((e)?exif_content_get_ifd((e)->parent):EXIF_IFD_COUNT)
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/src/libexif/exif-format.c b/src/libexif/exif-format.c
index e0c3650..d432e9e 100644
--- a/src/libexif/exif-format.c
+++ b/src/libexif/exif-format.c
@@ -1,6 +1,6 @@
/* exif-format.c
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
@@ -25,7 +25,7 @@
#include <stdlib.h>
-static struct {
+static const struct {
ExifFormat format;
const char *name;
unsigned char size;
@@ -51,7 +51,12 @@ exif_format_get_name (ExifFormat format)
unsigned int i;
/* FIXME: This belongs to somewhere else. */
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ /* libexif should use the default system locale.
+ * If an application specifically requires UTF-8, then we
+ * must give the application a way to tell libexif that.
+ *
+ * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ */
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
for (i = 0; ExifFormatTable[i].name; i++)
diff --git a/src/libexif/exif-format.h b/src/libexif/exif-format.h
index 0eae425..272c865 100644
--- a/src/libexif/exif-format.h
+++ b/src/libexif/exif-format.h
@@ -1,6 +1,6 @@
/* exif-format.h
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
diff --git a/src/libexif/exif-ifd.c b/src/libexif/exif-ifd.c
index 96de261..7240dce 100644
--- a/src/libexif/exif-ifd.c
+++ b/src/libexif/exif-ifd.c
@@ -1,6 +1,6 @@
/* exif-ifd.c
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -24,7 +24,7 @@
#include <stdlib.h>
-static struct {
+static const struct {
ExifIfd ifd;
const char *name;
} ExifIfdTable[] = {
diff --git a/src/libexif/exif-ifd.h b/src/libexif/exif-ifd.h
index 01f0019..48d2083 100644
--- a/src/libexif/exif-ifd.h
+++ b/src/libexif/exif-ifd.h
@@ -1,6 +1,6 @@
/* exif-ifd.h
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -22,12 +22,12 @@
#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
+ EXIF_IFD_0 = 0, /*!< */
+ EXIF_IFD_1, /*!< */
+ EXIF_IFD_EXIF, /*!< */
+ EXIF_IFD_GPS, /*!< */
+ EXIF_IFD_INTEROPERABILITY, /*!< */
+ EXIF_IFD_COUNT /*!< Not a real value, just (max_value + 1). */
} ExifIfd;
const char *exif_ifd_get_name (ExifIfd ifd);
diff --git a/src/libexif/exif-loader.c b/src/libexif/exif-loader.c
index d6eba7d..4e5b140 100644
--- a/src/libexif/exif-loader.c
+++ b/src/libexif/exif-loader.c
@@ -1,18 +1,46 @@
+/* exif-loader.c
+ *
+ * Copyright (c) 2002 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 <libexif/exif-loader.h>
+#include <libexif/exif-utils.h>
#include <libexif/i18n.h>
+#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#undef JPEG_MARKER_DHT
+#define JPEG_MARKER_DHT 0xc4
#undef JPEG_MARKER_SOI
#define JPEG_MARKER_SOI 0xd8
+#undef JPEG_MARKER_DQT
+#define JPEG_MARKER_DQT 0xdb
#undef JPEG_MARKER_APP0
#define JPEG_MARKER_APP0 0xe0
#undef JPEG_MARKER_APP1
#define JPEG_MARKER_APP1 0xe1
+#undef JPEG_MARKER_APP2
+#define JPEG_MARKER_APP2 0xe2
#undef JPEG_MARKER_APP13
#define JPEG_MARKER_APP13 0xed
#undef JPEG_MARKER_COM
@@ -60,10 +88,12 @@ exif_loader_alloc (ExifLoader *l, unsigned int i)
{
void *d;
- if (!l || !i) return NULL;
+ if (!l || !i)
+ return NULL;
d = exif_mem_alloc (l->mem, i);
- if (d) return d;
+ if (d)
+ return d;
EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i);
return NULL;
@@ -79,7 +109,8 @@ exif_loader_write_file (ExifLoader *l, const char *path)
int size;
unsigned char data[1024];
- if (!l) return;
+ if (!l)
+ return;
f = fopen (path, "rb");
if (!f) {
@@ -89,8 +120,10 @@ exif_loader_write_file (ExifLoader *l, const char *path)
}
while (1) {
size = fread (data, 1, sizeof (data), f);
- if (size <= 0) break;
- if (!exif_loader_write (l, data, size)) break;
+ if (size <= 0)
+ break;
+ if (!exif_loader_write (l, data, size))
+ break;
}
fclose (f);
}
@@ -98,11 +131,14 @@ exif_loader_write_file (ExifLoader *l, const char *path)
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 (!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;
+ 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);
@@ -117,13 +153,17 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
{
unsigned int i;
- if (!eld || (len && !buf)) return 0;
+ 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; }
+ if (eld->size > len) {
+ eld->size -= len;
+ return 1;
+ }
len -= eld->size;
buf += eld->size;
eld->size = 0;
@@ -141,6 +181,8 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
break;
}
+ if (!len)
+ return 1;
exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
"Scanning %i byte(s) of data...", len);
@@ -152,7 +194,8 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
if (i) {
memcpy (&eld->b[eld->b_len], buf, i);
eld->b_len += i;
- if (eld->b_len < sizeof (eld->b)) return 1;
+ if (eld->b_len < sizeof (eld->b))
+ return 1;
buf += i;
len -= i;
}
@@ -183,11 +226,13 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
switch (eld->state) {
case EL_EXIF_FOUND:
if (!exif_loader_copy (eld, eld->b + i,
- sizeof (eld->b) - i)) return 0;
+ 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;
+ if (!eld->size)
+ eld->state = EL_READ;
break;
case EL_READ_SIZE_BYTE_24:
@@ -225,11 +270,18 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
default:
switch (eld->b[i]) {
case JPEG_MARKER_APP1:
- eld->data_format = EL_DATA_FORMAT_EXIF;
+ if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) {
+ eld->data_format = EL_DATA_FORMAT_EXIF;
+ } else {
+ eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/
+ }
eld->size = 0;
eld->state = EL_READ_SIZE_BYTE_08;
break;
+ case JPEG_MARKER_DHT:
+ case JPEG_MARKER_DQT:
case JPEG_MARKER_APP0:
+ case JPEG_MARKER_APP2:
case JPEG_MARKER_APP13:
case JPEG_MARKER_COM:
eld->data_format = EL_DATA_FORMAT_JPEG;
@@ -274,10 +326,12 @@ exif_loader_new_mem (ExifMem *mem)
{
ExifLoader *loader;
- if (!mem) return NULL;
+ if (!mem)
+ return NULL;
loader = exif_mem_alloc (mem, sizeof (ExifLoader));
- if (!loader) return NULL;
+ if (!loader)
+ return NULL;
loader->ref_count = 1;
loader->mem = mem;
@@ -289,7 +343,8 @@ exif_loader_new_mem (ExifMem *mem)
void
exif_loader_ref (ExifLoader *loader)
{
- if (loader) loader->ref_count++;
+ if (loader)
+ loader->ref_count++;
}
static void
@@ -297,10 +352,12 @@ exif_loader_free (ExifLoader *loader)
{
ExifMem *mem;
- if (!loader) return;
+ if (!loader)
+ return;
mem = loader->mem;
exif_loader_reset (loader);
+ exif_log_unref (loader->log);
exif_mem_free (mem, loader);
exif_mem_unref (mem);
}
@@ -308,7 +365,8 @@ exif_loader_free (ExifLoader *loader)
void
exif_loader_unref (ExifLoader *loader)
{
- if (!loader) return;
+ if (!loader)
+ return;
if (!--loader->ref_count)
exif_loader_free (loader);
}
@@ -316,7 +374,8 @@ exif_loader_unref (ExifLoader *loader)
void
exif_loader_reset (ExifLoader *loader)
{
- if (!loader) return;
+ if (!loader)
+ return;
exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;
loader->size = 0;
loader->bytes_read = 0;
@@ -330,7 +389,9 @@ exif_loader_get_data (ExifLoader *loader)
{
ExifData *ed;
- if (!loader) return NULL;
+ if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN) ||
+ !loader->bytes_read)
+ return NULL;
ed = exif_data_new_mem (loader->mem);
exif_data_log (ed, loader->log);
@@ -342,7 +403,8 @@ exif_loader_get_data (ExifLoader *loader)
void
exif_loader_log (ExifLoader *loader, ExifLog *log)
{
- if (!loader) return;
+ 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
index cf900c8..697e019 100644
--- a/src/libexif/exif-loader.h
+++ b/src/libexif/exif-loader.h
@@ -1,6 +1,8 @@
-/* exif-loader.h
- *
- * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net>
+/*! \file exif-loader.h
+ * \brief Defines the ExifLoader type
+ */
+/*
+ * Copyright (c) 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
@@ -22,7 +24,6 @@
#define __EXIF_LOADER_H__
#include <libexif/exif-data.h>
-#include <libexif/exif-loader.h>
#include <libexif/exif-log.h>
#include <libexif/exif-mem.h>
@@ -32,21 +33,48 @@ extern "C" {
typedef struct _ExifLoader ExifLoader;
+/*! Allocate a new ExifLoader
+ * \returns the allocated ExifLoader
+ */
ExifLoader *exif_loader_new (void);
-ExifLoader *exif_loader_new_mem (ExifMem *);
-void exif_loader_ref (ExifLoader *);
-void exif_loader_unref (ExifLoader *);
+/*! Allocate a new ExifLoader using an ExifMem
+ * \param[in] mem the ExifMem
+ * \returns the allocated ExifLoader
+ */
+ExifLoader *exif_loader_new_mem (ExifMem *mem);
+/*! Increase the refcount of the ExifLoader
+ * \param[in] loader the ExifLoader to increase the refcount of.
+ */
+void exif_loader_ref (ExifLoader *loader);
+/*! Decrease the refcount of the ExifLoader
+ * \param[in] loader the ExifLoader to decrease the refcount of.
+ * If the refcount reaches 0, the ExifLoader is freeed.
+ */
+void exif_loader_unref (ExifLoader *loader);
-void exif_loader_write_file (ExifLoader *, const char *fname);
+/*! Write a file to the ExifLoader
+ * \param[in] loader the loader
+ * \param[in] fname the path to the file to read
+ */
+void exif_loader_write_file (ExifLoader *loader, 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.
+/*! Write a buffer to the ExifLoader
+ * \param[in] loader the loader to write too
+ * \param[in] buf the buffer to read from
+ * \param[in] sz the size of the buffer
+ * \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);
+unsigned char exif_loader_write (ExifLoader *loader, unsigned char *buf, unsigned int sz);
-void exif_loader_reset (ExifLoader *);
-ExifData *exif_loader_get_data (ExifLoader *);
+/*! Reset the ExifLoader
+ * \param[in] loader the loader
+ */
+void exif_loader_reset (ExifLoader *loader);
+/*! Get an ExifData out of an ExifLoader
+ * \param[in] loader the loader
+ * \returns and allocated ExifData
+ */
+ExifData *exif_loader_get_data (ExifLoader *loader);
void exif_loader_log (ExifLoader *, ExifLog *);
diff --git a/src/libexif/exif-log.c b/src/libexif/exif-log.c
index 5dde1ce..195bfe2 100644
--- a/src/libexif/exif-log.c
+++ b/src/libexif/exif-log.c
@@ -1,6 +1,6 @@
/* exif-log.c
*
- * Copyright © 2004 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2004 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
@@ -35,7 +35,7 @@ struct _ExifLog {
ExifMem *mem;
};
-static struct {
+static const struct {
ExifLogCode code;
const char *title;
const char *message;
@@ -127,6 +127,10 @@ exif_log_set_func (ExifLog *log, ExifLogFunc func, void *data)
log->data = data;
}
+#ifdef NO_VERBOSE_TAG_STRINGS
+/* exif_log forms part of the API and can't be commented away */
+#undef exif_log
+#endif
void
exif_log (ExifLog *log, ExifLogCode code, const char *domain,
const char *format, ...)
diff --git a/src/libexif/exif-log.h b/src/libexif/exif-log.h
index 01eed3f..41f4bcf 100644
--- a/src/libexif/exif-log.h
+++ b/src/libexif/exif-log.h
@@ -1,7 +1,7 @@
/*! \file exif-log.h
* \brief log message infrastructure
*
- * Copyright © 2004 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2004 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
@@ -55,18 +55,28 @@ typedef void (* ExifLogFunc) (ExifLog *log, ExifLogCode, const char *domain,
*/
void exif_log_set_func (ExifLog *log, ExifLogFunc func, void *data);
+#ifndef NO_VERBOSE_TAG_STRINGS
void exif_log (ExifLog *log, ExifLogCode, const char *domain,
const char *format, ...)
#ifdef __GNUC__
__attribute__((__format__(printf,4,5)))
#endif
;
+#else
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define exif_log(...) do { } while (0)
+#elif defined(__GNUC__)
+#define exif_log(x...) do { } while (0)
+#else
+#define exif_log (void)
+#endif
+#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)
+#define EXIF_LOG_NO_MEMORY(l,d,s) exif_log ((l), EXIF_LOG_CODE_NO_MEMORY, (d), "Could not allocate %lu byte(s).", (unsigned long)(s))
#ifdef __cplusplus
}
diff --git a/src/libexif/exif-mem.c b/src/libexif/exif-mem.c
index 12027d1..7290b9d 100644
--- a/src/libexif/exif-mem.c
+++ b/src/libexif/exif-mem.c
@@ -33,7 +33,8 @@ exif_mem_new (ExifMemAllocFunc alloc_func, ExifMemReallocFunc realloc_func,
{
ExifMem *mem;
- if (!alloc_func || !realloc_func) return NULL;
+ if (!alloc_func && !realloc_func)
+ return NULL;
mem = alloc_func ? alloc_func (sizeof (ExifMem)) :
realloc_func (NULL, sizeof (ExifMem));
if (!mem) return NULL;
diff --git a/src/libexif/exif-mem.h b/src/libexif/exif-mem.h
index aa774c6..454e034 100644
--- a/src/libexif/exif-mem.h
+++ b/src/libexif/exif-mem.h
@@ -1,6 +1,11 @@
+/*! \file exif-mem.h
+ * \brief Define the ExifMem data type and the associated functions.
+ * ExifMem defines the memory management functions used by the ExifLoader.
+ */
+
/* exif-mem.h
*
- * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 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
@@ -27,24 +32,49 @@
extern "C" {
#endif /* __cplusplus */
-/* Should work like calloc: Needs to return initialized memory. */
-typedef void * (* ExifMemAllocFunc) (ExifLong);
+/*! Should work like calloc()
+ * \param[in] s the size of the block to allocate.
+ * \returns the allocated memory and initialized.
+ */
+typedef void * (* ExifMemAllocFunc) (ExifLong s);
-typedef void * (* ExifMemReallocFunc) (void *, ExifLong);
-typedef void (* ExifMemFreeFunc) (void *);
+/*! Should work like realloc()
+ * \param[in] p the pointer to reallocate
+ * \param[in] s the size of the reallocated block
+ * \returns allocated memory
+ */
+typedef void * (* ExifMemReallocFunc) (void *p, ExifLong s);
+/*! Free method for ExifMem
+ * \param[in] p the pointer to free
+ * \returns the freed pointer
+ */
+typedef void (* ExifMemFreeFunc) (void *p);
+/*! ExifMem define a memory allocator */
typedef struct _ExifMem ExifMem;
-ExifMem *exif_mem_new (ExifMemAllocFunc, ExifMemReallocFunc,
- ExifMemFreeFunc);
+/*! Create a new ExifMem
+ * \param[in] a the allocator function
+ * \param[in] r the reallocator function
+ * \param[in] f the free function
+ */
+ExifMem *exif_mem_new (ExifMemAllocFunc a, ExifMemReallocFunc r,
+ ExifMemFreeFunc f);
+/*! Refcount an ExifMem
+ */
void exif_mem_ref (ExifMem *);
+/*! Unrefcount an ExifMem
+ * If the refcount reaches 0, the ExifMem is freed
+ */
void exif_mem_unref (ExifMem *);
-void *exif_mem_alloc (ExifMem *, ExifLong);
-void *exif_mem_realloc (ExifMem *, void *, ExifLong);
-void exif_mem_free (ExifMem *, void *);
+void *exif_mem_alloc (ExifMem *m, ExifLong s);
+void *exif_mem_realloc (ExifMem *m, void *p, ExifLong s);
+void exif_mem_free (ExifMem *m, void *p);
-/* For your convenience */
+/*! The default ExifMem for your convenience
+ * \returns return the default ExifMem
+ */
ExifMem *exif_mem_new_default (void);
#ifdef __cplusplus
diff --git a/src/libexif/exif-mnote-data-priv.h b/src/libexif/exif-mnote-data-priv.h
index 3a13883..f8e5317 100644
--- a/src/libexif/exif-mnote-data-priv.h
+++ b/src/libexif/exif-mnote-data-priv.h
@@ -1,6 +1,6 @@
/* exif-mnote-data-priv.h
*
- * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 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
diff --git a/src/libexif/exif-mnote-data.c b/src/libexif/exif-mnote-data.c
index f55cdd4..efd8173 100644
--- a/src/libexif/exif-mnote-data.c
+++ b/src/libexif/exif-mnote-data.c
@@ -1,6 +1,6 @@
/* exif-mnote-data.c
*
- * Copyright (C) 2003 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (C) 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
diff --git a/src/libexif/exif-mnote-data.h b/src/libexif/exif-mnote-data.h
index 015f2ae..7c68393 100644
--- a/src/libexif/exif-mnote-data.h
+++ b/src/libexif/exif-mnote-data.h
@@ -1,6 +1,6 @@
/* exif-mnote-data.h
*
- * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 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
diff --git a/src/libexif/exif-system.h b/src/libexif/exif-system.h
new file mode 100644
index 0000000..082db60
--- /dev/null
+++ b/src/libexif/exif-system.h
@@ -0,0 +1,31 @@
+/** \file exif-system.h
+ * \brief System specific definitions, not for installation!
+ *
+ * Copyright (C) 2007 Hans Ulrich Niedermann <gp@n-dimensional.de>
+ *
+ * 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_SYSTEM_H
+#define EXIF_SYSTEM_H
+
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+# define UNUSED(param) UNUSED_PARAM_##param __attribute__((unused))
+#else
+# define UNUSED(param) param
+#endif
+
+#endif /* !defined(EXIF_SYSTEM_H) */
diff --git a/src/libexif/exif-tag.c b/src/libexif/exif-tag.c
index 7781611..7a8c7e1 100644
--- a/src/libexif/exif-tag.c
+++ b/src/libexif/exif-tag.c
@@ -1,6 +1,6 @@
/* exif-tag.c
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
@@ -26,22 +26,28 @@
#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 */
+#define ESL_NNNN { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED }
+#define ESL_OOOO { EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL }
+#define ESL_MMMN { EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_NOT_RECORDED }
+#define ESL_MMMM { EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY }
+#define ESL_OMON { EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_NOT_RECORDED }
+#define ESL_NNOO { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL }
+#define ESL_NNMN { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_NOT_RECORDED }
+#define ESL_NNMM { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY }
+#define ESL_NNNM { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_MANDATORY }
+#define ESL_NNNO { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_OPTIONAL }
+#define ESL_GPS { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN }
-static struct {
+static const 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];
+ ExifSupportLevel esl[EXIF_IFD_COUNT][4];
} ExifTagTable[] = {
+#ifndef NO_VERBOSE_TAG_STRINGS
{EXIF_TAG_NEW_SUBFILE_TYPE, "NewSubfileType",
- "New Subfile Type", N_("A general indication of the kind of data "
+ N_("New Subfile Type"), N_("A general indication of the kind of data "
"contained in this subfile.")},
{EXIF_TAG_INTEROPERABILITY_INDEX, "InteroperabilityIndex",
"InteroperabilityIndex",
@@ -49,35 +55,37 @@ static struct {
"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.")},
+ "for other tags used for ExifR98."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_OOOO } },
{EXIF_TAG_INTEROPERABILITY_VERSION, "InteroperabilityVersion",
- "InteroperabilityVersion", ""},
+ "InteroperabilityVersion", "",
+ { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_OOOO } },
{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}},
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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}},
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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 "
+ "tag is 8. 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}},
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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}},
+ { ESL_MMMN, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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}},
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_FILL_ORDER, "FillOrder", N_("Fill Order"), ""},
{EXIF_TAG_DOCUMENT_NAME, "DocumentName", N_("Document Name"), ""},
{EXIF_TAG_IMAGE_DESCRIPTION, "ImageDescription",
@@ -87,92 +95,105 @@ static struct {
"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}},
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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}},
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN }},
{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}},
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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}},
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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}},
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "tag."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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>.")},
+ "needed and is omitted. See also <StripOffsets> and "
+ "<StripByteCounts>."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "data this designation is not needed and is omitted."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "is designated."),
+ { ESL_MMMM, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "direction. The same value as <XResolution> is designated."),
+ { ESL_MMMM, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "the TIFF default of 1 (chunky) is assumed."),
+ { ESL_OMON, ESL_OMON, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "the image resolution is unknown, 2 (inches) is designated."),
+ { ESL_MMMM, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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>).")},
+ "specified in the color space information tag (<ColorSpace>)."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "unknown."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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-2.1) it is the date and time the file was changed."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "left blank, it is treated as unknown."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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>).")},
+ "in the color space information tag (<ColorSpace>)."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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>).")},
+ "Normally this tag is not necessary, since color space is "
+ "specified in the color space information tag (<ColorSpace>)."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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.")},
@@ -181,7 +202,8 @@ static struct {
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.")},
+ "JPEG data."),
+ { ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
"JPEGInterchangeFormatLength", N_("JPEG Interchange Format Length"),
N_("The number of bytes of JPEG compressed thumbnail data. This "
@@ -190,7 +212,8 @@ static struct {
"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.")},
+ "recorded in APP1."),
+ { ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_YCBCR_COEFFICIENTS, "YCbCrCoefficients",
N_("YCbCr Coefficients"),
N_("The matrix coefficients for transformation from RGB to YCbCr "
@@ -199,12 +222,14 @@ static struct {
"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.")},
+ "Interoperability this condition."),
+ { ESL_NNOO, ESL_NNOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "is used instead of this tag."),
+ { ESL_NNMN, ESL_NNMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_YCBCR_POSITIONING, "YCbCrPositioning",
N_("YCbCr Positioning"),
N_("The position of chrominance components in relation to the "
@@ -219,7 +244,8 @@ static struct {
"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.")},
+ "be able to support both centered and co-sited positioning."),
+ { ESL_NNMM, ESL_NNOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_REFERENCE_BLACK_WHITE, "ReferenceBlackWhite",
N_("Reference Black/White"),
N_("The reference black point value and reference white point "
@@ -227,7 +253,8 @@ static struct {
"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.")},
+ "Interoperability these conditions."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_XML_PACKET, "XMLPacket", N_("XML Packet"), N_("XMP Metadata")},
{EXIF_TAG_RELATED_IMAGE_FILE_FORMAT, "RelatedImageFileFormat",
"RelatedImageFileFormat", ""},
@@ -263,84 +290,113 @@ static struct {
"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.")},
+ "as unknown."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_EXPOSURE_TIME, "ExposureTime", N_("Exposure Time"),
- N_("Exposure time, given in seconds (sec).")},
+ N_("Exposure time, given in seconds (sec)."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_FNUMBER, "FNumber", N_("FNumber"),
- N_("The F number.")},
+ N_("The F number."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_IPTC_NAA, "IPTC/NAA", "IPTC/NAA", ""},
{EXIF_TAG_IMAGE_RESOURCES, "ImageResources", N_("Image Resources Block"), ""},
- {EXIF_TAG_EXIF_IFD_POINTER, "ExifIFDPointer", "ExifIFDPointer",
+ {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.")},
+ "the case of TIFF."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_INTER_COLOR_PROFILE, "InterColorProfile",
"InterColorProfile", ""},
- {EXIF_TAG_EXPOSURE_PROGRAM, "ExposureProgram", "ExposureProgram",
+ {EXIF_TAG_EXPOSURE_PROGRAM, "ExposureProgram", N_("Exposure Program"),
N_("The class of the program used by the camera to set exposure "
- "when the picture is taken.")},
+ "when the picture is taken."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "with the standard developed by the ASTM Technical Committee."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{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", "",
+ "Exif IFD, has no image data."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_GPS_VERSION_ID, "GPSVersionID", N_("GPS tag version"),
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, "
+ "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", ""
+ "2.0.0.0, the tag value is 02000000.H)."), ESL_GPS},
+ {EXIF_TAG_GPS_LATITUDE_REF, "GPSLatitudeRef", N_("North or South Latitude"),
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", ""
+ "latitude."), ESL_GPS},
+ {EXIF_TAG_GPS_LATITUDE, "GPSLatitude", N_("Latitude"),
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", ""
+ "decimal places, the format is dd/1,mmmm/100,0/1."),
+ ESL_GPS},
+ {EXIF_TAG_GPS_LONGITUDE_REF, "GPSLongitudeRef", N_("East or West Longitude"),
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", ""
+ "longitude."), ESL_GPS},
+ {EXIF_TAG_GPS_LONGITUDE, "GPSLongitude", N_("Longitude"),
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
+ "two decimal places, the format is ddd/1,mmmm/100,0/1."),
+ ESL_GPS},
+ {EXIF_TAG_GPS_ALTITUDE_REF, "GPSAltitudeRef", N_("Altitude reference"),
+ N_("Indicates the altitude used as the reference altitude. If the "
+ "reference is sea level and the altitude is above sea level, 0 "
+ "is given. If the altitude is below sea level, a value of 1 is given "
+ "and the altitude is indicated as an absolute value in the "
+ "GSPAltitude tag. The reference unit is meters. Note that this tag "
+ "is BYTE type, unlike other reference tags."), ESL_GPS},
+ {EXIF_TAG_GPS_ALTITUDE, "GPSAltitude", N_("Altitude"),
+ N_("Indicates the altitude based on the reference in GPSAltitudeRef. "
+ "Altitude is expressed as one RATIONAL value. The reference unit "
+ "is meters."), ESL_GPS},
+ {EXIF_TAG_GPS_IMG_DIRECTION_REF, "GPSImgDirectionRef", N_("GPS Img Direction Reference"),
+ N_("Indicates the reference for giving the direction of the image when it is captured. "
+ "'T' denotes true direction and 'M' is magnetic direction."), ESL_GPS},
+ {EXIF_TAG_GPS_IMG_DIRECTION, "GPSImgDirection", N_("GPS Img Direction"),
+ N_("Indicates the direction of the image when it was captured. The range of values is "
+ "from 0.00 to 359.99."), ESL_GPS},
{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.")},
+ "input device as specified in ISO 12232."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_OECF, "OECF", "OECF",
- N_("Indicates the Opto-Electoric Conversion Function (OECF) "
+ N_("Indicates the Opto-Electronic Conversion Function (OECF) "
"specified in ISO 14524. <OECF> is the relationship between "
- "the camera optical input and the image values.")},
+ "the camera optical input and the image values."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "field is taken to mean nonconformance to the standard."),
+ { ESL_NNNN, ESL_NNNN, ESL_MMMM, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "the date and time the picture was taken are recorded."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_DATE_TIME_DIGITIZED, "DateTimeDigitized",
N_("Date and Time (digitized)"),
- N_("The date and time when the image was stored as digital data. ")},
+ N_("The date and time when the image was stored as digital data. "),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_COMPONENTS_CONFIGURATION, "ComponentsConfiguration",
- "ComponentsConfiguration",
+ N_("Components Configuration"),
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 "
@@ -348,44 +404,56 @@ static struct {
"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.")},
+ "Y, Cb, and Cr and to enable support of other sequences."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "per pixel."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNO, ESL_NNNN, ESL_NNNN } },
{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).")},
+ "Photographic Exposure) setting."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_APERTURE_VALUE, "ApertureValue", N_("Aperture"),
- N_("The lens aperture. The unit is the APEX value.")},
+ N_("The lens aperture. The unit is the APEX value."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "Ordinarily it is given in the range of -99.99 to 99.99."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "it is given in the range of -99.99 to 99.99."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "but it is not limited to this range."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_SUBJECT_DISTANCE, "SubjectDistance",
N_("Subject Distance"),
- N_("The distance to the subject, given in meters.")},
+ N_("The distance to the subject, given in meters."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_METERING_MODE, "MeteringMode", N_("Metering Mode"),
- N_("The metering mode.")},
+ N_("The metering mode."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_LIGHT_SOURCE, "LightSource", N_("Light Source"),
- N_("The kind of light source.")},
+ N_("The kind of light source."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "made to the focal length of a 35 mm film camera."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "information. The contents are up to the manufacturer."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{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 "
@@ -396,7 +464,7 @@ static struct {
"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 "
+ "is determined 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). "
@@ -409,20 +477,35 @@ static struct {
"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].")},
+ "part be filled with blank characters [20.H]."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_SUB_SEC_TIME, "SubsecTime", "SubsecTime",
N_("A tag used to record fractions of seconds for the "
- "<DateTime> tag.")},
+ "<DateTime> tag."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_SUB_SEC_TIME_ORIGINAL, "SubSecTimeOriginal",
"SubSecTimeOriginal",
N_("A tag used to record fractions of seconds for the "
- "<DateTimeOriginal> tag.")},
+ "<DateTimeOriginal> tag."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_SUB_SEC_TIME_DIGITIZED, "SubSecTimeDigitized",
"SubSecTimeDigitized",
N_("A tag used to record fractions of seconds for the "
- "<DateTimeDigitized> tag.")},
+ "<DateTimeDigitized> tag."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_XP_TITLE, "XPTitle", N_("XP Title"), "",
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_XP_COMMENT, "XPComment", N_("XP Comment"), "",
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_XP_AUTHOR, "XPAuthor", N_("XP Author"), "",
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_XP_KEYWORDS, "XPKeywords", N_("XP Keywords"), "",
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_XP_SUBJECT, "XPSubject", N_("XP Subject"), "",
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_FLASH_PIX_VERSION, "FlashPixVersion", "FlashPixVersion",
- N_("The FlashPix format version supported by a FPXR file.")},
+ N_("The FlashPix format version supported by a FPXR file."),
+ { ESL_NNNN, ESL_NNNN, ESL_MMMM, ESL_NNNN, ESL_NNNN } },
{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) "
@@ -430,14 +513,15 @@ static struct {
"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.")},
+ "converted to FlashPix."),
+ { ESL_NNNN, ESL_NNNN, ESL_MMMM, ESL_NNNN, ESL_NNNN } },
{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.")},
+ "should not exist in an uncompressed file."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN } },
{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 "
@@ -446,7 +530,8 @@ static struct {
"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.")},
+ "will in fact be the same as that recorded in the SOF."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_RELATED_SOUND_FILE, "RelatedSoundFile",
"RelatedSoundFile",
N_("This tag is used to record the name of an audio file related "
@@ -478,7 +563,8 @@ static struct {
"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.")},
+ "audio file end."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
{EXIF_TAG_INTEROPERABILITY_IFD_POINTER, "InteroperabilityIFDPointer",
"InteroperabilityIFDPointer",
N_("Interoperability IFD is composed of tags which stores the "
@@ -488,7 +574,8 @@ static struct {
"the same as TIFF defined IFD structure "
"but does not contain the "
"image data characteristically compared with normal TIFF "
- "IFD.")},
+ "IFD."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
{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).")},
@@ -517,9 +604,9 @@ static struct {
"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 "
+ "indicates the X column number and the second indicates "
"the Y row number.")},
- {EXIF_TAG_EXPOSURE_INDEX, "ExposureIndex", N_("Exposure index"),
+ {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"),
@@ -527,7 +614,7 @@ static struct {
"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 "
+ "the 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, "
@@ -570,7 +657,7 @@ static struct {
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.")},
+ "<SceneType> tag.")},
{EXIF_TAG_GAIN_CONTROL, "GainControl", N_("Gain Control"),
N_("This tag indicates the degree of overall image gain "
"adjustment.")},
@@ -596,6 +683,11 @@ static struct {
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.")},
+ {EXIF_TAG_GAMMA, "Gamma", N_("Gamma"),
+ N_("Indicates the value of coefficient gamma.")},
+ {EXIF_TAG_PRINT_IMAGE_MATCHING, "PrintImageMatching", N_("PRINT Image Matching"),
+ N_("Related to Epson's PRINT Image Matching technology")},
+#endif
{0, NULL, NULL, NULL}
};
@@ -622,55 +714,144 @@ exif_tag_table_count (void)
return sizeof (ExifTagTable) / sizeof (ExifTagTable[0]);
}
+#define RECORDED \
+((ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_CHUNKY] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \
+ (ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_PLANAR] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \
+ (ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_YCC] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \
+ (ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_COMPRESSED] != EXIF_SUPPORT_LEVEL_NOT_RECORDED))
+
const char *
-exif_tag_get_name (ExifTag tag)
+exif_tag_get_name_in_ifd (ExifTag tag, ExifIfd ifd)
{
unsigned int i;
+ if (ifd >= EXIF_IFD_COUNT) return NULL;
for (i = 0; ExifTagTable[i].name; i++)
- if (ExifTagTable[i].tag == tag)
- break;
-
+ if ((ExifTagTable[i].tag == tag) && RECORDED) break;
return ExifTagTable[i].name;
}
const char *
-exif_tag_get_title (ExifTag tag)
+exif_tag_get_title_in_ifd (ExifTag tag, ExifIfd ifd)
{
unsigned int i;
/* FIXME: This belongs to somewhere else. */
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ /* libexif should use the default system locale.
+ * If an application specifically requires UTF-8, then we
+ * must give the application a way to tell libexif that.
+ *
+ * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ */
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-
+ if (ifd >= EXIF_IFD_COUNT) return NULL;
for (i = 0; ExifTagTable[i].title; i++)
- if (ExifTagTable[i].tag == tag) break;
+ if ((ExifTagTable[i].tag == tag) && RECORDED) break;
return _(ExifTagTable[i].title);
}
const char *
-exif_tag_get_description (ExifTag tag)
+exif_tag_get_description_in_ifd (ExifTag tag, ExifIfd ifd)
{
unsigned int i;
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ /* libexif should use the default system locale.
+ * If an application specifically requires UTF-8, then we
+ * must give the application a way to tell libexif that.
+ *
+ * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ */
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ if (ifd >= EXIF_IFD_COUNT) return NULL;
for (i = 0; ExifTagTable[i].description; i++)
- if (ExifTagTable[i].tag == tag) break;
- return _(ExifTagTable[i].description);
+ if ((ExifTagTable[i].tag == tag) && RECORDED) {
+ /* GNU gettext acts strangely when given an empty string */
+ if (!*ExifTagTable[i].description)
+ return "";
+ return _(ExifTagTable[i].description);
+ }
+ return NULL;
+}
+
+
+/**********************************************************************
+ * convenience functions
+ **********************************************************************/
+
+/* generic part: iterate through IFD list and return first result */
+typedef const char * (*get_stuff_func) (ExifTag tag, ExifIfd ifd);
+
+static const char *
+exif_tag_get_stuff (ExifTag tag, get_stuff_func func)
+{
+ static const ExifIfd ifds[5] = {
+ EXIF_IFD_0,
+ EXIF_IFD_1,
+ EXIF_IFD_EXIF,
+ EXIF_IFD_INTEROPERABILITY,
+ EXIF_IFD_GPS
+ };
+ int i;
+ for (i=0; i<5; i++) {
+ const char *result = func(tag, ifds[i]);
+ if (result != NULL) {
+ return result;
+ }
+ }
+ return (const char *) NULL;
+}
+
+/* explicit functions */
+const char *
+exif_tag_get_name (ExifTag tag)
+{
+ return exif_tag_get_stuff(tag, exif_tag_get_name_in_ifd);
}
+const char *
+exif_tag_get_title (ExifTag tag)
+{
+ return exif_tag_get_stuff(tag, exif_tag_get_title_in_ifd);
+}
+
+const char *
+exif_tag_get_description (ExifTag tag)
+{
+ return exif_tag_get_stuff (tag, exif_tag_get_description_in_ifd);
+}
+
+
+
ExifTag
exif_tag_from_name (const char *name)
{
unsigned int i;
+ unsigned int result=0;
if (!name) return 0;
for (i = 0; ExifTagTable[i].name; i++)
- if (!strcmp (ExifTagTable[i].name, name)) break;
- return ExifTagTable[i].tag;
+ if (!strcmp (ExifTagTable[i].name, name)) {
+ result = ExifTagTable[i].tag;
+ break;
+ }
+ return result;
+}
+
+ExifSupportLevel
+exif_tag_get_support_level_in_ifd (ExifTag tag, ExifIfd ifd, ExifDataType t)
+{
+ unsigned int i;
+
+ if (ifd >= EXIF_IFD_COUNT) return EXIF_SUPPORT_LEVEL_UNKNOWN;
+ if (t >= EXIF_DATA_TYPE_COUNT) return EXIF_SUPPORT_LEVEL_UNKNOWN;
+
+ for (i = 0; ExifTagTable[i].description; i++)
+ if ((ExifTagTable[i].tag == tag) &&
+ (ExifTagTable[i].esl[ifd][t] != EXIF_SUPPORT_LEVEL_NOT_RECORDED))
+ return ExifTagTable[i].esl[ifd][t];
+ return EXIF_SUPPORT_LEVEL_NOT_RECORDED;
}
const char *
@@ -683,4 +864,3 @@ exif_tag_get_name_index (unsigned int i, ExifTag *tag)
return (ExifTagTable[i].name);
}
-
diff --git a/src/libexif/exif-tag.h b/src/libexif/exif-tag.h
index f928374..8b43405 100644
--- a/src/libexif/exif-tag.h
+++ b/src/libexif/exif-tag.h
@@ -1,6 +1,6 @@
/* exif-tag.h
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
@@ -25,6 +25,9 @@
extern "C" {
#endif /* __cplusplus */
+#include <libexif/exif-ifd.h>
+#include <libexif/exif-data-type.h>
+
typedef enum {
EXIF_TAG_INTEROPERABILITY_INDEX = 0x0001,
EXIF_TAG_INTEROPERABILITY_VERSION = 0x0002,
@@ -104,6 +107,11 @@ typedef enum {
EXIF_TAG_SUB_SEC_TIME = 0x9290,
EXIF_TAG_SUB_SEC_TIME_ORIGINAL = 0x9291,
EXIF_TAG_SUB_SEC_TIME_DIGITIZED = 0x9292,
+ EXIF_TAG_XP_TITLE = 0x9c9b,
+ EXIF_TAG_XP_COMMENT = 0x9c9c,
+ EXIF_TAG_XP_AUTHOR = 0x9c9d,
+ EXIF_TAG_XP_KEYWORDS = 0x9c9e,
+ EXIF_TAG_XP_SUBJECT = 0x9c9f,
EXIF_TAG_FLASH_PIX_VERSION = 0xa000,
EXIF_TAG_COLOR_SPACE = 0xa001,
EXIF_TAG_PIXEL_X_DIMENSION = 0xa002,
@@ -133,14 +141,66 @@ typedef enum {
EXIF_TAG_SHARPNESS = 0xa40a,
EXIF_TAG_DEVICE_SETTING_DESCRIPTION = 0xa40b,
EXIF_TAG_SUBJECT_DISTANCE_RANGE = 0xa40c,
- EXIF_TAG_IMAGE_UNIQUE_ID = 0xa420
+ EXIF_TAG_IMAGE_UNIQUE_ID = 0xa420,
+ EXIF_TAG_GAMMA = 0xa500,
+ EXIF_TAG_PRINT_IMAGE_MATCHING = 0xc4a5
} ExifTag;
-ExifTag exif_tag_from_name (const char *);
+/* GPS tags overlap with above ones. */
+#define EXIF_TAG_GPS_VERSION_ID 0x0000
+#define EXIF_TAG_GPS_LATITUDE_REF 0x0001 /* INTEROPERABILITY_INDEX */
+#define EXIF_TAG_GPS_LATITUDE 0x0002 /* INTEROPERABILITY_VERSION */
+#define EXIF_TAG_GPS_LONGITUDE_REF 0x0003
+#define EXIF_TAG_GPS_LONGITUDE 0x0004
+#define EXIF_TAG_GPS_ALTITUDE_REF 0x0005
+#define EXIF_TAG_GPS_ALTITUDE 0x0006
+#define EXIF_TAG_GPS_TIME_STAMP 0x0007
+#define EXIF_TAG_GPS_SATELLITES 0x0008
+#define EXIF_TAG_GPS_STATUS 0x0009
+#define EXIF_TAG_GPS_MEASURE_MODE 0x000a
+#define EXIF_TAG_GPS_DOP 0x000b
+#define EXIF_TAG_GPS_SPEED_REF 0x000c
+#define EXIF_TAG_GPS_SPEED 0x000d
+#define EXIF_TAG_GPS_TRACK_REF 0x000e
+#define EXIF_TAG_GPS_TRACK 0x000f
+#define EXIF_TAG_GPS_IMG_DIRECTION_REF 0x0010
+#define EXIF_TAG_GPS_IMG_DIRECTION 0x0011
+#define EXIF_TAG_GPS_MAP_DATUM 0x0012
+#define EXIF_TAG_GPS_DEST_LATITUDE_REF 0x0013
+#define EXIF_TAG_GPS_DEST_LATITUDE 0x0014
+#define EXIF_TAG_GPS_DEST_LONGITUDE_REF 0x0015
+#define EXIF_TAG_GPS_DEST_LONGITUDE 0x0016
+#define EXIF_TAG_GPS_DEST_BEARING_REF 0x0017
+#define EXIF_TAG_GPS_DEST_BEARING 0x0018
+#define EXIF_TAG_GPS_DEST_DISTANCE_REF 0x0019
+#define EXIF_TAG_GPS_DEST_DISTANCE 0x001a
+#define EXIF_TAG_GPS_PROCESSING_METHOD 0x001b
+#define EXIF_TAG_GPS_AREA_INFORMATION 0x001c
+#define EXIF_TAG_GPS_DATE_STAMP 0x001d
+#define EXIF_TAG_GPS_DIFFERENTIAL 0x001e
+
+typedef enum {
+ EXIF_SUPPORT_LEVEL_UNKNOWN = 0,
+ EXIF_SUPPORT_LEVEL_NOT_RECORDED,
+ EXIF_SUPPORT_LEVEL_MANDATORY,
+ EXIF_SUPPORT_LEVEL_OPTIONAL
+} ExifSupportLevel;
+
+ExifTag exif_tag_from_name (const char *);
+const char *exif_tag_get_name_in_ifd (ExifTag, ExifIfd);
+const char *exif_tag_get_title_in_ifd (ExifTag, ExifIfd);
+const char *exif_tag_get_description_in_ifd (ExifTag, ExifIfd);
+ExifSupportLevel exif_tag_get_support_level_in_ifd (ExifTag, ExifIfd,
+ ExifDataType);
+
+/* Don't use these functions. They are here for compatibility only. */
const char *exif_tag_get_name (ExifTag tag);
const char *exif_tag_get_title (ExifTag tag);
const char *exif_tag_get_description (ExifTag tag);
+/* Don't use these definitions. They are here for compatibility only. */
+#define EXIF_TAG_UNKNOWN_C4A5 EXIF_TAG_PRINT_IMAGE_MATCHING
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/src/libexif/exif-utils.c b/src/libexif/exif-utils.c
index 9386012..a6e7696 100644
--- a/src/libexif/exif-utils.c
+++ b/src/libexif/exif-utils.c
@@ -1,6 +1,6 @@
/* exif-utils.c
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
@@ -212,3 +212,40 @@ exif_set_srational (unsigned char *buf, ExifByteOrder order,
exif_set_slong (buf, order, value.numerator);
exif_set_slong (buf + 4, order, value.denominator);
}
+
+void
+exif_convert_utf16_to_utf8 (char *out, const unsigned short *in, int maxlen)
+{
+ /* This function converts rather UCS2 than UTF16 to UTF8 */
+ if (maxlen <= 0) {
+ return;
+ }
+ while (*in) {
+ if (*in < 0x80) {
+ if (maxlen > 1) {
+ *out++ = (char)*in++;
+ maxlen--;
+ } else {
+ break;
+ }
+ } else if (*in < 0x800) {
+ if (maxlen > 2) {
+ *out++ = ((*in >> 6) & 0x1F) | 0xC0;
+ *out++ = (*in++ & 0x3F) | 0x80;
+ maxlen -= 2;
+ } else {
+ break;
+ }
+ } else {
+ if (maxlen > 2) {
+ *out++ = ((*in >> 12) & 0x0F) | 0xE0;
+ *out++ = ((*in >> 6) & 0x3F) | 0x80;
+ *out++ = (*in++ & 0x3F) | 0x80;
+ maxlen -= 3;
+ } else {
+ break;
+ }
+ }
+ }
+ *out = 0;
+}
diff --git a/src/libexif/exif-utils.h b/src/libexif/exif-utils.h
index a75db0b..85b650a 100644
--- a/src/libexif/exif-utils.h
+++ b/src/libexif/exif-utils.h
@@ -1,6 +1,6 @@
/* exif-utils.h
*
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2001 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
@@ -33,14 +33,20 @@ extern "C" {
/* If these definitions don't work for you, please let us fix the
* macro generating _stdint.h */
-typedef char ExifByte; /* 1 byte */
+typedef unsigned char ExifByte; /* 1 byte */
+typedef signed char ExifSByte; /* 1 byte */
typedef char * ExifAscii;
typedef uint16_t ExifShort; /* 2 bytes */
typedef int16_t ExifSShort; /* 2 bytes */
typedef uint32_t ExifLong; /* 4 bytes */
+
+/** EXIF Unsigned Rational */
typedef struct {ExifLong numerator; ExifLong denominator;} ExifRational;
+
typedef char ExifUndefined; /* 1 byte */
typedef int32_t ExifSLong; /* 4 bytes */
+
+/** EXIF Signed Rational. */
typedef struct {ExifSLong numerator; ExifSLong denominator;} ExifSRational;
@@ -64,6 +70,8 @@ void exif_set_rational (unsigned char *b, ExifByteOrder order,
void exif_set_srational (unsigned char *b, ExifByteOrder order,
ExifSRational value);
+void exif_convert_utf16_to_utf8 (char *out, const unsigned short *in, int maxlen);
+
/* 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);
@@ -71,6 +79,9 @@ void exif_array_set_byte_order (ExifFormat, unsigned char *, unsigned int,
#undef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#undef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
/* For compatibility with older versions */
#define EXIF_TAG_SUBSEC_TIME EXIF_TAG_SUB_SEC_TIME
diff --git a/src/libexif/exif.c b/src/libexif/exif.c
deleted file mode 100644
index 3be72a3..0000000
--- a/src/libexif/exif.c
+++ /dev/null
@@ -1,1274 +0,0 @@
-/*
-
-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
deleted file mode 100644
index 32f0a6d..0000000
--- a/src/libexif/exif.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-
-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/fuji/exif-mnote-data-fuji.c b/src/libexif/fuji/exif-mnote-data-fuji.c
new file mode 100644
index 0000000..b7b311b
--- /dev/null
+++ b/src/libexif/fuji/exif-mnote-data-fuji.c
@@ -0,0 +1,297 @@
+/* exif-mnote-data-fuji.c
+ *
+ * Copyright (c) 2002 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 <stdlib.h>
+#include <string.h>
+
+
+#include <config.h>
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-utils.h>
+
+#include "exif-mnote-data-fuji.h"
+
+struct _MNoteFujiDataPrivate {
+ ExifByteOrder order;
+};
+
+static void
+exif_mnote_data_fuji_clear (ExifMnoteDataFuji *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_fuji_free (ExifMnoteData *n)
+{
+ if (!n) return;
+
+ exif_mnote_data_fuji_clear ((ExifMnoteDataFuji *) n);
+}
+
+static char *
+exif_mnote_data_fuji_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
+{
+ ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
+
+ if (!d || !val) return NULL;
+ if (i > n->count -1) return NULL;
+ exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
+ "Querying value for tag '%s'...",
+ mnote_fuji_tag_get_name (n->entries[i].tag));
+ return mnote_fuji_entry_get_value (&n->entries[i], val, maxlen);
+}
+
+static void
+exif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf,
+ unsigned int *buf_size)
+{
+ ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) ne;
+ size_t i, o, s, doff;
+ unsigned char *t;
+ size_t ts;
+
+ if (!n || !buf || !buf_size) return;
+
+ /*
+ * Allocate enough memory for all entries and the number
+ * of entries.
+ */
+ *buf_size = 8 + 4 + 2 + n->count * 12 + 4;
+ *buf = exif_mem_alloc (ne->mem, *buf_size);
+ if (!*buf) {
+ *buf_size = 0;
+ return;
+ }
+
+ /*
+ * Header: "FUJIFILM" and 4 bytes offset to the first entry.
+ * As the first entry will start right thereafter, the offset is 12.
+ */
+ memcpy (*buf, "FUJIFILM", 8);
+ exif_set_long (*buf + 8, n->order, 12);
+
+ /* Save the number of entries */
+ exif_set_short (*buf + 8 + 4, n->order, (ExifShort) n->count);
+
+ /* Save each entry */
+ for (i = 0; i < n->count; i++) {
+ o = 8 + 4 + 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 > 65536) {
+ /* Corrupt data: EXIF data size is limited to the
+ * maximum size of a JPEG segment (64 kb).
+ */
+ continue;
+ }
+ if (s > 4) {
+ ts = *buf_size + s;
+
+ /* Ensure even offsets. Set padding bytes to 0. */
+ if (s & 1) ts += 1;
+ t = exif_mem_realloc (ne->mem, *buf, ts);
+ if (!t) {
+ return;
+ }
+ *buf = t;
+ *buf_size = ts;
+ doff = *buf_size - s;
+ if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
+ exif_set_long (*buf + o, n->order, 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);
+ }
+}
+
+static void
+exif_mnote_data_fuji_load (ExifMnoteData *en,
+ const unsigned char *buf, unsigned int buf_size)
+{
+ ExifMnoteDataFuji *n = (ExifMnoteDataFuji*) en;
+ ExifLong c;
+ size_t i, o, s, datao = 6 + n->offset;
+ MnoteFujiEntry *t;
+
+ if (!n || !buf || !buf_size || (buf_size < datao + 12)) return;
+
+ /* Read the number of entries and remove old ones. */
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL);
+ c = exif_get_short (buf + datao, EXIF_BYTE_ORDER_INTEL);
+ datao += 2;
+ exif_mnote_data_fuji_clear (n);
+
+ /* Parse the entries */
+ for (i = 0; i < c; i++) {
+ o = datao + 12 * i;
+ if (datao + 12 > buf_size) return;
+
+ t = exif_mem_realloc (en->mem, n->entries,
+ sizeof (MnoteFujiEntry) * (i + 1));
+ if (!t) return;
+ n->count = i + 1;
+ n->entries = t;
+ memset (&n->entries[i], 0, sizeof (MnoteFujiEntry));
+ 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 + n->offset;
+ if (o + s > buf_size) return;
+
+ /* Sanity check */
+ n->entries[i].data = exif_mem_alloc (en->mem, 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_fuji_count (ExifMnoteData *n)
+{
+ return n ? ((ExifMnoteDataFuji *) n)->count : 0;
+}
+
+static unsigned int
+exif_mnote_data_fuji_get_id (ExifMnoteData *d, unsigned int n)
+{
+ ExifMnoteDataFuji *note = (ExifMnoteDataFuji *) d;
+
+ if (!note) return 0;
+ if (note->count <= n) return 0;
+ return note->entries[n].tag;
+}
+
+static const char *
+exif_mnote_data_fuji_get_name (ExifMnoteData *d, unsigned int i)
+{
+ ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
+
+ if (!n) return NULL;
+ if (i >= n->count) return NULL;
+ return mnote_fuji_tag_get_name (n->entries[i].tag);
+}
+
+static const char *
+exif_mnote_data_fuji_get_title (ExifMnoteData *d, unsigned int i)
+{
+ ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
+
+ if (!n) return NULL;
+ if (i >= n->count) return NULL;
+ return mnote_fuji_tag_get_title (n->entries[i].tag);
+}
+
+static const char *
+exif_mnote_data_fuji_get_description (ExifMnoteData *d, unsigned int i)
+{
+ ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
+
+ if (!n) return NULL;
+ if (i >= n->count) return NULL;
+ return mnote_fuji_tag_get_description (n->entries[i].tag);
+}
+
+static void
+exif_mnote_data_fuji_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
+{
+ ExifByteOrder o_orig;
+ ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) 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_fuji_set_offset (ExifMnoteData *n, unsigned int o)
+{
+ if (n) ((ExifMnoteDataFuji *) n)->offset = o;
+}
+
+ExifMnoteData *
+exif_mnote_data_fuji_new (ExifMem *mem)
+{
+ ExifMnoteData *d;
+
+ if (!mem) return NULL;
+
+ d = exif_mem_alloc (mem, sizeof (ExifMnoteDataFuji));
+ if (!d) return NULL;
+
+ exif_mnote_data_construct (d, mem);
+
+ /* Set up function pointers */
+ d->methods.free = exif_mnote_data_fuji_free;
+ d->methods.set_byte_order = exif_mnote_data_fuji_set_byte_order;
+ d->methods.set_offset = exif_mnote_data_fuji_set_offset;
+ d->methods.load = exif_mnote_data_fuji_load;
+ d->methods.save = exif_mnote_data_fuji_save;
+ d->methods.count = exif_mnote_data_fuji_count;
+ d->methods.get_id = exif_mnote_data_fuji_get_id;
+ d->methods.get_name = exif_mnote_data_fuji_get_name;
+ d->methods.get_title = exif_mnote_data_fuji_get_title;
+ d->methods.get_description = exif_mnote_data_fuji_get_description;
+ d->methods.get_value = exif_mnote_data_fuji_get_value;
+
+ return d;
+}
diff --git a/src/libexif/fuji/exif-mnote-data-fuji.h b/src/libexif/fuji/exif-mnote-data-fuji.h
new file mode 100644
index 0000000..298193a
--- /dev/null
+++ b/src/libexif/fuji/exif-mnote-data-fuji.h
@@ -0,0 +1,43 @@
+/* exif-mnote-data-fuji.h
+ *
+ * Copyright (c) 2002 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_FUJI_CONTENT_H__
+#define __MNOTE_FUJI_CONTENT_H__
+
+#include <libexif/exif-mnote-data.h>
+
+typedef struct _ExifMnoteDataFuji ExifMnoteDataFuji;
+
+#include <libexif/exif-mnote-data-priv.h>
+#include <libexif/fuji/mnote-fuji-entry.h>
+
+struct _ExifMnoteDataFuji {
+ ExifMnoteData parent;
+
+ MnoteFujiEntry *entries;
+ unsigned int count;
+
+ ExifByteOrder order;
+ unsigned int offset;
+};
+
+ExifMnoteData *exif_mnote_data_fuji_new (ExifMem *);
+
+#endif /* __MNOTE_FUJI_CONTENT_H__ */
diff --git a/src/libexif/fuji/mnote-fuji-entry.c b/src/libexif/fuji/mnote-fuji-entry.c
new file mode 100644
index 0000000..ea978ac
--- /dev/null
+++ b/src/libexif/fuji/mnote-fuji-entry.c
@@ -0,0 +1,306 @@
+/* mnote-fuji-entry.c
+ *
+ * Copyright (c) 2002 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <config.h>
+
+#include <libexif/i18n.h>
+
+#include "mnote-fuji-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 const struct {
+ ExifTag tag;
+ struct {
+ int index;
+ const char *string;
+ } elem[22];
+} items[] = {
+#ifndef NO_VERBOSE_TAG_DATA
+ { MNOTE_FUJI_TAG_SHARPNESS,
+ { {1, N_("Softest")},
+ {2, N_("Soft")},
+ {3, N_("Normal")},
+ {4, N_("Hard")},
+ {5, N_("Hardest")},
+ {0x0082, N_("Medium soft")},
+ {0x0084, N_("Medium hard")},
+ {0x8000, N_("Film simulation mode")},
+ {0xFFFF, N_("Off")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_WHITE_BALANCE,
+ { {0, N_("Auto")},
+ {0x100, N_("Daylight")},
+ {0x200, N_("Cloudy")},
+ {0x300, N_("Daylight-color fluorescent")},
+ {0x301, N_("DayWhite-color fluorescent")},
+ {0x302, N_("White fluorescent")},
+ {0x400, N_("Incandescent")},
+ {0x500, N_("Flash")},
+ {0xF00, N_("Custom")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_COLOR,
+ { {0, N_("Standard")},
+ {0x0080, N_("Medium high")},
+ {0x0100, N_("High")},
+ {0x0180, N_("Medium low")},
+ {0x0200, N_("Original")},
+ {0x0300, N_("Black & white")},
+ {0x8000, N_("Film simulation mode")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_TONE,
+ { {0, N_("Standard")},
+ {0x0080, N_("Medium hard")},
+ {0x0100, N_("Hard")},
+ {0x0180, N_("Medium soft")},
+ {0x0200, N_("Original")},
+ {0x8000, N_("Film simulation mode")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_FLASH_MODE,
+ { {0, N_("Auto")},
+ {1, N_("On")},
+ {2, N_("Off")},
+ {3, N_("Red-eye reduction")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_MACRO,
+ { {0, N_("Off")},
+ {1, N_("On")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_FOCUS_MODE,
+ { {0, N_("Auto")},
+ {1, N_("Manual")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_SLOW_SYNC,
+ { {0, N_("Off")},
+ {1, N_("On")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_PICTURE_MODE,
+ { {0, N_("Auto")},
+ {1, N_("Portrait")},
+ {2, N_("Landscape")},
+ {4, N_("Sports")},
+ {5, N_("Night")},
+ {6, N_("Program AE")},
+ {7, N_("Natural photo")},
+ {8, N_("Vibration reduction")},
+ {0x000A, N_("Sunset")},
+ {0x000B, N_("Museum")},
+ {0x000C, N_("Party")},
+ {0x000D, N_("Flower")},
+ {0x000E, N_("Text")},
+ {0x000F, N_("NP & flash")},
+ {0x0010, N_("Beach")},
+ {0x0011, N_("Snow")},
+ {0x0012, N_("Fireworks")},
+ {0x0013, N_("Underwater")},
+ {0x0100, N_("Aperture priority AE")},
+ {0x0200, N_("Shutter priority AE")},
+ {0x0300, N_("Manual exposure")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_CONT_TAKING,
+ { {0, N_("Off")},
+ {1, N_("On")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_FINEPIX_COLOR,
+ { {0x00, N_("F-Standard")},
+ {0x10, N_("F-Chrome")},
+ {0x30, N_("F-B&W")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_BLUR_CHECK,
+ { {0, N_("No blur")},
+ {1, N_("Blur warning")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_FOCUS_CHECK,
+ { {0, N_("Focus good")},
+ {1, N_("Out of focus")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_AUTO_EXPOSURE_CHECK,
+ { {0, N_("AE good")},
+ {1, N_("Over exposed")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_DYNAMIC_RANGE,
+ { {1, N_("Standard")},
+ {3, N_("Wide")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_FILM_MODE,
+ { {0, N_("F0/Standard")},
+ {0x0100, N_("F1/Studio portrait")},
+ {0x0110, N_("F1a/Professional portrait")},
+ {0x0120, N_("F1b/Professional portrait")},
+ {0x0130, N_("F1c/Professional portrait")},
+ {0x0200, N_("F2/Fujichrome")},
+ {0x0300, N_("F3/Studio portrait Ex")},
+ {0x0400, N_("F4/Velvia")},
+ {0, NULL}}},
+ { MNOTE_FUJI_TAG_DYNAMIC_RANGE_SETTING,
+ { {0, N_("Auto (100-400%)")},
+ {1, N_("RAW")},
+ {0x0100, N_("Standard (100%)")},
+ {0x0200, N_("Wide1 (230%)")},
+ {0x0201, N_("Wide2 (400%)")},
+ {0x8000, N_("Film simulation mode")},
+ {0, NULL}}},
+#endif
+ {0, {{0, NULL}}}
+};
+
+
+char *
+mnote_fuji_entry_get_value (MnoteFujiEntry *entry,
+ char *val, unsigned int maxlen)
+{
+ ExifLong vl;
+ ExifSLong vsl;
+ ExifShort vs, vs2;
+ ExifRational vr;
+ ExifSRational vsr;
+ int i, j;
+
+ if (!entry) return (NULL);
+
+ memset (val, 0, maxlen);
+ maxlen--;
+
+ switch (entry->tag) {
+ case MNOTE_FUJI_TAG_VERSION:
+ CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (entry->components, 4, val, maxlen);
+ memcpy (val, entry->data, MIN(maxlen, entry->size));
+ break;
+ case MNOTE_FUJI_TAG_SHARPNESS:
+ case MNOTE_FUJI_TAG_WHITE_BALANCE:
+ case MNOTE_FUJI_TAG_COLOR:
+ case MNOTE_FUJI_TAG_TONE:
+ case MNOTE_FUJI_TAG_FLASH_MODE:
+ case MNOTE_FUJI_TAG_MACRO:
+ case MNOTE_FUJI_TAG_FOCUS_MODE:
+ case MNOTE_FUJI_TAG_SLOW_SYNC:
+ case MNOTE_FUJI_TAG_PICTURE_MODE:
+ case MNOTE_FUJI_TAG_CONT_TAKING:
+ case MNOTE_FUJI_TAG_FINEPIX_COLOR:
+ case MNOTE_FUJI_TAG_BLUR_CHECK:
+ case MNOTE_FUJI_TAG_FOCUS_CHECK:
+ case MNOTE_FUJI_TAG_AUTO_EXPOSURE_CHECK:
+ case MNOTE_FUJI_TAG_DYNAMIC_RANGE:
+ case MNOTE_FUJI_TAG_FILM_MODE:
+ case MNOTE_FUJI_TAG_DYNAMIC_RANGE_SETTING:
+ 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) {
+ snprintf (val, maxlen,
+ _("Internal error (unknown value %i)"), vs);
+ 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;
+ }
+ strncpy (val, _(items[i].elem[j].string), maxlen);
+ break;
+ case MNOTE_FUJI_TAG_FOCUS_POINT:
+ CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
+ CC (entry->components, 2, val, maxlen);
+ vs = exif_get_short (entry->data, entry->order);
+ vs2 = exif_get_short (entry->data+2, entry->order);
+ snprintf (val, maxlen, "%i, %i", vs, vs2);
+ break;
+ case MNOTE_FUJI_TAG_MIN_FOCAL_LENGTH:
+ case MNOTE_FUJI_TAG_MAX_FOCAL_LENGTH:
+ CF (entry->format, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (entry->components, 1, val, maxlen);
+ vr = exif_get_rational (entry->data, entry->order);
+ if (!vr.denominator) break;
+ snprintf (val, maxlen, _("%2.2f mm"), (double) vr.numerator /
+ vr.denominator);
+ break;
+
+ default:
+ switch (entry->format) {
+ case EXIF_FORMAT_ASCII:
+ strncpy (val, (char *)entry->data, MIN(maxlen, entry->size));
+ 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, "%lu", (long unsigned) vl);
+ break;
+ case EXIF_FORMAT_SLONG:
+ vsl = exif_get_slong (entry->data, entry->order);
+ snprintf (val, maxlen, "%li", (long int) vsl);
+ break;
+ case EXIF_FORMAT_RATIONAL:
+ vr = exif_get_rational (entry->data, entry->order);
+ if (!vr.denominator) break;
+ snprintf (val, maxlen, "%2.4f", (double) vr.numerator /
+ vr.denominator);
+ break;
+ case EXIF_FORMAT_SRATIONAL:
+ vsr = exif_get_srational (entry->data, entry->order);
+ if (!vsr.denominator) break;
+ snprintf (val, maxlen, "%2.4f", (double) vsr.numerator /
+ vsr.denominator);
+ break;
+ case EXIF_FORMAT_UNDEFINED:
+ default:
+ snprintf (val, maxlen, _("%i bytes unknown data"),
+ entry->size);
+ break;
+ }
+ break;
+ }
+
+ return (val);
+}
diff --git a/src/libexif/fuji/mnote-fuji-entry.h b/src/libexif/fuji/mnote-fuji-entry.h
new file mode 100644
index 0000000..322d2d2
--- /dev/null
+++ b/src/libexif/fuji/mnote-fuji-entry.h
@@ -0,0 +1,45 @@
+/* mnote-fuji-entry.h
+ *
+ * Copyright (c) 2002 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_FUJI_ENTRY_H__
+#define __MNOTE_FUJI_ENTRY_H__
+
+#include <libexif/exif-format.h>
+#include <libexif/fuji/mnote-fuji-tag.h>
+
+typedef struct _MnoteFujiEntry MnoteFujiEntry;
+typedef struct _MnoteFujiEntryPrivate MnoteFujiEntryPrivate;
+
+#include <libexif/fuji/exif-mnote-data-fuji.h>
+
+struct _MnoteFujiEntry {
+ MnoteFujiTag tag;
+ ExifFormat format;
+ unsigned long components;
+
+ unsigned char *data;
+ unsigned int size;
+
+ ExifByteOrder order;
+};
+
+char *mnote_fuji_entry_get_value (MnoteFujiEntry *entry, char *val, unsigned int maxlen);
+
+#endif /* __MNOTE_FUJI_ENTRY_H__ */
diff --git a/src/libexif/fuji/mnote-fuji-tag.c b/src/libexif/fuji/mnote-fuji-tag.c
new file mode 100644
index 0000000..bff33d8
--- /dev/null
+++ b/src/libexif/fuji/mnote-fuji-tag.c
@@ -0,0 +1,105 @@
+/* mnote-fuji-tag.c
+ *
+ * Copyright (c) 2002 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 <stdlib.h>
+
+#include <config.h>
+#include <libexif/i18n.h>
+
+#include "mnote-fuji-tag.h"
+
+
+static struct {
+ MnoteFujiTag tag;
+ const char *name;
+ const char *title;
+ const char *description;
+} table[] = {
+#ifndef NO_VERBOSE_TAG_STRINGS
+ {MNOTE_FUJI_TAG_VERSION, "Version", N_("Maker Note Version"), ""},
+ {MNOTE_FUJI_TAG_SERIAL_NUMBER, "SerialNumber", N_("Serial Number"), N_("This number is unique, it contains the date of manufacture.")},
+ {MNOTE_FUJI_TAG_QUALITY, "Quality", N_("Quality"), ""},
+ {MNOTE_FUJI_TAG_SHARPNESS, "Sharpness", N_("Sharpness"), ""},
+ {MNOTE_FUJI_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance"), ""},
+ {MNOTE_FUJI_TAG_COLOR, "ChromaticitySaturation", N_("Chromaticity Saturation"), ""},
+ {MNOTE_FUJI_TAG_TONE, "Contrast", N_("Contrast"), ""},
+ {MNOTE_FUJI_TAG_FLASH_MODE, "FlashMode", N_("Flash Mode"), ""},
+ {MNOTE_FUJI_TAG_FLASH_STRENGTH, "FlashStrength", N_("Flash Firing Strength Compensation"), ""},
+ {MNOTE_FUJI_TAG_MACRO, "MacroMode", N_("Macro mode"), ""},
+ {MNOTE_FUJI_TAG_FOCUS_MODE, "FocusingMode", N_("Focusing Mode"), ""},
+ {MNOTE_FUJI_TAG_FOCUS_POINT, "FocusPoint", N_("Focus Point"), ""},
+ {MNOTE_FUJI_TAG_SLOW_SYNC, "SlowSynchro", N_("Slow Synchro Mode"), ""},
+ {MNOTE_FUJI_TAG_PICTURE_MODE, "PictureMode", N_("Picture Mode"), ""},
+ {MNOTE_FUJI_TAG_CONT_TAKING, "ContinuousTaking", N_("Continuous Taking"), ""},
+ {MNOTE_FUJI_TAG_SEQUENCE_NUMBER, "ContinuousSequence", N_("Continuous Sequence Number"), ""},
+ {MNOTE_FUJI_TAG_FINEPIX_COLOR, "FinePixColor", N_("FinePix Color"), ""},
+ {MNOTE_FUJI_TAG_BLUR_CHECK, "BlurCheck", N_("Blur Check"), ""},
+ {MNOTE_FUJI_TAG_FOCUS_CHECK, "AutoFocusCheck", N_("Auto Focus Check"), ""},
+ {MNOTE_FUJI_TAG_AUTO_EXPOSURE_CHECK, "AutoExposureCheck", N_("Auto Exposure Check"), ""},
+ {MNOTE_FUJI_TAG_DYNAMIC_RANGE, "DynamicRange", N_("Dynamic Range"), ""},
+ {MNOTE_FUJI_TAG_FILM_MODE, "FilmMode", N_("Film simulation Mode"), ""},
+ {MNOTE_FUJI_TAG_DYNAMIC_RANGE_SETTING, "DRangeMode", N_("Dynamic Range Wide Mode"), ""},
+ {MNOTE_FUJI_TAG_DEV_DYNAMIC_RANGE_SETTING, "DevDRangeMode", N_("Development Dynamic Range Wide Mode"), ""},
+ {MNOTE_FUJI_TAG_MIN_FOCAL_LENGTH, "MinFocalLen", N_("Minimum Focal Length"), ""},
+ {MNOTE_FUJI_TAG_MAX_FOCAL_LENGTH, "MaxFocalLen", N_("Maximum Focal Length"), ""},
+ {MNOTE_FUJI_TAG_MAX_APERT_AT_MIN_FOC, "MaxApertAtMinFoc", N_("Maximum Aperture at Minimum Focal"), ""},
+ {MNOTE_FUJI_TAG_MAX_APERT_AT_MAX_FOC, "MaxApertAtMaxFoc", N_("Maximum Aperture at Maximum Focal"), ""},
+ {MNOTE_FUJI_TAG_FILE_SOURCE, "FileSource", N_("File Source"), ""},
+ {MNOTE_FUJI_TAG_ORDER_NUMBER, "OrderNumber", N_("Order Number"), ""},
+ {MNOTE_FUJI_TAG_FRAME_NUMBER, "FrameNumber", N_("Frame Number"), ""},
+#endif
+ {0, NULL, NULL, NULL}
+};
+
+const char *
+mnote_fuji_tag_get_name (MnoteFujiTag 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_fuji_tag_get_title (MnoteFujiTag 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_fuji_tag_get_description (MnoteFujiTag t)
+{
+ unsigned int i;
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ if (table[i].tag == t) {
+ if (!*table[i].description)
+ return "";
+ return (_(table[i].description));
+ }
+ return NULL;
+}
diff --git a/src/libexif/fuji/mnote-fuji-tag.h b/src/libexif/fuji/mnote-fuji-tag.h
new file mode 100644
index 0000000..7ddde34
--- /dev/null
+++ b/src/libexif/fuji/mnote-fuji-tag.h
@@ -0,0 +1,92 @@
+/* mnote-fuji-tag.h
+ *
+ * Copyright (c) 2002 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_FUJI_TAG_H__
+#define __MNOTE_FUJI_TAG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-data.h>
+
+enum _MnoteFujiTag {
+ MNOTE_FUJI_TAG_VERSION = 0x0000,
+ MNOTE_FUJI_TAG_SERIAL_NUMBER = 0x0010,
+ MNOTE_FUJI_TAG_QUALITY = 0x1000,
+ MNOTE_FUJI_TAG_SHARPNESS = 0x1001,
+ MNOTE_FUJI_TAG_WHITE_BALANCE = 0x1002,
+ MNOTE_FUJI_TAG_COLOR = 0x1003,
+ MNOTE_FUJI_TAG_TONE = 0x1004,
+ MNOTE_FUJI_TAG_UNKNOWN_1006 = 0x1006,
+ MNOTE_FUJI_TAG_UNKNOWN_1007 = 0x1007,
+ MNOTE_FUJI_TAG_UNKNOWN_1008 = 0x1008,
+ MNOTE_FUJI_TAG_UNKNOWN_1009 = 0x1009,
+ MNOTE_FUJI_TAG_UNKNOWN_100A = 0x100A,
+ MNOTE_FUJI_TAG_UNKNOWN_100B = 0x100B,
+ MNOTE_FUJI_TAG_FLASH_MODE = 0x1010,
+ MNOTE_FUJI_TAG_FLASH_STRENGTH = 0x1011,
+ MNOTE_FUJI_TAG_MACRO = 0x1020,
+ MNOTE_FUJI_TAG_FOCUS_MODE = 0x1021,
+ MNOTE_FUJI_TAG_UNKNOWN_1022 = 0x1022,
+ MNOTE_FUJI_TAG_FOCUS_POINT = 0x1023,
+ MNOTE_FUJI_TAG_UNKNOWN_1024 = 0x1024,
+ MNOTE_FUJI_TAG_UNKNOWN_1025 = 0x1025,
+ MNOTE_FUJI_TAG_SLOW_SYNC = 0x1030,
+ MNOTE_FUJI_TAG_PICTURE_MODE = 0x1031,
+ MNOTE_FUJI_TAG_UNKNOWN_1032 = 0x1032,
+ MNOTE_FUJI_TAG_CONT_TAKING = 0x1100,
+ MNOTE_FUJI_TAG_SEQUENCE_NUMBER = 0x1101,
+ MNOTE_FUJI_TAG_UNKNOWN_1200 = 0x1200,
+ MNOTE_FUJI_TAG_FINEPIX_COLOR = 0x1210,
+ MNOTE_FUJI_TAG_BLUR_CHECK = 0x1300,
+ MNOTE_FUJI_TAG_FOCUS_CHECK = 0x1301,
+ MNOTE_FUJI_TAG_AUTO_EXPOSURE_CHECK = 0x1302,
+ MNOTE_FUJI_TAG_UNKNOWN_1303 = 0x1303,
+ MNOTE_FUJI_TAG_DYNAMIC_RANGE = 0x1400,
+ MNOTE_FUJI_TAG_FILM_MODE = 0x1401,
+ MNOTE_FUJI_TAG_DYNAMIC_RANGE_SETTING = 0x1402,
+ MNOTE_FUJI_TAG_DEV_DYNAMIC_RANGE_SETTING= 0x1403,
+ MNOTE_FUJI_TAG_MIN_FOCAL_LENGTH = 0x1404,
+ MNOTE_FUJI_TAG_MAX_FOCAL_LENGTH = 0x1405,
+ MNOTE_FUJI_TAG_MAX_APERT_AT_MIN_FOC = 0x1406,
+ MNOTE_FUJI_TAG_MAX_APERT_AT_MAX_FOC = 0x1407,
+ MNOTE_FUJI_TAG_UNKNOWN_1408 = 0x1408,
+ MNOTE_FUJI_TAG_UNKNOWN_1409 = 0x1409,
+ MNOTE_FUJI_TAG_UNKNOWN_140A = 0x140A,
+ MNOTE_FUJI_TAG_UNKNOWN_1410 = 0x1410,
+ MNOTE_FUJI_TAG_UNKNOWN_1421 = 0x1421,
+ MNOTE_FUJI_TAG_UNKNOWN_4100 = 0x4100,
+ MNOTE_FUJI_TAG_UNKNOWN_4800 = 0x4800,
+ MNOTE_FUJI_TAG_FILE_SOURCE = 0x8000,
+ MNOTE_FUJI_TAG_ORDER_NUMBER = 0x8002,
+ MNOTE_FUJI_TAG_FRAME_NUMBER = 0x8003
+};
+typedef enum _MnoteFujiTag MnoteFujiTag;
+
+const char *mnote_fuji_tag_get_name (MnoteFujiTag tag);
+const char *mnote_fuji_tag_get_title (MnoteFujiTag tag);
+const char *mnote_fuji_tag_get_description (MnoteFujiTag tag);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __MNOTE_FUJI_TAG_H__ */
diff --git a/src/libexif/i18n.h b/src/libexif/i18n.h
index 6d08e3c..289435c 100644
--- a/src/libexif/i18n.h
+++ b/src/libexif/i18n.h
@@ -35,6 +35,7 @@
#else
# define textdomain(String) (String)
# define gettext(String) (String)
+# define ngettext(String1,String2,Count) (Count==1?String1:String2)
# define dgettext(Domain,Message) (Message)
# define dcgettext(Domain,Message,Type) (Message)
#ifdef __WATCOMC__
diff --git a/src/libexif/olympus/exif-mnote-data-olympus.c b/src/libexif/olympus/exif-mnote-data-olympus.c
index 02794c5..200a276 100644
--- a/src/libexif/olympus/exif-mnote-data-olympus.c
+++ b/src/libexif/olympus/exif-mnote-data-olympus.c
@@ -1,6 +1,6 @@
/* exif-mnote-data-olympus.c
*
- * Copyright © 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ * Copyright (c) 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
@@ -71,13 +71,25 @@ exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val,
return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
}
+
+
+
+/**
+ * @brief save the MnoteData from ne to buf
+ *
+ * @param ne extract the data from this structure
+ * @param *buf write the mnoteData to this buffer (buffer will be allocated)
+ * @param buf_size the size of the buffer
+ */
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;
+ size_t i, o, s, doff, base = 0, o2 = 6 + 2;
+ size_t datao = 0;
+ unsigned char *t;
+ size_t ts;
if (!n || !buf || !buf_size) return;
@@ -86,29 +98,49 @@ exif_mnote_data_olympus_save (ExifMnoteData *ne,
*/
*buf_size = 6 + 2 + 2 + n->count * 12;
switch (n->version) {
- case 0: /* Olympus */
+ case olympusV1:
+ case sanyoV1:
*buf = exif_mem_alloc (ne->mem, *buf_size);
if (!*buf) return;
/* Write the header and the number of entries. */
- strcpy (*buf, "OLYMP");
- o2 += 2;
+ strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":"OLYMP");
+ exif_set_short (*buf + 6, n->order, (ExifShort) 1);
datao = n->offset;
break;
- case 1: /* Nikon v1 */
+ case olympusV2:
+ *buf_size += 8-6 + 4;
+ *buf = exif_mem_alloc (ne->mem, *buf_size);
+ if (!*buf) return;
+
+ /* Write the header and the number of entries. */
+ strcpy ((char *)*buf, "OLYMPUS");
+ exif_set_short (*buf + 8, n->order, (ExifShort) (
+ (n->order == EXIF_BYTE_ORDER_INTEL) ?
+ ('I' << 8) | 'I' :
+ ('M' << 8) | 'M'));
+ exif_set_short (*buf + 10, n->order, (ExifShort) 3);
+ o2 += 4;
+ break;
+ case nikonV1:
base = MNOTE_NIKON1_TAG_BASE;
- *buf_size -= 8;
+
+ /* v1 has offsets based to main IFD, not makernote IFD */
+ datao += n->offset + 10;
+ /* subtract the size here, so the increment in the next case will not harm us */
+ *buf_size -= 8 + 2;
/* Fall through */
- case 2: /* Nikon v2 */
- *buf_size += 8;
+ case nikonV2:
+ *buf_size += 8 + 2;
+ *buf_size += 4; /* Next IFD pointer */
*buf = exif_mem_alloc (ne->mem, *buf_size);
if (!*buf) return;
/* Write the header and the number of entries. */
- strcpy (*buf, "Nikon");
+ strcpy ((char *)*buf, "Nikon");
(*buf)[6] = n->version;
- o2 += 2; *buf_size += 2;
- if (n->version == 2) {
+
+ if (n->version == nikonV2) {
exif_set_short (*buf + 10, n->order, (ExifShort) (
(n->order == EXIF_BYTE_ORDER_INTEL) ?
('I' << 8) | 'I' :
@@ -117,8 +149,13 @@ exif_mnote_data_olympus_save (ExifMnoteData *ne,
exif_set_long (*buf + 14, n->order, (ExifShort) 8);
o2 += 2 + 8;
}
- datao = -10;
+ datao -= 10;
+ /* Reset next IFD pointer */
+ exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
break;
+
+ default:
+ return;
}
exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
@@ -136,12 +173,20 @@ exif_mnote_data_olympus_save (ExifMnoteData *ne,
o += 8;
s = exif_format_get_size (n->entries[i].format) *
n->entries[i].components;
+ if (s > 65536) {
+ /* Corrupt data: EXIF data size is limited to the
+ * maximum size of a JPEG segment (64 kb).
+ */
+ continue;
+ }
if (s > 4) {
doff = *buf_size;
- *buf_size += s;
- *buf = exif_mem_realloc (ne->mem, *buf,
- sizeof (char) * *buf_size);
- if (!*buf) return;
+ ts = *buf_size + s;
+ t = exif_mem_realloc (ne->mem, *buf,
+ sizeof (char) * ts);
+ if (!t) return;
+ *buf = t;
+ *buf_size = ts;
exif_set_long (*buf + o, n->order, datao + doff);
} else
doff = o;
@@ -162,7 +207,7 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
{
ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
ExifShort c;
- unsigned int i, s, o, o2 = 0, datao = 6, base = 0;
+ size_t i, s, o, o2 = 0, datao = 6, base = 0;
if (!n || !buf) return;
@@ -174,6 +219,9 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
* a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
* number of entries, and 12 for one entry.
*
+ * Sanyo format is identical and uses identical tags except that
+ * header starts with "SANYO".
+ *
* Nikon headers start with "Nikon" (6 bytes including '\0'),
* version number (1 or 2).
*
@@ -185,13 +233,46 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
* lastly 0x2A.
*/
if (buf_size - n->offset < 22) return;
- if (!memcmp (buf + o2, "OLYMP", 5)) {
+ if (!memcmp (buf + o2, "OLYMP", 6) || !memcmp (buf + o2, "SANYO", 6)) {
exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
- "Parsing Olympus maker note...");
+ "Parsing Olympus/Sanyo maker note v1...");
/* The number of entries is at position 8. */
- n->version = 0;
+ if (!memcmp (buf + o2, "SANYO", 6))
+ n->version = sanyoV1;
+ else
+ n->version = olympusV1;
+ if (buf[o2 + 6] == 1)
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ else if (buf[o2 + 6 + 1] == 1)
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
o2 += 8;
+ if (o2 >= buf_size) return;
+ c = exif_get_short (buf + o2, n->order);
+ if ((!(c & 0xFF)) && (c > 0x500)) {
+ if (n->order == EXIF_BYTE_ORDER_INTEL) {
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
+ } else {
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ }
+ }
+
+ } else if (!memcmp (buf + o2, "OLYMPUS", 8)) {
+ /* Olympus S760, S770 */
+ datao = o2;
+ o2 += 8;
+ exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
+ "Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
+ buf[o2], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
+
+ if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
+
+ /* The number of entries is at position 8+4. */
+ n->version = olympusV2;
+ o2 += 4;
} else if (!memcmp (buf + o2, "Nikon", 6)) {
o2 += 6;
@@ -199,8 +280,7 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
"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]);
-
+ 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];
@@ -210,12 +290,22 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
o2 += 1;
switch (n->version) {
- case 1:
+ case nikonV1:
base = MNOTE_NIKON1_TAG_BASE;
+ /* Fix endianness, if needed */
+ if (o2 >= buf_size) return;
+ c = exif_get_short (buf + o2, n->order);
+ if ((!(c & 0xFF)) && (c > 0x500)) {
+ if (n->order == EXIF_BYTE_ORDER_INTEL) {
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
+ } else {
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ }
+ }
break;
- case 2:
+ case nikonV2:
/* Skip 2 unknown bytes (00 00). */
o2 += 2;
@@ -226,9 +316,9 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
*/
datao = o2;
if (o2 >= buf_size) return;
- if (!strncmp (&buf[o2], "II", 2))
+ if (!strncmp ((char *)&buf[o2], "II", 2))
n->order = EXIF_BYTE_ORDER_INTEL;
- else if (!strncmp (&buf[o2], "MM", 2))
+ else if (!strncmp ((char *)&buf[o2], "MM", 2))
n->order = EXIF_BYTE_ORDER_MOTOROLA;
else {
exif_log (en->log, EXIF_LOG_CODE_DEBUG,
@@ -254,7 +344,9 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
return;
}
} else if (!memcmp (buf + o2, "\0\x1b", 2)) {
- n->version = 2;
+ n->version = nikonV2;
+ /* 00 1b is # of entries in Motorola order - the rest should also be in MM order */
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
} else {
return;
}
@@ -347,7 +439,7 @@ exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
if (!n) return NULL;
if (i >= n->count) return NULL;
- return mnote_olympus_tag_get_title (n->entries[i].tag);
+ return mnote_olympus_tag_get_description (n->entries[i].tag);
}
static void
diff --git a/src/libexif/olympus/exif-mnote-data-olympus.h b/src/libexif/olympus/exif-mnote-data-olympus.h
index b9b4209..4d55cab 100644
--- a/src/libexif/olympus/exif-mnote-data-olympus.h
+++ b/src/libexif/olympus/exif-mnote-data-olympus.h
@@ -1,6 +1,6 @@
/* mnote-olympus-data.h
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -26,6 +26,9 @@
#include <libexif/exif-byte-order.h>
#include <libexif/exif-mem.h>
+enum OlympusVersion {nikonV1 = 1, nikonV2 = 2, olympusV1 = 3, olympusV2 = 4, sanyoV1 = 5 };
+
+
typedef struct _ExifMnoteDataOlympus ExifMnoteDataOlympus;
struct _ExifMnoteDataOlympus {
diff --git a/src/libexif/olympus/mnote-olympus-entry.c b/src/libexif/olympus/mnote-olympus-entry.c
index 1eff6fe..1e9e1e2 100644
--- a/src/libexif/olympus/mnote-olympus-entry.c
+++ b/src/libexif/olympus/mnote-olympus-entry.c
@@ -1,6 +1,6 @@
/* mnote-olympus-entry.c
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -42,6 +42,19 @@
} \
}
+#define CF2(format,target1,target2,v,maxlen) \
+{ \
+ if ((format != target1) && (format != target2)) { \
+ snprintf (v, maxlen, \
+ _("Invalid format '%s', " \
+ "expected '%s' or '%s'."), \
+ exif_format_get_name (format), \
+ exif_format_get_name (target1), \
+ exif_format_get_name (target2)); \
+ break; \
+ } \
+}
+
#define CC(number,target,v,maxlen) \
{ \
if (number != target) { \
@@ -54,7 +67,7 @@
#define CC2(number,t1,t2,v,maxlen) \
{ \
- if ((number != t1) && (number != t2)) { \
+ if ((number < t1) || (number > t2)) { \
snprintf (v, maxlen, \
_("Invalid number of components (%i, " \
"expected %i or %i)."), (int) number, \
@@ -63,7 +76,7 @@
} \
}
-static struct {
+static const struct {
ExifTag tag;
ExifFormat fmt;
struct {
@@ -71,6 +84,7 @@ static struct {
const char *string;
} elem[10];
} items[] = {
+#ifndef NO_VERBOSE_TAG_DATA
{ MNOTE_NIKON_TAG_LENSTYPE, EXIF_FORMAT_BYTE,
{ {0, N_("AF non D Lens")},
{1, N_("Manual")},
@@ -116,7 +130,7 @@ static struct {
{ {0, N_("Auto")},
{1, N_("Preset")},
{2, N_("Daylight")},
- {3, N_("Incandescense")},
+ {3, N_("Incandescence")},
{4, N_("Fluorescence")},
{5, N_("Cloudy")},
{6, N_("SpeedLight")},
@@ -129,14 +143,25 @@ static struct {
{ {1, N_("SQ")},
{2, N_("HQ")},
{3, N_("SHQ")},
+ {4, N_("RAW")},
+ {5, N_("SQ1")},
+ {6, N_("SQ2")},
+ {17, N_("Standard")},
+ {529, N_("High")},
{0, NULL}}},
{ MNOTE_OLYMPUS_TAG_MACRO, EXIF_FORMAT_SHORT,
{ {0, N_("No")},
{1, N_("Yes")},
+ {2, N_("Super Macro")},
{0, NULL}}},
- { MNOTE_OLYMPUS_TAG_DIGIZOOM, EXIF_FORMAT_SHORT,
- { {0, N_("1x")},
- {2, N_("2x")},
+ { MNOTE_OLYMPUS_TAG_BWMODE, EXIF_FORMAT_SHORT,
+ { {0, N_("No")},
+ {1, N_("Yes")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_ONETOUCHWB, EXIF_FORMAT_SHORT,
+ { {0, N_("Off")},
+ {1, N_("On")},
+ {2, N_("On (Preset)")},
{0, NULL}}},
{ MNOTE_OLYMPUS_TAG_FLASHMODE, EXIF_FORMAT_SHORT,
{ {0, N_("Auto")},
@@ -144,21 +169,73 @@ static struct {
{2, N_("Fill")},
{3, N_("Off")},
{0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_FLASHDEVICE, EXIF_FORMAT_SHORT,
+ { {0, N_("None")},
+ {1, N_("Internal")},
+ {4, N_("External")},
+ {5, N_("Internal + External")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_FOCUSRANGE, EXIF_FORMAT_SHORT,
+ { {0, N_("Normal")},
+ {1, N_("Macro")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_MANFOCUS, EXIF_FORMAT_SHORT,
+ { {0, N_("Auto")},
+ {1, N_("Manual")},
+ {0, NULL}}},
{ MNOTE_OLYMPUS_TAG_SHARPNESS, EXIF_FORMAT_SHORT,
{ {0, N_("Normal")},
{1, N_("Hard")},
{2, N_("Soft")},
{0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_EXTERNALFLASHBOUNCE, EXIF_FORMAT_SHORT,
+ { {0, N_("No")},
+ {1, N_("Yes")},
+ {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,
+ { MNOTE_OLYMPUS_TAG_PREVIEWIMAGEVALID, EXIF_FORMAT_LONG,
+ { {0, N_("No")},
+ {1, N_("Yes")},
+ {0, NULL}}},
+ { MNOTE_OLYMPUS_TAG_CCDSCANMODE, EXIF_FORMAT_SHORT,
+ { {0, N_("Interlaced")},
+ {1, N_("Progressive")},
+ {0, NULL}}},
+ { MNOTE_SANYO_TAG_SEQUENTIALSHOT, EXIF_FORMAT_SHORT,
+ { {0, N_("None")},
+ {1, N_("Standard")},
+ {2, N_("Best")},
+ {3, N_("Adjust Exposure")},
+ {0, NULL}}},
+ { MNOTE_SANYO_TAG_RECORDSHUTTERRELEASE, EXIF_FORMAT_SHORT,
+ { {0, N_("Record while down")},
+ {1, N_("Press start, press stop")},
+ {0, NULL}}},
+ { MNOTE_SANYO_TAG_RESAVED, EXIF_FORMAT_SHORT,
{ {0, N_("No")},
{1, N_("Yes")},
{0, NULL}}},
- { 0, }
+ { MNOTE_SANYO_TAG_SCENESELECT, EXIF_FORMAT_SHORT,
+ { {0, N_("Off")},
+ {1, N_("Sport")},
+ {2, N_("TV")},
+ {3, N_("Night")},
+ {4, N_("User 1")},
+ {5, N_("User 2")},
+ {6, N_("Lamp")},
+ {0, NULL}}},
+ { MNOTE_SANYO_TAG_SEQUENCESHOTINTERVAL, EXIF_FORMAT_SHORT,
+ { {0, N_("5 frames/sec")},
+ {1, N_("10 frames/sec")},
+ {2, N_("15 frames/sec")},
+ {3, N_("20 frames/sec")},
+ {0, NULL}}},
+#endif
+ { 0, 0, { { 0, NULL } } }
};
char *
@@ -167,7 +244,8 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
char buf[30];
ExifLong vl;
ExifShort vs = 0;
- ExifRational vr;
+ ExifRational vr, vr2;
+ ExifSRational vsr;
int i, j;
double r, b;
@@ -177,7 +255,8 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
memset (v, 0, maxlen);
maxlen--;
- if ((!entry->data) && (entry->components > 0)) return (v);
+ if ((!entry->data) && (entry->components > 0))
+ return (v);
switch (entry->tag) {
@@ -212,7 +291,7 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
//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);
+ memcpy(v, entry->data, MIN(maxlen, entry->size));
//snprintf (v, maxlen, "%s<", ( entry->data - 9 );
break;
case MNOTE_NIKON_TAG_COLORMODE:
@@ -225,21 +304,43 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
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_SATURATION2:
+ CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen);
+ memcpy(v, entry->data, MIN (maxlen, entry->size));
+ 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;
+ 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_LENS_FSTOPS:
+ case MNOTE_NIKON_TAG_EXPOSUREDIFF: {
+ unsigned char a,b,c,d;
+ CF (entry->format, EXIF_FORMAT_UNDEFINED, v, maxlen);
+ CC (entry->components, 4, v, maxlen);
+ vl = exif_get_long (entry->data, entry->order);
+ a = (vl>>24)&0xff; b = (vl>>16)&0xff; c = (vl>>8)&0xff; d = (vl)&0xff;
+ snprintf (v, maxlen, "%.1f", c?(float)a*((float)b/(float)c):0 );
+ break;
+ }
+ case MNOTE_NIKON_TAG_FLASHEXPCOMPENSATION:
+ case MNOTE_NIKON_TAG_FLASHEXPOSUREBRACKETVAL:
+ CF (entry->format, EXIF_FORMAT_UNDEFINED, v, maxlen);
+ CC (entry->components, 4, v, maxlen);
+ vl = exif_get_long (entry->data, entry->order);
+ snprintf (v, maxlen, "%.1f", ((long unsigned int) vl>>24)/6.0 );
+ break;
+ case MNOTE_NIKON_TAG_SATURATION:
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_HUE:
+ case MNOTE_OLYMPUS_TAG_SENSORTEMPERATURE:
+ case MNOTE_OLYMPUS_TAG_LENSTEMPERATURE:
+ 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);
@@ -248,7 +349,7 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
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);
+ 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);
@@ -256,31 +357,69 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
vr = exif_get_rational (entry->data, entry->order);
if (vr.numerator) {
r = (double)vr.numerator / vr.denominator;
- snprintf (v, maxlen, "%2.2f meters", r);
+ 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:
+ case MNOTE_NIKON_TAG_SENSORPIXELSIZE:
CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);
- CC (entry->components, 1, v, maxlen);
+ CC (entry->components, 2, v, maxlen);
vr = exif_get_rational (entry->data, entry->order);
+ vr2 = exif_get_rational (entry->data+8, entry->order);
r = (double)vr.numerator / vr.denominator;
- snprintf (v, maxlen, "%2.2f", r);
+ b = (double)vr2.numerator / vr2.denominator;
+ snprintf (v, maxlen, "%2.2f x %2.2f um", r, b);
+ break;
+ case MNOTE_NIKON_TAG_BRACKETING:
+ CF2 (entry->format, EXIF_FORMAT_BYTE, EXIF_FORMAT_SHORT, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ if (EXIF_FORMAT_SHORT == entry->format) {
+ vs = exif_get_short (entry->data, entry->order);
+ } else {
+ vs = entry->data[0];
+ }
+ snprintf (v, maxlen, "%hd", vs);
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);
+ 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;
+ case 5: strncpy (v, _("AF Position: Upper-left"), maxlen); break;
+ case 6: strncpy (v, _("AF Position: Upper-right"), maxlen); break;
+ case 7: strncpy (v, _("AF Position: Lower-left"), maxlen); break;
+ case 8: strncpy (v, _("AF Position: Lower-right"), maxlen); break;
+ case 9: strncpy (v, _("AF Position: Far Left"), maxlen); break;
+ case 10: strncpy (v, _("AF Position: Far Right"), maxlen); break;
+ default: strncpy (v, _("Unknown AF Position"), maxlen);
}
break;
+ case MNOTE_OLYMPUS_TAG_FLASHDEVICE:
+ CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen);
+ CC (entry->components, 2, v, maxlen);
+ vs = exif_get_short(entry->data, entry->order);
+ /* search for the tag */
+ for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++)
+ ;
+ if (!items[i].tag) {
+ snprintf (v, maxlen, _("Internal error (unknown value %hi)"), vs);
+ break;
+ }
+ CF (entry->format, items[i].fmt, v, maxlen);
+ /* 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_OLYMPUS_TAG_DIGIZOOM:
if (entry->format == EXIF_FORMAT_RATIONAL) {
CC (entry->components, 1, v, maxlen);
@@ -304,17 +443,21 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
case MNOTE_NIKON1_TAG_CONVERTER:
case MNOTE_OLYMPUS_TAG_QUALITY:
case MNOTE_OLYMPUS_TAG_MACRO:
+ case MNOTE_OLYMPUS_TAG_BWMODE:
+ case MNOTE_OLYMPUS_TAG_ONETOUCHWB:
case MNOTE_OLYMPUS_TAG_FLASHMODE:
+ case MNOTE_OLYMPUS_TAG_FOCUSRANGE:
+ case MNOTE_OLYMPUS_TAG_MANFOCUS:
case MNOTE_OLYMPUS_TAG_SHARPNESS:
+ case MNOTE_OLYMPUS_TAG_EXTERNALFLASHBOUNCE:
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);
+ case MNOTE_OLYMPUS_TAG_PREVIEWIMAGEVALID:
+ case MNOTE_OLYMPUS_TAG_CCDSCANMODE:
+ case MNOTE_SANYO_TAG_SEQUENTIALSHOT:
+ case MNOTE_SANYO_TAG_RECORDSHUTTERRELEASE:
+ case MNOTE_SANYO_TAG_RESAVED:
+ case MNOTE_SANYO_TAG_SCENESELECT:
+ case MNOTE_SANYO_TAG_SEQUENCESHOTINTERVAL:
CC (entry->components, 1, v, maxlen);
switch (entry->format) {
case EXIF_FORMAT_BYTE:
@@ -328,16 +471,48 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
vs = 0;
break;
}
+ /* search for the tag */
+ for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++)
+ ;
+ if (!items[i].tag) {
+ snprintf (v, maxlen, _("Internal error (unknown value %hi)"), vs);
+ break;
+ }
+ CF (entry->format, items[i].fmt, v, maxlen);
/* 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);
+ snprintf (v, maxlen, _("Unknown value %hi"), vs);
+ break;
+ }
+ strncpy (v, _(items[i].elem[j].string), maxlen);
+ break;
+ case MNOTE_OLYMPUS_TAG_NOISEREDUCTION:
+ case MNOTE_SANYO_TAG_WIDERANGE:
+ case MNOTE_SANYO_TAG_COLORADJUSTMENTMODE:
+ case MNOTE_SANYO_TAG_QUICKSHOT:
+ case MNOTE_SANYO_TAG_SELFTIMER:
+ case MNOTE_SANYO_TAG_VOICEMEMO:
+ case MNOTE_SANYO_TAG_FLICKERREDUCE:
+ case MNOTE_SANYO_TAG_OPTICALZOOM:
+ case MNOTE_SANYO_TAG_DIGITALZOOM:
+ case MNOTE_SANYO_TAG_LIGHTSOURCESPECIAL:
+ CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen);
+ CC (entry->components, 1, v, maxlen);
+ vs = exif_get_short (entry->data, entry->order);
+ switch (vs) {
+ case 0:
+ strncpy (v, _("Off"), maxlen);
+ break;
+ case 1:
+ strncpy (v, _("On"), maxlen);
+ break;
+ default:
+ strncpy (v, _("Unknown"), maxlen);
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);
@@ -356,17 +531,6 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
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:
@@ -412,37 +576,47 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
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:
+ case MNOTE_OLYMPUS_TAG_LENSDISTORTION:
CF (entry->format, EXIF_FORMAT_SSHORT, v, maxlen);
- CC (entry->components, 1, v, maxlen);
+ CC (entry->components, 6, v, maxlen);
+ for (i=0; i < (int)entry->components; ++i) {
+ vs = exif_get_sshort (entry->data+2*i, entry->order);
+ sprintf (buf, "%hd ", vs);
+ strncat (v, buf, maxlen - strlen (v));
+ }
+ break;
+ case MNOTE_OLYMPUS_TAG_COLORCONTROL:
+ CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen);
+ CC (entry->components, 6, v, maxlen);
+ for (i=0; i < (int)entry->components; ++i) {
+ vs = exif_get_short (entry->data+2*i, entry->order);
+ sprintf (buf, "%hu ", vs);
+ strncat (v, buf, maxlen - strlen (v));
+ }
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));
+ strncpy (v, (char *)entry->data, MIN (maxlen, entry->size));
+ break;
+ case MNOTE_OLYMPUS_TAG_SERIALNUMBER2:
+ CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen);
+ strncpy (v, (char *)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));
+ CC2 (entry->components, 52, 60, v, maxlen);
+ strncpy (v, (char *)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));
+ strncpy (v, (char *)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);
+ /* TODO: display me */
break;
case MNOTE_OLYMPUS_TAG_FOCUSDIST:
CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);
@@ -493,7 +667,7 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
break;
}
if (colorTemp) {
- snprintf (v, maxlen, "Manual: %liK", colorTemp);
+ snprintf (v, maxlen, _("Manual: %liK"), colorTemp);
}
else {
strncpy (v, _("Manual: Unknown"), maxlen);
@@ -509,24 +683,75 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m
break;
}
break;
+ case MNOTE_OLYMPUS_TAG_REDBALANCE:
+ case MNOTE_OLYMPUS_TAG_BLUEBALANCE:
+ CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen);
+ CC (entry->components, 2, v, maxlen);
+ vs = exif_get_short (entry->data, entry->order);
+ snprintf (v, maxlen, "%hu ", vs);
+ vs = exif_get_short (entry->data + 2, entry->order);
+ sprintf (buf, "%hu", vs);
+ strncat (v, buf, maxlen - strlen (v));
+ break;
+ case MNOTE_OLYMPUS_TAG_BLACKLEVEL:
+ case MNOTE_NIKON_TAG_IMAGEBOUNDARY:
+ CC (entry->components, 4, v, maxlen);
+ /* Fall through to COLORMATRIX */
+ case MNOTE_OLYMPUS_TAG_COLORMATRIX:
+ CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen);
+ if (entry->tag == MNOTE_OLYMPUS_TAG_COLORMATRIX)
+ CC (entry->components, 9, v, maxlen);
+ for (i=0; i < (int)entry->components; ++i) {
+ vs = exif_get_short (entry->data+2*i, entry->order);
+ sprintf (buf, "%hu ", vs);
+ strncat (v, buf, maxlen - strlen (v));
+ }
+ break;
+ case MNOTE_NIKON1_TAG_FOCUS:
+ case MNOTE_NIKON_TAG_DIGITALZOOM:
+ case MNOTE_NIKON1_TAG_DIGITALZOOM:
+ case MNOTE_OLYMPUS_TAG_FOCALPLANEDIAGONAL:
+ CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);
+ /* Fall through to default handler for display */
default:
switch (entry->format) {
case EXIF_FORMAT_ASCII:
- strncpy (v, entry->data,
- MIN (maxlen, entry->components));
+ strncpy (v, (char *)entry->data, MIN (maxlen, entry->size));
break;
case EXIF_FORMAT_SHORT:
+ CC (entry->components, 1, v, maxlen);
vs = exif_get_short (entry->data, entry->order);
- snprintf (v, maxlen, "%hi", vs);
+ snprintf (v, maxlen, "%hu", vs);
break;
case EXIF_FORMAT_LONG:
+ CC (entry->components, 1, v, maxlen);
vl = exif_get_long (entry->data, entry->order);
snprintf (v, maxlen, "%li", (long int) vl);
break;
+ case EXIF_FORMAT_RATIONAL:
+ 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.3f", r);
+ }
+ break;
+ case EXIF_FORMAT_SRATIONAL:
+ CC (entry->components, 1, v, maxlen);
+ vsr = exif_get_srational (entry->data, entry->order);
+ if (!vsr.denominator) {
+ strncpy (v, _("Infinite"), maxlen);
+ } else {
+ r = (double)vsr.numerator / vsr.denominator;
+ snprintf (v, maxlen, "%2.3f", r);
+ }
+ break;
case EXIF_FORMAT_UNDEFINED:
default:
- snprintf (v, maxlen, _("%li bytes unknown data: "),
- (long int) entry->size);
+ snprintf (v, maxlen, _("%i bytes unknown data: "),
+ entry->size);
for (i = 0; i < (int)entry->size; i++) {
sprintf (buf, "%02x", entry->data[i]);
strncat (v, buf, maxlen - strlen (v));
diff --git a/src/libexif/olympus/mnote-olympus-entry.h b/src/libexif/olympus/mnote-olympus-entry.h
index a725228..9526bad 100644
--- a/src/libexif/olympus/mnote-olympus-entry.h
+++ b/src/libexif/olympus/mnote-olympus-entry.h
@@ -1,6 +1,6 @@
/* mnote-olympus-entry.h
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
diff --git a/src/libexif/olympus/mnote-olympus-tag.c b/src/libexif/olympus/mnote-olympus-tag.c
index b7beacd..37a6bdc 100644
--- a/src/libexif/olympus/mnote-olympus-tag.c
+++ b/src/libexif/olympus/mnote-olympus-tag.c
@@ -1,6 +1,6 @@
/* mnote-olympus-tag.c:
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -26,99 +26,163 @@
#include <stdlib.h>
-static struct {
+static const struct {
MnoteOlympusTag tag;
const char *name;
const char *title;
const char *description;
} table[] = {
-
+#ifndef NO_VERBOSE_TAG_STRINGS
/* 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_FIRMWARE, "Firmware", N_("Firmware Version"), ""},
+ {MNOTE_NIKON_TAG_ISO, "ISO", N_("ISO Setting"), ""},
+ {MNOTE_NIKON_TAG_COLORMODE1, "COLORMODE1", N_("Colormode (?)"), ""},
+ {MNOTE_NIKON_TAG_QUALITY, "QUALITY", N_("Quality"), ""},
+ {MNOTE_NIKON_TAG_WHITEBALANCE, "WHITEBALANCE", N_("Whitebalance"), ""},
+ {MNOTE_NIKON_TAG_SHARPENING, "SHARPENING", N_("Image Sharpening"), ""},
+ {MNOTE_NIKON_TAG_FOCUSMODE, "FOCUSMODE", N_("Focus Mode"), ""},
+ {MNOTE_NIKON_TAG_FLASHSETTING, "FLASHSETTING", N_("Flash Setting"), ""},
+ {MNOTE_NIKON_TAG_FLASHMODE, "FLASHMODE", N_("Flash Mode"), ""},
+ {MNOTE_NIKON_TAG_WHITEBALANCEFINE,"WHITEBALANCEFINE",N_("Whitebalance fine adjustment"), ""},
+ {MNOTE_NIKON_TAG_WHITEBALANCERB, "WHITEBALANCERB", N_("Whitebalance RB"), ""},
{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_ISOSELECTION, "ISOSELECTION", N_("Isoselection"), ""},
+ {MNOTE_NIKON_TAG_PREVIEWIMAGE, "PREVIEWIMAGE", N_("Preview Image"), ""},
+ {MNOTE_NIKON_TAG_EXPOSUREDIFF, "EXPOSUREDIFF", N_("Exposurediff ?"), ""},
+ {MNOTE_NIKON_TAG_FLASHEXPCOMPENSATION, "FLASHEXPCOMPENSATION", N_("Flash exposure compensation"), ""},
+ {MNOTE_NIKON_TAG_ISO2, "ISO", N_("ISO Setting"), ""},
+ {MNOTE_NIKON_TAG_IMAGEBOUNDARY, "IMAGEBOUNDARY", N_("Image Boundary"), ""},
{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_FLASHEXPOSUREBRACKETVAL, "FLASHEXPOSUREBRACKETVAL", N_("Flash exposure bracket value"), ""},
+ {MNOTE_NIKON_TAG_EXPOSUREBRACKETVAL, "EXPOSUREBRACKETVAL", N_("Exposure bracket value"), ""},
+ {MNOTE_NIKON_TAG_IMAGEADJUSTMENT, "ImageAdjustment", N_("Image Adjustment"), ""},
+ {MNOTE_NIKON_TAG_TONECOMPENSATION, "TONECOMPENSATION", N_("Tonecompensation"), ""},
+ {MNOTE_NIKON_TAG_ADAPTER, "ADAPTER", N_("Adapter"), ""},
+ {MNOTE_NIKON_TAG_LENSTYPE, "LENSTYPE", N_("Lenstype"), ""},
+ {MNOTE_NIKON_TAG_LENS, "LENS", N_("Lens"), ""},
+ {MNOTE_NIKON_TAG_MANUALFOCUSDISTANCE, "MANUALFOCUSDISTANCE", N_("Manual Focus Distance"), ""},
+ {MNOTE_NIKON_TAG_DIGITALZOOM, "DigitalZoom", N_("Digital Zoom"), ""},
+ {MNOTE_NIKON_TAG_FLASHUSED, "FLASHUSED", N_("Flash used"), ""},
+ {MNOTE_NIKON_TAG_AFFOCUSPOSITION, "AFFOCUSPOSITION", N_("AF Focus position"), ""},
+ {MNOTE_NIKON_TAG_BRACKETING, "BRACKETING", N_("Bracketing"), ""},
{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_LENS_FSTOPS, "LENSFSTOPS", N_("Lens F stops"), ""},
+ {MNOTE_NIKON_TAG_CURVE, "CURVE,", N_("Contrast curve"), ""},
+ {MNOTE_NIKON_TAG_COLORMODE, "COLORMODE,", N_("Colormode"), ""},
+ {MNOTE_NIKON_TAG_LIGHTTYPE, "LIGHTTYPE,", N_("Lighttype"), ""},
{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_HUE, "HUE", N_("Hue Adjustment"), ""},
+ {MNOTE_NIKON_TAG_SATURATION, "SATURATION", N_("Saturation"), ""},
+ {MNOTE_NIKON_TAG_NOISEREDUCTION, "NOISEREDUCTION,", N_("Noisereduction"), ""},
{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_SENSORPIXELSIZE, "SENSORPIXELSIZE", N_("Sensor pixel size"), ""},
{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_SERIALNUMBER, "SERIALNUMBER", N_("Serial number"), ""},
+ {MNOTE_NIKON_TAG_IMAGE_DATASIZE, "IMAGEDATASIZE", N_("Image datasize"), N_("Size of compressed image data in bytes.")},
{MNOTE_NIKON_TAG_UNKNOWN_0X00A3, NULL, NULL, NULL},
- {MNOTE_NIKON_TAG_TOTALPICTURES, "TOTALPICTURES,", N_("Total number of pictures taken"), NULL},
+ {MNOTE_NIKON_TAG_TOTALPICTURES, "TOTALPICTURES,", N_("Total number of pictures taken"), ""},
{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_OPTIMIZATION, "OPTIMIZATION,", N_("Optimize Image"), ""},
+ {MNOTE_NIKON_TAG_SATURATION, "SATURATION", N_("Saturation"), ""},
+ {MNOTE_NIKON_TAG_VARIPROGRAM, "VARIPROGRAM", N_("Vari Program"), ""},
+ {MNOTE_NIKON_TAG_CAPTUREEDITORDATA, "CAPTUREEDITORDATA", N_("Capture Editor Data"), ""},
+ {MNOTE_NIKON_TAG_CAPTUREEDITORVER, "CAPTUREEDITORVER", N_("Capture Editor Version"), ""},
{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_QUALITY, "QUALITY", N_("Quality"), ""},
+ {MNOTE_NIKON1_TAG_COLORMODE, "COLORMODE,", N_("Colormode"), ""},
+ {MNOTE_NIKON1_TAG_IMAGEADJUSTMENT, "ImageAdjustment", N_("Image Adjustment"), ""},
+ {MNOTE_NIKON1_TAG_CCDSENSITIVITY, "CCDSensitivity", N_("CCD Sensitivity"), ""},
+ {MNOTE_NIKON1_TAG_WHITEBALANCE, "WhiteBalance", N_("Whitebalance"), ""},
+ {MNOTE_NIKON1_TAG_FOCUS, "Focus", N_("Focus"), ""},
{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},
+ {MNOTE_NIKON1_TAG_DIGITALZOOM, "DigitalZoom", N_("Digital Zoom"), ""},
+ {MNOTE_NIKON1_TAG_CONVERTER, "Converter", N_("Converter"), ""},
- /* 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},
+ /* Olympus & some Sanyo */
+ {MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE, "ThumbnailImage", N_("Thumbnail Image"), ""},
+ {MNOTE_OLYMPUS_TAG_MODE, "Mode", N_("Speed/Sequence/Panorama direction"), ""},
+ {MNOTE_OLYMPUS_TAG_QUALITY, "Quality", N_("Quality"), ""},
+ {MNOTE_OLYMPUS_TAG_MACRO, "Macro", N_("Macro"), ""},
+ {MNOTE_OLYMPUS_TAG_BWMODE, "BWMode", N_("B&W Mode"), ""},
+ {MNOTE_OLYMPUS_TAG_DIGIZOOM, "DigiZoom", N_("Digital Zoom"), ""},
+ {MNOTE_OLYMPUS_TAG_FOCALPLANEDIAGONAL, "FocalPlaneDiagonal", N_("Focal Plane Diagonal"), ""},
+ {MNOTE_OLYMPUS_TAG_LENSDISTORTION, "LensDistortionParams", N_("Lens Distortion Parameters"), ""},
+ {MNOTE_OLYMPUS_TAG_VERSION, "FirmwareVersion", N_("Firmware version"), ""},
+ {MNOTE_OLYMPUS_TAG_INFO, "Info", N_("Info"), ""},
+ {MNOTE_OLYMPUS_TAG_ID, "CameraID", N_("Camera ID"), ""},
+ {MNOTE_OLYMPUS_TAG_PRECAPTUREFRAMES, "PreCaptureFrames", N_("Precapture Frames"), ""},
+ {MNOTE_OLYMPUS_TAG_WHITEBOARD, "WhiteBoard", N_("White Board"), ""},
+ {MNOTE_OLYMPUS_TAG_ONETOUCHWB, "OneTouchWB", N_("One Touch White Balance"), ""},
+ {MNOTE_OLYMPUS_TAG_WHITEBALANCEBRACKET, "WhiteBalanceBracket", N_("White Balance Bracket"), ""},
+ {MNOTE_OLYMPUS_TAG_WHITEBALANCEBIAS, "WhiteBalanceBias", N_("White Balance Bias"), ""},
+ {MNOTE_OLYMPUS_TAG_UNKNOWN_5, NULL, NULL, 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},
+ {MNOTE_OLYMPUS_TAG_SHUTTERSPEED, "ShutterSpeed", N_("Shutter Speed"), ""},
+ {MNOTE_OLYMPUS_TAG_ISOVALUE, "ISOValue", N_("ISO Value"), ""},
+ {MNOTE_OLYMPUS_TAG_APERTUREVALUE, "ApertureValue", N_("Aperture Value"), ""},
+ {MNOTE_OLYMPUS_TAG_BRIGHTNESSVALUE, "BrightnessValue", N_("Brightness Value"), ""},
+ {MNOTE_OLYMPUS_TAG_FLASHMODE, "FlashMode", N_("Flash Mode"), ""},
+ {MNOTE_OLYMPUS_TAG_FLASHDEVICE, "FlashDevice", N_("Flash Device"), ""},
+ {MNOTE_OLYMPUS_TAG_EXPOSURECOMP, "ExposureCompensation", N_("Exposure Compensation"), ""},
+ {MNOTE_OLYMPUS_TAG_SENSORTEMPERATURE, "SensorTemperature", N_("Sensor Temperature"), ""},
+ {MNOTE_OLYMPUS_TAG_LENSTEMPERATURE, "LensTemperature", N_("Lens Temperature"), ""},
+ {MNOTE_OLYMPUS_TAG_LIGHTCONDITION, "LightCondition", N_("Light Condition"), ""},
+ {MNOTE_OLYMPUS_TAG_FOCUSRANGE, "FocusRange", N_("Focus Range"), ""},
+ {MNOTE_OLYMPUS_TAG_MANFOCUS, "FocusMode", N_("Focus Mode"), "Automatic or manual focusing mode"},
+ {MNOTE_OLYMPUS_TAG_FOCUSDIST, "ManualFocusDistance", N_("Manual Focus Distance"), ""},
+ {MNOTE_OLYMPUS_TAG_ZOOMSTEPCOUNT, "ZoomStepCount", N_("Zoom Step Count"), ""},
+ {MNOTE_OLYMPUS_TAG_FOCUSSTEPCOUNT, "FocusStepCount", N_("Focus Step Count"), ""},
+ {MNOTE_OLYMPUS_TAG_SHARPNESS, "Sharpness", N_("Sharpness Setting"), ""},
+ {MNOTE_OLYMPUS_TAG_FLASHCHARGELEVEL, "FlashChargeLevel", N_("Flash Charge Level"), ""},
+ {MNOTE_OLYMPUS_TAG_COLORMATRIX, "ColorMatrix", N_("Color Matrix"), ""},
+ {MNOTE_OLYMPUS_TAG_BLACKLEVEL, "BlackLevel", N_("Black Level"), ""},
+ {MNOTE_OLYMPUS_TAG_WBALANCE, "WhiteBalance", N_("White Balance Setting"), ""},
+ {MNOTE_OLYMPUS_TAG_REDBALANCE, "RedBalance", N_("Red Balance"), ""},
+ {MNOTE_OLYMPUS_TAG_BLUEBALANCE, "BlueBalance", N_("Blue Balance"), ""},
+ {MNOTE_OLYMPUS_TAG_COLORMATRIXNUMBER, "ColorMatrixNumber", N_("Color Matrix Number"), ""},
+ {MNOTE_OLYMPUS_TAG_SERIALNUMBER2, "SerialNumber", N_("Serial Number"), ""},
+ {MNOTE_OLYMPUS_TAG_FLASHEXPOSURECOMP, "FlashExposureComp", N_("Flash Exposure Comp"), ""},
+ {MNOTE_OLYMPUS_TAG_INTERNALFLASHTABLE, "InternalFlashTable", N_("Internal Flash Table"), ""},
+ {MNOTE_OLYMPUS_TAG_EXTERNALFLASHGVALUE, "ExternalFlashGValue", N_("External Flash G Value"), ""},
+ {MNOTE_OLYMPUS_TAG_EXTERNALFLASHBOUNCE, "ExternalFlashBounce", N_("External Flash Bounce"), ""},
+ {MNOTE_OLYMPUS_TAG_EXTERNALFLASHZOOM, "ExternalFlashZoom", N_("External Flash Zoom"), ""},
+ {MNOTE_OLYMPUS_TAG_EXTERNALFLASHMODE, "ExternalFlashMode", N_("External Flash Mode"), ""},
+ {MNOTE_OLYMPUS_TAG_CONTRAST, "Contrast", N_("Contrast Setting"), ""},
+ {MNOTE_OLYMPUS_TAG_SHARPNESSFACTOR, "SharpnessFactor", N_("Sharpness Factor"), ""},
+ {MNOTE_OLYMPUS_TAG_COLORCONTROL, "ColorControl", N_("Color Control"), ""},
+ {MNOTE_OLYMPUS_TAG_IMAGEWIDTH, "OlympusImageWidth", N_("Olympus Image Width"), ""},
+ {MNOTE_OLYMPUS_TAG_IMAGEHEIGHT, "OlympusImageHeight", N_("Olympus Image Height"), ""},
+ {MNOTE_OLYMPUS_TAG_SCENEDETECT, "SceneDetect", N_("Scene Detect"), ""},
+ {MNOTE_OLYMPUS_TAG_COMPRESSIONRATIO, "CompressionRatio", N_("Compression Ratio"), ""},
+ {MNOTE_OLYMPUS_TAG_PREVIEWIMAGEVALID, "PreviewImageValid", N_("Preview Image Valid"), ""},
+ {MNOTE_OLYMPUS_TAG_AFRESULT, "AFResult", N_("AF Result"), ""},
+ {MNOTE_OLYMPUS_TAG_CCDSCANMODE, "CCDScanMode", N_("CCD Scan Mode"), ""},
+ {MNOTE_OLYMPUS_TAG_NOISEREDUCTION, "NoiseReduction", N_("Noise Reduction"), ""},
+ {MNOTE_OLYMPUS_TAG_INFINITYLENSSTEP, "InfinityLensStep", N_("Infinity Lens Step"), ""},
+ {MNOTE_OLYMPUS_TAG_NEARLENSSTEP, "NearLensStep", N_("Near Lens Step"), ""},
+ {MNOTE_OLYMPUS_TAG_LIGHTVALUECENTER, "LightValueCenter", N_("Light Value Center"), ""},
+ {MNOTE_OLYMPUS_TAG_LIGHTVALUEPERIPHERY, "LightValuePeriphery", N_("Light Value Periphery"), ""},
+
+ /* Sanyo */
+ {MNOTE_SANYO_TAG_SEQUENTIALSHOT, "SequentialShot", N_("Sequential Shot"), ""},
+ {MNOTE_SANYO_TAG_WIDERANGE, "WideRange", N_("Wide Range"), ""},
+ {MNOTE_SANYO_TAG_COLORADJUSTMENTMODE, "ColorAdjustmentMode", N_("Color Adjustment Mode"), ""},
+ {MNOTE_SANYO_TAG_QUICKSHOT, "QuickShot", N_("Quick Shot"), ""},
+ {MNOTE_SANYO_TAG_SELFTIMER, "SelfTimer", N_("Self Timer"), ""},
+ {MNOTE_SANYO_TAG_VOICEMEMO, "VoiceMemo", N_("Voice Memo"), ""},
+ {MNOTE_SANYO_TAG_RECORDSHUTTERRELEASE, "RecordShutterRelease", N_("Record Shutter Release"), ""},
+ {MNOTE_SANYO_TAG_FLICKERREDUCE, "FlickerReduce", N_("Flicker Reduce"), ""},
+ {MNOTE_SANYO_TAG_OPTICALZOOM, "OpticalZoom", N_("Optical Zoom"), ""},
+ {MNOTE_SANYO_TAG_DIGITALZOOM, "DigitalZoom", N_("Digital Zoom"), ""},
+ {MNOTE_SANYO_TAG_LIGHTSOURCESPECIAL, "LightSourceSpecial", N_("Light Source Special"), ""},
+ {MNOTE_SANYO_TAG_RESAVED, "Resaved", N_("Resaved"), ""},
+ {MNOTE_SANYO_TAG_SCENESELECT, "SceneSelect", N_("Scene Select"), ""},
+ {MNOTE_SANYO_TAG_MANUALFOCUSDISTANCE, "ManualFocusDistance", N_("Manual Focus Distance"), ""},
+ {MNOTE_SANYO_TAG_SEQUENCESHOTINTERVAL, "SequenceShotInterval", N_("Sequence Shot Interval"), ""},
+#endif
{0, NULL, NULL, NULL}
};
@@ -150,6 +214,10 @@ mnote_olympus_tag_get_description (MnoteOlympusTag t)
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
- if (table[i].tag == t) return (_(table[i].description));
+ if (table[i].tag == t) {
+ if (!table[i].description || !*table[i].description)
+ return "";
+ return (_(table[i].description));
+ }
return NULL;
}
diff --git a/src/libexif/olympus/mnote-olympus-tag.h b/src/libexif/olympus/mnote-olympus-tag.h
index 22278ac..9ec08a6 100644
--- a/src/libexif/olympus/mnote-olympus-tag.h
+++ b/src/libexif/olympus/mnote-olympus-tag.h
@@ -1,6 +1,6 @@
/* mnote-olympus-tag.h
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -42,13 +42,13 @@ enum _MnoteOlympusTag {
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_PREVIEWIMAGE = 0x0011,
+ MNOTE_NIKON_TAG_FLASHEXPCOMPENSATION = 0x0012,
MNOTE_NIKON_TAG_ISO2 = 0x0013,
- MNOTE_NIKON_TAG_UNKNOWN_0X0016 = 0x0016,
+ MNOTE_NIKON_TAG_IMAGEBOUNDARY = 0x0016,
MNOTE_NIKON_TAG_UNKNOWN_0X0017 = 0x0017,
- MNOTE_NIKON_TAG_UNKNOWN_0X0018 = 0x0018,
- MNOTE_NIKON_TAG_UNKNOWN_0X0019 = 0x0019,
+ MNOTE_NIKON_TAG_FLASHEXPOSUREBRACKETVAL = 0x0018,
+ MNOTE_NIKON_TAG_EXPOSUREBRACKETVAL = 0x0019,
MNOTE_NIKON_TAG_IMAGEADJUSTMENT = 0x0080,
MNOTE_NIKON_TAG_TONECOMPENSATION = 0x0081,
MNOTE_NIKON_TAG_ADAPTER = 0x0082,
@@ -60,26 +60,26 @@ enum _MnoteOlympusTag {
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_LENS_FSTOPS = 0x008b,
MNOTE_NIKON_TAG_CURVE = 0x008c,
MNOTE_NIKON_TAG_COLORMODE = 0x008d,
- MNOTE_NIKON_TAG_LIGHTYPE = 0x0090,
+ MNOTE_NIKON_TAG_LIGHTTYPE = 0x0090,
MNOTE_NIKON_TAG_UNKNOWN_0X0091 = 0x0091,
MNOTE_NIKON_TAG_HUE = 0x0092,
- MNOTE_NIKON_TAG_UNKNOWN_0X0094 = 0x0094,
+ MNOTE_NIKON_TAG_SATURATION = 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_SENSORPIXELSIZE = 0x009a,
MNOTE_NIKON_TAG_UNKNOWN_0X009B = 0x009b,
- MNOTE_NIKON_TAG_UNKNOWN_0X00A0 = 0x00a0,
- MNOTE_NIKON_TAG_UNKNOWN_0X00A2 = 0x00a2,
+ MNOTE_NIKON_TAG_SERIALNUMBER = 0x00a0,
+ MNOTE_NIKON_TAG_IMAGE_DATASIZE = 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_SATURATION2 = 0x00aa,
+ MNOTE_NIKON_TAG_VARIPROGRAM = 0x00ab,
MNOTE_NIKON_TAG_CAPTUREEDITORDATA = 0x0e01,
MNOTE_NIKON_TAG_CAPTUREEDITORVER = 0x0e09,
MNOTE_NIKON_TAG_UNKNOWN_0X0E0E = 0x0e0e,
@@ -98,27 +98,95 @@ enum _MnoteOlympusTag {
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
+ /* Olympus and some Sanyo */
+ MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE = 0x0100,
+ MNOTE_OLYMPUS_TAG_MODE = 0x0200,
+ MNOTE_OLYMPUS_TAG_QUALITY = 0x0201,
+ MNOTE_OLYMPUS_TAG_MACRO = 0x0202,
+ MNOTE_OLYMPUS_TAG_BWMODE = 0x0203,
+ MNOTE_OLYMPUS_TAG_DIGIZOOM = 0x0204,
+ MNOTE_OLYMPUS_TAG_FOCALPLANEDIAGONAL = 0x0205,
+ MNOTE_OLYMPUS_TAG_LENSDISTORTION = 0x0206,
+ MNOTE_OLYMPUS_TAG_VERSION = 0x0207,
+ MNOTE_OLYMPUS_TAG_INFO = 0x0208,
+ MNOTE_OLYMPUS_TAG_ID = 0x0209,
+ MNOTE_OLYMPUS_TAG_PRECAPTUREFRAMES = 0x0300,
+ MNOTE_OLYMPUS_TAG_WHITEBOARD = 0x0301,
+ MNOTE_OLYMPUS_TAG_ONETOUCHWB = 0x0302,
+ MNOTE_OLYMPUS_TAG_WHITEBALANCEBRACKET = 0x0303,
+ MNOTE_OLYMPUS_TAG_WHITEBALANCEBIAS = 0x0304,
+ MNOTE_OLYMPUS_TAG_UNKNOWN_5 = 0x0f00,
+ MNOTE_OLYMPUS_TAG_UNKNOWN_4 = 0x0f04,
+ MNOTE_OLYMPUS_TAG_SHUTTERSPEED = 0x1000,
+ MNOTE_OLYMPUS_TAG_ISOVALUE = 0x1001,
+ MNOTE_OLYMPUS_TAG_APERTUREVALUE = 0x1002,
+ MNOTE_OLYMPUS_TAG_BRIGHTNESSVALUE = 0x1003,
+ MNOTE_OLYMPUS_TAG_FLASHMODE = 0x1004,
+ MNOTE_OLYMPUS_TAG_FLASHDEVICE = 0x1005,
+ MNOTE_OLYMPUS_TAG_EXPOSURECOMP = 0x1006,
+ MNOTE_OLYMPUS_TAG_SENSORTEMPERATURE = 0x1007,
+ MNOTE_OLYMPUS_TAG_LENSTEMPERATURE = 0x1008,
+ MNOTE_OLYMPUS_TAG_LIGHTCONDITION = 0x1009,
+ MNOTE_OLYMPUS_TAG_FOCUSRANGE = 0x100a,
+ MNOTE_OLYMPUS_TAG_MANFOCUS = 0x100b,
+ MNOTE_OLYMPUS_TAG_FOCUSDIST = 0x100c,
+ MNOTE_OLYMPUS_TAG_ZOOMSTEPCOUNT = 0x100d,
+ MNOTE_OLYMPUS_TAG_FOCUSSTEPCOUNT = 0x100e,
+ MNOTE_OLYMPUS_TAG_SHARPNESS = 0x100f,
+ MNOTE_OLYMPUS_TAG_FLASHCHARGELEVEL = 0x1010,
+ MNOTE_OLYMPUS_TAG_COLORMATRIX = 0x1011,
+ MNOTE_OLYMPUS_TAG_BLACKLEVEL = 0x1012,
+ MNOTE_OLYMPUS_TAG_WBALANCE = 0x1015,
+ MNOTE_OLYMPUS_TAG_REDBALANCE = 0x1017,
+ MNOTE_OLYMPUS_TAG_BLUEBALANCE = 0x1018,
+ MNOTE_OLYMPUS_TAG_COLORMATRIXNUMBER = 0x1019,
+ MNOTE_OLYMPUS_TAG_SERIALNUMBER2 = 0x101a,
+ MNOTE_OLYMPUS_TAG_FLASHEXPOSURECOMP = 0x1023,
+ MNOTE_OLYMPUS_TAG_INTERNALFLASHTABLE = 0x1024,
+ MNOTE_OLYMPUS_TAG_EXTERNALFLASHGVALUE = 0x1025,
+ MNOTE_OLYMPUS_TAG_EXTERNALFLASHBOUNCE = 0x1026,
+ MNOTE_OLYMPUS_TAG_EXTERNALFLASHZOOM = 0x1027,
+ MNOTE_OLYMPUS_TAG_EXTERNALFLASHMODE = 0x1028,
+ MNOTE_OLYMPUS_TAG_CONTRAST = 0x1029,
+ MNOTE_OLYMPUS_TAG_SHARPNESSFACTOR = 0x102a,
+ MNOTE_OLYMPUS_TAG_COLORCONTROL = 0x102b,
+ MNOTE_OLYMPUS_TAG_IMAGEWIDTH = 0x102e,
+ MNOTE_OLYMPUS_TAG_IMAGEHEIGHT = 0x102f,
+ MNOTE_OLYMPUS_TAG_SCENEDETECT = 0x1030,
+ MNOTE_OLYMPUS_TAG_COMPRESSIONRATIO = 0x1034,
+ MNOTE_OLYMPUS_TAG_PREVIEWIMAGEVALID = 0x1035,
+ MNOTE_OLYMPUS_TAG_AFRESULT = 0x1038,
+ MNOTE_OLYMPUS_TAG_CCDSCANMODE = 0x1039,
+ MNOTE_OLYMPUS_TAG_NOISEREDUCTION = 0x103a,
+ MNOTE_OLYMPUS_TAG_INFINITYLENSSTEP = 0x103b,
+ MNOTE_OLYMPUS_TAG_NEARLENSSTEP = 0x103c,
+ MNOTE_OLYMPUS_TAG_LIGHTVALUECENTER = 0x103d,
+ MNOTE_OLYMPUS_TAG_LIGHTVALUEPERIPHERY = 0x103e,
+
+ /* Sanyo */
+ MNOTE_SANYO_TAG_SEQUENTIALSHOT = 0x020e,
+ MNOTE_SANYO_TAG_WIDERANGE = 0x020f,
+ MNOTE_SANYO_TAG_COLORADJUSTMENTMODE = 0x0210,
+ MNOTE_SANYO_TAG_QUICKSHOT = 0x0213,
+ MNOTE_SANYO_TAG_SELFTIMER = 0x0214,
+ MNOTE_SANYO_TAG_VOICEMEMO = 0x0216,
+ MNOTE_SANYO_TAG_RECORDSHUTTERRELEASE = 0x0217,
+ MNOTE_SANYO_TAG_FLICKERREDUCE = 0x0218,
+ MNOTE_SANYO_TAG_OPTICALZOOM = 0x0219,
+ MNOTE_SANYO_TAG_DIGITALZOOM = 0x021b,
+ MNOTE_SANYO_TAG_LIGHTSOURCESPECIAL = 0x021d,
+ MNOTE_SANYO_TAG_RESAVED = 0x021e,
+ MNOTE_SANYO_TAG_SCENESELECT = 0x021f,
+ MNOTE_SANYO_TAG_MANUALFOCUSDISTANCE = 0x0223,
+ MNOTE_SANYO_TAG_SEQUENCESHOTINTERVAL = 0x0224
};
typedef enum _MnoteOlympusTag MnoteOlympusTag;
+/* Don't use these definitions. They are here for compatibility only. */
+#define MNOTE_OLYMPUS_TAG_UNKNOWN_1 MNOTE_OLYMPUS_TAG_BWMODE
+#define MNOTE_OLYMPUS_TAG_UNKNOWN_2 MNOTE_OLYMPUS_TAG_FOCALPLANEDIAGONAL
+#define MNOTE_OLYMPUS_TAG_UNKNOWN_3 MNOTE_OLYMPUS_TAG_LENSDISTORTION
+
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);
diff --git a/src/libexif/pentax/exif-mnote-data-pentax.c b/src/libexif/pentax/exif-mnote-data-pentax.c
index cc2cc12..0d17d62 100644
--- a/src/libexif/pentax/exif-mnote-data-pentax.c
+++ b/src/libexif/pentax/exif-mnote-data-pentax.c
@@ -1,6 +1,6 @@
/* exif-mnote-data-pentax.c
*
- * Copyright © 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ * Copyright (c) 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
@@ -73,41 +73,67 @@ exif_mnote_data_pentax_load (ExifMnoteData *en,
const unsigned char *buf, unsigned int buf_size)
{
ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) en;
- unsigned int i, o, s;
+ size_t i, o, s, datao = 6 + n->offset, base = 0;
ExifShort c;
/* Number of entries */
- if (buf_size < 2) return;
- c = exif_get_short (buf + 6 + n->offset, n->order);
+ if (buf_size < datao + (4 + 2) + 2) return;
+ if (!memcmp(buf + datao, "AOC", 4)) {
+ if ((buf[datao + 4] == 'I') && (buf[datao + 5] == 'I')) {
+ n->version = pentaxV3;
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ } else if ((buf[datao + 4] == 'M') && (buf[datao + 5] == 'M')) {
+ n->version = pentaxV3;
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
+ } else {
+ /* Uses Casio v2 tags */
+ n->version = pentaxV2;
+ }
+ datao += 4 + 2;
+ base = MNOTE_PENTAX2_TAG_BASE;
+ } if (!memcmp(buf + datao, "QVC", 4)) {
+ n->version = casioV2;
+ base = MNOTE_CASIO2_TAG_BASE;
+ datao += 4 + 2;
+ } else {
+ n->version = pentaxV1;
+ }
+ c = exif_get_short (buf + datao, 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) *
+ o = datao + 2 + 12 * i;
+ if (o + 8 > buf_size) return;
+
+ n->count = i + 1;
+ n->entries[i].tag = exif_get_short (buf + o + 0, 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;
+
+ /*
+ * 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;
+ if (s > 65536) {
+ /* Corrupt data: EXIF data size is limited to the
+ * maximum size of a JPEG segment (64 kb).
+ */
+ continue;
+ }
+ 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);
+ /* Sanity check */
+ n->entries[i].data = exif_mem_alloc (en->mem, s);
+ if (!n->entries[i].data) return;
+ n->entries[i].size = s;
+ memcpy (n->entries[i].data, buf + o, s);
}
}
diff --git a/src/libexif/pentax/exif-mnote-data-pentax.h b/src/libexif/pentax/exif-mnote-data-pentax.h
index c04bc41..62f9739 100644
--- a/src/libexif/pentax/exif-mnote-data-pentax.h
+++ b/src/libexif/pentax/exif-mnote-data-pentax.h
@@ -1,6 +1,6 @@
/* exif-mnote-data-pentax.h
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -27,6 +27,8 @@
#include <libexif/pentax/mnote-pentax-entry.h>
#include <libexif/exif-mem.h>
+enum PentaxVersion {pentaxV1 = 1, pentaxV2 = 2, pentaxV3 = 4, casioV2 = 4 };
+
typedef struct _ExifMnoteDataPentax ExifMnoteDataPentax;
struct _ExifMnoteDataPentax {
@@ -37,6 +39,8 @@ struct _ExifMnoteDataPentax {
ExifByteOrder order;
unsigned int offset;
+
+ enum PentaxVersion version;
};
ExifMnoteData *exif_mnote_data_pentax_new (ExifMem *);
diff --git a/src/libexif/pentax/mnote-pentax-entry.c b/src/libexif/pentax/mnote-pentax-entry.c
index 3469f22..ac15108 100644
--- a/src/libexif/pentax/mnote-pentax-entry.c
+++ b/src/libexif/pentax/mnote-pentax-entry.c
@@ -1,6 +1,6 @@
/* mnote-pentax-entry.c
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -34,37 +34,50 @@
#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; \
- } \
+ 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; \
- } \
+ if (number != target) { \
+ snprintf (v, maxlen, \
+ _("Invalid number of components (%i, " \
+ "expected %i)."), (int) number, (int) target); \
+ break; \
+ } \
}
-static struct {
+#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 const struct {
ExifTag tag;
struct {
int index;
const char *string;
- } elem[7];
+ } elem[33];
} items[] = {
+#ifndef NO_VERBOSE_TAG_DATA
{ MNOTE_PENTAX_TAG_MODE,
{ {0, N_("Auto")},
{1, N_("Night-scene")},
{2, N_("Manual")},
+ {4, N_("Multi-exposure")},
{0, NULL}}},
{ MNOTE_PENTAX_TAG_QUALITY,
{ {0, N_("Good")},
@@ -114,6 +127,181 @@ static struct {
{2, N_("Black & White")},
{3, N_("Sepia")},
{0, NULL}}},
+ { MNOTE_PENTAX2_TAG_MODE,
+ { {0, N_("Auto")},
+ {1, N_("Night-scene")},
+ {2, N_("Manual")},
+ {4, N_("Multi-exposure")},
+ {0, NULL}}},
+ { MNOTE_PENTAX2_TAG_QUALITY,
+ { {0, N_("Good")},
+ {1, N_("Better")},
+ {2, N_("Best")},
+ {3, N_("TIFF")},
+ {4, N_("RAW")},
+ {0, NULL}}},
+ { MNOTE_PENTAX2_TAG_IMAGE_SIZE,
+ { {0, "640x480"},
+ {1, N_("Full")},
+ {2, "1024x768"},
+ {3, "1280x960"},
+ {4, "1600x1200"},
+ {5, "2048x1536"},
+ {8, N_("2560x1920 or 2304x1728")},
+ {9, "3072x2304"},
+ {10, "3264x2448"},
+ {19, "320x240"},
+ {20, "2288x1712"},
+ {21, "2592x1944"},
+ {22, N_("2304x1728 or 2592x1944")},
+ {23, "3056x2296"},
+ {25, N_("2816x2212 or 2816x2112")},
+ {27, "3648x2736"},
+ {36, "3008x2008"},
+ {0, NULL}}},
+ { MNOTE_PENTAX2_TAG_PICTURE_MODE,
+ { {0, N_("Program")},
+ {2, N_("Program AE")},
+ {3, N_("Manual")},
+ {5, N_("Portrait")},
+ {6, N_("Landscape")},
+ {8, N_("Sport")},
+ {9, N_("Night Scene")},
+ {11, N_("Soft")},
+ {12, N_("Surf & Snow")},
+ {13, N_("Sunset or Candlelight")},
+ {14, N_("Autumn")},
+ {15, N_("Macro")},
+ {17, N_("Fireworks")},
+ {18, N_("Text")},
+ {19, N_("Panorama")},
+ {30, N_("Self Portrait")},
+ {31, N_("Illustrations")},
+ {33, N_("Digital Filter")},
+ {37, N_("Museum")},
+ {38, N_("Food")},
+ {40, N_("Green Mode")},
+ {49, N_("Light Pet")},
+ {50, N_("Dark Pet")},
+ {51, N_("Medium Pet")},
+ {53, N_("Underwater")},
+ {54, N_("Candlelight")},
+ {55, N_("Natural Skin Tone")},
+ {56, N_("Synchro Sound Record")},
+ {58, N_("Frame Composite")},
+ {0, NULL}}},
+ { MNOTE_PENTAX2_TAG_FLASH_MODE,
+ { {0x0000, N_("Auto, Did not fire")},
+ {0x0001, N_("Off")},
+ {0x0003, N_("Auto, Did not fire, Red-eye reduction")},
+ {0x0100, N_("Auto, Fired")},
+ {0x0102, N_("On")},
+ {0x0103, N_("Auto, Fired, Red-eye reduction")},
+ {0x0104, N_("On, Red-eye reduction")},
+ {0x0105, N_("On, Wireless")},
+ {0x0108, N_("On, Soft")},
+ {0x0109, N_("On, Slow-sync")},
+ {0x010a, N_("On, Slow-sync, Red-eye reduction")},
+ {0x010b, N_("On, Trailing-curtain Sync")},
+ {0, NULL}}},
+ { MNOTE_PENTAX2_TAG_FOCUS_MODE,
+ { {0, N_("Normal")},
+ {1, N_("Macro")},
+ {2, N_("Infinity")},
+ {3, N_("Manual")},
+ {5, N_("Pan Focus")},
+ {16, N_("AF-S")},
+ {17, N_("AF-C")},
+ {0, NULL}}},
+ { MNOTE_PENTAX2_TAG_AFPOINT_SELECTED,
+ { {1, N_("Upper-left")},
+ {2, N_("Top")},
+ {3, N_("Upper-right")},
+ {4, N_("Left")},
+ {5, N_("Mid-left")},
+ {6, N_("Center")},
+ {7, N_("Mid-right")},
+ {8, N_("Right")},
+ {9, N_("Lower-left")},
+ {10, N_("Bottom")},
+ {11, N_("Lower-right")},
+ {0xfffe, N_("Fixed Center")},
+ {0xffff, N_("Auto")},
+ {0, NULL}}},
+ { MNOTE_PENTAX2_TAG_AUTO_AFPOINT,
+ { {0, N_("Multiple")},
+ {1, N_("Top-left")},
+ {2, N_("Top-center")},
+ {3, N_("Top-right")},
+ {4, N_("Left")},
+ {5, N_("Center")},
+ {6, N_("Right")},
+ {7, N_("Bottom-left")},
+ {8, N_("Bottom-center")},
+ {9, N_("Bottom-right")},
+ {0xffff, N_("None")},
+ {0, NULL}}},
+ { MNOTE_PENTAX2_TAG_WHITE_BALANCE,
+ { {0, N_("Auto")},
+ {1, N_("Daylight")},
+ {2, N_("Shade")},
+ {3, N_("Fluorescent")},
+ {4, N_("Tungsten")},
+ {5, N_("Manual")},
+ {6, N_("Daylight Fluorescent")},
+ {7, N_("Daywhite Fluorescent")},
+ {8, N_("White Fluorescent")},
+ {9, N_("Flash")},
+ {10, N_("Cloudy")},
+ {0xfffe, N_("Unknown")},
+ {0xffff, N_("User Selected")},
+ {0, NULL}}},
+ {MNOTE_CASIO2_TAG_BESTSHOT_MODE,
+ { {0, N_("Off")},
+ {1, N_("On")},
+ {0, NULL}}},
+#endif
+ {0, {{0, NULL}}}
+};
+
+/* Two-component values */
+static const struct {
+ ExifTag tag;
+ struct {
+ int index1, index2;
+ const char *string;
+ } elem[39];
+} items2[] = {
+#ifndef NO_VERBOSE_TAG_DATA
+ { MNOTE_PENTAX2_TAG_IMAGE_SIZE,
+ { {0, 0, "2304x1728"},
+ {4, 0, "1600x1200"},
+ {5, 0, "2048x1536"},
+ {8, 0, "2560x1920"},
+ {34, 0, "1536x1024"},
+ {36, 0, N_("3008x2008 or 3040x2024")},
+ {37, 0, "3008x2000"},
+ {35, 1, "2400x1600"},
+ {32, 2, "960x480"},
+ {33, 2, "1152x768"},
+ {34, 2, "1536x1024"},
+ {0, 0, NULL}}},
+ { MNOTE_PENTAX2_TAG_PICTURE_MODE,
+ { {0, 0, N_("Auto")},
+ {5, 0, N_("Portrait")},
+ {53, 0, N_("Underwater")},
+ {255, 0, N_("Digital Filter?")},
+ {5, 1, N_("Portrait")},
+ {9, 1, N_("Night Scene")},
+ {13, 1, N_("Candlelight")},
+ {15, 1, N_("Macro")},
+ {53, 1, N_("Underwater")},
+ {0, 2, N_("Program AE")},
+ {5, 2, N_("Portrait")},
+ {6, 2, N_("Landscape")},
+ {0, 0, NULL}}},
+#endif
+ {0, {{0, 0, NULL}}}
};
char *
@@ -121,7 +309,7 @@ mnote_pentax_entry_get_value (MnotePentaxEntry *entry,
char *val, unsigned int maxlen)
{
ExifLong vl;
- ExifShort vs;
+ ExifShort vs, vs2;
int i = 0, j = 0;
if (!entry) return (NULL);
@@ -140,26 +328,63 @@ mnote_pentax_entry_get_value (MnotePentaxEntry *entry,
case MNOTE_PENTAX_TAG_SATURATION:
case MNOTE_PENTAX_TAG_ISO_SPEED:
case MNOTE_PENTAX_TAG_COLOR:
+ case MNOTE_PENTAX2_TAG_MODE:
+ case MNOTE_PENTAX2_TAG_QUALITY:
+ case MNOTE_PENTAX2_TAG_FLASH_MODE:
+ case MNOTE_PENTAX2_TAG_FOCUS_MODE:
+ case MNOTE_PENTAX2_TAG_AFPOINT_SELECTED:
+ case MNOTE_PENTAX2_TAG_AUTO_AFPOINT:
+ case MNOTE_PENTAX2_TAG_WHITE_BALANCE:
+ case MNOTE_PENTAX2_TAG_PICTURE_MODE:
+ case MNOTE_PENTAX2_TAG_IMAGE_SIZE:
+ case MNOTE_CASIO2_TAG_BESTSHOT_MODE:
CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
- CC (entry->components, 1, val, maxlen);
- vs = exif_get_short (entry->data, entry->order);
+ CC2 (entry->components, 1, 2, val, maxlen);
+ if (entry->components == 1) {
+ 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;
- }
+ /* search the tag */
+ for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++);
+ if (!items[i].tag) {
+ snprintf (val, maxlen,
+ _("Internal error (unknown value %i)"), vs);
+ break;
+ }
- /* find the value */
- for (j = 0; items[i].elem[j].string &&
+ /* 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;
+ if (items[i].elem[j].index != vs) {
+ snprintf (val, maxlen,
+ _("Internal error (unknown value %i)"), vs);
+ break;
+ }
+ strncpy (val, _(items[i].elem[j].string), maxlen);
+ } else {
+ /* Two-component values */
+ CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);
+ CC2 (entry->components, 1, 2, val, maxlen);
+ vs = exif_get_short (entry->data, entry->order);
+ vs2 = exif_get_short (entry->data+2, entry->order) << 16;
+
+ /* search the tag */
+ for (i = 0; (items2[i].tag && items2[i].tag != entry->tag); i++);
+ if (!items2[i].tag) {
+ snprintf (val, maxlen,
+ _("Internal error (unknown value %i %i)"), vs, vs2);
+ break;
+ }
+
+ /* find the value */
+ for (j = 0; items2[i].elem[j].string && ((items2[i].elem[j].index2 < vs2)
+ || ((items2[i].elem[j].index2 == vs2) && (items2[i].elem[j].index1 < vs))); j++);
+ if ((items2[i].elem[j].index1 != vs) || (items2[i].elem[j].index2 != vs2)) {
+ snprintf (val, maxlen,
+ _("Internal error (unknown value %i %i)"), vs, vs2);
+ break;
+ }
+ strncpy (val, _(items2[i].elem[j].string), maxlen);
}
- snprintf (val, maxlen, "%s", items[i].elem[j].string);
break;
case MNOTE_PENTAX_TAG_ZOOM:
@@ -171,23 +396,23 @@ mnote_pentax_entry_get_value (MnotePentaxEntry *entry,
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);
+ snprintf (val, maxlen, _("%i bytes unknown data"),
+ entry->size);
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);
+ strncpy (val, (char*)entry->data, MIN(maxlen, entry->size));
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);
+ strncpy (val, (char*)entry->data, MIN(maxlen, entry->size));
break;
default:
switch (entry->format) {
case EXIF_FORMAT_ASCII:
- strncpy (val, entry->data, MIN(maxlen, entry->components));
+ strncpy (val, (char *)entry->data, MIN(maxlen, entry->size));
break;
case EXIF_FORMAT_SHORT:
vs = exif_get_short (entry->data, entry->order);
@@ -199,8 +424,8 @@ mnote_pentax_entry_get_value (MnotePentaxEntry *entry,
break;
case EXIF_FORMAT_UNDEFINED:
default:
- snprintf (val, maxlen, "%li bytes unknown data",
- entry->components);
+ snprintf (val, maxlen, _("%i bytes unknown data"),
+ entry->size);
break;
}
break;
diff --git a/src/libexif/pentax/mnote-pentax-entry.h b/src/libexif/pentax/mnote-pentax-entry.h
index 628d5dd..a7025e6 100644
--- a/src/libexif/pentax/mnote-pentax-entry.h
+++ b/src/libexif/pentax/mnote-pentax-entry.h
@@ -1,6 +1,6 @@
/* mnote-pentax-entry.h
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
diff --git a/src/libexif/pentax/mnote-pentax-tag.c b/src/libexif/pentax/mnote-pentax-tag.c
index 76823a4..dd06cd9 100644
--- a/src/libexif/pentax/mnote-pentax-tag.c
+++ b/src/libexif/pentax/mnote-pentax-tag.c
@@ -1,6 +1,6 @@
/* mnote-pentax-tag.c:
*
- * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002 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
@@ -25,39 +25,53 @@
#include <libexif/i18n.h>
-static struct {
+static const 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},
+#ifndef NO_VERBOSE_TAG_STRINGS
+ {MNOTE_PENTAX_TAG_MODE, "Mode", N_("Capture Mode"), ""},
+ {MNOTE_PENTAX_TAG_QUALITY, "Quality", N_("Quality Level"), ""},
+ {MNOTE_PENTAX_TAG_FOCUS, "Focus", N_("Focus Mode"), ""},
+ {MNOTE_PENTAX_TAG_FLASH, "Flash", N_("Flash Mode"), ""},
{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_WHITE_BALANCE, "WhiteBalance", N_("White Balance"), ""},
{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_SHARPNESS, "Sharpness", N_("Sharpness"), ""},
+ {MNOTE_PENTAX_TAG_CONTRAST, "Contrast", N_("Contrast"), ""},
+ {MNOTE_PENTAX_TAG_SATURATION, "Saturation", N_("Saturation"), ""},
{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_ISO_SPEED, "ISOSpeed", N_("ISOSpeed"), ""},
{MNOTE_PENTAX_TAG_UNKNOWN_21, NULL, NULL, NULL},
- {MNOTE_PENTAX_TAG_COLOR, "Color", N_("Color"), NULL},
+ {MNOTE_PENTAX_TAG_COLOR, "Color", N_("Colors"), ""},
{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},
+ {MNOTE_PENTAX_TAG_PRINTIM, "PrintIM", N_("PrintIM Settings"), ""},
+ {MNOTE_PENTAX_TAG_TZ_CITY, "TimeZone", N_("Time Zone"), ""},
+ {MNOTE_PENTAX_TAG_TZ_DST, "DaylightSavings", N_("Daylight Savings"), ""},
+ {MNOTE_PENTAX2_TAG_MODE, "Mode", N_("Capture Mode"), ""},
+ {MNOTE_PENTAX2_TAG_QUALITY, "Quality", N_("Quality Level"), ""},
+ {MNOTE_PENTAX2_TAG_IMAGE_SIZE, "ImageSize", N_("Image Size"), ""},
+ {MNOTE_PENTAX2_TAG_PICTURE_MODE, "PictureMode", N_("PictureMode"), ""},
+ {MNOTE_PENTAX2_TAG_FLASH_MODE, "FlashMode", N_("Flash Mode"), ""},
+ {MNOTE_PENTAX2_TAG_FOCUS_MODE, "FocusMode", N_("Focus Mode"), ""},
+ {MNOTE_PENTAX2_TAG_AFPOINT_SELECTED, "AFPointSelected", N_("AF Point Selected"), ""},
+ {MNOTE_PENTAX2_TAG_AUTO_AFPOINT, "AutoAFPoint", N_("Auto AF Point"), ""},
+ {MNOTE_PENTAX2_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance"), ""},
+ {MNOTE_CASIO2_TAG_OBJECT_DISTANCE, "ObjectDistance", N_("Object Distance"), N_("Distance of photographed object in millimeters.")},
+ {MNOTE_CASIO2_TAG_TIME_ZONE, "TimeZone", N_("Time Zone"), ""},
+ {MNOTE_CASIO2_TAG_BESTSHOT_MODE, "BestshotMode", N_("Bestshot mode"), ""},
+#endif
{0, NULL, NULL, NULL}
};
@@ -89,6 +103,10 @@ mnote_pentax_tag_get_description (MnotePentaxTag t)
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
- if (table[i].tag == t) return (_(table[i].description));
+ if (table[i].tag == t) {
+ if (!table[i].description || !*table[i].description)
+ return "";
+ return (_(table[i].description));
+ }
return NULL;
}
diff --git a/src/libexif/pentax/mnote-pentax-tag.h b/src/libexif/pentax/mnote-pentax-tag.h
index a261102..872222b 100644
--- a/src/libexif/pentax/mnote-pentax-tag.h
+++ b/src/libexif/pentax/mnote-pentax-tag.h
@@ -1,6 +1,6 @@
/* mnote-pentax-tag.h
*
- * Copyright © 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ * Copyright (c) 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
@@ -59,7 +59,86 @@ enum _MnotePentaxTag {
MNOTE_PENTAX_TAG_UNKNOWN_25 = 0x0019,
MNOTE_PENTAX_TAG_PRINTIM = 0x0e00,
MNOTE_PENTAX_TAG_TZ_CITY = 0x1000,
- MNOTE_PENTAX_TAG_TZ_DST = 0x1001
+ MNOTE_PENTAX_TAG_TZ_DST = 0x1001,
+
+ /* Pentax v2, v3: real values + our proprietary base to distinguish from v1 */
+ MNOTE_PENTAX2_TAG_BASE = 0x4000,
+ MNOTE_PENTAX2_TAG_MODE = 0x0001 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_PREVIEW_SIZE = 0x0002 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_PREVIEW_LENGTH = 0x0003 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_PREVIEW_START = 0x0004 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_MODEL_ID = 0x0005 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_DATE = 0x0006 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_TIME = 0x0007 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_QUALITY = 0x0008 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_IMAGE_SIZE = 0x0009 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_PICTURE_MODE = 0x000b + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_FLASH_MODE = 0x000c + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_FOCUS_MODE = 0x000d + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_AFPOINT_SELECTED = 0x000e + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_AUTO_AFPOINT = 0x000f + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_FOCUS_POSITION = 0x0010 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_EXPOSURE_TIME = 0x0012 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_FNUMBER = 0x0013 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_ISO = 0x0014 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_EXPOSURE_COMPENSATION = 0x0016 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_METERING_MODE = 0x0017 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_AUTO_BRACKETING = 0x0018 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_WHITE_BALANCE = 0x0019 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_WHITE_BALANCE_MODE= 0x001a + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_BLUE_BALANCE = 0x001b + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_RED_BALANCE = 0x001c + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_FOCAL_LENGTH = 0x001d + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_DIGITAL_ZOOM = 0x001e + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_SATURATION = 0x001f + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_CONTRAST = 0x0020 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_SHARPNESS = 0x0021 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_WORLDTIME_LOCATION = 0x0022 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_HOMETOWN_CITY = 0x0023 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_DESTINATION_CITY = 0x0024 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_HOMETOWN_DST = 0x0025 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_DESTINATION_DST = 0x0026 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_FRAME_NUMBER = 0x0029 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_IMAGE_PROCESSING = 0x0032 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_PICTURE_MODE2 = 0x0033 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_DRIVE_MODE = 0x0034 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_COLOR_SPACE = 0x0037 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_IMAGE_AREA_OFFSET = 0x0038 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_RAW_IMAGE_SIZE = 0x0039 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_AFPOINTS_USED = 0x003c + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_LENS_TYPE = 0x003f + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_CAMERA_TEMPERATURE = 0x0047 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_NOISE_REDUCTION = 0x0049 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_FLASH_EXPOSURE_COMP = 0x004d + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_IMAGE_TONE = 0x004f + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_SHAKE_REDUCTION_INFO = 0x005c + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_BLACK_POINT = 0x0200 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_WHITE_POINT = 0x0201 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_AE_INFO = 0x0206 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_LENS_INFO = 0x0207 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_FLASH_INFO = 0x0208 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_CAMERA_INFO = 0x0215 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_BATTERY_INFO = 0x0216 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_HOMETOWN_CITY_CODE = 0x1000 + MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_PENTAX2_TAG_DESTINATION_CITY_CODE = 0x1001 + MNOTE_PENTAX2_TAG_BASE,
+
+ /* Casio v2: some Casio v2 tags match Pentax v2 tags */
+ MNOTE_CASIO2_TAG_BASE = MNOTE_PENTAX2_TAG_BASE,
+ MNOTE_CASIO2_TAG_PREVIEW_START = 0x2000 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_WHITE_BALANCE_BIAS = 0x2011 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_WHITE_BALANCE = 0x2012 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_OBJECT_DISTANCE = 0x2022 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_FLASH_DISTANCE = 0x2034 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_RECORD_MODE = 0x3000 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_SELF_TIMER = 0x3001 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_QUALITY = 0x3002 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_FOCUS_MODE = 0x3003 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_TIME_ZONE = 0x3006 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_BESTSHOT_MODE = 0x3007 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_CCS_ISO_SENSITIVITY = 0x3014 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_COLOR_MODE = 0x3015 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_ENHANCEMENT = 0x3016 + MNOTE_CASIO2_TAG_BASE,
+ MNOTE_CASIO2_TAG_FINER = 0x3017 + MNOTE_CASIO2_TAG_BASE
};
typedef enum _MnotePentaxTag MnotePentaxTag;