diff options
Diffstat (limited to 'src/libexif')
54 files changed, 4297 insertions, 2678 deletions
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; |