diff options
Diffstat (limited to 'src')
55 files changed, 4298 insertions, 2678 deletions
diff --git a/src/config.mak b/src/config.mak index d2c3c0d..059eb74 100644 --- a/src/config.mak +++ b/src/config.mak @@ -55,6 +55,7 @@ SRCZLIB  := $(addprefix zlib/, $(SRCZLIB))  INCLUDES += zlib  SRCEXIF = \ +    fuji/exif-mnote-data-fuji.c  fuji/mnote-fuji-entry.c  fuji/mnote-fuji-tag.c              \      canon/exif-mnote-data-canon.c  canon/mnote-canon-entry.c  canon/mnote-canon-tag.c              \      olympus/exif-mnote-data-olympus.c  olympus/mnote-olympus-entry.c  olympus/mnote-olympus-tag.c  \      pentax/exif-mnote-data-pentax.c  pentax/mnote-pentax-entry.c  pentax/mnote-pentax-tag.c        \ diff --git a/src/libexif/canon/exif-mnote-data-canon.c b/src/libexif/canon/exif-mnote-data-canon.c index b1c5dab..2783d15 100644 --- a/src/libexif/canon/exif-mnote-data-canon.c +++ b/src/libexif/canon/exif-mnote-data-canon.c @@ -1,7 +1,7 @@  /* exif-mnote-data-canon.c   * - * Copyright © 2002, 2003 Lutz Müller <lutz@users.sourceforge.net> - * Copyright © 2003 Matthieu Castet <mat-c@users.sourceforge.net> + * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net> + * Copyright (c) 2003 Matthieu Castet <mat-c@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -60,14 +60,33 @@ exif_mnote_data_canon_free (ExifMnoteData *n)  	exif_mnote_data_canon_clear ((ExifMnoteDataCanon *) n);  } +static void +exif_mnote_data_canon_get_tags (ExifMnoteDataCanon *dc, unsigned int n, +		unsigned int *m, unsigned int *s) +{ +	unsigned int from = 0, to; + +	if (!dc || !m) return; +	for (*m = 0; *m < dc->count; (*m)++) { +		to = from + mnote_canon_entry_count_values (&dc->entries[*m]); +		if (to > n) { +			if (s) *s = n - from; +			break; +		} +		from = to; +	} +} +  static char *  exif_mnote_data_canon_get_value (ExifMnoteData *note, unsigned int n, char *val, unsigned int maxlen)  { -	ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note; +	ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note; +	unsigned int m, s; -	if (!note) return NULL; -	if (cnote->count <= n) return NULL; -	return mnote_canon_entry_get_value (&cnote->entries[n], val, maxlen); +	if (!dc) return NULL; +	exif_mnote_data_canon_get_tags (dc, n, &m, &s); +	if (m >= dc->count) return NULL; +	return mnote_canon_entry_get_value (&dc->entries[m], s, val, maxlen);  }  static void @@ -99,7 +118,9 @@ exif_mnote_data_canon_save (ExifMnoteData *ne,  	unsigned char **buf, unsigned int *buf_size)  {  	ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne; -	unsigned int i, o, s, doff; +	size_t i, o, s, doff; +	unsigned char *t; +	size_t ts;  	if (!n || !buf || !buf_size) return; @@ -124,14 +145,22 @@ exif_mnote_data_canon_save (ExifMnoteData *ne,  		o += 8;  		s = exif_format_get_size (n->entries[i].format) *  						n->entries[i].components; +		if (s > 65536) { +			/* Corrupt data: EXIF data size is limited to the +			 * maximum size of a JPEG segment (64 kb). +			 */ +			continue; +		}  		if (s > 4) { -			*buf_size += s; +			ts = *buf_size + s;  			/* Ensure even offsets. Set padding bytes to 0. */ -			if (s & 1) *buf_size += 1; -			*buf = exif_mem_realloc (ne->mem, *buf, -						 sizeof (char) * *buf_size); -			if (!*buf) return; +			if (s & 1) ts += 1; +			t = exif_mem_realloc (ne->mem, *buf, +						 sizeof (char) * ts); +			if (!t) return; +			*buf = t; +			*buf_size = ts;  			doff = *buf_size - s;  			if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }  			exif_set_long (*buf + o, n->order, n->offset + doff); @@ -166,7 +195,8 @@ exif_mnote_data_canon_load (ExifMnoteData *ne,  {  	ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;  	ExifShort c; -	unsigned int i, o, s; +	size_t i, o, s; +	MnoteCanonEntry *t;  	if (!n || !buf || !buf_size || (buf_size < 6 + n->offset + 2)) return; @@ -176,86 +206,102 @@ exif_mnote_data_canon_load (ExifMnoteData *ne,  	/* Parse the entries */  	for (i = 0; i < c; i++) { -	    o = 6 + 2 + n->offset + 12 * i; -	    if (o + 8 > buf_size) return; - -	    n->count = i + 1; -	    n->entries = exif_mem_realloc (ne->mem, n->entries, -					   sizeof (MnoteCanonEntry) * (i+1)); -	    memset (&n->entries[i], 0, sizeof (MnoteCanonEntry)); -	    n->entries[i].tag        = exif_get_short (buf + o, n->order); -	    n->entries[i].format     = exif_get_short (buf + o + 2, n->order); -	    n->entries[i].components = exif_get_long (buf + o + 4, n->order); -	    n->entries[i].order      = n->order; - -	    /* -	     * Size? If bigger than 4 bytes, the actual data is not -	     * in the entry but somewhere else (offset). -	     */ -	    s = exif_format_get_size (n->entries[i].format) * -		    		      n->entries[i].components; -	    if (!s) return; -	    o += 8; -	    if (s > 4) o = exif_get_long (buf + o, n->order) + 6; -	    if (o + s > buf_size) return; -	     -	    /* Sanity check */ -	    n->entries[i].data = exif_mem_alloc (ne->mem, sizeof (char) * s); -	    if (!n->entries[i].data) return; -	    n->entries[i].size = s; -	    memcpy (n->entries[i].data, buf + o, s); +		o = 6 + 2 + n->offset + 12 * i; +	  if (o + 8 > buf_size) return; + +		t = exif_mem_realloc (ne->mem, n->entries, +				sizeof (MnoteCanonEntry) * (i + 1)); +		if (!t) return; +		n->count = i + 1; +		n->entries = t; +		memset (&n->entries[i], 0, sizeof (MnoteCanonEntry)); +	  n->entries[i].tag        = exif_get_short (buf + o, n->order); +	  n->entries[i].format     = exif_get_short (buf + o + 2, n->order); +	  n->entries[i].components = exif_get_long (buf + o + 4, n->order); +	  n->entries[i].order      = n->order; + +	  /* +	   * Size? If bigger than 4 bytes, the actual data is not +	   * in the entry but somewhere else (offset). +	   */ +	  s = exif_format_get_size (n->entries[i].format) * n->entries[i].components; +		if (!s) return; +		o += 8; +		if (s > 4) o = exif_get_long (buf + o, n->order) + 6; +		if (o + s > buf_size) return; + +		/* Sanity check */ +		n->entries[i].data = exif_mem_alloc (ne->mem, sizeof (char) * s); +		if (!n->entries[i].data) return; +		n->entries[i].size = s; +		memcpy (n->entries[i].data, buf + o, s);  	}  }  static unsigned int  exif_mnote_data_canon_count (ExifMnoteData *n)  { -	return n ? ((ExifMnoteDataCanon *) n)->count : 0; +	ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) n; +	unsigned int i, c; + +	for (i = c = 0; dc && (i < dc->count); i++) +		c += mnote_canon_entry_count_values (&dc->entries[i]); +	return c;  }  static unsigned int -exif_mnote_data_canon_get_id (ExifMnoteData *d, unsigned int n) +exif_mnote_data_canon_get_id (ExifMnoteData *d, unsigned int i)  { -	ExifMnoteDataCanon *note = (ExifMnoteDataCanon *) d; +	ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) d; +	unsigned int m; -	if (!note) return 0; -	if (note->count <= n) return 0; -	return note->entries[n].tag; +	if (!dc) return 0; +	exif_mnote_data_canon_get_tags (dc, i, &m, NULL); +	if (m >= dc->count) return 0; +	return dc->entries[m].tag;  }  static const char *  exif_mnote_data_canon_get_name (ExifMnoteData *note, unsigned int i)  { -	ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note; +	ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note; +	unsigned int m, s; -	if (!note) return NULL; -	if (i >= cnote->count) return NULL; -	return mnote_canon_tag_get_name (cnote->entries[i].tag); +	if (!dc) return NULL; +	exif_mnote_data_canon_get_tags (dc, i, &m, &s); +	if (m >= dc->count) return NULL; +	return mnote_canon_tag_get_name_sub (dc->entries[m].tag, s, dc->options);  }  static const char *  exif_mnote_data_canon_get_title (ExifMnoteData *note, unsigned int i)  { -	ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note; +	ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note; +	unsigned int m, s; -	if (!note) return NULL; -	if (i >= cnote->count) return NULL; -	return mnote_canon_tag_get_title (cnote->entries[i].tag); +	if (!dc) return NULL; +	exif_mnote_data_canon_get_tags (dc, i, &m, &s); +	if (m >= dc->count) return NULL; +	return mnote_canon_tag_get_title_sub (dc->entries[m].tag, s, dc->options);  }  static const char *  exif_mnote_data_canon_get_description (ExifMnoteData *note, unsigned int i)  { -	ExifMnoteDataCanon *cnote = (ExifMnoteDataCanon *) note; -	if (!note) return NULL; -	if (i >= cnote->count) return NULL; -	return mnote_canon_tag_get_description (cnote->entries[i].tag); +	ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note; +	unsigned int m; + +	if (!dc) return NULL; +	exif_mnote_data_canon_get_tags (dc, i, &m, NULL); +	if (m >= dc->count) return NULL; +	return mnote_canon_tag_get_description (dc->entries[m].tag);  }  ExifMnoteData * -exif_mnote_data_canon_new (ExifMem *mem) +exif_mnote_data_canon_new (ExifMem *mem, ExifDataOption o)  {  	ExifMnoteData *d; +	ExifMnoteDataCanon *dc;  	if (!mem) return NULL; @@ -277,5 +323,7 @@ exif_mnote_data_canon_new (ExifMem *mem)  	d->methods.get_description = exif_mnote_data_canon_get_description;  	d->methods.get_value       = exif_mnote_data_canon_get_value; +	dc = (ExifMnoteDataCanon*)d; +	dc->options = o;  	return d;  } diff --git a/src/libexif/canon/exif-mnote-data-canon.h b/src/libexif/canon/exif-mnote-data-canon.h index a476ca0..6d46432 100644 --- a/src/libexif/canon/exif-mnote-data-canon.h +++ b/src/libexif/canon/exif-mnote-data-canon.h @@ -1,6 +1,6 @@  /* exif-mnote-data-canon.h   * - * Copyright © 2002, 2003 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -25,6 +25,7 @@  #include <libexif/exif-mnote-data.h>  #include <libexif/exif-mnote-data-priv.h>  #include <libexif/exif-mem.h> +#include <libexif/exif-data.h>  typedef struct _ExifMnoteDataCanon ExifMnoteDataCanon; @@ -38,8 +39,10 @@ struct _ExifMnoteDataCanon {  	ExifByteOrder order;  	unsigned int offset; + +	ExifDataOption options;  }; -ExifMnoteData *exif_mnote_data_canon_new (ExifMem *mem); +ExifMnoteData *exif_mnote_data_canon_new (ExifMem *mem, ExifDataOption o);  #endif /* __EXIF_MNOTE_DATA_CANON_H__ */ diff --git a/src/libexif/canon/mnote-canon-entry.c b/src/libexif/canon/mnote-canon-entry.c index 5fa4991..2a206de 100644 --- a/src/libexif/canon/mnote-canon-entry.c +++ b/src/libexif/canon/mnote-canon-entry.c @@ -1,7 +1,7 @@  /* mnote-canon-entry.c   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> - * Copyright © 2003 Matthieu Castet <mat-c@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net> + * Copyright (c) 2003 Matthieu Castet <mat-c@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -25,6 +25,7 @@  #include <stdio.h>  #include <stdlib.h>  #include <string.h> +#include <math.h>  #include <libexif/exif-format.h>  #include <libexif/exif-utils.h> @@ -32,9 +33,6 @@  /* #define DEBUG */ -#undef  MIN -#define MIN(a, b)  (((a) < (b)) ? (a) : (b)) -  #define CF(format,target,v,maxlen)                              \  {                                                               \          if (format != target) {                                 \ @@ -67,470 +65,637 @@  	}                                                               \  } +#define UNDEFINED 0xFF +     +static const struct canon_entry_table_t { +  unsigned int subtag; +  ExifShort value; +  const char *name; +} entries_settings_1 [] = { +#ifndef NO_VERBOSE_TAG_DATA +  { 0,  1, N_("Macro")}, +  { 0,  2, N_("Normal")}, +  { 2,  1, N_("Economy")}, +  { 2,  2, N_("Normal")},   +  { 2,  3, N_("Fine")}, +  { 2,  4, N_("RAW")}, +  { 2,  5, N_("Superfine")}, +  { 3,  0, N_("Off")}, +  { 3,  1, N_("Auto")}, +  { 3,  2, N_("On")}, +  { 3,  3, N_("Red-eye reduction")}, +  { 3,  4, N_("Slow synchro")}, +  { 3,  5, N_("Auto + Red-eye reduction")}, +  { 3,  6, N_("On + Red-eye reduction")}, +  { 3, 16, N_("External flash")}, +  { 4,  0, N_("Single")}, +  { 4,  1, N_("Continuous")}, +  { 4,  2, N_("Movie")}, +  { 4,  3, N_("Continuous, speed priority")}, +  { 4,  4, N_("Continuous, low")}, +  { 4,  5, N_("Continuous, high")}, +  { 6,  0, N_("One-shot AF")}, +  { 6,  1, N_("AI servo AF")}, +  { 6,  2, N_("AI focus AF")}, +  { 6,  3, N_("Manual focus")}, +  { 6,  4, N_("Single")}, +  { 6,  5, N_("Continuous")}, +  { 6,  6, N_("Manual focus")}, +  { 6,  16, N_("Pan focus")}, +  { 8,  1, N_("JPEG")}, +  { 8,  2, N_("CRW+THM")}, +  { 8,  3, N_("AVI+THM")}, +  { 8,  4, N_("TIF")}, +  { 8,  5, N_("TIF+JPEG")}, +  { 8,  6, N_("CR2")}, +  { 8,  7, N_("CR2+JPEG")}, +  { 9,  0, N_("Large")}, +  { 9,  1, N_("Medium")}, +  { 9,  2, N_("Small")}, +  { 9,  5, N_("Medium 1")}, +  { 9,  6, N_("Medium 2")}, +  { 9,  7, N_("Medium 3")}, +  { 9,  8, N_("Postcard")}, +  { 9,  9, N_("Widescreen")}, +  {10,  0, N_("Full auto")}, +  {10,  1, N_("Manual")}, +  {10,  2, N_("Landscape")}, +  {10,  3, N_("Fast shutter")}, +  {10,  4, N_("Slow shutter")}, +  {10,  5, N_("Night")}, +  {10,  6, N_("Grayscale")}, +  {10,  7, N_("Sepia")}, +  {10,  8, N_("Portrait")}, +  {10,  9, N_("Sports")}, +  {10, 10, N_("Macro")}, +  {10, 11, N_("Black & white")}, +  {10, 12, N_("Pan focus")}, +  {10, 13, N_("Vivid")}, +  {10, 14, N_("Neutral")}, +  {10, 15, N_("Flash off")}, +  {10, 16, N_("Long shutter")}, +  {10, 17, N_("Super macro")}, +  {10, 18, N_("Foliage")}, +  {10, 19, N_("Indoor")}, +  {10, 20, N_("Fireworks")}, +  {10, 21, N_("Beach")}, +  {10, 22, N_("Underwater")}, +  {10, 23, N_("Snow")}, +  {10, 24, N_("Kids & pets")}, +  {10, 25, N_("Night snapshot")}, +  {10, 26, N_("Digital macro")}, +  {10, 27, N_("My colors")}, +  {10, 28, N_("Still image")}, +  {10, 30, N_("Color accent")}, +  {10, 31, N_("Color swap")}, +  {10, 32, N_("Aquarium")}, +  {10, 33, N_("ISO 3200")}, +  {11, 0, N_("None")}, +  {11, 1, N_("2x")}, +  {11, 2, N_("4x")}, +  {11, 3, N_("Other")}, +  {12, 0x0000, N_("Normal")}, +  {12, 0x0001, N_("High")}, +  {12, 0xffff, N_("Low")}, +  {13, 0x0000, N_("Normal")}, +  {13, 0x0001, N_("High")}, +  {13, 0xffff, N_("Low")}, +  {14, 0x0000, N_("Normal")}, +  {14, 0x0001, N_("High")}, +  {14, 0xffff, N_("Low")}, +  {15, 14, N_("Auto high")}, +  {15, 15, N_("Auto")}, +  {15, 16, N_("50")}, +  {15, 17, N_("100")}, +  {15, 18, N_("200")}, +  {15, 19, N_("400")}, +  {15, 20, N_("800")}, +  {16,  0, N_("Default")}, +  {16,  1, N_("Spot")}, +  {16,  2, N_("Average")},	 +  {16,  3, N_("Evaluative")}, +  {16,  4, N_("Partial")}, +  {16,  5, N_("Center-weighted average")}, +  {17,  0, N_("Manual")}, +  {17,  1, N_("Auto")}, +  {17,  2, N_("Not known")}, +  {17,  3, N_("Macro")}, +  {17,  4, N_("Very close")}, +  {17,  5, N_("Close")}, +  {17,  6, N_("Middle range")}, +  {17,  7, N_("Far range")}, +  {17,  8, N_("Pan focus")}, +  {17,  9, N_("Super macro")}, +  {17,  10, N_("Infinity")}, +  {18, 0x2005, N_("Manual AF point selection")}, +  {18, 0x3000, N_("None (MF)")}, +  {18, 0x3001, N_("Auto-selected")}, +  {18, 0x3002, N_("Right")}, +  {18, 0x3003, N_("Center")}, +  {18, 0x3004, N_("Left")}, +  {18, 0x4001, N_("Auto AF point selection")}, +  {19,  0, N_("Easy shooting")}, +  {19,  1, N_("Program")}, +  {19,  2, N_("Tv-priority")}, +  {19,  3, N_("Av-priority")}, +  {19,  4, N_("Manual")}, +  {19,  5, N_("A-DEP")}, +  {19,  6, N_("M-DEP")}, +  {21,   1, N_("Canon EF 50mm f/1.8")}, +  {21,   2, N_("Canon EF 28mm f/2.8")}, +  {21,   4, N_("Sigma UC Zoom 35-135mm f/4-5.6")}, +  {21,   6, N_("Tokina AF193-2 19-35mm f/3.5-4.5")}, +  {21,   7, N_("Canon EF 100-300mm F5.6L")}, +  {21,  10, N_("Sigma 50mm f/2.8 EX or 28mm f/1.8")}, +  {21,  11, N_("Canon EF 35mm f/2")}, +  {21,  13, N_("Canon EF 15mm f/2.8")}, +  {21,  21, N_("Canon EF 80-200mm f/2.8L")}, +  {21,  22, N_("Tokina AT-X280AF PRO 28-80mm F2.8 ASPHERICAL")}, +  {21,  26, N_("Cosina 100mm f/3.5 Macro AF")}, +  {21,  28, N_("Tamron AF Aspherical 28-200mm f/3.8-5.6")}, +  {21,  29, N_("Canon EF 50mm f/1.8 MkII")}, +  {21,  31, N_("Tamron SP AF 300mm f/2.8 LD IF")}, +  {21,  32, N_("Canon EF 24mm f/2.8 or Sigma 15mm f/2.8 EX Fisheye")}, +  {21,  39, N_("Canon EF 75-300mm f/4-5.6")}, +  {21,  40, N_("Canon EF 28-80mm f/3.5-5.6")}, +  {21,  43, N_("Canon EF 28-105mm f/4-5.6")}, +  {21,  45, N_("Canon EF-S 18-55mm f/3.5-5.6")}, +  {21, 124, N_("Canon MP-E 65mm f/2.8 1-5x Macro Photo")}, +  {21, 125, N_("Canon TS-E 24mm f/3.5L")}, +  {21, 126, N_("Canon TS-E 45mm f/2.8")}, +  {21, 127, N_("Canon TS-E 90mm f/2.8")}, +  {21, 130, N_("Canon EF 50mm f/1.0L")}, +  {21, 131, N_("Sigma 17-35mm f2.8-4 EX Aspherical HSM")}, +  {21, 134, N_("Canon EF 600mm f/4L IS")}, +  {21, 135, N_("Canon EF 200mm f/1.8L")}, +  {21, 136, N_("Canon EF 300mm f/2.8L")}, +  {21, 137, N_("Canon EF 85mm f/1.2L")}, +  {21, 139, N_("Canon EF 400mm f/2.8L")}, +  {21, 141, N_("Canon EF 500mm f/4.5L")}, +  {21, 142, N_("Canon EF 300mm f/2.8L IS")}, +  {21, 143, N_("Canon EF 500mm f/4L IS")}, +  {21, 149, N_("Canon EF 100mm f/2")}, +  {21, 150, N_("Sigma 20mm EX f/1.8")}, +  {21, 151, N_("Canon EF 200mm f/2.8L")}, +  {21, 152, N_("Sigma 10-20mm F4-5.6 or 12-24mm f/4.5-5.6 or 14mm f/2.8")}, +  {21, 153, N_("Canon EF 35-350mm f/3.5-5.6L")}, +  {21, 155, N_("Canon EF 85mm f/1.8 USM")}, +  {21, 156, N_("Canon EF 28-105mm f/3.5-4.5 USM")}, +  {21, 160, N_("Canon EF 20-35mm f/3.5-4.5 USM")}, +  {21, 161, N_("Canon EF 28-70mm f/2.8L or Sigma 24-70mm EX f/2.8")}, +  {21, 165, N_("Canon EF 70-200mm f/2.8 L")}, +  {21, 166, N_("Canon EF 70-200mm f/2.8 L + x1.4")}, +  {21, 167, N_("Canon EF 70-200mm f/2.8 L + x2")}, +  {21, 168, N_("Canon EF 28mm f/1.8 USM")}, +  {21, 169, N_("Sigma 15-30mm f/3.5-4.5 EX DG Aspherical")}, +  {21, 170, N_("Canon EF 200mm f/2.8L II")}, +  {21, 173, N_("Canon EF 180mm Macro f/3.5L or Sigma 180mm EX HSM Macro f/3.5")}, +  {21, 174, N_("Canon EF 135mm f/2L")}, +  {21, 176, N_("Canon EF 24-85mm f/3.5-4.5 USM")}, +  {21, 177, N_("Canon EF 300mm f/4L IS")}, +  {21, 178, N_("Canon EF 28-135mm f/3.5-5.6 IS")}, +  {21, 180, N_("Canon EF 35mm f/1.4L")}, +  {21, 181, N_("Canon EF 100-400mm f/4.5-5.6L IS + x1.4")}, +  {21, 182, N_("Canon EF 100-400mm f/4.5-5.6L IS + x2")}, +  {21, 183, N_("Canon EF 100-400mm f/4.5-5.6L IS")}, +  {21, 184, N_("Canon EF 400mm f/2.8L + x2")}, +  {21, 186, N_("Canon EF 70-200mm f/4L")}, +  {21, 190, N_("Canon EF 100mm f/2.8 Macro")}, +  {21, 191, N_("Canon EF 400mm f/4 DO IS")}, +  {21, 197, N_("Canon EF 75-300mm f/4-5.6 IS")}, +  {21, 198, N_("Canon EF 50mm f/1.4")}, +  {21, 202, N_("Canon EF 28-80 f/3.5-5.6 USM IV")}, +  {21, 211, N_("Canon EF 28-200mm f/3.5-5.6")}, +  {21, 213, N_("Canon EF 90-300mm f/4.5-5.6")}, +  {21, 214, N_("Canon EF-S 18-55mm f/3.5-4.5 USM")}, +  {21, 224, N_("Canon EF 70-200mm f/2.8L IS USM")}, +  {21, 225, N_("Canon EF 70-200mm f/2.8L IS USM + x1.4")}, +  {21, 226, N_("Canon EF 70-200mm f/2.8L IS USM + x2")}, +  {21, 229, N_("Canon EF 16-35mm f/2.8L")}, +  {21, 230, N_("Canon EF 24-70mm f/2.8L")}, +  {21, 231, N_("Canon EF 17-40mm f/4L")}, +  {21, 232, N_("Canon EF 70-300mm f/4.5-5.6 DO IS USM")}, +  {21, 234, N_("Canon EF-S 17-85mm f4-5.6 IS USM")}, +  {21, 235, N_("Canon EF-S10-22mm F3.5-4.5 USM")}, +  {21, 236, N_("Canon EF-S60mm F2.8 Macro USM")}, +  {21, 237, N_("Canon EF 24-105mm f/4L IS")}, +  {21, 238, N_("Canon EF 70-300mm F4-5.6 IS USM")}, +  {21, 241, N_("Canon EF 50mm F1.2L USM")}, +  {21, 242, N_("Canon EF 70-200mm f/4L IS USM")}, +  {28, 0, N_("Manual")}, +  {28, 1, N_("TTL")}, +  {28, 2, N_("A-TTL")}, +  {28, 3, N_("E-TTL")}, +  {28, 4, N_("FP sync enabled")}, +  {28, 7, N_("2nd-curtain sync used")}, +  {28, 11, N_("FP sync used")}, +  {28, 13, N_("Internal")}, +  {28, 14, N_("External")}, +  {31,  0, N_("Single")}, +  {31,  1, N_("Continuous")}, +  {32, 0, N_("Normal AE")}, +  {32, 1, N_("Exposure compensation")}, +  {32, 2, N_("AE lock")}, +  {32, 3, N_("AE lock + Exposure compensation")}, +  {32, 4, N_("No AE")}, +  {33, 0, N_("Off")}, +  {33, 1, N_("On")}, +  {33, 2, N_("On, shot only")}, +  {39, 0, N_("Off")}, +  {39, 1, N_("Vivid")}, +  {39, 2, N_("Neutral")}, +  {39, 3, N_("Smooth")}, +  {39, 4, N_("Sepia")}, +  {39, 5, N_("Black & white")}, +  {39, 6, N_("Custom")}, +  {39, 100, N_("My color data")}, +  {40, 0, N_("Off")}, +  {40, 0x0500, N_("Full")}, +  {40, 0x0502, N_("2/3")}, +  {40, 0x0504, N_("1/3")}, +#endif +  { 0,  0, NULL} +}, +entries_focal_length [] = { +#ifndef NO_VERBOSE_TAG_DATA +	{0, 1, N_("Fixed")}, +	{0, 2, N_("Zoom")}, +#endif +	{0, 0, NULL} +}, +entries_settings_2 [] = { +#ifndef NO_VERBOSE_TAG_DATA +  { 6,  0, N_("Auto")}, +  { 6,  1, N_("Sunny")}, +  { 6,  2, N_("Cloudy")}, +  { 6,  3, N_("Tungsten")}, +  { 6,  4, N_("Fluorescent")}, +  { 6,  5, N_("Flash")}, +  { 6,  6, N_("Custom")}, +  { 6,  7, N_("Black & white")}, +  { 6,  8, N_("Shade")}, +  { 6,  9, N_("Manual temperature (Kelvin)")}, +  { 6,  10, N_("PC set 1")}, +  { 6,  11, N_("PC set 2")}, +  { 6,  12, N_("PC set 3")}, +  { 6,  14, N_("Daylight fluorescent")}, +  { 6,  15, N_("Custom 1")}, +  { 6,  16, N_("Custom 2")}, +  { 6,  17, N_("Underwater")}, +  { 7,  0, N_("Off")}, +  { 7,  1, N_("Night scene")}, +  { 7,  2, N_("On")}, +  { 7,  3, N_("None")}, +  { 13,  0x3000, N_("None (MF)")}, +  { 13,  0x3001, N_("Right")}, +  { 13,  0x3002, N_("Center")}, +  { 13,  0x3003, N_("Center + Right")}, +  { 13,  0x3004, N_("Left")}, +  { 13,  0x3005, N_("Left + Right")}, +  { 13,  0x3006, N_("Left + Center")}, +  { 13,  0x3007, N_("All")}, +  { 15,  0, N_("Off")}, +  { 15,  1, N_("On (shot 1)")}, +  { 15,  2, N_("On (shot 2)")}, +  { 15,  3, N_("On (shot 3)")}, +  { 15,  0xffff, N_("On")}, +  { 25,  248, N_("EOS high-end")}, +  { 25,  250, N_("Compact")}, +  { 25,  252, N_("EOS mid-range")}, +  { 26,  0, N_("None")}, +  { 26,  1, N_("Rotate 90 CW")}, +  { 26,  2, N_("Rotate 180")}, +  { 26,  3, N_("Rotate 270 CW")}, +  { 26,  0xffff, N_("Rotated by software")}, +  { 27,  0, N_("Off")}, +  { 27,  1, N_("On")},  +  { 32,  0, N_("Off")}, +  { 32,  0x0014, N_("1/3")}, +  { 32,  0x008c, N_("2/3")}, +  { 32,  0x07d0, N_("Full")}, +#endif +  {0, 0, NULL} +}, +entries_panorama [] = { +#ifndef NO_VERBOSE_TAG_DATA +	{0, 0, N_("Left to right")}, +	{0, 1, N_("Right to left")}, +	{0, 2, N_("Bottom to top")}, +	{0, 3, N_("Top to bottom")}, +	{0, 4, N_("2x2 matrix (clockwise)")}, +#endif +	{0, 0, NULL} +}, +color_information [] = { +#ifndef NO_VERBOSE_TAG_DATA +  {0, 0, N_("Standard")}, +  {0, 1, N_("Manual")}, +  {0, 2, N_("Custom")}, +  {2, 0, N_("N/A")}, +  {2, 1, N_("Lowest")}, +  {2, 2, N_("Low")}, +  {2, 3, N_("Standard")}, +  {2, 4, N_("High")}, +  {2, 5, N_("Highest")}, +  {7,  0, N_("Auto")}, +  {7,  1, N_("Daylight")}, +  {7,  2, N_("Cloudy")}, +  {7,  3, N_("Tungsten")}, +  {7,  4, N_("Fluorescent")}, +  {7,  5, N_("Flash")}, +  {7,  6, N_("Custom")}, +  {7,  7, N_("Black & White")}, +  {7,  8, N_("Shade")}, +  {7,  9, N_("Manual Temperature (Kelvin)")}, +  {7, 10, N_("PC Set1")}, +  {7, 11, N_("PC Set2")}, +  {7, 12, N_("PC Set3")}, +  {7, 14, N_("Daylight Fluorescent")}, +  {7, 15, N_("Custom 1")}, +  {7, 16, N_("Custom 2")}, +  {7, 17, N_("Underwater")}, +  {9, 0x00, N_("None")}, +  {9, 0x01, N_("Standard")}, +  {9, 0x02, N_("Set 1")}, +  {9, 0x03, N_("Set 2")}, +  {9, 0x04, N_("Set 3")}, +  {9, 0x21, N_("User Def. 1")}, +  {9, 0x22, N_("User Def. 2")}, +  {9, 0x23, N_("User Def. 3")}, +  {9, 0x41, N_("External 1")}, +  {9, 0x42, N_("External 2")}, +  {9, 0x43, N_("External 3")}, +  {9, 0x81, N_("Standard")}, +  {9, 0x82, N_("Portrait")}, +  {9, 0x83, N_("Landscape")}, +  {9, 0x84, N_("Neutral")}, +  {9, 0x85, N_("Faithful")}, +  {9, 0x86, N_("Monochrome")}, +#endif +  {0, 0, NULL} +}; + +static void +canon_search_table_value (const struct canon_entry_table_t table[], +    unsigned int t, ExifShort vs, char *val, unsigned int maxlen) +{ +	unsigned int j; + +	/* Search the table for the first matching subtag and value. */ +	for (j = 0; table[j].name && ((table[j].subtag < t) || +			((table[j].subtag == t) && table[j].value <= vs)); j++) { +		if ((table[j].subtag == t) && (table[j].value == vs)) { +			break; +		} +	} +	if ((table[j].subtag == t) && (table[j].value == vs) && table[j].name) { +		/* Matching subtag and value found. */ +		strncpy (val, _(table[j].name), maxlen); +	} else { +		/* No matching subtag and/or value found. */ +		snprintf (val, maxlen, "0x%04x", vs); +	} +} + +static void +canon_search_table_bitfield (const struct canon_entry_table_t table[], +    unsigned int t, ExifShort vs, char *val, unsigned int maxlen) +{ +	unsigned int j; + +	/* Search the table for the first matching subtag. */ +	for (j = 0; table[j].name && (table[j].subtag <= t); j++) { +		if (table[j].subtag == t) { +			break; +		} +	} +	if ((table[j].subtag == t) && table[j].name) { +		unsigned int i, bit, lastbit = 0; + +		/* +		 * Search the table for the last matching bit, because +		 * that one needs no additional comma appended. +		 */ +		for (i = j; table[i].name && (table[i].subtag == t); i++) { +			bit = table[i].value; +			if ((vs >> bit) & 1) { +				lastbit = bit; +			} +		} +		/* Search the table for all matching bits. */ +		for (i = j; table[i].name && (table[i].subtag == t); i++) { +			bit = table[i].value; +			if ((vs >> bit) & 1) { +				strncat(val, table[i].name, maxlen - strlen (val)); +				if (bit != lastbit)  +					strncat (val, N_(", "), maxlen - strlen (val)); +			} +		} +	} else { +		/* No matching subtag found. */ +		snprintf (val, maxlen, "0x%04x", vs); +	} +} + +unsigned int +mnote_canon_entry_count_values (const MnoteCanonEntry *entry) +{ +	unsigned int  val; + +	if (!entry) return 0; + +	switch (entry->tag) { +	case MNOTE_CANON_TAG_FOCAL_LENGTH: +	case MNOTE_CANON_TAG_PANORAMA: +		return entry->components; +	case MNOTE_CANON_TAG_SETTINGS_1: +	case MNOTE_CANON_TAG_SETTINGS_2: +	case MNOTE_CANON_TAG_CUSTOM_FUNCS: +	case MNOTE_CANON_TAG_COLOR_INFORMATION: +		if (entry->format != EXIF_FORMAT_SHORT) return 0; + +		val = exif_get_short (entry->data, entry->order); +		/* val is buffer size, i.e. # of values plus 1 */ +		return MIN (entry->size - 2, val) / 2; +	default: +		return 1; +	} +} + +/* + * For reference, see Exif 2.1 specification (Appendix C),  + * or http://en.wikipedia.org/wiki/APEX_system + */ +static double +apex_value_to_aperture (double x) +{ +	return pow (2, x / 2.); +} + +static double +apex_value_to_shutter_speed(double x) +{ +	return 1.0 / pow (2, x); +} + +static double +apex_value_to_iso_speed (double x) +{ +	return 3.125 * pow (2, x); +} +  char * -mnote_canon_entry_get_value (const MnoteCanonEntry *entry, char *val, unsigned int maxlen) +mnote_canon_entry_get_value (const MnoteCanonEntry *entry, unsigned int t, char *val, unsigned int maxlen)  { -    char buf[128]; -    ExifLong vl; -    ExifShort vs, n; -    int i; -    unsigned char *data = entry->data; +	char buf[128]; +	ExifLong vl; +	ExifShort vs, n; +	unsigned char *data; +	double d; -    if (!entry) return NULL; +	if (!entry)  +		return NULL; -    memset (val, 0, maxlen); -    maxlen--; +	data = entry->data; + +	memset (val, 0, maxlen); +	maxlen--;  	switch (entry->tag) {  	case MNOTE_CANON_TAG_SETTINGS_1:  		CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen);  		n = exif_get_short (data, entry->order) / 2; -		data += 2; +		if (t >= n) return NULL;  		CC (entry->components, n, val, maxlen); -		for (i = 1; i < n; i++) { -		    vs = exif_get_short (data, entry->order); -		    data += 2; -		    switch (i) { -		    case 1: -			strncpy (val, _("Macro mode : "), maxlen); -			switch (vs) { -			case 1: -			    strncat (val, _("Macro"), maxlen - strlen(val)); -			    break; -			case 2: -			    strncat (val, _("Normal"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("%i???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); -			} -			break; -		    case 2: -			if (vs) { -				snprintf (buf, sizeof (buf), -					_(" / Self Timer : %i (ms)"), vs*100); -				strncat (val, buf, maxlen - strlen(val)); +		vs = exif_get_short (data + 2 + t * 2, entry->order); +		switch (t) { +		case 1: +			if (!vs) { +				strncpy(val, _("Off"), maxlen); +				break;  			} +			snprintf (val, maxlen, _("%i (ms)"), vs * 100);  			break; -		    case 4: -			strncat (val, _(" / Flash mode : "), maxlen - strlen(val)); -			switch (vs) { -			case 0: -			    strncat (val, _("Flash not fired"), maxlen - strlen(val)); -			    break; -			case 1: -			    strncat (val, _("auto"), maxlen - strlen(val)); -			    break; -			case 2: -			    strncat (val, _("on"), maxlen - strlen(val)); -			    break; -			case 3: -			    strncat (val, _("red eyes reduction"), maxlen - strlen(val)); -			    break; -			case 4: -			    strncat (val, _("slow synchro"), maxlen - strlen(val)); -			    break; -			case 5: -			    strncat (val, _("auto + red eyes reduction"), maxlen - strlen(val)); -			    break; -			case 6: -			    strncat (val, _("on + red eyes reduction"), maxlen - strlen(val)); -			    break; -			case 16: -			    strncat (val, _("external"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("%i???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); +		case 15: +			if (((vs & 0xC000) == 0x4000) && (vs != 0x7FFF)) { +				/* Canon S3 IS - directly specified value */ +				snprintf (val, maxlen, _("%i"), vs & ~0x4000); +			} else { +				/* Standard Canon - index into lookup table */ +				canon_search_table_value (entries_settings_1, t, vs, val, maxlen);  			}  			break; -		    case 5: -			strncat (val, _(" / Continuous drive mode : "), maxlen - strlen(val)); -			switch (vs) { -			case 0: -			    strncat (val, _("single or timer"), maxlen - strlen(val)); -			    break; -			case 1: -			    strncat (val, _("continuous"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("%i???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); -			} +		case 22: +		case 23: +		case 24: +			snprintf (val, maxlen, "%u", vs);  			break; -		    case 7: -			strncat (val, _(" / Focus mode : "), maxlen - strlen(val)); -			switch (vs) { -			case 0: -			    strncat (val, _("One-Shot"), maxlen - strlen(val)); -			    break; -			case 1: -			    strncat (val, _("AI Servo"), maxlen - strlen(val)); -			    break; -			case 2: -			    strncat (val, _("AI Focus"), maxlen - strlen(val)); -			    break; -			case 3: -			    strncat (val, _("MF"), maxlen - strlen(val)); -			    break; -			case 4: -			    strncat (val, _("Single"), maxlen - strlen(val)); -			    break; -			case 5: -			    strncat (val, _("Continuous"), maxlen - strlen(val)); -			    break; -			case 6: -			    strncat (val, _("MF"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("%i???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); -			} +		case 25: +		case 26: +			snprintf (val, maxlen, "%.2f", apex_value_to_aperture (vs / 32.0));  			break; -		    case 10: -			strncat (val, _(" / Image size : "), maxlen - strlen(val)); -			switch (vs) { -			case 0: -			    strncat (val, _("Large"), maxlen - strlen(val)); -			    break; -			case 1: -			    strncat (val, _("Medium"), maxlen - strlen(val)); -			    break; -			case 2: -			    strncat (val, _("Small"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("%i???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); -			} +		case 28: +			canon_search_table_bitfield(entries_settings_1, t, vs, val, maxlen);  			break; -		    case 11: -			strncat (val, _(" / Easy shooting mode : "), maxlen - strlen(val)); -			switch (vs) { -			case 0: -			    strncat (val, _("Full Auto"), maxlen - strlen(val)); -			    break; -			case 1: -			    strncat (val, _("Manual"), maxlen - strlen(val)); -			    break; -			case 2: -			    strncat (val, _("Landscape"), maxlen - strlen(val)); -			    break; -			case 3: -			    strncat (val, _("Fast Shutter"), maxlen - strlen(val)); -			    break; -			case 4: -			    strncat (val, _("Slow Shutter"), maxlen - strlen(val)); -			    break; -			case 5: -			    strncat (val, _("Night"), maxlen - strlen(val)); -			    break; -			case 6: -			    strncat (val, _("Black & White"), maxlen - strlen(val)); -			    break; -			case 7: -			    strncat (val, _("Sepia"), maxlen - strlen(val)); -			    break; -			case 8: -			    strncat (val, _("Portrait"), maxlen - strlen(val)); -			    break; -			case 9: -			    strncat (val, _("Sports"), maxlen - strlen(val)); -			    break; -			case 10: -			    strncat (val, _("Macro / Close-Up"), maxlen - strlen(val)); -			    break; -			case 11: -			    strncat (val, _("Pan Focus"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("%i???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); -			} +		case 34: +			snprintf (val, maxlen, "%.2f", vs / 10.0);  			break; -		    case 13: -			strncat (val, _(" / Contrast : "), maxlen - strlen(val)); -			switch (vs) { -			case 0xffff: -			    strncat (val, _("Low"), maxlen - strlen(val)); -			    break; -			case 0x0000: -			    strncat (val, _("Normal"), maxlen - strlen(val)); -			    break; -			case 0x0001: -			    strncat (val, _("High"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("%i???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); -			} +		case 35: +		case 36: +			snprintf (val, maxlen, "%u", vs);  			break; -		    case 14: -			strncat (val, _(" / Saturation : "), maxlen - strlen(val)); -			switch (vs) { -			case 0xffff: -			    strncat (val, _("Low"), maxlen - strlen(val)); -			    break; -			case 0x0000: -			    strncat (val, _("Normal"), maxlen - strlen(val)); -			    break; -			case 0x0001: -			    strncat (val, _("High"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("%i???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); -			} -			break; -		    case 15: -			strncat (val, _(" / Sharpness : "), maxlen - strlen(val)); -			switch (vs) { -			case 0xffff: -			    strncat (val, _("Low"), maxlen - strlen(val)); -			    break; -			case 0x0000: -			    strncat (val, _("Normal"), maxlen - strlen(val)); -			    break; -			case 0x0001: -			    strncat (val, _("High"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("%i???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); -			} -			break; -		    case 16: -			if (vs) { -			    strncat (val, _(" / ISO : "), maxlen - strlen(val)); -			    switch (vs) { -			    case 15: -				strncat (val, _("auto"), maxlen - strlen(val)); -				break; -			    case 16: -				strncat (val, _("50"), maxlen - strlen(val)); -				break; -			    case 17: -				strncat (val, _("100"), maxlen - strlen(val)); -				break; -			    case 18: -				strncat (val, _("200"), maxlen - strlen(val)); -				break; -			    case 19: -				strncat (val, _("400"), maxlen - strlen(val)); -				break; -			    default: -				snprintf (buf, sizeof (buf), _("%i???"), vs); -				strncat (val, buf, maxlen - strlen(val)); -			    } -			    break; -			} -		    case 17: -			strncat (val, _(" / Metering mode : "), maxlen - strlen(val)); -			switch (vs) { -			case 3: -			    strncat (val, _("Evaluative"), maxlen - strlen(val)); -			    break; -			case 4: -			    strncat (val, _("Partial"), maxlen - strlen(val)); -			    break; -			case 5: -			    strncat (val, _("Center-weighted"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("%i???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); -			} +		default: +			canon_search_table_value (entries_settings_1, t, vs, val, maxlen); +		} +		break; + +	case MNOTE_CANON_TAG_FOCAL_LENGTH: +		CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen); +		vs = exif_get_short (data + t * 2, entry->order); +		switch (t) { +		case 1: +			snprintf (val, maxlen, "%u", vs);  			break; -		    case 19: -			strncat (val, _(" / AF point selected : "), maxlen - strlen(val)); -			switch (vs) { -			case 0x3000: -			    strncat (val, _("none (MF)"), maxlen - strlen(val)); -			    break; -			case 0x3001: -			    strncat (val, _("auto-selected"), maxlen - strlen(val)); -			    break; -			case 0x3002: -			    strncat (val, _("right"), maxlen - strlen(val)); -			    break; -			case 0x3003: -			    strncat (val, _("center"), maxlen - strlen(val)); -			    break; -			case 0x3004: -			    strncat (val, _("left"), maxlen - strlen(val)); -			    break; -			default: -			    snprintf (buf, sizeof (buf), _("0x%x???"), vs); -			    strncat (val, buf, maxlen - strlen(val)); -			} +		case 2: +		case 3: +			snprintf (val, maxlen, _("%.2f mm"), vs * 25.4 / 1000);  			break; -		    case 20: -				strncat (val, _(" / Exposure mode : "), maxlen - strlen(val)); -				switch (vs) { -           		case 0: -					strncat (val, _("Easy shooting"), maxlen - strlen(val)); -                    break; -                case 1: -					strncat (val, _("Program"), maxlen - strlen(val)); -					break; -				case 2: -					strncat (val, _("Tv-priority"), maxlen - strlen(val)); -					break; -				case 3: -					strncat (val, _("Av-priority"), maxlen - strlen(val)); -					break; -				case 4: -					strncat (val, _("Manual"), maxlen - strlen(val)); -					break; -				case 5: -					strncat (val, _("A-DEP"), maxlen - strlen(val)); -					break; -				default: -					snprintf (buf, sizeof (buf), _("%i???"), vs); -					strncat (val, buf, maxlen - strlen(val)); -                } -				break; -			case 23: -				snprintf (buf, sizeof (buf), _(" / long focal length of lens (in focal units) : %u"), vs); -				strncat (val, buf, maxlen - strlen(val)); -				break; -			case 24: -				snprintf (buf, sizeof (buf), _(" / short focal length of lens (in focal units) : %u"), vs); -				strncat (val, buf, maxlen - strlen(val)); -				break; -			case 25: -				snprintf (buf, sizeof (buf), _(" / focal units per mm : %u"), vs); -				strncat (val, buf, maxlen - strlen(val)); -				break; -			case 29: -				strncat (val, _(" / Flash details : "), maxlen - strlen(val)); -				if ((vs>>14)&1) -					strncat (val, _("External E-TTL"), maxlen - strlen(val)); -				if ((vs>>13)&1) -					strncat (val, _("Internal flash"), maxlen - strlen(val)); -				if ((vs>>11)&1) -					strncat (val, _("FP sync used"), maxlen - strlen(val)); -				if ((vs>>4)&1) -					strncat (val, _("FP sync enabled"), maxlen - strlen(val)); -#ifdef DEBUG -				printf ("Value29=0x%08x\n", vs); -#endif -				break; -			case 32: -				strncat (val, _(" / Focus mode2 : "), maxlen - strlen(val)); -				switch (vs) { -				case 0: -					strncat (val, _("Single"), maxlen - strlen(val)); -					break; -				case 1: -					strncat (val, _("Continuous"), maxlen - strlen(val)); -					break; -				default: -					snprintf (buf, sizeof (buf), _("%i???"), vs); -					strncat (val, buf, maxlen - strlen(val)); -				} -				break; -#ifdef DEBUG -			default: -                        	printf ("Value%d=%d\n", i, vs); -#endif -			} +		default: +			canon_search_table_value (entries_focal_length, t, vs, val, maxlen);  		} - -                break; +		break;  	case MNOTE_CANON_TAG_SETTINGS_2:  		CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen); -		n = exif_get_short (data, entry->order)/2; -		data += 2; +		n = exif_get_short (data, entry->order) / 2; +		if (t >= n) return NULL;  		CC (entry->components, n, val, maxlen); -#ifdef DEBUG -		printf ("Setting2 size %d %d\n",n,entry->size); -#endif -		for (i=1;i<n;i++) -		{ -			vs = exif_get_short (data, entry->order); -			data+=2; -			switch(i) { -			case 7: -				strncpy (val, _("White balance : "), maxlen - strlen(val)); -				switch (vs) { -				case 0: -					strncat (val, _("Auto"), maxlen - strlen(val)); -					break; -				case 1: -					strncat (val, _("Sunny"), maxlen - strlen(val)); -					break; -				case 2: -					strncat (val, _("Cloudy"), maxlen - strlen(val)); -					break; -				case 3: -					strncat (val, _("Tungsten"), maxlen - strlen(val)); -					break; -				case 4: -					strncat (val, _("Flourescent"), maxlen - strlen(val)); -					break; -				case 5: -					strncat (val, _("Flash"), maxlen - strlen(val)); -					break; -				case 6: -					strncat (val, _("Custom"), maxlen - strlen(val)); -					break; -				default: -					snprintf (buf, sizeof (buf), _("%i???"), vs); -					strncat (val, buf, maxlen - strlen(val)); -				} -				break; -			case 9: -				snprintf (buf, sizeof (buf), _(" / Sequence number : %u"), vs); -				strncat (val, buf, maxlen - strlen(val)); -				break; -			case 14: -				if (vs>>12) -				{ -					strncat (val, _(" / AF point used : "), maxlen - strlen(val)); -					if (vs&1) -						strncat (val, _("Right"), maxlen - strlen(val)); -					if ((vs>>1)&1) -						strncat (val, _("Center"), maxlen - strlen(val)); -					if ((vs>>2)&1) -						strncat (val, _("Left"), maxlen - strlen(val)); -					snprintf (buf, sizeof (buf), _(" (%u available focus point)"), vs>>12); -					strncat (val, buf, maxlen - strlen(val)); -				} -#ifdef DEBUG -					printf ("0x%08x\n", vs); -#endif -				break; -			case 15: -				snprintf (buf, sizeof (buf), _(" / Flash bias : %.2f EV"), vs/32.0); -				strncat (val, buf, maxlen - strlen(val)); - -				break; -			case 19: -				snprintf (buf, sizeof (buf), _(" / Subject Distance (mm) : %u"), vs); -				strncat (val, buf, maxlen - strlen(val)); +		vs = exif_get_short (data + 2 + t * 2, entry->order); +		switch (t) { +		case 0: +			snprintf (val, maxlen, "%.3f", pow (2, (ExifSShort)vs / 32.0)); +			break; +		case 1: +			snprintf (val, maxlen, "%.0f", apex_value_to_iso_speed ((ExifSShort)vs / 32.0)); +			break; +		case 2: +		case 5: +		case 14: +		case 16: +			snprintf (val, maxlen, _("%.2f EV"), vs / 32.0); +			break; +		case 3: +		case 20: +			snprintf (val, maxlen, "%.2f", apex_value_to_aperture (vs / 32.0)); +			break; +		case 4: +		case 21: +			d = apex_value_to_shutter_speed ((ExifSShort)vs / 32.0); +			if (d < 1) +				snprintf (val, maxlen, _("1/%d"),(int)(1.0 / d)); +			else +				snprintf (val, maxlen, _("%d"), (int) d); +			break; +		case 8: +			snprintf (val, maxlen, "%u", vs); +			break; +		case 12: +			snprintf (val, maxlen, "%.2f", vs / 32.0); +			break; +		case 18: +		case 19: +			snprintf (val, maxlen, _("%u mm"), vs); +			break; +		case 28: +			if ((ExifSShort)vs <= 0) { +				strncpy(val, _("Off"), maxlen);  				break; -#ifdef DEBUG -			default: -				printf ("Value%d=%d\n", i, vs); -#endif  			} +			snprintf (val, maxlen, _("%i (ms)"), vs * 100); +			break; +		default: +			canon_search_table_value (entries_settings_2, t, vs, val, maxlen);  		} +		break; +	case MNOTE_CANON_TAG_PANORAMA: +		CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen); +		vs = exif_get_short (data + t * 2, entry->order); +		canon_search_table_value (entries_panorama, t, vs, val, maxlen);  		break; -	case MNOTE_CANON_TAG_IMAGE_TYPE:  	case MNOTE_CANON_TAG_OWNER: -		CF (entry->format, EXIF_FORMAT_ASCII, val, maxlen);  		CC (entry->components, 32, val, maxlen); -		strncpy (val, data, MIN (entry->size, maxlen)); +		/* Fall through; ImageType can have many sizes */ +	case MNOTE_CANON_TAG_IMAGE_TYPE: +		CF (entry->format, EXIF_FORMAT_ASCII, val, maxlen); +		strncpy (val, (char *)data, MIN (entry->size, maxlen));  		break;  	case MNOTE_CANON_TAG_FIRMWARE:  		CF (entry->format, EXIF_FORMAT_ASCII, val, maxlen); -		CC2 (entry->components, 24, 32, val, maxlen); -		strncpy (val, data, MIN (entry->size, maxlen)); +/*		CC2 (entry->components, 24, 32, val, maxlen); Can also be 22 */ +		strncpy (val, (char *)data, MIN (entry->size, maxlen));  		break;  	case MNOTE_CANON_TAG_IMAGE_NUMBER: @@ -551,23 +716,27 @@ mnote_canon_entry_get_value (const MnoteCanonEntry *entry, char *val, unsigned i  	case MNOTE_CANON_TAG_CUSTOM_FUNCS:  		CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen); -		n = exif_get_short (data, entry->order)/2; -		data+=2; +		n = exif_get_short (data, entry->order) / 2; +		if (t >= n) return NULL;  		CC (entry->components, n, val, maxlen); -#ifdef DEBUG -		printf ("Custom Function size %d %d\n",n,entry->size); -#endif -		for (i=1;i<n;i++) -		{ -			vs = exif_get_short (data, entry->order); -			data += 2; -			snprintf (buf, sizeof(buf), _("C.F%d : %u"), i, vs); -			strncat (val, buf, maxlen - strlen(val)); -		} +		vs = exif_get_short (data + 2 + t * 2, entry->order); +		snprintf (buf, sizeof (buf), "%u", vs); +		strncat (val, buf, maxlen - strlen (val)); +		break; + +	case MNOTE_CANON_TAG_COLOR_INFORMATION: +		CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen); +		n = exif_get_short (data, entry->order) / 2; +		if (t >= n) return NULL; +		CC (entry->components, n, val, maxlen); +		vs = exif_get_short (data + 2 + t * 2, entry->order); +		canon_search_table_value (color_information, t, vs, val, maxlen);  		break;  	default:  #ifdef DEBUG +	  { +		int i;  		if (entry->format == EXIF_FORMAT_SHORT)  		for(i=0;i<entry->components;i++) {  			vs = exif_get_short (data, entry->order); @@ -582,9 +751,9 @@ mnote_canon_entry_get_value (const MnoteCanonEntry *entry, char *val, unsigned i  		}  		else if (entry->format == EXIF_FORMAT_ASCII)  		    strncpy (val, data, MIN (entry->size, maxlen)); +	  }  #endif  		break; -        } - -        return val; +	} +	return val;  } diff --git a/src/libexif/canon/mnote-canon-entry.h b/src/libexif/canon/mnote-canon-entry.h index 62345d8..e78c639 100644 --- a/src/libexif/canon/mnote-canon-entry.h +++ b/src/libexif/canon/mnote-canon-entry.h @@ -1,6 +1,6 @@  /* mnote-canon-entry.h   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -38,6 +38,7 @@ struct _MnoteCanonEntry {  	ExifByteOrder order;  }; -char *mnote_canon_entry_get_value (const MnoteCanonEntry *entry, char *val, unsigned int maxlen); +unsigned int mnote_canon_entry_count_values (const MnoteCanonEntry *); +char        *mnote_canon_entry_get_value    (const MnoteCanonEntry *, unsigned int t, char *val, unsigned int maxlen);  #endif /* __MNOTE_CANON_ENTRY_H__ */ diff --git a/src/libexif/canon/mnote-canon-tag.c b/src/libexif/canon/mnote-canon-tag.c index 890a5fc..447caab 100644 --- a/src/libexif/canon/mnote-canon-tag.c +++ b/src/libexif/canon/mnote-canon-tag.c @@ -1,6 +1,6 @@  /* mnote-canon-tag.c   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -25,34 +25,137 @@  #include <libexif/i18n.h> -static struct { +static const struct {  	MnoteCanonTag tag;  	const char *name;  	const char *title;  	const char *description;  } table[] = { +#ifndef NO_VERBOSE_TAG_STRINGS  	{MNOTE_CANON_TAG_SETTINGS_1, "Settings1", N_("Settings (first part)"), ""}, +	{MNOTE_CANON_TAG_FOCAL_LENGTH, "FocalLength", N_("Focal length"), ""},  	{MNOTE_CANON_TAG_SETTINGS_2, "Settings2", N_("Settings (second part)"), ""}, +	{MNOTE_CANON_TAG_PANORAMA, "Panorama", N_("Panorama"), ""},  	{MNOTE_CANON_TAG_IMAGE_TYPE, "ImageType", N_("Image type"), ""},  	{MNOTE_CANON_TAG_FIRMWARE, "FirmwareVersion", N_("Firmware version"), ""},  	{MNOTE_CANON_TAG_IMAGE_NUMBER, "ImageNumber", N_("Image number"), ""},  	{MNOTE_CANON_TAG_OWNER, "OwnerName", N_("Owner name"), ""}, +	{MNOTE_CANON_TAG_COLOR_INFORMATION, "ColorInformation", N_("Color information"), ""},  	{MNOTE_CANON_TAG_SERIAL_NUMBER, "SerialNumber", N_("Serial number"), ""},  	{MNOTE_CANON_TAG_CUSTOM_FUNCS, "CustomFunctions", N_("Custom functions"), ""}, +#endif  	{0, NULL, NULL, NULL}  }; +static const struct { +	MnoteCanonTag tag; +	unsigned int subtag; +	const char *name; +} table_sub[] = { +#ifndef NO_VERBOSE_TAG_STRINGS +	{MNOTE_CANON_TAG_SETTINGS_1,  0, N_("Macro mode")}, +	{MNOTE_CANON_TAG_SETTINGS_1,  1, N_("Self-timer")}, +	{MNOTE_CANON_TAG_SETTINGS_1,  2, N_("Quality")}, +	{MNOTE_CANON_TAG_SETTINGS_1,  3, N_("Flash mode")}, +	{MNOTE_CANON_TAG_SETTINGS_1,  4, N_("Drive mode")}, +	{MNOTE_CANON_TAG_SETTINGS_1,  6, N_("Focus mode")}, +	{MNOTE_CANON_TAG_SETTINGS_1,  8, N_("Record mode")}, +	{MNOTE_CANON_TAG_SETTINGS_1,  9, N_("Image size")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 10, N_("Easy shooting mode")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 11, N_("Digital zoom")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 12, N_("Contrast")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 13, N_("Saturation")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 14, N_("Sharpness")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 15, N_("ISO")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 16, N_("Metering mode")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 17, N_("Focus range")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 18, N_("AF point")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 19, N_("Exposure mode")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 21, N_("Lens type")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 22, N_("Long focal length of lens")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 23, N_("Short focal length of lens")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 24, N_("Focal units per mm")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 25, N_("Maximal aperture")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 26, N_("Minimal aperture")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 27, N_("Flash activity")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 28, N_("Flash details")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 31, N_("Focus mode")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 32, N_("AE setting")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 33, N_("Image stabilization")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 34, N_("Display aperture")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 35, N_("Zoom source width")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 36, N_("Zoom target width")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 39, N_("Photo effect")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 40, N_("Manual flash output")}, +	{MNOTE_CANON_TAG_SETTINGS_1, 41, N_("Color tone")}, +	{MNOTE_CANON_TAG_FOCAL_LENGTH, 0, N_("Focal type")}, +	{MNOTE_CANON_TAG_FOCAL_LENGTH, 1, N_("Focal length")}, +	{MNOTE_CANON_TAG_FOCAL_LENGTH, 2, N_("Focal plane x size")}, +	{MNOTE_CANON_TAG_FOCAL_LENGTH, 3, N_("Focal plane y size")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 0, N_("Auto ISO")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 1, N_("Shot ISO")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 2, N_("Measured EV")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 3, N_("Target aperture")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 4, N_("Target exposure time")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 5, N_("Exposure compensation")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 6, N_("White balance")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 7, N_("Slow shutter")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 8, N_("Sequence number")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 12, N_("Flash guide number")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 13, N_("AF point")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 14, N_("Flash exposure compensation")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 15, N_("AE bracketing")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 16, N_("AE bracket value")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 18, N_("Focus distance upper")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 19, N_("Focus distance lower")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 20, N_("FNumber")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 21, N_("Exposure time")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 23, N_("Bulb duration")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 25, N_("Camera type")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 26, N_("Auto rotate")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 27, N_("ND filter")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 28, N_("Self-timer")}, +	{MNOTE_CANON_TAG_SETTINGS_2, 32, N_("Manual flash output")}, +	{MNOTE_CANON_TAG_PANORAMA, 2, N_("Panorama frame")}, +	{MNOTE_CANON_TAG_PANORAMA, 5, N_("Panorama direction")}, +	{MNOTE_CANON_TAG_COLOR_INFORMATION, 0, N_("Tone curve")}, +	{MNOTE_CANON_TAG_COLOR_INFORMATION, 2, N_("Sharpness frequency")}, +	{MNOTE_CANON_TAG_COLOR_INFORMATION, 7, N_("White balance")}, +	{MNOTE_CANON_TAG_COLOR_INFORMATION, 9, N_("Picture style")}, +#endif +	{0, 0, NULL} +}; +  const char *  mnote_canon_tag_get_name (MnoteCanonTag t)  {  	unsigned int i;  	for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) -		if (table[i].tag == t) return (_(table[i].name)); +		if (table[i].tag == t) return table[i].name; /* do not translate */  	return NULL;  }  const char * +mnote_canon_tag_get_name_sub (MnoteCanonTag t, unsigned int s, ExifDataOption o) +{ +	unsigned int i; +	int tag_found = 0; + +	for (i = 0; i < sizeof (table_sub) / sizeof (table_sub[0]); i++) { +		if (table_sub[i].tag == t) { +			if (table_sub[i].subtag == s) +				return table_sub[i].name; +			tag_found = 1; +		} +	} +	if (!tag_found || !(o & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS)) +		return mnote_canon_tag_get_name (t); +	else +		return NULL; +} + +const char *  mnote_canon_tag_get_title (MnoteCanonTag t)  {  	unsigned int i; @@ -64,12 +167,35 @@ mnote_canon_tag_get_title (MnoteCanonTag t)  }  const char * +mnote_canon_tag_get_title_sub (MnoteCanonTag t, unsigned int s, ExifDataOption o) +{ +	unsigned int i; +	int tag_found = 0; + +	for (i = 0; i < sizeof (table_sub) / sizeof (table_sub[0]); i++) { +		if (table_sub[i].tag == t) { +			if (table_sub[i].subtag == s) +				return _(table_sub[i].name); +			tag_found = 1; +		} +	} +	if (!tag_found || !(o & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS)) +		return mnote_canon_tag_get_title (t); +	else +		return NULL; +} + +const char *  mnote_canon_tag_get_description (MnoteCanonTag t)  {  	unsigned int i;  	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);  	for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) -		if (table[i].tag == t) return (_(table[i].description)); +		if (table[i].tag == t) { +			if (!*table[i].description) +				return ""; +			return (_(table[i].description)); +		}  	return NULL;  } diff --git a/src/libexif/canon/mnote-canon-tag.h b/src/libexif/canon/mnote-canon-tag.h index ce1a72e..aead76e 100644 --- a/src/libexif/canon/mnote-canon-tag.h +++ b/src/libexif/canon/mnote-canon-tag.h @@ -1,6 +1,6 @@  /* mnote-canon-tag.h   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -21,6 +21,8 @@  #ifndef __MNOTE_CANON_TAG_H__  #define __MNOTE_CANON_TAG_H__ +#include <libexif/exif-data.h> +  #ifdef __cplusplus  extern "C" {  #endif /* __cplusplus */ @@ -28,8 +30,10 @@ extern "C" {  enum _MnoteCanonTag {  	MNOTE_CANON_TAG_UNKNOWN_0	= 0x0,  	MNOTE_CANON_TAG_SETTINGS_1	= 0x1, +	MNOTE_CANON_TAG_FOCAL_LENGTH	= 0x2,  	MNOTE_CANON_TAG_UNKNOWN_3	= 0x3,  	MNOTE_CANON_TAG_SETTINGS_2	= 0x4, +	MNOTE_CANON_TAG_PANORAMA	= 0x5,  	MNOTE_CANON_TAG_IMAGE_TYPE	= 0x6,  	MNOTE_CANON_TAG_FIRMWARE	= 0x7,  	MNOTE_CANON_TAG_IMAGE_NUMBER	= 0x8, @@ -37,13 +41,16 @@ enum _MnoteCanonTag {  	MNOTE_CANON_TAG_UNKNOWN_10	= 0xa,  	MNOTE_CANON_TAG_SERIAL_NUMBER	= 0xc,  	MNOTE_CANON_TAG_UNKNOWN_13	= 0xd, -	MNOTE_CANON_TAG_CUSTOM_FUNCS	= 0xf +	MNOTE_CANON_TAG_CUSTOM_FUNCS	= 0xf, +	MNOTE_CANON_TAG_COLOR_INFORMATION = 0xa0  };  typedef enum _MnoteCanonTag MnoteCanonTag; -const char *mnote_canon_tag_get_name        (MnoteCanonTag tag); -const char *mnote_canon_tag_get_title       (MnoteCanonTag tag); -const char *mnote_canon_tag_get_description (MnoteCanonTag tag); +const char *mnote_canon_tag_get_name        (MnoteCanonTag); +const char *mnote_canon_tag_get_name_sub    (MnoteCanonTag, unsigned int, ExifDataOption); +const char *mnote_canon_tag_get_title       (MnoteCanonTag); +const char *mnote_canon_tag_get_title_sub   (MnoteCanonTag, unsigned int, ExifDataOption); +const char *mnote_canon_tag_get_description (MnoteCanonTag);  #ifdef __cplusplus  } diff --git a/src/libexif/exif-byte-order.c b/src/libexif/exif-byte-order.c index 1a4279f..444fece 100644 --- a/src/libexif/exif-byte-order.c +++ b/src/libexif/exif-byte-order.c @@ -1,6 +1,6 @@  /* exif-byte-order.c   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public diff --git a/src/libexif/exif-byte-order.h b/src/libexif/exif-byte-order.h index bd51d3c..a7c98c9 100644 --- a/src/libexif/exif-byte-order.h +++ b/src/libexif/exif-byte-order.h @@ -1,6 +1,6 @@  /* exif-byte-order.h   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public diff --git a/src/libexif/exif-content.c b/src/libexif/exif-content.c index 39d73ad..c763751 100644 --- a/src/libexif/exif-content.c +++ b/src/libexif/exif-content.c @@ -1,6 +1,6 @@  /* exif-content.c   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -21,12 +21,15 @@  #include <config.h>  #include <libexif/exif-content.h> +#include <libexif/exif-system.h>  #include <stdlib.h>  #include <stdio.h>  #include <string.h> -static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; +/* unused constant + * static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; + */  struct _ExifContentPrivate  { @@ -120,7 +123,7 @@ exif_content_dump (ExifContent *content, unsigned int indent)  	if (!content)  		return; -	printf ("%sDumping exif content (%i entries)...\n", buf, +	printf ("%sDumping exif content (%u entries)...\n", buf,  		content->count);  	for (i = 0; i < content->count; i++)  		exif_entry_dump (content->entries[i], indent + 1); @@ -129,6 +132,7 @@ exif_content_dump (ExifContent *content, unsigned int indent)  void  exif_content_add_entry (ExifContent *c, ExifEntry *entry)  { +	ExifEntry **entries;  	if (!c || !c->priv || !entry || entry->parent) return;  	/* One tag can only be added once to an IFD. */ @@ -140,19 +144,20 @@ exif_content_add_entry (ExifContent *c, ExifEntry *entry)  		return;  	} +	entries = exif_mem_realloc (c->priv->mem, +		c->entries, sizeof (ExifEntry*) * (c->count + 1)); +	if (!entries) return;  	entry->parent = c; -	c->entries = exif_mem_realloc (c->priv->mem, -		c->entries, sizeof (ExifEntry) * (c->count + 1)); -	if (!c->entries) return; -	c->entries[c->count] = entry; +	entries[c->count++] = entry; +	c->entries = entries;  	exif_entry_ref (entry); -	c->count++;  }  void  exif_content_remove_entry (ExifContent *c, ExifEntry *e)  {  	unsigned int i; +	ExifEntry **t, *temp;  	if (!c || !c->priv || !e || (e->parent != c)) return; @@ -161,13 +166,26 @@ exif_content_remove_entry (ExifContent *c, ExifEntry *e)  	if (i == c->count) return;  	/* Remove the entry */ -	memmove (&c->entries[i], &c->entries[i + 1], -		 sizeof (ExifEntry) * (c->count - i - 1)); -	c->count--; +	temp = c->entries[c->count-1]; +	if (c->count > 1) { +		t = exif_mem_realloc (c->priv->mem, c->entries, +					sizeof(ExifEntry*) * (c->count - 1)); +		if (!t) { +			return; +		} +		c->entries = t; +		c->count--; +		if (i != c->count) { /* we deallocated the last slot already */  +			memmove (&t[i], &t[i + 1], sizeof (ExifEntry*) * (c->count - i - 1)); +			t[c->count-1] = temp; +		}  +	} else { +		exif_mem_free (c->priv->mem, c->entries); +		c->entries = NULL; +		c->count = 0; +	}  	e->parent = NULL;  	exif_entry_unref (e); -	c->entries = exif_mem_realloc (c->priv->mem, c->entries, -					sizeof(ExifEntry) * c->count);  }  ExifEntry * @@ -207,3 +225,70 @@ exif_content_log (ExifContent *content, ExifLog *log)  	content->priv->log = log;  	exif_log_ref (log);  } + +ExifIfd +exif_content_get_ifd (ExifContent *c) +{ +	if (!c || !c->parent) return EXIF_IFD_COUNT; + +	return  +		((c)->parent->ifd[EXIF_IFD_0] == (c)) ? EXIF_IFD_0 : +		((c)->parent->ifd[EXIF_IFD_1] == (c)) ? EXIF_IFD_1 : +		((c)->parent->ifd[EXIF_IFD_EXIF] == (c)) ? EXIF_IFD_EXIF : +		((c)->parent->ifd[EXIF_IFD_GPS] == (c)) ? EXIF_IFD_GPS : +		((c)->parent->ifd[EXIF_IFD_INTEROPERABILITY] == (c)) ? EXIF_IFD_INTEROPERABILITY : +		EXIF_IFD_COUNT; +} + +static void +fix_func (ExifEntry *e, void *UNUSED(data)) +{ +	exif_entry_fix (e); +} + +void +exif_content_fix (ExifContent *c) +{ +	ExifIfd ifd = exif_content_get_ifd (c); +	ExifDataType dt; +	ExifTag t; +	ExifEntry *e; + +	if (!c) return; + +	dt = exif_data_get_data_type (c->parent); + +	/* First of all, fix all existing entries. */ +	exif_content_foreach_entry (c, fix_func, NULL); + +	/* +	 * Then check for existing tags that are not allowed and for +	 * non-existing mandatory tags. +	 */ +	for (t = 0; t <= 0xffff; t++) { +		switch (exif_tag_get_support_level_in_ifd (t, ifd, dt)) { +		case EXIF_SUPPORT_LEVEL_MANDATORY: +			if (exif_content_get_entry (c, t)) break; +			exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content", +					"Tag '%s' is mandatory in IFD '%s' and has therefore been added.", +					exif_tag_get_name_in_ifd (t, ifd), exif_ifd_get_name (ifd)); +			e = exif_entry_new (); +			exif_content_add_entry (c, e); +			exif_entry_initialize (e, t); +			exif_entry_unref (e); +			break; +		case EXIF_SUPPORT_LEVEL_NOT_RECORDED: +			e = exif_content_get_entry (c, t); +			if (!e) break; +			exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content", +					"Tag '%s' is not recorded in IFD '%s' and has therefore been " +					"removed.", exif_tag_get_name_in_ifd (t, ifd), +					exif_ifd_get_name (ifd)); +			exif_content_remove_entry (c, e); +			break; +		case EXIF_SUPPORT_LEVEL_OPTIONAL: +		default: +			break; +		} +	} +} diff --git a/src/libexif/exif-content.h b/src/libexif/exif-content.h index 115f8ed..ade2e01 100644 --- a/src/libexif/exif-content.h +++ b/src/libexif/exif-content.h @@ -1,6 +1,6 @@  /* exif-content.h   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -52,9 +52,10 @@ void         exif_content_ref     (ExifContent *content);  void         exif_content_unref   (ExifContent *content);  void         exif_content_free    (ExifContent *content); -void         exif_content_add_entry     (ExifContent *content, ExifEntry *e); -void         exif_content_remove_entry  (ExifContent *content, ExifEntry *e); -ExifEntry   *exif_content_get_entry     (ExifContent *content, ExifTag tag); +void         exif_content_add_entry    (ExifContent *, ExifEntry *); +void         exif_content_remove_entry (ExifContent *, ExifEntry *); +ExifEntry   *exif_content_get_entry    (ExifContent *, ExifTag); +void         exif_content_fix          (ExifContent *);  typedef void (* ExifContentForeachEntryFunc) (ExifEntry *, void *user_data);  void         exif_content_foreach_entry (ExifContent *content, @@ -62,6 +63,7 @@ void         exif_content_foreach_entry (ExifContent *content,  					 void *user_data);  /* For your convenience */ +ExifIfd exif_content_get_ifd (ExifContent *);  #define exif_content_get_value(c,t,v,m)					\  	(exif_content_get_entry (c,t) ?					\  	 exif_entry_get_value (exif_content_get_entry (c,t),v,m) : NULL) diff --git a/src/libexif/exif-data-type.h b/src/libexif/exif-data-type.h new file mode 100644 index 0000000..271a2f2 --- /dev/null +++ b/src/libexif/exif-data-type.h @@ -0,0 +1,40 @@ +/* exif-data-tag.h + * + * Copyright (c) 2005 Lutz Mueller <lutz@users.sourceforge.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful,  + * but WITHOUT ANY WARRANTY; without even the implied warranty of  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.  + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __EXIF_DATA_TYPE_H__ +#define __EXIF_DATA_TYPE_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef enum { +	EXIF_DATA_TYPE_UNCOMPRESSED_CHUNKY = 0, +	EXIF_DATA_TYPE_UNCOMPRESSED_PLANAR, +	EXIF_DATA_TYPE_UNCOMPRESSED_YCC, +	EXIF_DATA_TYPE_COMPRESSED, +	EXIF_DATA_TYPE_COUNT +} ExifDataType; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __EXIF_TAG_H__ */ diff --git a/src/libexif/exif-data.c b/src/libexif/exif-data.c index 92e5857..314fd8b 100644 --- a/src/libexif/exif-data.c +++ b/src/libexif/exif-data.c @@ -1,6 +1,6 @@  /* exif-data.c   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -28,18 +28,17 @@  #include <libexif/exif-loader.h>  #include <libexif/exif-log.h>  #include <libexif/i18n.h> +#include <libexif/exif-system.h> -#include <libexif/olympus/exif-mnote-data-olympus.h>  #include <libexif/canon/exif-mnote-data-canon.h> +#include <libexif/fuji/exif-mnote-data-fuji.h> +#include <libexif/olympus/exif-mnote-data-olympus.h>  #include <libexif/pentax/exif-mnote-data-pentax.h>  #include <stdlib.h>  #include <stdio.h>  #include <string.h> -#undef MAX -#define MAX(a, b)  (((a) > (b)) ? (a) : (b)) -  #if defined(__WATCOMC__) || defined(_MSC_VER)  #      define strncasecmp strnicmp  #endif @@ -66,6 +65,9 @@ struct _ExifDataPrivate  	/* Temporarily used while loading data */  	unsigned int offset_mnote; + +	ExifDataOption options; +	ExifDataType data_type;  };  static void * @@ -73,10 +75,12 @@ exif_data_alloc (ExifData *data, unsigned int i)  {  	void *d; -	if (!data || !i) return NULL; +	if (!data || !i)  +		return NULL;  	d = exif_mem_alloc (data->priv->mem, i); -	if (d) return d; +	if (d)  +		return d;  	EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", i);  	return NULL; @@ -105,12 +109,17 @@ exif_data_new_mem (ExifMem *mem)  	ExifData *data;  	unsigned int i; -	if (!mem) return NULL; +	if (!mem)  +		return NULL;  	data = exif_mem_alloc (mem, sizeof (ExifData)); -	if (!data) return (NULL); +	if (!data)  +		return (NULL);  	data->priv = exif_mem_alloc (mem, sizeof (ExifDataPrivate)); -	if (!data->priv) { exif_mem_free (mem, data); return (NULL); } +	if (!data->priv) {  +	  	exif_mem_free (mem, data);  +		return (NULL);  +	}  	data->priv->ref_count = 1;  	data->priv->mem = mem; @@ -125,6 +134,19 @@ exif_data_new_mem (ExifMem *mem)  		data->ifd[i]->parent = data;  	} +	/* Default options */ +#ifndef NO_VERBOSE_TAG_STRINGS +	/* +	 * When the tag list is compiled away, setting this option prevents +	 * any tags from being loaded +	 */ +	exif_data_set_option (data, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS); +#endif +	exif_data_set_option (data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); + +	/* Default data type: none */ +	exif_data_set_data_type (data, EXIF_DATA_TYPE_COUNT); +  	return (data);  } @@ -138,7 +160,7 @@ exif_data_new_from_data (const unsigned char *data, unsigned int size)  	return (edata);  } -static void +static int  exif_data_load_data_entry (ExifData *data, ExifEntry *entry,  			   const unsigned char *d,  			   unsigned int size, unsigned int offset) @@ -153,41 +175,56 @@ exif_data_load_data_entry (ExifData *data, ExifEntry *entry,  		  "Loading entry 0x%x ('%s')...", entry->tag,  		  exif_tag_get_name (entry->tag)); +	/* {0,1,2,4,8} x { 0x00000000 .. 0xffffffff }  +	 *   -> { 0x000000000 .. 0x7fffffff8 } */ +	s = exif_format_get_size(entry->format) * entry->components; +	if (s < entry->components) { +		return 0; +	} +	if (0 == s) +		return 0;  	/*  	 * Size? If bigger than 4 bytes, the actual data is not  	 * in the entry but somewhere else (offset).  	 */ -	s = exif_format_get_size (entry->format) * entry->components; -	if (!s) -		return;  	if (s > 4)  		doff = exif_get_long (d + offset + 8, data->priv->order);  	else  		doff = offset + 8; -	/* Sanity check */ +	/* Sanity checks */ +	if ((doff + s < doff) || (doff + s < s)) +		return 0;  	if (size < doff + s) -		return; +		return 0;  	entry->data = exif_data_alloc (data, s);  	if (entry->data) {  		entry->size = s;  		memcpy (entry->data, d + doff, s); +	} else { +		/* FIXME: What do our callers do if (entry->data == NULL)? */ +		EXIF_LOG_NO_MEMORY(data->priv->log, "ExifData", s);  	}  	/* If this is the MakerNote, remember the offset */  	if (entry->tag == EXIF_TAG_MAKER_NOTE) { -		if (entry->size > 6) exif_log (data->priv->log, -			  EXIF_LOG_CODE_DEBUG, "ExifData", -		          "MakerNote found (%02x %02x %02x %02x " -			  "%02x %02x %02x...).", -			  entry->data[0], entry->data[1], entry->data[2], -			  entry->data[3], entry->data[4], entry->data[5], -			  entry->data[6]); +		if (!entry->data) { +			exif_log (data->priv->log, +                                               EXIF_LOG_CODE_DEBUG, "ExifData", +                                               "MakerNote found with NULL data");	 +		} else if (entry->size > 6) { +			exif_log (data->priv->log, +					       EXIF_LOG_CODE_DEBUG, "ExifData", +					       "MakerNote found (%02x %02x %02x %02x " +					       "%02x %02x %02x...).", +					       entry->data[0], entry->data[1], entry->data[2], +					       entry->data[3], entry->data[4], entry->data[5], +					       entry->data[6]); +		}  		data->priv->offset_mnote = doff;  	} - -	exif_entry_fix (entry); +	return 1;  }  static void @@ -196,8 +233,11 @@ exif_data_save_data_entry (ExifData *data, ExifEntry *e,  			   unsigned int offset)  {  	unsigned int doff, s; +	unsigned char *t; +	unsigned int ts; -	if (!data || !data->priv) return; +	if (!data || !data->priv)  +		return;  	/*  	 * Each entry is 12 bytes long. The memory for the entry has @@ -208,17 +248,17 @@ exif_data_save_data_entry (ExifData *data, ExifEntry *e,  	exif_set_short (*d + 6 + offset + 2,  			data->priv->order, (ExifShort) e->format); -#ifndef EXIF_DONT_CHANGE_MAKER_NOTE -	/* If this is the maker note tag, update it. */ -	if ((e->tag == EXIF_TAG_MAKER_NOTE) && data->priv->md) { -		exif_mem_free (data->priv->mem, e->data); -		e->data = NULL; -		e->size = 0; -		exif_mnote_data_set_offset (data->priv->md, *ds - 6); -		exif_mnote_data_save (data->priv->md, &e->data, &e->size); -		e->components = e->size; +	if (!(data->priv->options & EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE)) { +		/* If this is the maker note tag, update it. */ +		if ((e->tag == EXIF_TAG_MAKER_NOTE) && data->priv->md) { +			exif_mem_free (data->priv->mem, e->data); +			e->data = NULL; +			e->size = 0; +			exif_mnote_data_set_offset (data->priv->md, *ds - 6); +			exif_mnote_data_save (data->priv->md, &e->data, &e->size); +			e->components = e->size; +		}  	} -#endif  	exif_set_long  (*d + 6 + offset + 4,  			data->priv->order, e->components); @@ -230,50 +270,62 @@ exif_data_save_data_entry (ExifData *data, ExifEntry *e,  	s = exif_format_get_size (e->format) * e->components;  	if (s > 4) {  		doff = *ds - 6; -		*ds += s; +		ts = *ds + s;  		/*  		 * According to the TIFF specification,  		 * the offset must be an even number. If we need to introduce  		 * a padding byte, we set it to 0.  		 */ -		if (s & 1) (*ds)++; -		*d = exif_mem_realloc (data->priv->mem, *d, *ds); -		if (!*d) { -			EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", *ds); +		if (s & 1) +			ts++; +		t = exif_mem_realloc (data->priv->mem, *d, ts); +		if (!t) { +			EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts);  		  	return;  		} +		*d = t; +		*ds = ts;  		exif_set_long (*d + 6 + offset + 8, data->priv->order, doff); -		if (s & 1) *(*d + *ds - 1) = '\0'; +		if (s & 1)  +			*(*d + *ds - 1) = '\0';  	} else  		doff = offset + 8; -	/* Write the data. Fill unneeded bytes with 0. */ -	memcpy (*d + 6 + doff, e->data, s); -	if (s < 4) memset (*d + 6 + doff + s, 0, (4 - s)); +	/* Write the data. Fill unneeded bytes with 0. Do not crash with +	 * e->data is NULL */ +	if (e->data) { +		memcpy (*d + 6 + doff, e->data, s); +	} else { +		memset (*d + 6 + doff, 0, s); +	} +	if (s < 4)  +		memset (*d + 6 + doff + s, 0, (4 - s));  }  static void  exif_data_load_data_thumbnail (ExifData *data, const unsigned char *d,  			       unsigned int ds, ExifLong offset, ExifLong size)  { -	if (ds < offset + size) { +	if ((ds < offset + size) || (offset > ds)) {  		exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", -			  "Bogus thumbnail offset and size: %i < %i + %i.", -			  (int) ds, (int) offset, (int) size); +			  "Bogus thumbnail offset (%u) or size (%u).", +			  offset, size);  		return;  	} -	if (data->data) exif_mem_free (data->priv->mem, data->data); +	if (data->data)  +		exif_mem_free (data->priv->mem, data->data);  	data->size = size;  	data->data = exif_data_alloc (data, data->size); -	if (!data->data) return; +	if (!data->data)  +		return;  	memcpy (data->data, d + offset, data->size);  }  #undef CHECK_REC  #define CHECK_REC(i) 					\ -if (data->ifd[(i)] == ifd) {				\ +if ((i) == ifd) {				\  	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \  		"ExifData", "Recursive entry in IFD "	\  		"'%s' detected. Skipping...",		\ @@ -282,7 +334,7 @@ if (data->ifd[(i)] == ifd) {				\  }							\  if (data->ifd[(i)]->count) {				\  	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG,	\ -		"ExifData", "Attemt to load IFD "	\ +		"ExifData", "Attempt to load IFD "	\  		"'%s' multiple times detected. "	\  		"Skipping...",				\  		exif_ifd_get_name (i));			\ @@ -290,9 +342,9 @@ if (data->ifd[(i)]->count) {				\  }  static void -exif_data_load_data_content (ExifData *data, ExifContent *ifd, +exif_data_load_data_content (ExifData *data, ExifIfd ifd,  			     const unsigned char *d, -			     unsigned int ds, unsigned int offset) +			     unsigned int ds, unsigned int offset, unsigned int recursion_depth)  {  	ExifLong o, thumbnail_offset = 0, thumbnail_length = 0;  	ExifShort n; @@ -300,17 +352,30 @@ exif_data_load_data_content (ExifData *data, ExifContent *ifd,  	unsigned int i;  	ExifTag tag; -	if (!data || !data->priv) return; +	if (!data || !data->priv)  +		return; + +	/* check for valid ExifIfd enum range */ +	if (( ((int)ifd) < 0) || ( ((int)ifd) >= EXIF_IFD_COUNT)) +	  return; + +	if (recursion_depth > 150) { +		exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", +			  "Deep recursion detected!"); +		return; +	}  	/* Read the number of entries */ -	if (offset >= ds - 1) return; +	if (offset >= ds - 1)  +		return;  	n = exif_get_short (d + offset, data->priv->order);  	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",  	          "Loading %i entries...", n);  	offset += 2;  	/* Check if we have enough data. */ -	if (offset + 12 * n > ds) n = (ds - offset) / 12; +	if (offset + 12 * n > ds)  +		n = (ds - offset) / 12;  	for (i = 0; i < n; i++) { @@ -326,32 +391,29 @@ exif_data_load_data_content (ExifData *data, ExifContent *ifd,  			switch (tag) {  			case EXIF_TAG_EXIF_IFD_POINTER:  				CHECK_REC (EXIF_IFD_EXIF); -				exif_data_load_data_content (data, -					data->ifd[EXIF_IFD_EXIF], d, ds, o); +				exif_data_load_data_content (data, EXIF_IFD_EXIF, d, ds, o, recursion_depth + 1);  				break;  			case EXIF_TAG_GPS_INFO_IFD_POINTER:  				CHECK_REC (EXIF_IFD_GPS); -				exif_data_load_data_content (data, -					data->ifd[EXIF_IFD_GPS], d, ds, o); +				exif_data_load_data_content (data, EXIF_IFD_GPS, d, ds, o, recursion_depth + 1);  				break;  			case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:  				CHECK_REC (EXIF_IFD_INTEROPERABILITY); -				exif_data_load_data_content (data, -					data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds, o); +				exif_data_load_data_content (data, EXIF_IFD_INTEROPERABILITY, d, ds, o, recursion_depth + 1);  				break;  			case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:  				thumbnail_offset = o;  				if (thumbnail_offset && thumbnail_length)  					exif_data_load_data_thumbnail (data, d, -						ds, thumbnail_offset, -						thumbnail_length); +								       ds, thumbnail_offset, +								       thumbnail_length);  				break;  			case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:  				thumbnail_length = o;  				if (thumbnail_offset && thumbnail_length)  					exif_data_load_data_thumbnail (data, d, -						ds, thumbnail_offset, -						thumbnail_length); +								       ds, thumbnail_offset, +								       thumbnail_length);  				break;  			default:  				return; @@ -360,18 +422,33 @@ exif_data_load_data_content (ExifData *data, ExifContent *ifd,  		default:  			/* -			 * If we don't know the tag, chances are high -			 * that the EXIF data does not follow the standard. +			 * If we don't know the tag, don't fail. It could be that new  +			 * versions of the standard have defined additional tags. Note that +			 * 0 is a valid tag in the GPS IFD.  			 */ -			if (!exif_tag_get_name (tag)) { +			if (!exif_tag_get_name_in_ifd (tag, ifd)) { + +				/* +				 * Special case: Tag and format 0. That's against specification. +				 * At least up to 2.2. But Photoshop writes it anyways. +				 */ +				if (!memcmp (d + offset + 12 * i, "\0\0\0\0", 4)) { +					exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", +						  "Skipping empty entry at position %i in '%s'.", i,  +						  exif_ifd_get_name (ifd)); +					break; +				}  				exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", -				  "Unknown tag %x (entry %i)", tag, i); -				return; +					  "Unknown tag 0x%04x (entry %i in '%s'). Please report this tag " +					  "to <libexif-devel@lists.sourceforge.net>.", tag, i, +					  exif_ifd_get_name (ifd)); +				if (data->priv->options & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS) +					break;  			}  			entry = exif_entry_new_mem (data->priv->mem); -			exif_data_load_data_entry (data, entry, d, ds, -						   offset + 12 * i); -			exif_content_add_entry (ifd, entry); +			if (exif_data_load_data_entry (data, entry, d, ds, +						   offset + 12 * i)) +				exif_content_add_entry (data->ifd[ifd], entry);  			exif_entry_unref (entry);  			break;  		} @@ -391,14 +468,14 @@ static int  cmp_func_intel (const void *elem1, const void *elem2)  {  	return cmp_func ((const unsigned char *) elem1, -			(const unsigned char *) elem2, EXIF_BYTE_ORDER_INTEL); +			 (const unsigned char *) elem2, EXIF_BYTE_ORDER_INTEL);  }  static int  cmp_func_motorola (const void *elem1, const void *elem2)  {  	return cmp_func ((const unsigned char *) elem1, -			(const unsigned char *) elem2, EXIF_BYTE_ORDER_MOTOROLA); +			 (const unsigned char *) elem2, EXIF_BYTE_ORDER_MOTOROLA);  }  static void @@ -408,8 +485,11 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,  {  	unsigned int j, n_ptr = 0, n_thumb = 0;  	ExifIfd i; +	unsigned char *t; +	unsigned int ts; -	if (!data || !data->priv || !ifd || !d || !ds) return; +	if (!data || !data->priv || !ifd || !d || !ds)  +		return;  	for (i = 0; i < EXIF_IFD_COUNT; i++)  		if (ifd == data->ifd[i]) @@ -451,24 +531,33 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,  	 * Allocate enough memory for all entries  	 * and the number of entries.  	 */ -	*ds += (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4); -	*d = exif_mem_realloc (data->priv->mem, *d, *ds); -	if (!*d) { -		EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", *ds); +	ts = *ds + (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4); +	t = exif_mem_realloc (data->priv->mem, *d, ts); +	if (!t) { +		EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts);  	  	return;  	} +	*d = t; +	*ds = ts;  	/* Save the number of entries */  	exif_set_short (*d + 6 + offset, data->priv->order,  			(ExifShort) (ifd->count + n_ptr + n_thumb));  	offset += 2; -	/* Save each entry */ +	/* +	 * Save each entry. Make sure that no memcpys from NULL pointers are +	 * performed +	 */  	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",  		  "Saving %i entries (IFD '%s', offset: %i)...",  		  ifd->count, exif_ifd_get_name (i), offset); -	for (j = 0; j < ifd->count; j++) -		exif_data_save_data_entry (data, ifd->entries[j], d, ds, offset + 12 * j); +	for (j = 0; j < ifd->count; j++) { +		if (ifd->entries[j]) { +			exif_data_save_data_entry (data, ifd->entries[j], d, ds, +				offset + 12 * j); +		} +	}  	offset += 12 * ifd->count; @@ -493,7 +582,7 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,  			exif_set_long  (*d + 6 + offset + 8, data->priv->order,  					*ds - 6);  			exif_data_save_data_content (data, -				data->ifd[EXIF_IFD_EXIF], d, ds, *ds - 6); +						     data->ifd[EXIF_IFD_EXIF], d, ds, *ds - 6);  			offset += 12;  		} @@ -508,7 +597,7 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,  			exif_set_long  (*d + 6 + offset + 8, data->priv->order,  					*ds - 6);  			exif_data_save_data_content (data, -				data->ifd[EXIF_IFD_GPS], d, ds, *ds - 6); +						     data->ifd[EXIF_IFD_GPS], d, ds, *ds - 6);  			offset += 12;  		} @@ -529,8 +618,8 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,  			exif_set_long  (*d + 6 + offset + 8, data->priv->order,  					*ds - 6);  			exif_data_save_data_content (data, -				data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds, -				*ds - 6); +						     data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds, +						     *ds - 6);  			offset += 12;  		} @@ -552,19 +641,21 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,  					1);  			exif_set_long  (*d + 6 + offset + 8, data->priv->order,  					*ds - 6); -			*ds += data->size; -			*d = exif_mem_realloc (data->priv->mem, *d, *ds); -			if (!*d) { +			ts = *ds + data->size; +			t = exif_mem_realloc (data->priv->mem, *d, ts); +			if (!t) {  				EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", -						    *ds); +						    ts);  			  	return;  			} +			*d = t; +			*ds = ts;  			memcpy (*d + *ds - data->size, data->data, data->size);  			offset += 12;  			/* EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH */  			exif_set_short (*d + 6 + offset + 0, data->priv->order, -				EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); +					EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);  			exif_set_short (*d + 6 + offset + 2, data->priv->order,  					EXIF_FORMAT_LONG);  			exif_set_long  (*d + 6 + offset + 4, data->priv->order, @@ -581,12 +672,12 @@ exif_data_save_data_content (ExifData *data, ExifContent *ifd,  	/* Sort the directory according to TIFF specification */  	qsort (*d + 6 + offset - (ifd->count + n_ptr + n_thumb) * 12, -			(ifd->count + n_ptr + n_thumb), 12, -			data->priv->order == EXIF_BYTE_ORDER_INTEL ? cmp_func_intel : cmp_func_motorola); +	       (ifd->count + n_ptr + n_thumb), 12, +	       (data->priv->order == EXIF_BYTE_ORDER_INTEL) ? cmp_func_intel : cmp_func_motorola);  	/* Correctly terminate the directory */  	if (i == EXIF_IFD_0 && (data->ifd[EXIF_IFD_1]->count || -					     data->size)) { +				data->size)) {  		/*  		 * We are saving IFD 0. Tell where IFD 1 starts and save @@ -603,7 +694,10 @@ typedef enum {  	EXIF_DATA_TYPE_MAKER_NOTE_NONE		= 0,  	EXIF_DATA_TYPE_MAKER_NOTE_CANON		= 1,  	EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS	= 2, -	EXIF_DATA_TYPE_MAKER_NOTE_PENTAX	= 3 +	EXIF_DATA_TYPE_MAKER_NOTE_PENTAX		= 3, +	EXIF_DATA_TYPE_MAKER_NOTE_NIKON		= 4, +	EXIF_DATA_TYPE_MAKER_NOTE_CASIO		= 5, +	EXIF_DATA_TYPE_MAKER_NOTE_FUJI 		= 6  } ExifDataTypeMakerNote;  static ExifDataTypeMakerNote @@ -612,18 +706,23 @@ exif_data_get_type_maker_note (ExifData *d)  	ExifEntry *e, *em;  	char value[1024]; -	if (!d) return EXIF_DATA_TYPE_MAKER_NOTE_NONE; +	if (!d)  +		return EXIF_DATA_TYPE_MAKER_NOTE_NONE;  	e = exif_data_get_entry (d, EXIF_TAG_MAKER_NOTE); -        if (!e) return EXIF_DATA_TYPE_MAKER_NOTE_NONE; - -	/* Olympus & Nikon */ -	if ((e->size >= 5) && (!memcmp (e->data, "OLYMP", 5) || -			       !memcmp (e->data, "Nikon", 5))) +	if (!e)  +		return EXIF_DATA_TYPE_MAKER_NOTE_NONE; + +	/* Olympus & Nikon & Sanyo */ +	if ((e->size >= 8) && ( !memcmp (e->data, "OLYMP", 6) || +				!memcmp (e->data, "OLYMPUS", 8) || +				!memcmp (e->data, "SANYO", 6) || +				!memcmp (e->data, "Nikon", 6)))  		return EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS;  	em = exif_data_get_entry (d, EXIF_TAG_MAKE); -	if (!em) return EXIF_DATA_TYPE_MAKER_NOTE_NONE; +	if (!em)  +		return EXIF_DATA_TYPE_MAKER_NOTE_NONE;  	/* Canon */  	if (!strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon")) @@ -632,12 +731,21 @@ exif_data_get_type_maker_note (ExifData *d)  	/* Pentax & some variant of Nikon */  	if ((e->size >= 2) && (e->data[0] == 0x00) && (e->data[1] == 0x1b)) {  		if (!strncasecmp ( -			exif_entry_get_value (em, value, sizeof(value)), -					      "Nikon", 5)) -			return EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS; +			    exif_entry_get_value (em, value, sizeof(value)), +			    "Nikon", 5)) +			return EXIF_DATA_TYPE_MAKER_NOTE_NIKON;  		else  			return EXIF_DATA_TYPE_MAKER_NOTE_PENTAX;  	} +	if ((e->size >= 8) && !memcmp (e->data, "AOC", 4)) { +		return EXIF_DATA_TYPE_MAKER_NOTE_PENTAX; +	} +	if ((e->size >= 8) && !memcmp (e->data, "QVC", 4)) { +		return EXIF_DATA_TYPE_MAKER_NOTE_CASIO; +	} +	if ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8)) { +		return EXIF_DATA_TYPE_MAKER_NOTE_FUJI; +	}  	return EXIF_DATA_TYPE_MAKER_NOTE_NONE;  } @@ -656,7 +764,8 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,  	const unsigned char *d = d_orig;  	unsigned int ds = ds_orig, len; -	if (!data || !data->priv || !d || !ds) return; +	if (!data || !data->priv || !d || !ds)  +		return;  	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",  		  "Parsing %i byte(s) EXIF data...\n", ds); @@ -731,7 +840,7 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,  	}  	if (memcmp (d, ExifHeader, 6)) {  		exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, -				"ExifData", _("EXIF header not found.")); +			  "ExifData", _("EXIF header not found."));  		return;  	} @@ -747,7 +856,7 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,  		data->priv->order = EXIF_BYTE_ORDER_MOTOROLA;  	else {  		exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, -				"ExifData", _("Unknown encoding.")); +			  "ExifData", _("Unknown encoding."));  		return;  	} @@ -761,8 +870,7 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,  		  "IFD 0 at %i.", (int) offset);  	/* Parse the actual exif data (usually offset 14 from start) */ -	exif_data_load_data_content (data, data->ifd[EXIF_IFD_0], d + 6, -				     ds - 6, offset); +	exif_data_load_data_content (data, EXIF_IFD_0, d + 6, ds - 6, offset, 0);  	/* IFD 1 offset */  	if (offset + 6 + 2 > ds) { @@ -780,12 +888,10 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,  		/* Sanity check. */  		if (offset > ds - 6) {  			exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, -				  "ExifData", "Bogus offset."); -			return; +				  "ExifData", "Bogus offset of IFD1."); +		} else { +		   exif_data_load_data_content (data, EXIF_IFD_1, d + 6, ds - 6, offset, 0);  		} - -		exif_data_load_data_content (data, data->ifd[EXIF_IFD_1], d + 6, -					     ds - 6, offset);  	}  	/* @@ -796,13 +902,18 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,  	 */  	switch (exif_data_get_type_maker_note (data)) {  	case EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS: +	case EXIF_DATA_TYPE_MAKER_NOTE_NIKON:  		data->priv->md = exif_mnote_data_olympus_new (data->priv->mem);  		break;  	case EXIF_DATA_TYPE_MAKER_NOTE_PENTAX: +	case EXIF_DATA_TYPE_MAKER_NOTE_CASIO:  		data->priv->md = exif_mnote_data_pentax_new (data->priv->mem);  		break;  	case EXIF_DATA_TYPE_MAKER_NOTE_CANON: -		data->priv->md = exif_mnote_data_canon_new (data->priv->mem); +		data->priv->md = exif_mnote_data_canon_new (data->priv->mem, data->priv->options); +		break; +	case EXIF_DATA_TYPE_MAKER_NOTE_FUJI: +		data->priv->md = exif_mnote_data_fuji_new (data->priv->mem);  		break;  	default:  		break; @@ -819,18 +930,27 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,  					    data->priv->offset_mnote);  		exif_mnote_data_load (data->priv->md, d, ds);  	} + +	if (data->priv->options & EXIF_DATA_OPTION_FOLLOW_SPECIFICATION) +		exif_data_fix (data);  }  void  exif_data_save_data (ExifData *data, unsigned char **d, unsigned int *ds)  { +	if (ds) +		*ds = 0;	/* This means something went wrong */ +  	if (!data || !d || !ds)  		return;  	/* Header */  	*ds = 14;  	*d = exif_data_alloc (data, *ds); -	if (!*d) return; +	if (!*d)  { +		*ds = 0; +		return; +	}  	memcpy (*d, ExifHeader, 6);  	/* Order (offset 6) */ @@ -886,10 +1006,12 @@ exif_data_ref (ExifData *data)  void  exif_data_unref (ExifData *data)  { -	if (!data) return; +	if (!data)  +		return;  	data->priv->ref_count--; -	if (!data->priv->ref_count) exif_data_free (data); +	if (!data->priv->ref_count)  +		exif_data_free (data);  }  void @@ -898,7 +1020,8 @@ exif_data_free (ExifData *data)  	unsigned int i;  	ExifMem *mem = (data && data->priv) ? data->priv->mem : NULL; -	if (!data) return; +	if (!data)  +		return;  	for (i = 0; i < EXIF_IFD_COUNT; i++) {  		if (data->ifd[i]) { @@ -1020,7 +1143,8 @@ exif_data_log (ExifData *data, ExifLog *log)  {  	unsigned int i; -	if (!data || !data->priv) return; +	if (!data || !data->priv)  +		return;  	exif_log_unref (data->priv->log);  	data->priv->log = log;  	exif_log_ref (log); @@ -1034,6 +1158,112 @@ ExifLog *exif_data_get_log (ExifData *);  ExifLog *  exif_data_get_log (ExifData *data)  { -	if (!data || !data->priv) return NULL; +	if (!data || !data->priv)  +		return NULL;  	return data->priv->log;  } + +static const struct { +	ExifDataOption option; +	const char *name; +	const char *description; +} exif_data_option[] = { +	{EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS, N_("Ignore unknown tags"), +	 N_("Ignore unknown tags when loading EXIF data.")}, +	{EXIF_DATA_OPTION_FOLLOW_SPECIFICATION, N_("Follow specification"), +	 N_("Add, correct and remove entries to get EXIF data that follows " +	    "the specification.")}, +	{EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE, N_("Do not change maker note"), +	 N_("When loading and resaving Exif data, save the maker note unmodified." +	    " Be aware that the maker note can get corrupted.")}, +	{0, NULL, NULL} +}; + +const char * +exif_data_option_get_name (ExifDataOption o) +{ +	unsigned int i; + +	for (i = 0; exif_data_option[i].name; i++) +		if (exif_data_option[i].option == o)  +			break; +	return _(exif_data_option[i].name); +} + +const char * +exif_data_option_get_description (ExifDataOption o) +{ +	unsigned int i; + +	for (i = 0; exif_data_option[i].description; i++) +		if (exif_data_option[i].option == o)  +			break; +	return _(exif_data_option[i].description); +} + +void +exif_data_set_option (ExifData *d, ExifDataOption o) +{ +	if (!d)  +		return; + +	d->priv->options |= o; +} + +void +exif_data_unset_option (ExifData *d, ExifDataOption o) +{ +	if (!d)  +		return; + +	d->priv->options &= ~o; +} + +static void +fix_func (ExifContent *c, void *UNUSED(data)) +{ +	switch (exif_content_get_ifd (c)) { +	case EXIF_IFD_1: +		if (c->parent->data) +			exif_content_fix (c); +		else { +			exif_log (c->parent->priv->log, EXIF_LOG_CODE_DEBUG, "exif-data", +				  "No thumbnail but entries on thumbnail. These entries have been " +				  "removed."); +			while (c->count) { +				unsigned int cnt = c->count; +				exif_content_remove_entry (c, c->entries[c->count - 1]); +				if (cnt == c->count) { +					/* safety net */ +					exif_log (c->parent->priv->log, EXIF_LOG_CODE_DEBUG, "exif-data", +					"failed to remove last entry from entries."); +					c->count--; +				} +			} +		} +		break; +	default: +		exif_content_fix (c); +	} +} + +void +exif_data_fix (ExifData *d) +{ +	exif_data_foreach_content (d, fix_func, NULL); +} + +void +exif_data_set_data_type (ExifData *d, ExifDataType dt) +{ +	if (!d || !d->priv)  +		return; + +	d->priv->data_type = dt; +} + +ExifDataType +exif_data_get_data_type (ExifData *d) +{ +	return (d && d->priv) ? d->priv->data_type : EXIF_DATA_TYPE_COUNT; +} diff --git a/src/libexif/exif-data.h b/src/libexif/exif-data.h index 9ecad1d..3b99412 100644 --- a/src/libexif/exif-data.h +++ b/src/libexif/exif-data.h @@ -1,7 +1,7 @@  /*! \file exif-data.h - * \brief FIXME foo bar blah + * \brief Defines the ExifData type and the associated functions.   * - * \author Lutz Müller <lutz@users.sourceforge.net> + * \author Lutz Mueller <lutz@users.sourceforge.net>   * \date 2001-2005   *   * This library is free software; you can redistribute it and/or @@ -28,6 +28,7 @@ extern "C" {  #endif /* __cplusplus */  #include <libexif/exif-byte-order.h> +#include <libexif/exif-data-type.h>  #include <libexif/exif-ifd.h>  #include <libexif/exif-log.h>  #include <libexif/exif-tag.h> @@ -54,8 +55,6 @@ ExifData *exif_data_new_mem       (ExifMem *);  /*! \brief load exif data from file   *  \param[in] path filename including path - *   - *  Foo bar blah bleh baz.   */  ExifData *exif_data_new_from_file (const char *path);  ExifData *exif_data_new_from_data (const unsigned char *data, @@ -74,17 +73,32 @@ ExifByteOrder exif_data_get_byte_order  (ExifData *data);  void          exif_data_set_byte_order  (ExifData *data, ExifByteOrder order);  ExifMnoteData *exif_data_get_mnote_data (ExifData *); +void           exif_data_fix (ExifData *);  typedef void (* ExifDataForeachContentFunc) (ExifContent *, void *user_data);  void          exif_data_foreach_content (ExifData *data,  					 ExifDataForeachContentFunc func,  					 void *user_data); +typedef enum { +	EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS = 1 << 0, +	EXIF_DATA_OPTION_FOLLOW_SPECIFICATION = 1 << 1, +	EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE = 1 << 2 +} ExifDataOption; + +const char *exif_data_option_get_name        (ExifDataOption); +const char *exif_data_option_get_description (ExifDataOption); +void        exif_data_set_option             (ExifData *, ExifDataOption); +void        exif_data_unset_option           (ExifData *, ExifDataOption); + +void         exif_data_set_data_type (ExifData *, ExifDataType); +ExifDataType exif_data_get_data_type (ExifData *); +  /* For debugging purposes and error reporting */  void exif_data_dump (ExifData *data);  void exif_data_log  (ExifData *data, ExifLog *log); -/* For your convenience */ +/** convenience macro. */  #define exif_data_get_entry(d,t)					\  	(exif_content_get_entry(d->ifd[EXIF_IFD_0],t) ?			\  	 exif_content_get_entry(d->ifd[EXIF_IFD_0],t) :			\ diff --git a/src/libexif/exif-entry.c b/src/libexif/exif-entry.c index 09d37e2..02ec510 100644 --- a/src/libexif/exif-entry.c +++ b/src/libexif/exif-entry.c @@ -1,6 +1,6 @@  /* exif-entry.c   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -30,6 +30,7 @@  #include <stdio.h>  #include <string.h>  #include <time.h> +#define _USE_MATH_DEFINES  /* required by MS compilers to define M_PI */  #include <math.h>  struct _ExifEntryPrivate @@ -42,6 +43,7 @@ struct _ExifEntryPrivate  /* This function is hidden in exif-data.c */  ExifLog *exif_data_get_log (ExifData *); +#ifndef NO_VERBOSE_TAG_STRINGS  static void  exif_entry_log (ExifEntry *e, ExifLogCode code, const char *format, ...)  { @@ -54,6 +56,15 @@ exif_entry_log (ExifEntry *e, ExifLogCode code, const char *format, ...)  	exif_logv (l, code, "ExifEntry", format, args);  	va_end (args);  } +#else +#if defined(__STDC_VERSION__) &&  __STDC_VERSION__ >= 199901L +#define exif_entry_log(...) do { } while (0) +#elif defined(__GNUC__) +#define exif_entry_log(x...) do { } while (0) +#else +#define exif_entry_log (void) +#endif +#endif  static void *  exif_entry_alloc (ExifEntry *e, unsigned int i) @@ -199,9 +210,9 @@ exif_entry_fix (ExifEntry *e)  				exif_format_get_size (e->format);  			e->data = exif_entry_realloc (e, e->data, e->size);  			exif_entry_log (e, EXIF_LOG_CODE_DEBUG, -				"Tag '%s' was of format '%s' (which is " +				_("Tag '%s' was of format '%s' (which is "  				"against specification) and has been " -				"changed to format '%s'.", +				"changed to format '%s'."),  				exif_tag_get_name (e->tag),   				exif_format_get_name (EXIF_FORMAT_LONG),  				exif_format_get_name (EXIF_FORMAT_SHORT)); @@ -233,9 +244,9 @@ exif_entry_fix (ExifEntry *e)  			}  			e->format = EXIF_FORMAT_RATIONAL;  			exif_entry_log (e, EXIF_LOG_CODE_DEBUG, -				"Tag '%s' was of format '%s' (which is " +				_("Tag '%s' was of format '%s' (which is "  				"against specification) and has been " -				"changed to format '%s'.", +				"changed to format '%s'."),  				exif_tag_get_name (e->tag),  				exif_format_get_name (EXIF_FORMAT_SRATIONAL),  				exif_format_get_name (EXIF_FORMAT_RATIONAL)); @@ -250,30 +261,18 @@ exif_entry_fix (ExifEntry *e)  		/* Format needs to be UNDEFINED. */  		if (e->format != EXIF_FORMAT_UNDEFINED) {  			exif_entry_log (e, EXIF_LOG_CODE_DEBUG, -				"Tag 'UserComment' had invalid format '%s'. " -				"Format has been set to 'undefined'.", +				_("Tag 'UserComment' had invalid format '%s'. " +				"Format has been set to 'undefined'."),  				exif_format_get_name (e->format));  			e->format = EXIF_FORMAT_UNDEFINED;  		} +  		/* Some packages like Canon ZoomBrowser EX 4.5 store  		   only one zero byte followed by 7 bytes of rubbish */  		if ((e->size >= 8) && (e->data[0] == 0)) {  			memcpy(e->data, "\0\0\0\0\0\0\0\0", 8);  		} -		/* Some cameras fill the tag with '\0' or ' '. */ -		for (i = 0; i < e->size && -			    (!e->data[i] || (e->data[i] == ' ')); i++); -		if (i && (i == e->size)) { -			exif_entry_log (e, EXIF_LOG_CODE_DEBUG, -				"Tag 'UserComment' contained unnecessary " -				"data which has been removed."); -			exif_mem_free (e->priv->mem, e->data); -			e->data = NULL; -			e->size = 0; -			e->components = 0; -		} -  		/* There need to be at least 8 bytes. */  		if (e->size < 8) {  			e->data = exif_entry_realloc (e, e->data, 8 + e->size); @@ -289,9 +288,9 @@ exif_entry_fix (ExifEntry *e)  			e->size += 8;  			e->components += 8;  			exif_entry_log (e, EXIF_LOG_CODE_DEBUG, -				"Tag 'UserComment' has been expanded to at " +				_("Tag 'UserComment' has been expanded to at "  				"least 8 bytes in order to follow the " -				"specification."); +				"specification."));  			break;  		} @@ -300,14 +299,20 @@ exif_entry_fix (ExifEntry *e)  		 * afterwards, let's assume ASCII and claim the 8 first  		 * bytes for the format specifyer.  		 */ -		if (i >= 8) { +		for (i = 0; (i < e->size) && !e->data[i]; i++); +		if (!i) for ( ; (i < e->size) && (e->data[i] == ' '); i++); +		if ((i >= 8) && (i < e->size)) {  			exif_entry_log (e, EXIF_LOG_CODE_DEBUG, -				"Tag 'UserComment' did not start with " +				"Tag 'UserComment' is not empty but does not start with "  				"format identifyer. This has been fixed.");  			memcpy (e->data, "ASCII\0\0\0", 8); +			break;  		} -		/* First 8 bytes need to follow the specification. */ +		/*  +		 * First 8 bytes need to follow the specification. If they don't,  +		 * assume ASCII. +		 */  		if (memcmp (e->data, "ASCII\0\0\0"     , 8) &&  		    memcmp (e->data, "UNICODE\0"       , 8) &&  		    memcmp (e->data, "JIS\0\0\0\0\0"   , 8) && @@ -325,8 +330,8 @@ exif_entry_fix (ExifEntry *e)  			e->size += 8;  			e->components += 8;  			exif_entry_log (e, EXIF_LOG_CODE_DEBUG, -				"Tag 'UserComment' did not start with " -				"format identifyer. This has been fixed."); +				_("Tag 'UserComment' did not start with " +				"format identifier. This has been fixed."));  			break;  		} @@ -384,10 +389,11 @@ exif_entry_dump (ExifEntry *e, unsigned int indent)  	}								\  } -static struct { +static const struct {  	ExifTag tag;  	const char *strings[10];  } list[] = { +#ifndef NO_VERBOSE_TAG_DATA    { EXIF_TAG_PLANAR_CONFIGURATION,      { N_("chunky format"), N_("planar format"), NULL}},    { EXIF_TAG_SENSING_METHOD, @@ -401,7 +407,9 @@ static struct {        N_("right - bottom"), N_("left - bottom"), NULL}},    { EXIF_TAG_YCBCR_POSITIONING,      { "", N_("centered"), N_("co-sited"), NULL}}, -  { EXIF_TAG_PHOTOMETRIC_INTERPRETATION, {"", N_("RGB"), N_("YCbCr"), NULL}}, +  { EXIF_TAG_PHOTOMETRIC_INTERPRETATION, +    {N_("Reversed mono"), N_("Normal mono"), N_("RGB"), N_("Palette"), "", +      N_("CMYK"), N_("YCbCr"), "", N_("CieLAB"), NULL}},    { EXIF_TAG_CUSTOM_RENDERED,      { N_("Normal process"), N_("Custom process"), NULL}},    { EXIF_TAG_EXPOSURE_MODE, @@ -418,16 +426,18 @@ static struct {      { N_("Normal"), N_("Low saturation"), N_("High saturation"), NULL}},    { EXIF_TAG_CONTRAST , {N_("Normal"), N_("Soft"), N_("Hard"), NULL}},    { EXIF_TAG_SHARPNESS, {N_("Normal"), N_("Soft"), N_("Hard"), NULL}}, +#endif    { 0, {NULL}}  }; -static struct { +static const struct {    ExifTag tag;    struct {      int index;      const char *values[4];    } elem[25];  } list2[] = { +#ifndef NO_VERBOSE_TAG_DATA    { EXIF_TAG_METERING_MODE,      { {  0, {N_("Unknown"), NULL}},        {  1, {N_("Average"), N_("avg"), NULL}}, @@ -442,6 +452,9 @@ static struct {      { {1, {N_("Uncompressed"), NULL}},        {5, {N_("LZW compression"), NULL}},        {6, {N_("JPEG compression"), NULL}}, +      {7, {N_("JPEG compression"), NULL}}, +      {8, {N_("Deflate/ZIP compression"), NULL}}, +      {32773, {N_("PackBits compression"), NULL}},        {0, {NULL}}}},    { EXIF_TAG_LIGHT_SOURCE,      { {  0, {N_("Unknown"), NULL}}, @@ -450,7 +463,7 @@ static struct {        {  3, {N_("Tungsten incandescent light"), N_("Tungsten"), NULL}},        {  4, {N_("Flash"), NULL}},        {  9, {N_("Fine weather"), NULL}}, -      { 10, {N_("Cloudy weather"), N_("cloudy"), NULL}}, +      { 10, {N_("Cloudy weather"), N_("Cloudy"), NULL}},        { 11, {N_("Shade"), NULL}},        { 12, {N_("Daylight fluorescent"), NULL}},        { 13, {N_("Day white fluorescent"), NULL}}, @@ -481,7 +494,7 @@ static struct {        {4, {N_("Shutter priority"),N_("Shutter"), NULL}},        {5, {N_("Creative program (biased toward depth of field)"),  	   N_("Creative"), NULL}}, -      {6, {N_("Creative program (biased toward fast shutter speed"), +      {6, {N_("Creative program (biased toward fast shutter speed)"),  	   N_("Action"), NULL}},        {7, {N_("Portrait mode (for closeup photos with the background out "  	      "of focus)"), N_("Portrait"), NULL}}, @@ -494,12 +507,13 @@ static struct {        {0x0005, {N_("Strobe return light not detected."), N_("W/o strobe"),  		NULL}},        {0x0007, {N_("Strobe return light detected."), N_("W. strobe"), NULL}}, -      {0x0009, {N_("Flash fired, compulsatory flash mode"), NULL}}, -      {0x000d, {N_("Flash fired, compulsatory flash mode, return light " +      {0x0008, {N_("Flash did not fire."), NULL}}, /* Olympus E-330 */ +      {0x0009, {N_("Flash fired, compulsory flash mode."), NULL}}, +      {0x000d, {N_("Flash fired, compulsory flash mode, return light "  		   "not detected."), NULL}}, -      {0x000f, {N_("Flash fired, compulsatory flash mode, return light " +      {0x000f, {N_("Flash fired, compulsory flash mode, return light "  		   "detected."), NULL}}, -      {0x0010, {N_("Flash did not fire, compulsatory flash mode."), NULL}}, +      {0x0010, {N_("Flash did not fire, compulsory flash mode."), NULL}},        {0x0018, {N_("Flash did not fire, auto mode."), NULL}},        {0x0019, {N_("Flash fired, auto mode."), NULL}},        {0x001d, {N_("Flash fired, auto mode, return light not detected."), @@ -514,11 +528,11 @@ static struct {        {0x0049, {N_("Flash fired, compulsory flash mode, red-eye reduction "  		   "mode."), NULL}},        {0x004d, {N_("Flash fired, compulsory flash mode, red-eye reduction " -		  "mode, return light not detected"), NULL}}, -      {0x004f, {N_("Flash fired, compulsory flash mode, red-eye reduction, " -		   "return light detected"), NULL}}, -      {0x0058, {N_("Flash did not fire, auto mode, red-eye reduction mode"), NULL}}, -      {0x0059, {N_("Flash fired, auto mode, red-eye reduction mode"), NULL}}, +		  "mode, return light not detected."), NULL}}, +      {0x004f, {N_("Flash fired, compulsory flash mode, red-eye reduction mode, " +		   "return light detected."), NULL}}, +      {0x0058, {N_("Flash did not fire, auto mode, red-eye reduction mode."), NULL}}, +      {0x0059, {N_("Flash fired, auto mode, red-eye reduction mode."), NULL}},        {0x005d, {N_("Flash fired, auto mode, return light not detected, "  		   "red-eye reduction mode."), NULL}},        {0x005f, {N_("Flash fired, auto mode, return light detected, " @@ -527,13 +541,16 @@ static struct {    {EXIF_TAG_SUBJECT_DISTANCE_RANGE,       { {0, {N_("Unknown"), N_("?"), NULL}},        {1, {N_("Macro"), NULL}}, -      {2, {N_("Close view"), N_("close"), NULL}}, -      {3, {N_("Distant view"), N_("distant"), NULL}}, +      {2, {N_("Close view"), N_("Close"), NULL}}, +      {3, {N_("Distant view"), N_("Distant"), NULL}},        {0, {NULL}}}},    { EXIF_TAG_COLOR_SPACE,      { {1, {N_("sRGB"), NULL}}, -      {0xffff, {N_("Uncalibrated"), NULL}}}}, -  {0, } +      {2, {N_("Adobe RGB"), NULL}}, +      {0xffff, {N_("Uncalibrated"), NULL}}, +      {0x0000, {NULL}}}}, +#endif +  {0, { { 0, {NULL}}} }  };  const char * @@ -552,8 +569,8 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  	ExifByteOrder o;  	double d;  	ExifEntry *entry; -	static struct { -		char *label; +	static const struct { +		const char *label;  		char major, minor;  	} versions[] = {  		{"0110", 1,  1}, @@ -566,18 +583,24 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  	};  	/* FIXME: This belongs to somewhere else. */ -	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +	/* libexif should use the default system locale. +	 * If an application specifically requires UTF-8, then we +	 * must give the application a way to tell libexif that. +	 *  +	 * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +	 */  	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); +	/* make sure the returned string is zero terminated */ +	memset (val, 0, maxlen); +	maxlen--; +	memset (b, 0, sizeof (b)); +  	/* We need the byte order */  	if (!e || !e->parent || !e->parent->parent)  		return val;  	o = exif_data_get_byte_order (e->parent->parent); -	memset (val, 0, maxlen); -	memset (b, 0, sizeof (b)); -	maxlen--; -  	/* Sanity check */  	if (e->size != e->components * exif_format_get_size (e->format)) {  		snprintf (val, maxlen, _("Invalid size of entry (%i, " @@ -632,11 +655,11 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		 * Print as much as possible.  		 */  		exif_entry_log (e, EXIF_LOG_CODE_DEBUG, -			"Tag UserComment does not comply " -			"with standard but contains data."); +			_("Tag UserComment does not comply " +			"with standard but contains data."));  		for (; (i < e->size)  && (strlen (val) < maxlen - 1); i++) {  			exif_entry_log (e, EXIF_LOG_CODE_DEBUG, -				"Byte at position %i: 0x%02x", i, e->data[i]); +				_("Byte at position %i: 0x%02x"), i, e->data[i]);  			val[strlen (val)] =  				isprint (e->data[i]) ? e->data[i] : '.';  		} @@ -674,7 +697,7 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		 * Some cameras store a string like "   " here. Ignore it.  		 */  		if (e->size && e->data && -		    (strspn (e->data, " ") != strlen ((char *) e->data))) +		    (strspn ((char *)e->data, " ") != strlen ((char *) e->data)))  			strncpy (val, (char *) e->data, MIN (maxlen, e->size));  		else  			strncpy (val, _("[None]"), maxlen); @@ -682,14 +705,15 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		strncat (val, _("(Photographer)"), maxlen - strlen (val));  		/* Second part: Editor. */ -		t = e->data + strlen ((char *) e->data) + 1; -		ts = e->data + e->size - t;  		strncat (val, " - ", maxlen - strlen (val)); -		if (e->size && e->data && (ts > 0) && -		    (strspn (t, " ") != ts)) -			strncat (val, t, MIN (maxlen - strlen (val), ts)); -		else +		if (e->size && e->data) { +		    t = e->data + strlen ((char *) e->data) + 1; +		    ts = e->data + e->size - t; +		    if ((ts > 0) && (strspn ((char *)t, " ") != ts)) +			strncat (val, (char *)t, MIN (maxlen - strlen (val), ts)); +		} else {  			strncat (val, _("[None]"), maxlen - strlen (val)); +		}  		strncat (val, " ", maxlen - strlen (val));  		strncat (val, _("(Editor)"), maxlen - strlen (val)); @@ -699,17 +723,20 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		CC (e, 1, val, maxlen);  		v_rat = exif_get_rational (e->data, o);  		if (!v_rat.denominator) return val; -		snprintf (val, maxlen, "f/%.01f", (float) v_rat.numerator / -						    (float) v_rat.denominator); +		d = (double) v_rat.numerator / (double) v_rat.denominator; +		snprintf (val, maxlen, "f/%.01lf", d);  		break;  	case EXIF_TAG_APERTURE_VALUE: +	case EXIF_TAG_MAX_APERTURE_VALUE:  		CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);  		CC (e, 1, val, maxlen);  		v_rat = exif_get_rational (e->data, o);  		if (!v_rat.denominator) return val; -		snprintf (val, maxlen, "f/%.01f", -			  pow (2 , ((float) v_rat.numerator / -				    (float) v_rat.denominator) / 2.)); +		d = (double) v_rat.numerator / (double) v_rat.denominator; +		snprintf (val, maxlen, _("%.02lf EV"), d); +		snprintf (b, sizeof (b), _(" (f/%.01f)"), pow (2, d / 2.)); +		if (maxlen > strlen (val) + strlen (b)) +			strncat (val, b, maxlen - strlen (val) - 1);  		break;  	case EXIF_TAG_FOCAL_LENGTH:  		CF (e, EXIF_FORMAT_RATIONAL, val, maxlen); @@ -726,14 +753,14 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		entry = exif_content_get_entry (  			e->parent->parent->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);  		if (entry && entry->data && -		    !strncmp (entry->data, "Minolta", 7)) { +		    !strncmp ((char *)entry->data, "Minolta", 7)) {  			entry = exif_content_get_entry (  					e->parent->parent->ifd[EXIF_IFD_0],  					EXIF_TAG_MODEL);  			if (entry && entry->data) { -				if (!strncmp (entry->data, "DiMAGE 7", 8)) +				if (!strncmp ((char *)entry->data, "DiMAGE 7", 8))  					d = 3.9; -				else if (!strncmp (entry->data, "DiMAGE 5", 8)) +				else if (!strncmp ((char *)entry->data, "DiMAGE 5", 8))  					d = 4.9;  			}  		} @@ -742,8 +769,8 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  				  (int) (d * (double) v_rat.numerator /  				  	     (double) v_rat.denominator)); -		snprintf (val, maxlen, "%.1f mm", -			(float) v_rat.numerator / (float) v_rat.denominator); +		d = (double) v_rat.numerator / (double) v_rat.denominator; +		snprintf (val, maxlen, "%.1lf mm", d);  		if (maxlen > strlen (val) + strlen (b))  			strncat (val, b, maxlen - strlen (val) - 1);  		break; @@ -752,8 +779,8 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		CC (e, 1, val, maxlen);  		v_rat = exif_get_rational (e->data, o);  		if (!v_rat.denominator) return val; -		snprintf (val, maxlen, "%.1f m", (float) v_rat.numerator / -						   (float) v_rat.denominator); +		d = (double) v_rat.numerator / (double) v_rat.denominator; +		snprintf (val, maxlen, "%.1lf m", d);  		break;  	case EXIF_TAG_EXPOSURE_TIME:  		CF (e, EXIF_FORMAT_RATIONAL, val, maxlen); @@ -762,8 +789,7 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		if (!v_rat.denominator) return val;  		d = (double) v_rat.numerator / (double) v_rat.denominator;  		if (d < 1) -			snprintf (val, maxlen, _("1/%d"), -				  (int) (1. / d)); +			snprintf (val, maxlen, _("1/%d"), (int) (0.5 + 1. / d));  		else  			snprintf (val, maxlen, _("%d"), (int) d);  		if (maxlen > strlen (val) + strlen (_(" sec."))) @@ -774,23 +800,32 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		CC (e, 1, val, maxlen);  		v_srat = exif_get_srational (e->data, o);  		if (!v_srat.denominator) return val; -		snprintf (val, maxlen, "%.0f/%.0f", (float) v_srat.numerator, -			  (float) v_srat.denominator); -		if (maxlen > strlen (val) + strlen (_(" sec."))) -			strncat (val, _(" sec."), maxlen - strlen (val) - 1); -		snprintf (b, sizeof (b), " (APEX: %i)", -			(int) pow (sqrt(2), (float) v_srat.numerator / -				            (float) v_srat.denominator)); +		d = (double) v_srat.numerator / (double) v_srat.denominator; +		snprintf (val, maxlen, _("%.02f EV"), d); +		snprintf (b, sizeof (b), " (APEX: %i)", (int) pow (sqrt(2), d));  		if (maxlen > strlen (val) + strlen (b))  			strncat (val, b, maxlen - strlen (val) - 1); +    d = 1. / pow (2, d); +    if (d < 1) +      snprintf (b, sizeof (b), _(" 1/%d sec.)"), (int) (1. / d)); +    else +      snprintf (b, sizeof (b), _(" %d sec.)"), (int) d); +    if (maxlen > strlen (val) + strlen (b)) { +      val[strlen (val) - 1] = ','; +      strncat (val, b, maxlen - strlen (val) - 1); +    }  		break;  	case EXIF_TAG_BRIGHTNESS_VALUE:  		CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);  		CC (e, 1, val, maxlen);  		v_srat = exif_get_srational (e->data, o); -		snprintf (val, maxlen, "%i/%i", (int) v_srat.numerator, -						  (int) v_srat.denominator); -		/* FIXME: How do I calculate the APEX value? */ +		if (!v_srat.denominator) return val; +		d = (double) v_srat.numerator / (double) v_srat.denominator; +		snprintf (val, maxlen, _("%.02f EV"), d); +		snprintf (b, sizeof (b), _(" (%.02f cd/m^2)"), +			1. / (M_PI * 0.3048 * 0.3048) * pow (2, d)); +		if (maxlen > strlen (val) + strlen (b)) +			strncat (val, b, maxlen - strlen (val) - 1);  		break;  	case EXIF_TAG_FILE_SOURCE:  		CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen); @@ -823,10 +858,8 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		CC (e, 1, val, maxlen);  		v_srat = exif_get_srational (e->data, o);  		if (!v_srat.denominator) return val; -		snprintf (val, maxlen, "%s%.01f", -			  v_srat.denominator * v_srat.numerator > 0 ? "+" : "", -			  (double) v_srat.numerator / -			  (double) v_srat.denominator); +		d = (double) v_srat.numerator / (double) v_srat.denominator; +		snprintf (val, maxlen, _("%.02f EV"), d);  		break;  	case EXIF_TAG_YCBCR_SUB_SAMPLING:  		CF (e, EXIF_FORMAT_SHORT, val, maxlen); @@ -842,11 +875,6 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		else  			snprintf (val, maxlen, "%i, %i", v_short, v_short2);  		break; -	case EXIF_TAG_MAKER_NOTE: -		CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen); -		snprintf (val, maxlen, _("%i bytes unknown data"), -			  (int) e->components); -		break;  	case EXIF_TAG_SUBJECT_AREA:  		CF (e, EXIF_FORMAT_SHORT, val, maxlen);  		switch (e->components) { @@ -896,26 +924,26 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		/* Search the tag */  		for (i = 0; list2[i].tag && (list2[i].tag != e->tag); i++);  		if (!list2[i].tag) { -			strncpy (val, "Internal error.", maxlen - 1); +			snprintf (val, maxlen, _("Internal error (unknown " +				  "value %i)"), v_short);  			break;  		}  		/* Find the value */ -		for (j = 0; list2[i].elem[j].values && +		for (j = 0; list2[i].elem[j].values[0] &&  			    (list2[i].elem[j].index < v_short); j++);  		if (list2[i].elem[j].index != v_short) { -			snprintf (val, maxlen, "Internal error (unknown " -				  "value %i).", v_short); +			snprintf (val, maxlen, _("Internal error (unknown " +				  "value %i)"), v_short);  			break;  		}  		/* Find a short enough value */  		memset (val, 0, maxlen); -		for (k = 0; list2[i].elem[j].values && -			    list2[i].elem[j].values[k]; k++) { +		for (k = 0; list2[i].elem[j].values[k]; k++) {  		  l = strlen (_(list2[i].elem[j].values[k]));  		  if ((maxlen > l) && (strlen (val) < l)) -		    strncpy (val, _(list2[i].elem[j].values[k]), maxlen - 1); +		    strncpy (val, _(list2[i].elem[j].values[k]), maxlen);  		}  		if (!strlen (val)) snprintf (val, maxlen, "%i", v_short); @@ -940,7 +968,8 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		/* Search the tag */  		for (i = 0; list[i].tag && (list[i].tag != e->tag); i++);  		if (!list[i].tag) { -			strncpy (val, "Internal error.", maxlen - 1); +			snprintf (val, maxlen, _("Internal error (unknown " +				  "value %i)"), v_short);  			break;  		} @@ -948,13 +977,35 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  		for (j = 0; list[i].strings[j] && (j < v_short); j++);  		if (!list[i].strings[j])  			snprintf (val, maxlen, "%i", v_short); +		else if (!*list[i].strings[j]) +			val[0] = 0;  		else -			strncpy (val, _(list[i].strings[j]), maxlen - 1); -		break; 	 +			strncpy (val, _(list[i].strings[j]), maxlen); +		break; +	case EXIF_TAG_XP_TITLE: +	case EXIF_TAG_XP_COMMENT: +	case EXIF_TAG_XP_AUTHOR: +	case EXIF_TAG_XP_KEYWORDS: +	case EXIF_TAG_XP_SUBJECT: +		/* Warning! The texts are converted from UTF16 to UTF8 */ +		exif_convert_utf16_to_utf8(val, (unsigned short*)e->data, MIN(maxlen, e->size)); +		break; +	case EXIF_TAG_INTEROPERABILITY_VERSION: +		if (e->format == EXIF_FORMAT_UNDEFINED) { +			strncpy (val, (char *) e->data, MIN (maxlen, e->size)); +			break; +		} +		/* Fall through - EXIF_TAG_GPS_LATITUDE is same as INTEROPERABILITY_VERSION */  	default: -		if (!e->components) break; +		if (!e->size) break;  		switch (e->format) {  		case EXIF_FORMAT_UNDEFINED: +			if ((e->tag == EXIF_TAG_SCENE_TYPE) && (e->size == 1)) { +				snprintf (val, maxlen, "%i", e->data[0]); +			} else { +				snprintf (val, maxlen, _("%i bytes undefined data"), +					  e->size); +			}  			break;  		case EXIF_FORMAT_BYTE:  		case EXIF_FORMAT_SBYTE: @@ -1019,20 +1070,29 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  			break;  		case EXIF_FORMAT_RATIONAL:  			v_rat = exif_get_rational (e->data, o); -			if (v_rat.denominator) { -				snprintf (val, maxlen, "%2.2f", (double)v_rat.numerator / v_rat.denominator); -			} else { -				snprintf (val, maxlen, "%i/%i", v_rat.numerator,  v_rat.denominator); -			} +			if (v_rat.denominator) +				snprintf (val, maxlen, "%2.2lf", +				          (double) v_rat.numerator / +					  (double) v_rat.denominator); +			else +				snprintf (val, maxlen, "%2.2lf/%2.2lf", +				          (double) v_rat.numerator, +					  (double) v_rat.denominator);  			maxlen -= strlen (val);  			for (i = 1; i < e->components; i++) {  				v_rat = exif_get_rational (  					e->data + 8 * i, o); -				snprintf (b, sizeof (b), ", %2.2f", -					   (double)v_rat.numerator / v_rat.denominator); +				if (v_rat.denominator) +					snprintf (b, sizeof (b), ", %2.2lf", +					          (double) v_rat.numerator / +					          (double) v_rat.denominator); +				else +					snprintf (b, sizeof (b), ", %2.2lf/%2.2lf", +					          (double) v_rat.numerator, +						  (double) v_rat.denominator);  				strncat (val, b, maxlen);  				maxlen -= strlen (b); -				if ((signed)maxlen <= 0) break; +				if ((signed) maxlen <= 0) break;  			}  			break;  		case EXIF_FORMAT_SRATIONAL: @@ -1064,6 +1124,10 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)  	return val;  } + +/** + * \bug Log and report failed exif_mem_malloc() calls. + */  void  exif_entry_initialize (ExifEntry *e, ExifTag tag)  { @@ -1092,6 +1156,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  		e->format = EXIF_FORMAT_LONG;  		e->size = exif_format_get_size (e->format) * e->components;  		e->data = exif_entry_alloc (e, e->size); +		if (!e->data) break;  		break;  	/* SHORT, 1 component, no default */ @@ -1104,8 +1169,8 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  	case EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM:  	case EXIF_TAG_GAIN_CONTROL:  	case EXIF_TAG_SUBJECT_DISTANCE_RANGE: -	case EXIF_TAG_FLASH:  	case EXIF_TAG_COLOR_SPACE: +	case EXIF_TAG_FLASH:  	/* SHORT, 1 component, default 0 */  	case EXIF_TAG_IMAGE_WIDTH: @@ -1122,36 +1187,40 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  		e->format = EXIF_FORMAT_SHORT;  		e->size = exif_format_get_size (e->format) * e->components;  		e->data = exif_entry_alloc (e, e->size); +		if (!e->data) break;  		exif_set_short (e->data, o, 0);  		break;  	/* SHORT, 1 component, default 1 */ -	case EXIF_TAG_ORIENTATION: -	case EXIF_TAG_PLANAR_CONFIGURATION: -	case EXIF_TAG_YCBCR_POSITIONING: +    case EXIF_TAG_ORIENTATION: +    case EXIF_TAG_PLANAR_CONFIGURATION: +    case EXIF_TAG_YCBCR_POSITIONING:  		e->components = 1;  		e->format = EXIF_FORMAT_SHORT;  		e->size = exif_format_get_size (e->format) * e->components;  		e->data = exif_entry_alloc (e, e->size); +		if (!e->data) break;  		exif_set_short (e->data, o, 1);  		break;  	/* SHORT, 1 component, default 2 */ -	case EXIF_TAG_RESOLUTION_UNIT: +    case EXIF_TAG_RESOLUTION_UNIT:  	case EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT:  		e->components = 1;  		e->format = EXIF_FORMAT_SHORT;  		e->size = exif_format_get_size (e->format) * e->components;  		e->data = exif_entry_alloc (e, e->size); +		if (!e->data) break;  		exif_set_short (e->data, o, 2);  		break;  	/* SHORT, 1 component, default 3 */ -	case EXIF_TAG_SAMPLES_PER_PIXEL: +    case EXIF_TAG_SAMPLES_PER_PIXEL:  		e->components = 1;  		e->format = EXIF_FORMAT_SHORT;  		e->size = exif_format_get_size (e->format) * e->components;  		e->data = exif_entry_alloc (e, e->size); +		if (!e->data) break;  		exif_set_short (e->data, o, 3);  		break; @@ -1198,6 +1267,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  		e->format = EXIF_FORMAT_SRATIONAL;  		e->size = exif_format_get_size (e->format) * e->components;  		e->data = exif_entry_alloc (e, e->size); +		if (!e->data) break;  		break;  	/* RATIONAL, 1 component, no default */ @@ -1218,6 +1288,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  		e->format = EXIF_FORMAT_RATIONAL;  		e->size = exif_format_get_size (e->format) * e->components;  		e->data = exif_entry_alloc (e, e->size); +		if (!e->data) break;  		break;  	/* RATIONAL, 1 component, default 72/1 */ @@ -1227,6 +1298,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  		e->format = EXIF_FORMAT_RATIONAL;  		e->size = exif_format_get_size (e->format) * e->components;  		e->data = exif_entry_alloc (e, e->size); +		if (!e->data) break;  		r.numerator = 72;  		r.denominator = 1;  		exif_set_rational (e->data, o, r); @@ -1238,6 +1310,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  		e->format = EXIF_FORMAT_RATIONAL;  		e->size = exif_format_get_size (e->format) * e->components;  		e->data = exif_entry_alloc (e, e->size); +		if (!e->data) break;  		break;  	/* RATIONAL, 6 components */ @@ -1267,6 +1340,21 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  			e->data + 5 * exif_format_get_size (e->format), o, r);  		break; +	/* EXIF_FORMAT_ASCII, 13 components */ +	case EXIF_TAG_RELATED_SOUND_FILE: +		e->components = 13; +		e->format = EXIF_FORMAT_ASCII; +		e->size = exif_format_get_size (e->format) * e->components; +		e->data = exif_entry_alloc (e, e->size); +		break; + +	case EXIF_TAG_IMAGE_UNIQUE_ID: +		e->components = 33; +		e->format = EXIF_FORMAT_ASCII; +		e->size = exif_format_get_size (e->format) * e->components; +		e->data = exif_entry_alloc (e, e->size); +		break; +  	/* ASCII, 20 components, default current time */  	case EXIF_TAG_DATE_TIME:  	case EXIF_TAG_DATE_TIME_ORIGINAL: @@ -1284,21 +1372,6 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  			  tm->tm_hour, tm->tm_min, tm->tm_sec);  		break; -	/* EXIF_FORMAT_ASCII, 13 components */ -	case EXIF_TAG_RELATED_SOUND_FILE: -		e->components = 13; -		e->format = EXIF_FORMAT_ASCII; -		e->size = exif_format_get_size (e->format) * e->components; -		e->data = exif_entry_alloc (e, e->size); -		break; - -	case EXIF_TAG_IMAGE_UNIQUE_ID: -		e->components = 33; -		e->format = EXIF_FORMAT_ASCII; -		e->size = exif_format_get_size (e->format) * e->components; -		e->data = exif_entry_alloc (e, e->size); -		break; -  	/* ASCII, any components, no default */  	case EXIF_TAG_SPECTRAL_SENSITIVITY:  	case EXIF_TAG_SUB_SEC_TIME: @@ -1317,12 +1390,14 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  		break;  	/* UNDEFINED, no components, no default */ +	/* Use this if the tag is otherwise unsupported */  	case EXIF_TAG_OECF:											   	case EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE:  	case EXIF_TAG_NEW_CFA_PATTERN:					   	case EXIF_TAG_DEVICE_SETTING_DESCRIPTION:  	case EXIF_TAG_MAKER_NOTE:  	case EXIF_TAG_USER_COMMENT: +	default:  		e->components = 0;  		e->format = EXIF_FORMAT_UNDEFINED;  		e->size = 0; @@ -1350,24 +1425,24 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  		break;  	/* UNDEFINED, 4 components, default 0 1 0 0 */ -	case EXIF_TAG_FLASH_PIX_VERSION: -		e->components = 4; -		e->format = EXIF_FORMAT_UNDEFINED; -		e->size = exif_format_get_size (e->format) * e->components; -		e->data = exif_entry_alloc (e, e->size); +        case EXIF_TAG_FLASH_PIX_VERSION: +                e->components = 4; +                e->format = EXIF_FORMAT_UNDEFINED; +                e->size = exif_format_get_size (e->format) * e->components; +                e->data = exif_entry_alloc (e, e->size);  		if (!e->data) break; -			memcpy (e->data, "0100", 4); -		break; - -	/* UNDEFINED, 4 components, default 0 2 1 0 */ -	case EXIF_TAG_EXIF_VERSION: -		e->components = 4; -		e->format = EXIF_FORMAT_UNDEFINED; -		e->size = exif_format_get_size (e->format) * e->components; -		e->data = exif_entry_alloc (e, e->size); +                memcpy (e->data, "0100", 4); +                break; + +        /* UNDEFINED, 4 components, default 0 2 1 0 */ +        case EXIF_TAG_EXIF_VERSION: +                e->components = 4; +                e->format = EXIF_FORMAT_UNDEFINED; +                e->size = exif_format_get_size (e->format) * e->components; +                e->data = exif_entry_alloc (e, e->size);  		if (!e->data) break; -			memcpy (e->data, "0210", 4); -		break; +                memcpy (e->data, "0210", 4); +                break;  	/* UNDEFINED, 4 components, no default */  	case EXIF_TAG_COMPONENTS_CONFIGURATION: @@ -1377,7 +1452,5 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)  		e->data = malloc (e->size);  		break; -	default: -		break;  	}  } diff --git a/src/libexif/exif-entry.h b/src/libexif/exif-entry.h index 072ee29..23731fe 100644 --- a/src/libexif/exif-entry.h +++ b/src/libexif/exif-entry.h @@ -1,6 +1,7 @@ -/* exif-entry.h +/*! \file exif-entry.h + *  \brief Handling EXIF entries   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -32,6 +33,7 @@ typedef struct _ExifEntryPrivate ExifEntryPrivate;  #include <libexif/exif-format.h>  #include <libexif/exif-mem.h> +/*! */  struct _ExifEntry {          ExifTag tag;          ExifFormat format; @@ -47,21 +49,44 @@ struct _ExifEntry {  };  /* Lifecycle */ + +/*! Reserve memory for and initialize new #ExifEntry* */  ExifEntry  *exif_entry_new     (void); +  ExifEntry  *exif_entry_new_mem (ExifMem *); + +/*! Increase reference counter for #ExifEntry* */  void        exif_entry_ref     (ExifEntry *entry); + +/*! Decrease reference counter for #ExifEntry* */  void        exif_entry_unref   (ExifEntry *entry); + +/*! Actually free the #ExifEntry* + * + * \deprecated Should not be called directly. Use exif_entry_ref() and + *             exif_entry_unref() instead. + */  void        exif_entry_free  (ExifEntry *entry);  void        exif_entry_initialize (ExifEntry *entry, ExifTag tag);  void        exif_entry_fix        (ExifEntry *entry);  /* For your convenience */ + +/*! Return the value of the EXIF entry + * + * CAUTION: The character set of the returned string is not defined. + *          It may be UTF-8, latin1, the native encoding of the + *          computer, or the native encoding of the camera. + */  const char *exif_entry_get_value (ExifEntry *entry, char *val,  				  unsigned int maxlen); +/*! Dump text representation of #ExifEntry to stdout */  void        exif_entry_dump      (ExifEntry *entry, unsigned int indent); +#define exif_entry_get_ifd(e) ((e)?exif_content_get_ifd((e)->parent):EXIF_IFD_COUNT) +  #ifdef __cplusplus  }  #endif /* __cplusplus */ diff --git a/src/libexif/exif-format.c b/src/libexif/exif-format.c index e0c3650..d432e9e 100644 --- a/src/libexif/exif-format.c +++ b/src/libexif/exif-format.c @@ -1,6 +1,6 @@  /* exif-format.c   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@  #include <stdlib.h> -static struct { +static const struct {          ExifFormat format;  	const char *name;          unsigned char size; @@ -51,7 +51,12 @@ exif_format_get_name (ExifFormat format)  	unsigned int i;  	/* FIXME: This belongs to somewhere else. */ -	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +	/* libexif should use the default system locale. +	 * If an application specifically requires UTF-8, then we +	 * must give the application a way to tell libexif that. +	 *  +	 * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +	 */  	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);  	for (i = 0; ExifFormatTable[i].name; i++) diff --git a/src/libexif/exif-format.h b/src/libexif/exif-format.h index 0eae425..272c865 100644 --- a/src/libexif/exif-format.h +++ b/src/libexif/exif-format.h @@ -1,6 +1,6 @@  /* exif-format.h   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public diff --git a/src/libexif/exif-ifd.c b/src/libexif/exif-ifd.c index 96de261..7240dce 100644 --- a/src/libexif/exif-ifd.c +++ b/src/libexif/exif-ifd.c @@ -1,6 +1,6 @@  /* exif-ifd.c   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,7 @@  #include <stdlib.h> -static struct { +static const struct {  	ExifIfd ifd;  	const char *name;  } ExifIfdTable[] = { diff --git a/src/libexif/exif-ifd.h b/src/libexif/exif-ifd.h index 01f0019..48d2083 100644 --- a/src/libexif/exif-ifd.h +++ b/src/libexif/exif-ifd.h @@ -1,6 +1,6 @@  /* exif-ifd.h   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -22,12 +22,12 @@  #define __EXIF_IFD_H__  typedef enum { -	EXIF_IFD_0 = 0, -	EXIF_IFD_1, -	EXIF_IFD_EXIF, -	EXIF_IFD_GPS, -	EXIF_IFD_INTEROPERABILITY, -	EXIF_IFD_COUNT +	EXIF_IFD_0 = 0,                /*!< */ +	EXIF_IFD_1,                    /*!< */ +	EXIF_IFD_EXIF,                 /*!< */ +	EXIF_IFD_GPS,                  /*!< */ +	EXIF_IFD_INTEROPERABILITY,     /*!< */ +	EXIF_IFD_COUNT                 /*!< Not a real value, just (max_value + 1). */  } ExifIfd;  const char *exif_ifd_get_name (ExifIfd ifd); diff --git a/src/libexif/exif-loader.c b/src/libexif/exif-loader.c index d6eba7d..4e5b140 100644 --- a/src/libexif/exif-loader.c +++ b/src/libexif/exif-loader.c @@ -1,18 +1,46 @@ +/* exif-loader.c + * + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful,  + * but WITHOUT ANY WARRANTY; without even the implied warranty of  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.  + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +  #include <config.h>  #include <libexif/exif-loader.h> +#include <libexif/exif-utils.h>  #include <libexif/i18n.h> +#include <sys/types.h>  #include <stdlib.h>  #include <string.h>  #include <stdio.h> +#undef JPEG_MARKER_DHT +#define JPEG_MARKER_DHT  0xc4  #undef JPEG_MARKER_SOI  #define JPEG_MARKER_SOI  0xd8 +#undef JPEG_MARKER_DQT +#define JPEG_MARKER_DQT  0xdb  #undef JPEG_MARKER_APP0  #define JPEG_MARKER_APP0 0xe0  #undef JPEG_MARKER_APP1  #define JPEG_MARKER_APP1 0xe1 +#undef JPEG_MARKER_APP2 +#define JPEG_MARKER_APP2 0xe2  #undef JPEG_MARKER_APP13  #define JPEG_MARKER_APP13 0xed  #undef JPEG_MARKER_COM @@ -60,10 +88,12 @@ exif_loader_alloc (ExifLoader *l, unsigned int i)  {  	void *d; -	if (!l || !i) return NULL; +	if (!l || !i)  +		return NULL;  	d = exif_mem_alloc (l->mem, i); -	if (d) return d; +	if (d)  +		return d;  	EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i);  	return NULL; @@ -79,7 +109,8 @@ exif_loader_write_file (ExifLoader *l, const char *path)  	int size;  	unsigned char data[1024]; -	if (!l) return; +	if (!l)  +		return;  	f = fopen (path, "rb");  	if (!f) { @@ -89,8 +120,10 @@ exif_loader_write_file (ExifLoader *l, const char *path)  	}  	while (1) {  		size = fread (data, 1, sizeof (data), f); -		if (size <= 0) break; -		if (!exif_loader_write (l, data, size)) break; +		if (size <= 0)  +			break; +		if (!exif_loader_write (l, data, size))  +			break;  	}  	fclose (f);  } @@ -98,11 +131,14 @@ exif_loader_write_file (ExifLoader *l, const char *path)  static unsigned int  exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len)  { -	if (!eld || (len && !buf) || (eld->bytes_read >= eld->size)) return 0; +	if (!eld || (len && !buf) || (eld->bytes_read >= eld->size))  +		return 0;  	/* If needed, allocate the buffer. */ -	if (!eld->buf) eld->buf = exif_loader_alloc (eld, eld->size); -	if (!eld->buf) return 0; +	if (!eld->buf)  +		eld->buf = exif_loader_alloc (eld, eld->size); +	if (!eld->buf)  +		return 0;  	/* Copy memory */  	len = MIN (len, eld->size - eld->bytes_read); @@ -117,13 +153,17 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)  {  	unsigned int i; -	if (!eld || (len && !buf)) return 0; +	if (!eld || (len && !buf))  +		return 0;  	switch (eld->state) {  	case EL_EXIF_FOUND:  		return exif_loader_copy (eld, buf, len);  	case EL_SKIP_BYTES: -		if (eld->size > len) { eld->size -= len; return 1; } +		if (eld->size > len) {  +			eld->size -= len;  +			return 1;  +		}  		len -= eld->size;  		buf += eld->size;  		eld->size = 0; @@ -141,6 +181,8 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)  		break;  	} +	if (!len) +		return 1;  	exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",  		  "Scanning %i byte(s) of data...", len); @@ -152,7 +194,8 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)  	if (i) {  		memcpy (&eld->b[eld->b_len], buf, i);  		eld->b_len += i; -		if (eld->b_len < sizeof (eld->b)) return 1; +		if (eld->b_len < sizeof (eld->b))  +			return 1;  		buf += i;  		len -= i;  	} @@ -183,11 +226,13 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)  		switch (eld->state) {  		case EL_EXIF_FOUND:  			if (!exif_loader_copy (eld, eld->b + i, -					sizeof (eld->b) - i)) return 0; +					sizeof (eld->b) - i))  +				return 0;  			return exif_loader_copy (eld, buf, len);  		case EL_SKIP_BYTES:  			eld->size--; -			if (!eld->size) eld->state = EL_READ; +			if (!eld->size)  +				eld->state = EL_READ;  			break;  		case EL_READ_SIZE_BYTE_24: @@ -225,11 +270,18 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)  		default:  			switch (eld->b[i]) {  			case JPEG_MARKER_APP1: -				eld->data_format = EL_DATA_FORMAT_EXIF; +			  if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) { +					eld->data_format = EL_DATA_FORMAT_EXIF; +				} else { +					eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/ +				}  				eld->size = 0;  				eld->state = EL_READ_SIZE_BYTE_08;  				break; +			case JPEG_MARKER_DHT: +			case JPEG_MARKER_DQT:  			case JPEG_MARKER_APP0: +			case JPEG_MARKER_APP2:  			case JPEG_MARKER_APP13:  			case JPEG_MARKER_COM:  				eld->data_format = EL_DATA_FORMAT_JPEG; @@ -274,10 +326,12 @@ exif_loader_new_mem (ExifMem *mem)  {  	ExifLoader *loader; -	if (!mem) return NULL; +	if (!mem)  +		return NULL;  	loader = exif_mem_alloc (mem, sizeof (ExifLoader)); -	if (!loader) return NULL; +	if (!loader)  +		return NULL;  	loader->ref_count = 1;  	loader->mem = mem; @@ -289,7 +343,8 @@ exif_loader_new_mem (ExifMem *mem)  void  exif_loader_ref (ExifLoader *loader)  { -	if (loader) loader->ref_count++; +	if (loader)  +		loader->ref_count++;  }  static void @@ -297,10 +352,12 @@ exif_loader_free (ExifLoader *loader)  {  	ExifMem *mem; -	if (!loader) return; +	if (!loader)  +		return;  	mem = loader->mem;  	exif_loader_reset (loader); +	exif_log_unref (loader->log);  	exif_mem_free (mem, loader);  	exif_mem_unref (mem);  } @@ -308,7 +365,8 @@ exif_loader_free (ExifLoader *loader)  void  exif_loader_unref (ExifLoader *loader)  { -	if (!loader) return; +	if (!loader)  +		return;  	if (!--loader->ref_count)  		exif_loader_free (loader);  } @@ -316,7 +374,8 @@ exif_loader_unref (ExifLoader *loader)  void  exif_loader_reset (ExifLoader *loader)  { -	if (!loader) return; +	if (!loader)  +		return;  	exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;  	loader->size = 0;  	loader->bytes_read = 0; @@ -330,7 +389,9 @@ exif_loader_get_data (ExifLoader *loader)  {  	ExifData *ed; -	if (!loader) return NULL; +	if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN) || +	    !loader->bytes_read) +		return NULL;  	ed = exif_data_new_mem (loader->mem);  	exif_data_log (ed, loader->log); @@ -342,7 +403,8 @@ exif_loader_get_data (ExifLoader *loader)  void  exif_loader_log (ExifLoader *loader, ExifLog *log)  { -	if (!loader) return; +	if (!loader)  +		return;  	exif_log_unref (loader->log);  	loader->log = log;  	exif_log_ref (log); diff --git a/src/libexif/exif-loader.h b/src/libexif/exif-loader.h index cf900c8..697e019 100644 --- a/src/libexif/exif-loader.h +++ b/src/libexif/exif-loader.h @@ -1,6 +1,8 @@ -/* exif-loader.h - * - * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net> +/*! \file exif-loader.h + * \brief Defines the ExifLoader type + */ +/* + * Copyright (c) 2003 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -22,7 +24,6 @@  #define __EXIF_LOADER_H__  #include <libexif/exif-data.h> -#include <libexif/exif-loader.h>  #include <libexif/exif-log.h>  #include <libexif/exif-mem.h> @@ -32,21 +33,48 @@ extern "C" {  typedef struct _ExifLoader ExifLoader; +/*! Allocate a new ExifLoader + *  \returns the allocated ExifLoader + */  ExifLoader *exif_loader_new     (void); -ExifLoader *exif_loader_new_mem (ExifMem *); -void        exif_loader_ref     (ExifLoader *); -void        exif_loader_unref   (ExifLoader *); +/*! Allocate a new ExifLoader using an ExifMem + *  \param[in] mem the ExifMem + *  \returns the allocated ExifLoader + */ +ExifLoader *exif_loader_new_mem (ExifMem *mem); +/*! Increase the refcount of the ExifLoader + *  \param[in] loader the ExifLoader to increase the refcount of. + */ +void        exif_loader_ref     (ExifLoader *loader); +/*! Decrease the refcount of the ExifLoader + *  \param[in] loader the ExifLoader to decrease the refcount of. + *  If the refcount reaches 0, the ExifLoader is freeed. + */ +void        exif_loader_unref   (ExifLoader *loader); -void        exif_loader_write_file (ExifLoader *, const char *fname); +/*! Write a file to the ExifLoader + * \param[in] loader the loader + * \param[in] fname the path to the file to read + */ +void        exif_loader_write_file (ExifLoader *loader, const char *fname); -/* - * Returns 1 while EXIF data is read (or while there is still  - * hope that there will be EXIF data later on), 0 otherwise. +/*! Write a buffer to the ExifLoader + * \param[in] loader the loader to write too + * \param[in] buf the buffer to read from + * \param[in] sz the size of the buffer + * \returns 1 while EXIF data is read (or while there is still hope that there will be EXIF data later on), 0 otherwise.   */ -unsigned char exif_loader_write (ExifLoader *, unsigned char *, unsigned int); +unsigned char exif_loader_write (ExifLoader *loader, unsigned char *buf, unsigned int sz); -void          exif_loader_reset (ExifLoader *); -ExifData     *exif_loader_get_data (ExifLoader *); +/*! Reset the ExifLoader + * \param[in] loader the loader + */ +void          exif_loader_reset (ExifLoader *loader); +/*! Get an ExifData out of an ExifLoader + * \param[in] loader the loader + * \returns and allocated ExifData + */ +ExifData     *exif_loader_get_data (ExifLoader *loader);  void exif_loader_log (ExifLoader *, ExifLog *); diff --git a/src/libexif/exif-log.c b/src/libexif/exif-log.c index 5dde1ce..195bfe2 100644 --- a/src/libexif/exif-log.c +++ b/src/libexif/exif-log.c @@ -1,6 +1,6 @@  /* exif-log.c   * - * Copyright © 2004 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2004 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -35,7 +35,7 @@ struct _ExifLog {  	ExifMem *mem;  }; -static struct { +static const struct {  	ExifLogCode code;  	const char *title;  	const char *message; @@ -127,6 +127,10 @@ exif_log_set_func (ExifLog *log, ExifLogFunc func, void *data)  	log->data = data;  } +#ifdef NO_VERBOSE_TAG_STRINGS +/* exif_log forms part of the API and can't be commented away */ +#undef exif_log +#endif  void  exif_log (ExifLog *log, ExifLogCode code, const char *domain,  	  const char *format, ...) diff --git a/src/libexif/exif-log.h b/src/libexif/exif-log.h index 01eed3f..41f4bcf 100644 --- a/src/libexif/exif-log.h +++ b/src/libexif/exif-log.h @@ -1,7 +1,7 @@  /*! \file exif-log.h   *  \brief log message infrastructure   * - * Copyright © 2004 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2004 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -55,18 +55,28 @@ typedef void (* ExifLogFunc) (ExifLog *log, ExifLogCode, const char *domain,   */  void     exif_log_set_func (ExifLog *log, ExifLogFunc func, void *data); +#ifndef NO_VERBOSE_TAG_STRINGS  void     exif_log  (ExifLog *log, ExifLogCode, const char *domain,  		    const char *format, ...)  #ifdef __GNUC__  			__attribute__((__format__(printf,4,5)))  #endif  ; +#else +#if defined(__STDC_VERSION__) &&  __STDC_VERSION__ >= 199901L +#define exif_log(...) do { } while (0) +#elif defined(__GNUC__) +#define exif_log(x...) do { } while (0) +#else +#define exif_log (void) +#endif +#endif  void     exif_logv (ExifLog *log, ExifLogCode, const char *domain,  		    const char *format, va_list args);  /* For your convenience */ -#define EXIF_LOG_NO_MEMORY(l,d,s) exif_log (l, EXIF_LOG_CODE_NO_MEMORY, d, "Could not allocate %i byte(s).", s) +#define EXIF_LOG_NO_MEMORY(l,d,s) exif_log ((l), EXIF_LOG_CODE_NO_MEMORY, (d), "Could not allocate %lu byte(s).", (unsigned long)(s))  #ifdef __cplusplus  } diff --git a/src/libexif/exif-mem.c b/src/libexif/exif-mem.c index 12027d1..7290b9d 100644 --- a/src/libexif/exif-mem.c +++ b/src/libexif/exif-mem.c @@ -33,7 +33,8 @@ exif_mem_new (ExifMemAllocFunc alloc_func, ExifMemReallocFunc realloc_func,  {  	ExifMem *mem; -	if (!alloc_func || !realloc_func) return NULL; +	if (!alloc_func && !realloc_func)  +		return NULL;  	mem = alloc_func ? alloc_func (sizeof (ExifMem)) :  		           realloc_func (NULL, sizeof (ExifMem));  	if (!mem) return NULL; diff --git a/src/libexif/exif-mem.h b/src/libexif/exif-mem.h index aa774c6..454e034 100644 --- a/src/libexif/exif-mem.h +++ b/src/libexif/exif-mem.h @@ -1,6 +1,11 @@ +/*! \file exif-mem.h + *  \brief Define the ExifMem data type and the associated functions. + *  ExifMem defines the memory management functions used by the ExifLoader. + */ +  /* exif-mem.h   * - * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2003 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -27,24 +32,49 @@  extern "C" {  #endif /* __cplusplus */ -/* Should work like calloc: Needs to return initialized memory. */ -typedef void * (* ExifMemAllocFunc)   (ExifLong); +/*! Should work like calloc() + *  \param[in] s the size of the block to allocate. + *  \returns the allocated memory and initialized.  + */ +typedef void * (* ExifMemAllocFunc)   (ExifLong s); -typedef void * (* ExifMemReallocFunc) (void *, ExifLong); -typedef void   (* ExifMemFreeFunc)    (void *); +/*! Should work like realloc() + * \param[in] p the pointer to reallocate + * \param[in] s the size of the reallocated block + * \returns allocated memory  + */ +typedef void * (* ExifMemReallocFunc) (void *p, ExifLong s); +/*! Free method for ExifMem + * \param[in] p the pointer to free + * \returns the freed pointer + */ +typedef void   (* ExifMemFreeFunc)    (void *p); +/*! ExifMem define a memory allocator */  typedef struct _ExifMem ExifMem; -ExifMem *exif_mem_new   (ExifMemAllocFunc, ExifMemReallocFunc, -			 ExifMemFreeFunc); +/*! Create a new ExifMem + * \param[in] a the allocator function + * \param[in] r the reallocator function + * \param[in] f the free function + */ +ExifMem *exif_mem_new   (ExifMemAllocFunc a, ExifMemReallocFunc r, +			 ExifMemFreeFunc f); +/*! Refcount an ExifMem + */  void     exif_mem_ref   (ExifMem *); +/*! Unrefcount an ExifMem + * If the refcount reaches 0, the ExifMem is freed + */  void     exif_mem_unref (ExifMem *); -void *exif_mem_alloc   (ExifMem *, ExifLong); -void *exif_mem_realloc (ExifMem *, void *, ExifLong); -void  exif_mem_free    (ExifMem *, void *); +void *exif_mem_alloc   (ExifMem *m, ExifLong s); +void *exif_mem_realloc (ExifMem *m, void *p, ExifLong s); +void  exif_mem_free    (ExifMem *m, void *p); -/* For your convenience */ +/*! The default ExifMem for your convenience + * \returns return the default ExifMem + */  ExifMem *exif_mem_new_default (void);  #ifdef __cplusplus diff --git a/src/libexif/exif-mnote-data-priv.h b/src/libexif/exif-mnote-data-priv.h index 3a13883..f8e5317 100644 --- a/src/libexif/exif-mnote-data-priv.h +++ b/src/libexif/exif-mnote-data-priv.h @@ -1,6 +1,6 @@  /* exif-mnote-data-priv.h   * - * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2003 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public diff --git a/src/libexif/exif-mnote-data.c b/src/libexif/exif-mnote-data.c index f55cdd4..efd8173 100644 --- a/src/libexif/exif-mnote-data.c +++ b/src/libexif/exif-mnote-data.c @@ -1,6 +1,6 @@  /* exif-mnote-data.c   * - * Copyright (C) 2003 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (C) 2003 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public diff --git a/src/libexif/exif-mnote-data.h b/src/libexif/exif-mnote-data.h index 015f2ae..7c68393 100644 --- a/src/libexif/exif-mnote-data.h +++ b/src/libexif/exif-mnote-data.h @@ -1,6 +1,6 @@  /* exif-mnote-data.h   * - * Copyright © 2003 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2003 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public diff --git a/src/libexif/exif-system.h b/src/libexif/exif-system.h new file mode 100644 index 0000000..082db60 --- /dev/null +++ b/src/libexif/exif-system.h @@ -0,0 +1,31 @@ +/** \file exif-system.h + * \brief System specific definitions, not for installation! + * + * Copyright (C) 2007 Hans Ulrich Niedermann <gp@n-dimensional.de> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful,  + * but WITHOUT ANY WARRANTY; without even the implied warranty of  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.  + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef EXIF_SYSTEM_H +#define EXIF_SYSTEM_H + +#if defined(__GNUC__) && (__GNUC__ >= 2) +# define UNUSED(param) UNUSED_PARAM_##param __attribute__((unused)) +#else +# define UNUSED(param) param +#endif + +#endif /* !defined(EXIF_SYSTEM_H) */ diff --git a/src/libexif/exif-tag.c b/src/libexif/exif-tag.c index 7781611..7a8c7e1 100644 --- a/src/libexif/exif-tag.c +++ b/src/libexif/exif-tag.c @@ -1,6 +1,6 @@  /* exif-tag.c   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -26,22 +26,28 @@  #include <stdlib.h>  #include <string.h> -typedef enum { -	ESL_MANDATORY    = 1, /* Mandatory               */ -	ESL_CMANDATORY   = 2, /* Conditionally mandatory */ -	ESL_OPTIONAL     = 3, /* Optional                */ -	ESL_NOT_RECORDED = 4  /* Not recorded            */ -} ExifSL;                     /* Exif Support Level      */ +#define ESL_NNNN { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED } +#define ESL_OOOO { EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL } +#define ESL_MMMN { EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_NOT_RECORDED } +#define ESL_MMMM { EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY } +#define ESL_OMON { EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_NOT_RECORDED } +#define ESL_NNOO { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL } +#define ESL_NNMN { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_NOT_RECORDED } +#define ESL_NNMM { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY } +#define ESL_NNNM { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_MANDATORY } +#define ESL_NNNO { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_OPTIONAL } +#define ESL_GPS { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN } -static struct { +static const struct {  	ExifTag tag;  	const char *name;  	const char *title;  	const char *description; -	ExifSL esl_0[4], esl_1[4], esl_exif[4], esl_gps[4]; +	ExifSupportLevel esl[EXIF_IFD_COUNT][4];  } ExifTagTable[] = { +#ifndef NO_VERBOSE_TAG_STRINGS  	{EXIF_TAG_NEW_SUBFILE_TYPE, "NewSubfileType", -	 "New Subfile Type", N_("A general indication of the kind of data " +	 N_("New Subfile Type"), N_("A general indication of the kind of data "  	    "contained in this subfile.")},  	{EXIF_TAG_INTEROPERABILITY_INDEX, "InteroperabilityIndex",  	 "InteroperabilityIndex", @@ -49,35 +55,37 @@ static struct {  	    "Use \"R98\" for stating ExifR98 Rules. Four bytes used "  	    "including the termination code (NULL). see the separate "  	    "volume of Recommended Exif Interoperability Rules (ExifR98) " -	    "for other tags used for ExifR98.")}, +	    "for other tags used for ExifR98."), +	 { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_OOOO } },  	{EXIF_TAG_INTEROPERABILITY_VERSION, "InteroperabilityVersion", -	 "InteroperabilityVersion", ""}, +	 "InteroperabilityVersion", "", +	 { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_OOOO } },  	{EXIF_TAG_IMAGE_WIDTH, "ImageWidth", N_("Image Width"),  	 N_("The number of columns of image data, equal to the number of "  	    "pixels per row. In JPEG compressed data a JPEG marker is "  	    "used instead of this tag."), -	 {ESL_MANDATORY, ESL_MANDATORY, ESL_MANDATORY, ESL_NOT_RECORDED}}, +	 { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_IMAGE_LENGTH, "ImageLength", N_("Image Length"),  	 N_("The number of rows of image data. In JPEG compressed data a "  	    "JPEG marker is used instead of this tag."),  -	 {ESL_MANDATORY, ESL_MANDATORY, ESL_MANDATORY, ESL_NOT_RECORDED}}, +	 { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_BITS_PER_SAMPLE, "BitsPerSample", N_("Bits per Sample"),  	 N_("The number of bits per image component. In this standard each "  	    "component of the image is 8 bits, so the value for this " -	    "tag is 9. See also <SamplesPerPixel>. In JPEG compressed data " +	    "tag is 8. See also <SamplesPerPixel>. In JPEG compressed data "  	    "a JPEG marker is used instead of this tag."), -	 {ESL_MANDATORY, ESL_MANDATORY, ESL_MANDATORY, ESL_NOT_RECORDED}}, +	 { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_COMPRESSION, "Compression", N_("Compression"),  	 N_("The compression scheme used for the image data. When a "  	    "primary image is JPEG compressed, this designation is "  	    "not necessary and is omitted. When thumbnails use JPEG "  	    "compression, this tag value is set to 6."), -	 {ESL_MANDATORY, ESL_MANDATORY, ESL_MANDATORY, ESL_NOT_RECORDED}}, +	 { ESL_MMMN, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_PHOTOMETRIC_INTERPRETATION, "PhotometricInterpretation",  	 N_("Photometric Interpretation"),  	 N_("The pixel composition. In JPEG compressed data a JPEG "  	    "marker is used instead of this tag."), -	 {ESL_MANDATORY, ESL_MANDATORY, ESL_MANDATORY, ESL_NOT_RECORDED}}, +	 { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_FILL_ORDER, "FillOrder", N_("Fill Order"), ""},  	{EXIF_TAG_DOCUMENT_NAME, "DocumentName", N_("Document Name"), ""},  	{EXIF_TAG_IMAGE_DESCRIPTION, "ImageDescription", @@ -87,92 +95,105 @@ static struct {  	    "the like. Two-bytes character codes cannot be used. "  	    "When a 2-bytes code is necessary, the Exif Private tag "  	    "<UserComment> is to be used."), -	 {ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY}}, +	 { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_MAKE, "Make", N_("Manufacturer"),  	 N_("The manufacturer of the recording "  	    "equipment. This is the manufacturer of the DSC, scanner, "  	    "video digitizer or other equipment that generated the "  	    "image. When the field is left blank, it is treated as "  	    "unknown."), -	 {ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY}}, +	 { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN }},  	{EXIF_TAG_MODEL, "Model", N_("Model"),  	 N_("The model name or model number of the equipment. This is the "  	    "model name or number of the DSC, scanner, video digitizer "  	    "or other equipment that generated the image. When the field "  	    "is left blank, it is treated as unknown."), -	 {ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY}}, +	 { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_STRIP_OFFSETS, "StripOffsets", N_("Strip Offsets"),  	 N_("For each strip, the byte offset of that strip. It is "  	    "recommended that this be selected so the number of strip "  	    "bytes does not exceed 64 Kbytes. With JPEG compressed "  	    "data this designation is not needed and is omitted. See also "  	    "<RowsPerStrip> and <StripByteCounts>."), -	 {ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY}}, +	 { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_ORIENTATION, "Orientation", N_("Orientation"),  	 N_("The image orientation viewed in terms of rows and columns."), -	 {ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY, ESL_CMANDATORY}}, +	 { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_SAMPLES_PER_PIXEL, "SamplesPerPixel",  	 N_("Samples per Pixel"),  	 N_("The number of components per pixel. Since this standard applies "  	    "to RGB and YCbCr images, the value set for this tag is 3. "  	    "In JPEG compressed data a JPEG marker is used instead of this " -	    "tag.")}, +	    "tag."),  +	 { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_ROWS_PER_STRIP, "RowsPerStrip", N_("Rows per Strip"),  	 N_("The number of rows per strip. This is the number of rows "  	    "in the image of one strip when an image is divided into "  	    "strips. With JPEG compressed data this designation is not " -	    "needed and is omitted. See also <RowsPerStrip> and " -	    "<StripByteCounts>.")}, +	    "needed and is omitted. See also <StripOffsets> and " +	    "<StripByteCounts>."), +	 { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_STRIP_BYTE_COUNTS, "StripByteCounts", N_("Strip Byte Count"),  	 N_("The total number of bytes in each strip. With JPEG compressed " -	    "data this designation is not needed and is omitted.")}, +	    "data this designation is not needed and is omitted."), +	 { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_X_RESOLUTION, "XResolution", N_("x-Resolution"),  	 N_("The number of pixels per <ResolutionUnit> in the <ImageWidth> "  	    "direction. When the image resolution is unknown, 72 [dpi] " -	    "is designated.")}, +	    "is designated."), +	 { ESL_MMMM, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_Y_RESOLUTION, "YResolution", N_("y-Resolution"),  	 N_("The number of pixels per <ResolutionUnit> in the <ImageLength> " -	    "direction. The same value as <XResolution> is designated.")}, +	    "direction. The same value as <XResolution> is designated."), +	 { ESL_MMMM, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_PLANAR_CONFIGURATION, "PlanarConfiguration",  	 N_("Planar Configuration"),  	 N_("Indicates whether pixel components are recorded in a chunky "  	    "or planar format. In JPEG compressed files a JPEG marker "  	    "is used instead of this tag. If this field does not exist, " -	    "the TIFF default of 1 (chunky) is assumed.")}, +	    "the TIFF default of 1 (chunky) is assumed."), +	 { ESL_OMON, ESL_OMON, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_RESOLUTION_UNIT, "ResolutionUnit", N_("Resolution Unit"),  	 N_("The unit for measuring <XResolution> and <YResolution>. The same "  	    "unit is used for both <XResolution> and <YResolution>. If " -	    "the image resolution is unknown, 2 (inches) is designated.")}, +	    "the image resolution is unknown, 2 (inches) is designated."), +	 { ESL_MMMM, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_TRANSFER_FUNCTION, "TransferFunction",  	 N_("Transfer Function"),  	 N_("A transfer function for the image, described in tabular style. "  	    "Normally this tag is not necessary, since color space is " -	    "specified in the color space information tag (<ColorSpace>).")}, +	    "specified in the color space information tag (<ColorSpace>)."), +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_SOFTWARE, "Software", N_("Software"),  	 N_("This tag records the name and version of the software or "  	    "firmware of the camera or image input device used to "  	    "generate the image. The detailed format is not specified, but "  	    "it is recommended that the example shown below be "  	    "followed. When the field is left blank, it is treated as " -	    "unknown.")}, +	    "unknown."), +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_DATE_TIME, "DateTime", N_("Date and Time"),  	 N_("The date and time of image creation. In this standard " -	    "(EXIF-2.1) it is the date and time the file was changed.")}, +	    "(EXIF-2.1) it is the date and time the file was changed."), +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_ARTIST, "Artist", N_("Artist"),  	 N_("This tag records the name of the camera owner, photographer or "  	    "image creator. The detailed format is not specified, but it is "  	    "recommended that the information be written as in the example "  	    "below for ease of Interoperability. When the field is " -	    "left blank, it is treated as unknown.")}, +	    "left blank, it is treated as unknown."), +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_WHITE_POINT, "WhitePoint", N_("White Point"),  	 N_("The chromaticity of the white point of the image. Normally "  	    "this tag is not necessary, since color space is specified " -	    "in the colorspace information tag (<ColorSpace>).")}, +	    "in the color space information tag (<ColorSpace>)."), +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_PRIMARY_CHROMATICITIES, "PrimaryChromaticities",  	 N_("Primary Chromaticities"),  	 N_("The chromaticity of the three primary colors of the image. " -	    "Normally this tag is not necessary, since colorspace is " -	    "specified in the colorspace information tag (<ColorSpace>).")}, +	    "Normally this tag is not necessary, since color space is " +	    "specified in the color space information tag (<ColorSpace>)."), +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_TRANSFER_RANGE, "TransferRange", N_("Transfer Range"), ""},  	{EXIF_TAG_SUB_IFDS, "SubIFDs", "SubIFD Offsets", N_("Defined by Adobe Corporation "  	    "to enable TIFF Trees within a TIFF file.")}, @@ -181,7 +202,8 @@ static struct {  	 N_("JPEG Interchange Format"),  	 N_("The offset to the start byte (SOI) of JPEG compressed "  	    "thumbnail data. This is not used for primary image " -	    "JPEG data.")}, +	    "JPEG data."), +	 { ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,  	 "JPEGInterchangeFormatLength", N_("JPEG Interchange Format Length"),  	 N_("The number of bytes of JPEG compressed thumbnail data. This " @@ -190,7 +212,8 @@ static struct {  	    "bitstream from SOI to EOI. Appn and COM markers should "  	    "not be recorded. Compressed thumbnails must be recorded in no "  	    "more than 64 Kbytes, including all other data to be " -	    "recorded in APP1.")}, +	    "recorded in APP1."), +	 { ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_YCBCR_COEFFICIENTS, "YCbCrCoefficients",  	 N_("YCbCr Coefficients"),  	 N_("The matrix coefficients for transformation from RGB to YCbCr " @@ -199,12 +222,14 @@ static struct {  	    "as the default. The color space is declared in a "  	    "color space information tag, with the default being the value "  	    "that gives the optimal image characteristics " -	    "Interoperability this condition.")}, +	    "Interoperability this condition."), +	 { ESL_NNOO, ESL_NNOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_YCBCR_SUB_SAMPLING, "YCbCrSubSampling",  	 N_("YCbCr Sub-Sampling"),  	 N_("The sampling ratio of chrominance components in relation to the "  	    "luminance component. In JPEG compressed data a JPEG marker " -	    "is used instead of this tag.")}, +	    "is used instead of this tag."), +	 { ESL_NNMN, ESL_NNMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_YCBCR_POSITIONING, "YCbCrPositioning",  	 N_("YCbCr Positioning"),  	 N_("The position of chrominance components in relation to the " @@ -219,7 +244,8 @@ static struct {  	    "does not have the capability of supporting both kinds of "  	    "<YCbCrPositioning>, it shall follow the TIFF default regardless "  	    "of the value in this field. It is preferable that readers " -	    "be able to support both centered and co-sited positioning.")}, +	    "be able to support both centered and co-sited positioning."), +	 { ESL_NNMM, ESL_NNOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_REFERENCE_BLACK_WHITE, "ReferenceBlackWhite",  	 N_("Reference Black/White"),  	 N_("The reference black point value and reference white point " @@ -227,7 +253,8 @@ static struct {  	    "below are given as defaults here. The color space is declared "  	    "in a color space information tag, with the default "  	    "being the value that gives the optimal image characteristics " -	    "Interoperability these conditions.")}, +	    "Interoperability these conditions."), +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_XML_PACKET, "XMLPacket", N_("XML Packet"), N_("XMP Metadata")},  	{EXIF_TAG_RELATED_IMAGE_FILE_FORMAT, "RelatedImageFileFormat",  	 "RelatedImageFileFormat", ""}, @@ -263,84 +290,113 @@ static struct {  	    "the photographer copyright part consists of one space followed "  	    "by a terminating NULL code, then the editor copyright is given "  	    "(see example 3). When the field is left blank, it is treated " -	    "as unknown.")}, +	    "as unknown."), +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_EXPOSURE_TIME, "ExposureTime", N_("Exposure Time"), -	 N_("Exposure time, given in seconds (sec).")}, +	 N_("Exposure time, given in seconds (sec)."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_FNUMBER, "FNumber", N_("FNumber"), -	 N_("The F number.")}, +	 N_("The F number."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_IPTC_NAA, "IPTC/NAA", "IPTC/NAA", ""},  	{EXIF_TAG_IMAGE_RESOURCES, "ImageResources", N_("Image Resources Block"), ""}, -	{EXIF_TAG_EXIF_IFD_POINTER, "ExifIFDPointer", "ExifIFDPointer", +	{EXIF_TAG_EXIF_IFD_POINTER, "ExifIfdPointer", "ExifIFDPointer",  	 N_("A pointer to the Exif IFD. Interoperability, Exif IFD has the "  	    "same structure as that of the IFD specified in TIFF. "  	    "ordinarily, however, it does not contain image data as in " -	    "the case of TIFF.")}, +	    "the case of TIFF."), +	 { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_INTER_COLOR_PROFILE, "InterColorProfile",  	 "InterColorProfile", ""}, -	{EXIF_TAG_EXPOSURE_PROGRAM, "ExposureProgram", "ExposureProgram", +	{EXIF_TAG_EXPOSURE_PROGRAM, "ExposureProgram", N_("Exposure Program"),  	 N_("The class of the program used by the camera to set exposure " -	    "when the picture is taken.")}, +	    "when the picture is taken."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_SPECTRAL_SENSITIVITY, "SpectralSensitivity",  	 N_("Spectral Sensitivity"),  	 N_("Indicates the spectral sensitivity of each channel of the "  	    "camera used. The tag value is an ASCII string compatible " -	    "with the standard developed by the ASTM Technical committee.")}, +	    "with the standard developed by the ASTM Technical Committee."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_GPS_INFO_IFD_POINTER, "GPSInfoIFDPointer",   	 "GPSInfoIFDPointer",  	 N_("A pointer to the GPS Info IFD. The "  	    "Interoperability structure of the GPS Info IFD, like that of " -	    "Exif IFD, has no image data.")}, -#if 0 -	{EXIF_TAG_GPS_VERSION_ID, "GPSVersionID", "", +	    "Exif IFD, has no image data."), +	 { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } }, +	{EXIF_TAG_GPS_VERSION_ID, "GPSVersionID", N_("GPS tag version"),  	 N_("Indicates the version of <GPSInfoIFD>. The version is given "  	    "as 2.0.0.0. This tag is mandatory when <GPSInfo> tag is " -	    "present. (Note: The <GPSVersionID tag is given in bytes, " +	    "present. (Note: The <GPSVersionID> tag is given in bytes, "  	    "unlike the <ExifVersion> tag. When the version is " -	    "2.0.0.0, the tag value is 02000000.H).")}, -	{EXIF_TAG_GPS_LATITUDE_REF, "GPSLatitudeRef", "" +	    "2.0.0.0, the tag value is 02000000.H)."), ESL_GPS}, +	{EXIF_TAG_GPS_LATITUDE_REF, "GPSLatitudeRef", N_("North or South Latitude"),  	 N_("Indicates whether the latitude is north or south latitude. The "  	    "ASCII value 'N' indicates north latitude, and 'S' is south " -	    "latitude.")}, -	{EXIF_TAG_GPS_LATITUDE, "GPSLatitude", "" +	    "latitude."), ESL_GPS}, +	{EXIF_TAG_GPS_LATITUDE, "GPSLatitude", N_("Latitude"),  	 N_("Indicates the latitude. The latitude is expressed as three "  	    "RATIONAL values giving the degrees, minutes, and seconds, "  	    "respectively. When degrees, minutes and seconds are expressed, "  	    "the format is dd/1,mm/1,ss/1. When degrees and minutes are used "  	    "and, for example, fractions of minutes are given up to two " -	    "two decimal places, the format is dd/1,mmmm/100,0/1.")}, -	{EXIF_TAG_GPS_LONGITUDE_REF, "GPSLongitudeRef", "" +	    "decimal places, the format is dd/1,mmmm/100,0/1."), +	 ESL_GPS}, +	{EXIF_TAG_GPS_LONGITUDE_REF, "GPSLongitudeRef", N_("East or West Longitude"),  	 N_("Indicates whether the longitude is east or west longitude. "  	    "ASCII 'E' indicates east longitude, and 'W' is west " -	    "longitude.")}, -	{EXIF_TAG_GPS_LONGITUDE, "GPSLongitude", "" +	    "longitude."), ESL_GPS}, +	{EXIF_TAG_GPS_LONGITUDE, "GPSLongitude", N_("Longitude"),  	 N_("Indicates the longitude. The longitude is expressed as three "  	    "RATIONAL values giving the degrees, minutes, and seconds, "  	    "respectively. When degrees, minutes and seconds are expressed, "  	    "the format is ddd/1,mm/1,ss/1. When degrees and minutes are "  	    "used and, for example, fractions of minutes are given up to " -	    "two decimal places, the format is ddd/1,mmmm/100,0/1.")},  -#endif +	    "two decimal places, the format is ddd/1,mmmm/100,0/1."), +	 ESL_GPS}, +	{EXIF_TAG_GPS_ALTITUDE_REF, "GPSAltitudeRef", N_("Altitude reference"), +	 N_("Indicates the altitude used as the reference altitude. If the " +	    "reference is sea level and the altitude is above sea level, 0 " +	    "is given. If the altitude is below sea level, a value of 1 is given " +	    "and the altitude is indicated as an absolute value in the " +	    "GSPAltitude tag. The reference unit is meters. Note that this tag " +	    "is BYTE type, unlike other reference tags."), ESL_GPS}, +	{EXIF_TAG_GPS_ALTITUDE, "GPSAltitude", N_("Altitude"), +	 N_("Indicates the altitude based on the reference in GPSAltitudeRef. " +	    "Altitude is expressed as one RATIONAL value. The reference unit " +	    "is meters."), ESL_GPS}, +	{EXIF_TAG_GPS_IMG_DIRECTION_REF, "GPSImgDirectionRef", N_("GPS Img Direction Reference"), +	 N_("Indicates the reference for giving the direction of the image when it is captured. " +	    "'T' denotes true direction and 'M' is magnetic direction."), ESL_GPS}, +	{EXIF_TAG_GPS_IMG_DIRECTION, "GPSImgDirection", N_("GPS Img Direction"), +	 N_("Indicates the direction of the image when it was captured. The range of values is " +	    "from 0.00 to 359.99."), ESL_GPS},  	{EXIF_TAG_ISO_SPEED_RATINGS, "ISOSpeedRatings",  	 N_("ISO Speed Ratings"),  	 N_("Indicates the ISO Speed and ISO Latitude of the camera or " -	    "input device as specified in ISO 12232.")}, +	    "input device as specified in ISO 12232."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_OECF, "OECF", "OECF", -	 N_("Indicates the Opto-Electoric Conversion Function (OECF) " +	 N_("Indicates the Opto-Electronic Conversion Function (OECF) "  	    "specified in ISO 14524. <OECF> is the relationship between " -	    "the camera optical input and the image values.")}, +	    "the camera optical input and the image values."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_EXIF_VERSION, "ExifVersion", N_("Exif Version"),  	 N_("The version of this standard supported. Nonexistence of this " -	    "field is taken to mean nonconformance to the standard.")}, +	    "field is taken to mean nonconformance to the standard."), +	 { ESL_NNNN, ESL_NNNN, ESL_MMMM, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_DATE_TIME_ORIGINAL, "DateTimeOriginal",  	 N_("Date and Time (original)"),  	 N_("The date and time when the original image data was generated. "  	    "For a digital still camera " -	    "the date and time the picture was taken are recorded.")}, +	    "the date and time the picture was taken are recorded."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_DATE_TIME_DIGITIZED, "DateTimeDigitized",  	 N_("Date and Time (digitized)"), -	 N_("The date and time when the image was stored as digital data. ")}, +	 N_("The date and time when the image was stored as digital data. "), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_COMPONENTS_CONFIGURATION, "ComponentsConfiguration", -	 "ComponentsConfiguration", +	 N_("Components Configuration"),  	 N_("Information specific to compressed data. The channels of "  	    "each component are arranged in order from the 1st "  	    "component to the 4th. For uncompressed data the data " @@ -348,44 +404,56 @@ static struct {  	    "However, since <PhotometricInterpretation> can only "  	    "express the order of Y, Cb and Cr, this tag is provided "  	    "for cases when compressed data uses components other than " -	    "Y, Cb, and Cr and to enable support of other sequences.")}, +	    "Y, Cb, and Cr and to enable support of other sequences."), +	 { ESL_NNNN, ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_COMPRESSED_BITS_PER_PIXEL, "CompressedBitsPerPixel",  	 N_("Compressed Bits per Pixel"),  	 N_("Information specific to compressed data. The compression mode "  	    "used for a compressed image is indicated in unit bits " -	    "per pixel.")}, +	    "per pixel."), +	 { ESL_NNNN, ESL_NNNN, ESL_NNNO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_SHUTTER_SPEED_VALUE, "ShutterSpeedValue", N_("Shutter speed"),  	 N_("Shutter speed. The unit is the APEX (Additive System of " -	    "Photographic Exposure) setting (see Appendix C).")}, +	    "Photographic Exposure) setting."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_APERTURE_VALUE, "ApertureValue", N_("Aperture"), -	 N_("The lens aperture. The unit is the APEX value.")}, +	 N_("The lens aperture. The unit is the APEX value."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_BRIGHTNESS_VALUE, "BrightnessValue", N_("Brightness"),  	 N_("The value of brightness. The unit is the APEX value. " -	    "Ordinarily it is given in the range of -99.99 to 99.99.")}, +	    "Ordinarily it is given in the range of -99.99 to 99.99."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_EXPOSURE_BIAS_VALUE, "ExposureBiasValue",  	 N_("Exposure Bias"),  	 N_("The exposure bias. The units is the APEX value. Ordinarily " -	    "it is given in the range of -99.99 to 99.99.")}, +	    "it is given in the range of -99.99 to 99.99."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_MAX_APERTURE_VALUE, "MaxApertureValue", "MaxApertureValue",  	 N_("The smallest F number of the lens. The unit is the APEX value. "  	    "Ordinarily it is given in the range of 00.00 to 99.99, " -	    "but it is not limited to this range.")}, +	    "but it is not limited to this range."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_SUBJECT_DISTANCE, "SubjectDistance",  	 N_("Subject Distance"), -	 N_("The distance to the subject, given in meters.")}, +	 N_("The distance to the subject, given in meters."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_METERING_MODE, "MeteringMode", N_("Metering Mode"), -	 N_("The metering mode.")}, +	 N_("The metering mode."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_LIGHT_SOURCE, "LightSource", N_("Light Source"), -	 N_("The kind of light source.")}, +	 N_("The kind of light source."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_FLASH, "Flash", N_("Flash"),  	 N_("This tag is recorded when an image is taken using a strobe "  	    "light (flash).")},  	{EXIF_TAG_FOCAL_LENGTH, "FocalLength", N_("Focal Length"),  	 N_("The actual focal length of the lens, in mm. Conversion is not " -	    "made to the focal length of a 35 mm film camera.")}, +	    "made to the focal length of a 35 mm film camera."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_MAKER_NOTE, "MakerNote", N_("Maker Note"),  	 N_("A tag for manufacturers of Exif writers to record any desired " -	    "information. The contents are up to the manufacturer.")}, +	    "information. The contents are up to the manufacturer."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_USER_COMMENT, "UserComment", N_("User Comment"),  	 N_("A tag for Exif users to write keywords or comments on the image "  	    "besides those in <ImageDescription>, and without the " @@ -396,7 +464,7 @@ static struct {  	    "with NULL (\"00.h\"). ID codes are assigned by means of "  	    "registration. The designation method and references for each "  	    "character code are given in Table 6. The value of CountN " -	    "is determinated based on the 8 bytes in the character code " +	    "is determined based on the 8 bytes in the character code "  	    "area and the number of bytes in the user comment part. Since "  	    "the TYPE is not ASCII, NULL termination is not necessary "  	    "(see Fig. 9). " @@ -409,20 +477,35 @@ static struct {  	    "do not use the <UserComment> tag (see Table 7). "  	    "When a <UserComment> area is set aside, it is recommended that "  	    "the ID code be ASCII and that the following user comment " -	    "part be filled with blank characters [20.H].")}, +	    "part be filled with blank characters [20.H]."), +			{ ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_SUB_SEC_TIME, "SubsecTime", "SubsecTime",  	 N_("A tag used to record fractions of seconds for the " -	    "<DateTime> tag.")}, +	    "<DateTime> tag."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_SUB_SEC_TIME_ORIGINAL, "SubSecTimeOriginal",  	 "SubSecTimeOriginal",  	 N_("A tag used to record fractions of seconds for the " -	    "<DateTimeOriginal> tag.")}, +	    "<DateTimeOriginal> tag."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_SUB_SEC_TIME_DIGITIZED, "SubSecTimeDigitized",  	 "SubSecTimeDigitized",  	 N_("A tag used to record fractions of seconds for the " -	    "<DateTimeDigitized> tag.")}, +	    "<DateTimeDigitized> tag."), +	 { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } }, +	{EXIF_TAG_XP_TITLE, "XPTitle", N_("XP Title"), "", +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } }, +	{EXIF_TAG_XP_COMMENT, "XPComment", N_("XP Comment"), "", +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } }, +	{EXIF_TAG_XP_AUTHOR, "XPAuthor", N_("XP Author"), "", +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } }, +	{EXIF_TAG_XP_KEYWORDS, "XPKeywords", N_("XP Keywords"), "", +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } }, +	{EXIF_TAG_XP_SUBJECT, "XPSubject", N_("XP Subject"), "", +	 { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_FLASH_PIX_VERSION, "FlashPixVersion", "FlashPixVersion", -	 N_("The FlashPix format version supported by a FPXR file.")}, +	 N_("The FlashPix format version supported by a FPXR file."), +	 { ESL_NNNN, ESL_NNNN, ESL_MMMM, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_COLOR_SPACE, "ColorSpace", N_("Color Space"),  	 N_("The color space information tag is always "  	    "recorded as the color space specifier. Normally sRGB (=1) " @@ -430,14 +513,15 @@ static struct {  	    "conditions and environment. If a color space other than "  	    "sRGB is used, Uncalibrated (=FFFF.H) is set. Image data "  	    "recorded as Uncalibrated can be treated as sRGB when it is " -	    "converted to FlashPix. On sRGB see Appendix E.")}, +	    "converted to FlashPix."), +	 { ESL_NNNN, ESL_NNNN, ESL_MMMM, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_PIXEL_X_DIMENSION, "PixelXDimension", "PixelXDimension",  	 N_("Information specific to compressed data. When a "  	    "compressed file is recorded, the valid width of the "  	    "meaningful image must be recorded in this tag, whether or "  	    "not there is padding data or a restart marker. This tag " -	    "should not exist in an uncompressed file. For details see " -	    "section 2.8.1 and Appendix F.")}, +	    "should not exist in an uncompressed file."), +	 { ESL_NNNN, ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_PIXEL_Y_DIMENSION, "PixelYDimension", "PixelYDimension",  	 N_("Information specific to compressed data. When a compressed "  	    "file is recorded, the valid height of the meaningful image " @@ -446,7 +530,8 @@ static struct {  	    "uncompressed file. For details see section 2.8.1 and Appendix "  	    "F. Since data padding is unnecessary in the vertical direction, "  	    "the number of lines recorded in this valid image height tag " -	    "will in fact be the same as that recorded in the SOF.")}, +	    "will in fact be the same as that recorded in the SOF."), +	 { ESL_NNNN, ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_RELATED_SOUND_FILE, "RelatedSoundFile",  	 "RelatedSoundFile",  	 N_("This tag is used to record the name of an audio file related " @@ -478,7 +563,8 @@ static struct {  	    "information is an ASCII character string, it is terminated by "  	    "NULL. When this tag is used to map audio files, the relation "  	    "of the audio file to image data must also be indicated on the " -	    "audio file end.")}, +	    "audio file end."), +			{ ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_INTEROPERABILITY_IFD_POINTER, "InteroperabilityIFDPointer",  	 "InteroperabilityIFDPointer",  	 N_("Interoperability IFD is composed of tags which stores the " @@ -488,7 +574,8 @@ static struct {  	    "the same as TIFF defined IFD structure "  	    "but does not contain the "  	    "image data characteristically compared with normal TIFF " -	    "IFD.")}, +	    "IFD."), +	 { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },  	{EXIF_TAG_FLASH_ENERGY, "FlashEnergy", N_("Flash Energy"),  	 N_("Indicates the strobe energy at the time the image is "  	    "captured, as measured in Beam Candle Power Seconds (BCPS).")}, @@ -517,9 +604,9 @@ static struct {  	    "value of this tag represents the pixel at the center of the "  	    "main subject relative to the left edge, prior to rotation "  	    "processing as per the <Rotation> tag. The first value " -	    "indicates the X column number and second indicates " +	    "indicates the X column number and the second indicates "  	    "the Y row number.")}, -	{EXIF_TAG_EXPOSURE_INDEX, "ExposureIndex", N_("Exposure index"), +	{EXIF_TAG_EXPOSURE_INDEX, "ExposureIndex", N_("Exposure Index"),  	 N_("Indicates the exposure index selected on the camera or "  	    "input device at the time the image is captured.")},  	{EXIF_TAG_SENSING_METHOD, "SensingMethod", N_("Sensing Method"), @@ -527,7 +614,7 @@ static struct {  	    "device.")},  	{EXIF_TAG_FILE_SOURCE, "FileSource", N_("File Source"),  	 N_("Indicates the image source. If a DSC recorded the image, " -	    "this tag value of this tag always be set to 3, indicating " +	    "the tag value of this tag always be set to 3, indicating "  	    "that the image was recorded on a DSC.")},  	{EXIF_TAG_SCENE_TYPE, "SceneType", N_("Scene Type"),  	 N_("Indicates the type of scene. If a DSC recorded the image, " @@ -570,7 +657,7 @@ static struct {  	 N_("This tag indicates the type of scene that was shot. It can "  	    "also be used to record the mode in which the image was "  	    "shot. Note that this differs from the scene type " -	    "(SceneType) tag.")}, +	    "<SceneType> tag.")},  	{EXIF_TAG_GAIN_CONTROL, "GainControl", N_("Gain Control"),  	 N_("This tag indicates the degree of overall image gain "  	    "adjustment.")}, @@ -596,6 +683,11 @@ static struct {  	 N_("This tag indicates an identifier assigned uniquely to "  	    "each image. It is recorded as an ASCII string equivalent "  	    "to hexadecimal notation and 128-bit fixed length.")}, +	{EXIF_TAG_GAMMA, "Gamma", N_("Gamma"), +	 N_("Indicates the value of coefficient gamma.")}, +	{EXIF_TAG_PRINT_IMAGE_MATCHING, "PrintImageMatching", N_("PRINT Image Matching"), +	 N_("Related to Epson's PRINT Image Matching technology")}, +#endif  	{0, NULL, NULL, NULL}  }; @@ -622,55 +714,144 @@ exif_tag_table_count (void)  	return sizeof (ExifTagTable) / sizeof (ExifTagTable[0]);  } +#define RECORDED \ +((ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_CHUNKY] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \ + (ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_PLANAR] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \ + (ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_YCC] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \ + (ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_COMPRESSED] != EXIF_SUPPORT_LEVEL_NOT_RECORDED)) +  const char * -exif_tag_get_name (ExifTag tag) +exif_tag_get_name_in_ifd (ExifTag tag, ExifIfd ifd)  {  	unsigned int i; +	if (ifd >= EXIF_IFD_COUNT) return NULL;  	for (i = 0; ExifTagTable[i].name; i++) -		if (ExifTagTable[i].tag == tag) -			break; - +		if ((ExifTagTable[i].tag == tag) && RECORDED) break;  	return ExifTagTable[i].name;  }  const char * -exif_tag_get_title (ExifTag tag) +exif_tag_get_title_in_ifd (ExifTag tag, ExifIfd ifd)  {  	unsigned int i;  	/* FIXME: This belongs to somewhere else. */ -	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +	/* libexif should use the default system locale. +	 * If an application specifically requires UTF-8, then we +	 * must give the application a way to tell libexif that. +	 *  +	 * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +	 */  	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - +	if (ifd >= EXIF_IFD_COUNT) return NULL;  	for (i = 0; ExifTagTable[i].title; i++) -		if (ExifTagTable[i].tag == tag) break; +		if ((ExifTagTable[i].tag == tag) && RECORDED) break;  	return _(ExifTagTable[i].title);  }  const char * -exif_tag_get_description (ExifTag tag) +exif_tag_get_description_in_ifd (ExifTag tag, ExifIfd ifd)  {  	unsigned int i; -	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +	/* libexif should use the default system locale. +	 * If an application specifically requires UTF-8, then we +	 * must give the application a way to tell libexif that. +	 *  +	 * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +	 */  	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); +	if (ifd >= EXIF_IFD_COUNT) return NULL;  	for (i = 0; ExifTagTable[i].description; i++) -		if (ExifTagTable[i].tag == tag) break; -	return _(ExifTagTable[i].description); +		if ((ExifTagTable[i].tag == tag) && RECORDED) { +			/* GNU gettext acts strangely when given an empty string */ +			if (!*ExifTagTable[i].description) +				return ""; +			return _(ExifTagTable[i].description); +		} +	return NULL; +} + + +/********************************************************************** + * convenience functions + **********************************************************************/ + +/* generic part: iterate through IFD list and return first result */ +typedef const char * (*get_stuff_func) (ExifTag tag, ExifIfd ifd); + +static const char * +exif_tag_get_stuff (ExifTag tag, get_stuff_func func) +{ +	static const ExifIfd ifds[5] = { +		EXIF_IFD_0, +		EXIF_IFD_1, +		EXIF_IFD_EXIF, +		EXIF_IFD_INTEROPERABILITY, +		EXIF_IFD_GPS +	}; +	int i; +	for (i=0; i<5; i++) { +		const char *result = func(tag, ifds[i]); +		if (result != NULL) { +			return result; +		} +	} +	return (const char *) NULL; +} + +/* explicit functions */ +const char * +exif_tag_get_name (ExifTag tag) +{ +	return exif_tag_get_stuff(tag, exif_tag_get_name_in_ifd);  } +const char * +exif_tag_get_title (ExifTag tag) +{ +	return exif_tag_get_stuff(tag, exif_tag_get_title_in_ifd); +} + +const char * +exif_tag_get_description (ExifTag tag) +{ +	return exif_tag_get_stuff (tag, exif_tag_get_description_in_ifd); +} + + +  ExifTag   exif_tag_from_name (const char *name)  {  	unsigned int i; +	unsigned int result=0;  	if (!name) return 0;  	for (i = 0; ExifTagTable[i].name; i++) -		if (!strcmp (ExifTagTable[i].name, name)) break; -	return ExifTagTable[i].tag; +		if (!strcmp (ExifTagTable[i].name, name))  { +		  	result = ExifTagTable[i].tag; +		  	break; +		} +	return result; +} + +ExifSupportLevel +exif_tag_get_support_level_in_ifd (ExifTag tag, ExifIfd ifd, ExifDataType t) +{ +	unsigned int i; + +	if (ifd >= EXIF_IFD_COUNT) return EXIF_SUPPORT_LEVEL_UNKNOWN; +	if (t >= EXIF_DATA_TYPE_COUNT) return EXIF_SUPPORT_LEVEL_UNKNOWN; + +	for (i = 0; ExifTagTable[i].description; i++) +		if ((ExifTagTable[i].tag == tag) && +				(ExifTagTable[i].esl[ifd][t] != EXIF_SUPPORT_LEVEL_NOT_RECORDED)) +			return ExifTagTable[i].esl[ifd][t]; +	return EXIF_SUPPORT_LEVEL_NOT_RECORDED;  }  const char * @@ -683,4 +864,3 @@ exif_tag_get_name_index (unsigned int i, ExifTag *tag)  	return (ExifTagTable[i].name);  } - diff --git a/src/libexif/exif-tag.h b/src/libexif/exif-tag.h index f928374..8b43405 100644 --- a/src/libexif/exif-tag.h +++ b/src/libexif/exif-tag.h @@ -1,6 +1,6 @@  /* exif-tag.h   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -25,6 +25,9 @@  extern "C" {  #endif /* __cplusplus */ +#include <libexif/exif-ifd.h> +#include <libexif/exif-data-type.h> +  typedef enum {  	EXIF_TAG_INTEROPERABILITY_INDEX		= 0x0001,  	EXIF_TAG_INTEROPERABILITY_VERSION	= 0x0002, @@ -104,6 +107,11 @@ typedef enum {  	EXIF_TAG_SUB_SEC_TIME			= 0x9290,  	EXIF_TAG_SUB_SEC_TIME_ORIGINAL		= 0x9291,  	EXIF_TAG_SUB_SEC_TIME_DIGITIZED		= 0x9292, +	EXIF_TAG_XP_TITLE			= 0x9c9b, +	EXIF_TAG_XP_COMMENT			= 0x9c9c, +	EXIF_TAG_XP_AUTHOR			= 0x9c9d, +	EXIF_TAG_XP_KEYWORDS			= 0x9c9e, +	EXIF_TAG_XP_SUBJECT			= 0x9c9f,  	EXIF_TAG_FLASH_PIX_VERSION		= 0xa000,  	EXIF_TAG_COLOR_SPACE			= 0xa001,  	EXIF_TAG_PIXEL_X_DIMENSION		= 0xa002, @@ -133,14 +141,66 @@ typedef enum {  	EXIF_TAG_SHARPNESS			= 0xa40a,  	EXIF_TAG_DEVICE_SETTING_DESCRIPTION	= 0xa40b,  	EXIF_TAG_SUBJECT_DISTANCE_RANGE		= 0xa40c, -	EXIF_TAG_IMAGE_UNIQUE_ID		= 0xa420 +	EXIF_TAG_IMAGE_UNIQUE_ID		= 0xa420, +	EXIF_TAG_GAMMA				= 0xa500, +	EXIF_TAG_PRINT_IMAGE_MATCHING		= 0xc4a5  } ExifTag; -ExifTag         exif_tag_from_name       (const char *); +/* GPS tags overlap with above ones. */ +#define EXIF_TAG_GPS_VERSION_ID        0x0000 +#define EXIF_TAG_GPS_LATITUDE_REF      0x0001 /* INTEROPERABILITY_INDEX   */ +#define EXIF_TAG_GPS_LATITUDE          0x0002 /* INTEROPERABILITY_VERSION */ +#define EXIF_TAG_GPS_LONGITUDE_REF     0x0003 +#define EXIF_TAG_GPS_LONGITUDE         0x0004 +#define EXIF_TAG_GPS_ALTITUDE_REF      0x0005 +#define EXIF_TAG_GPS_ALTITUDE          0x0006 +#define EXIF_TAG_GPS_TIME_STAMP        0x0007 +#define EXIF_TAG_GPS_SATELLITES        0x0008 +#define EXIF_TAG_GPS_STATUS            0x0009 +#define EXIF_TAG_GPS_MEASURE_MODE      0x000a +#define EXIF_TAG_GPS_DOP               0x000b +#define EXIF_TAG_GPS_SPEED_REF         0x000c +#define EXIF_TAG_GPS_SPEED             0x000d +#define EXIF_TAG_GPS_TRACK_REF         0x000e +#define EXIF_TAG_GPS_TRACK             0x000f +#define EXIF_TAG_GPS_IMG_DIRECTION_REF 0x0010 +#define EXIF_TAG_GPS_IMG_DIRECTION     0x0011 +#define EXIF_TAG_GPS_MAP_DATUM         0x0012 +#define EXIF_TAG_GPS_DEST_LATITUDE_REF 0x0013 +#define EXIF_TAG_GPS_DEST_LATITUDE     0x0014 +#define EXIF_TAG_GPS_DEST_LONGITUDE_REF 0x0015 +#define EXIF_TAG_GPS_DEST_LONGITUDE     0x0016 +#define EXIF_TAG_GPS_DEST_BEARING_REF   0x0017 +#define EXIF_TAG_GPS_DEST_BEARING       0x0018 +#define EXIF_TAG_GPS_DEST_DISTANCE_REF  0x0019 +#define EXIF_TAG_GPS_DEST_DISTANCE      0x001a +#define EXIF_TAG_GPS_PROCESSING_METHOD  0x001b +#define EXIF_TAG_GPS_AREA_INFORMATION   0x001c +#define EXIF_TAG_GPS_DATE_STAMP         0x001d +#define EXIF_TAG_GPS_DIFFERENTIAL       0x001e + +typedef enum { +	EXIF_SUPPORT_LEVEL_UNKNOWN = 0, +	EXIF_SUPPORT_LEVEL_NOT_RECORDED, +	EXIF_SUPPORT_LEVEL_MANDATORY, +	EXIF_SUPPORT_LEVEL_OPTIONAL +} ExifSupportLevel; + +ExifTag          exif_tag_from_name                (const char *); +const char      *exif_tag_get_name_in_ifd          (ExifTag, ExifIfd); +const char      *exif_tag_get_title_in_ifd         (ExifTag, ExifIfd); +const char      *exif_tag_get_description_in_ifd   (ExifTag, ExifIfd); +ExifSupportLevel exif_tag_get_support_level_in_ifd (ExifTag, ExifIfd, +                                                    ExifDataType); + +/* Don't use these functions. They are here for compatibility only. */  const char     *exif_tag_get_name        (ExifTag tag);  const char     *exif_tag_get_title       (ExifTag tag);  const char     *exif_tag_get_description (ExifTag tag); +/* Don't use these definitions. They are here for compatibility only. */ +#define EXIF_TAG_UNKNOWN_C4A5 EXIF_TAG_PRINT_IMAGE_MATCHING +  #ifdef __cplusplus  }  #endif /* __cplusplus */ diff --git a/src/libexif/exif-utils.c b/src/libexif/exif-utils.c index 9386012..a6e7696 100644 --- a/src/libexif/exif-utils.c +++ b/src/libexif/exif-utils.c @@ -1,6 +1,6 @@  /* exif-utils.c   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -212,3 +212,40 @@ exif_set_srational (unsigned char *buf, ExifByteOrder order,  	exif_set_slong (buf, order, value.numerator);  	exif_set_slong (buf + 4, order, value.denominator);  } + +void +exif_convert_utf16_to_utf8 (char *out, const unsigned short *in, int maxlen) +{ +	/* This function converts rather UCS2 than UTF16 to UTF8 */ +	if (maxlen <= 0) { +		return; +	} +	while (*in) { +		if (*in < 0x80) { +			if (maxlen > 1) { +				*out++ = (char)*in++; +				maxlen--; +			} else { +				break; +			} +		} else if (*in < 0x800) { +			if (maxlen > 2) { +				*out++ = ((*in >> 6) & 0x1F) | 0xC0; +				*out++ = (*in++ & 0x3F) | 0x80; +				maxlen -= 2; +			} else { +				break; +			} +		} else { +			if (maxlen > 2) { +				*out++ = ((*in >> 12) & 0x0F) | 0xE0; +				*out++ = ((*in >> 6) & 0x3F) | 0x80; +				*out++ = (*in++ & 0x3F) | 0x80; +				maxlen -= 3; +			} else { +				break; +			} +		} +	} +	*out = 0; +} diff --git a/src/libexif/exif-utils.h b/src/libexif/exif-utils.h index a75db0b..85b650a 100644 --- a/src/libexif/exif-utils.h +++ b/src/libexif/exif-utils.h @@ -1,6 +1,6 @@  /* exif-utils.h   * - * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -33,14 +33,20 @@ extern "C" {  /* If these definitions don't work for you, please let us fix the    * macro generating _stdint.h */ -typedef char		ExifByte;          /* 1 byte  */ +typedef unsigned char	ExifByte;          /* 1 byte  */ +typedef signed char	ExifSByte;         /* 1 byte  */  typedef char *		ExifAscii;  typedef uint16_t	ExifShort;         /* 2 bytes */  typedef int16_t         ExifSShort;        /* 2 bytes */  typedef uint32_t	ExifLong;          /* 4 bytes */ + +/** EXIF Unsigned Rational */  typedef struct {ExifLong numerator; ExifLong denominator;} ExifRational; +  typedef char		ExifUndefined;     /* 1 byte  */  typedef int32_t		ExifSLong;         /* 4 bytes */ + +/** EXIF Signed Rational. */  typedef struct {ExifSLong numerator; ExifSLong denominator;} ExifSRational; @@ -64,6 +70,8 @@ void exif_set_rational  (unsigned char *b, ExifByteOrder order,  void exif_set_srational (unsigned char *b, ExifByteOrder order,  			 ExifSRational value); +void exif_convert_utf16_to_utf8 (char *out, const unsigned short *in, int maxlen); +  /* Please do not use this function outside of the library. */  void exif_array_set_byte_order (ExifFormat, unsigned char *, unsigned int,  		ExifByteOrder o_orig, ExifByteOrder o_new); @@ -71,6 +79,9 @@ void exif_array_set_byte_order (ExifFormat, unsigned char *, unsigned int,  #undef  MIN  #define MIN(a, b)  (((a) < (b)) ? (a) : (b)) +#undef  MAX +#define MAX(a, b)  (((a) > (b)) ? (a) : (b)) +  /* For compatibility with older versions */  #define EXIF_TAG_SUBSEC_TIME EXIF_TAG_SUB_SEC_TIME diff --git a/src/libexif/exif.c b/src/libexif/exif.c deleted file mode 100644 index 3be72a3..0000000 --- a/src/libexif/exif.c +++ /dev/null @@ -1,1274 +0,0 @@ -/* - -Copyright © 2000 Matthias Wandel, The PHP Group, Curtis Galloway - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -*/ - -#include <sys/time.h> -#include <malloc.h> -#include <stdio.h> -#include <string.h> - -#include <math.h> -#include <sys/stat.h> -#include <stdarg.h> -#include <fcntl.h> - -#include "exif.h" - -typedef unsigned char uchar; - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -/*  -   This structure stores global state for an EXIF image file. -*/ -typedef struct { -	exif_data_t *d; -	int MotorolaOrder; -	const char *filename; - -	char *Thumbnail; -	int ThumbnailSize; -} ImageInfoType; - -void *(*exif_malloc_fn)(int); -void *(*exif_realloc_fn)(void *, int); -void (*exif_free_fn)(void *); - -static char * -exif_strndup(char *str, int len) -{ -	char *rval = (*exif_malloc_fn)(len+1); -	strncpy(rval, str, len); -	rval[len] = '\0'; -	return rval; -} - -struct exif_data * -exif_alloc(void) -{ -	exif_data_t *d; - -	d = (*exif_malloc_fn)(sizeof(exif_data_t)); -	bzero(d, sizeof(*d)); -	return d; -} - -static void -exif_error(char *fmt, ...) -{ -	va_list ap; -	va_start(ap, fmt); -	vprintf(fmt, ap); -	va_end(ap); -} - - -/* This structure is used to store a section of a Jpeg file. */ -typedef struct { -    uchar *Data; -    int      Type; -    unsigned Size; -} Section_t; - -#define EXIT_FAILURE  1 -#define EXIT_SUCCESS  0 - - -/*  -   JPEG markers consist of one or more 0xFF bytes, followed by a marker -   code byte (which is not an FF).  Here are the marker codes of interest -   in this program.  (See jdmarker.c for a more complete list.) -*/ - -#define M_SOF0  0xC0            /* Start Of Frame N                        */ -#define M_SOF1  0xC1            /* N indicates which compression process   */ -#define M_SOF2  0xC2            /* Only SOF0-SOF2 are now in common use    */ -#define M_SOF3  0xC3 -#define M_SOF5  0xC5            /* NB: codes C4 and CC are NOT SOF markers */ -#define M_SOF6  0xC6 -#define M_SOF7  0xC7 -#define M_SOF9  0xC9 -#define M_SOF10 0xCA -#define M_SOF11 0xCB -#define M_SOF13 0xCD -#define M_SOF14 0xCE -#define M_SOF15 0xCF -#define M_SOI   0xD8            /* Start Of Image (beginning of datastream) */ -#define M_EOI   0xD9            /* End Of Image (end of datastream)         */ -#define M_SOS   0xDA            /* Start Of Scan (begins compressed data)   */ -#define M_EXIF  0xE1             -#define M_COM   0xFE            /* COMment                                  */ - - -#define PSEUDO_IMAGE_MARKER 0x123; /* Extra value. */ - -#define EXIF_ALLOC_SIZE 16 - -/* - * The name gets copied, so you can pass a static string; - * the data is not copied, so if it is a string, - * you must allocate it yourself. - */ -static int -exif_append_data(exif_data_t **d_p, -				 char *name, -				 char rec_type, -				 int exif_format, -				 exif_rec_data_t *data) -{ -	exif_data_t *d = *d_p; - -	if (rec_type == '\0') -		return EXIT_FAILURE; - -	if (d->n_alloc <= d->n_recs) { -		d->n_alloc += EXIF_ALLOC_SIZE; -		d = (*exif_realloc_fn)(d, sizeof(exif_data_t) + -							   sizeof(exif_record_t) * d->n_alloc); -		*d_p = d; -	} -	d->recs[d->n_recs].rec_type = rec_type; -	bcopy(data, &d->recs[d->n_recs].rec_data, sizeof(exif_rec_data_t)); -	d->recs[d->n_recs].rec_name = (char*)strdup(name); -	d->n_recs++; -	return EXIT_SUCCESS; -} - -/* -   Get 16 bits motorola order (always) for jpeg header stuff. -*/ -static int -Get16m(void *Short) -{ -    return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1]; -} - - -/* -   Process a COM marker. -   We want to print out the marker contents as legible text; -   we must guard against random junk and varying newline representations. -*/ -static void -process_COM (ImageInfoType *ImageInfo, uchar *Data, int length) -{ -    int ch; -    char *Comment; -    int nch; -    int a; -    exif_rec_data_t rd; - -    nch = 0; -    Comment = (*exif_malloc_fn)(length+1); - -    for (a=2;a<length;a++) { -        ch = Data[a]; - -        if (ch == '\r' && Data[a+1] == '\n') continue; /* Remove cr followed by lf. */ - -        if (isprint(ch) || ch == '\n' || ch == '\t') { -            Comment[nch++] = (char)ch; -        } else { -            Comment[nch++] = '?'; -        } -    } - -    Comment[nch] = '\0'; /* Null terminate */ - -    rd.s = Comment; -    exif_append_data(&ImageInfo->d, "Comment", 's', EXIF_FMT_COMPUTED, &rd); -} -  -/* Process a SOFn marker.  This is useful for the image dimensions. */ -static void -process_SOFn (ImageInfoType *ImageInfo, uchar *Data, int marker) -{ -    int data_precision, num_components; -    const char *process; -    exif_rec_data_t rd; - -    data_precision = Data[2]; -    rd.l = Get16m(Data+3); -    exif_append_data(&ImageInfo->d, -					 "Height", -					 'l', -					 EXIF_FMT_COMPUTED, -					 &rd); -    rd.l = Get16m(Data+5); -    exif_append_data(&ImageInfo->d, -					 "Width", -					 'l', -					 EXIF_FMT_COMPUTED, -					 &rd); -    num_components = Data[7]; - -    if (num_components == 3) { -		rd.l = 1; -    } else { -		rd.l = 0; -    } -    exif_append_data(&ImageInfo->d, "IsColor", 'l', EXIF_FMT_COMPUTED, &rd); - -    switch (marker) { -	case M_SOF0:  process = "Baseline";  break; -	case M_SOF1:  process = "Extended sequential";  break; -	case M_SOF2:  process = "Progressive";  break; -	case M_SOF3:  process = "Lossless";  break; -	case M_SOF5:  process = "Differential sequential";  break; -	case M_SOF6:  process = "Differential progressive";  break; -	case M_SOF7:  process = "Differential lossless";  break; -	case M_SOF9:  process = "Extended sequential, arithmetic coding";  break; -	case M_SOF10: process = "Progressive, arithmetic coding";  break; -	case M_SOF11: process = "Lossless, arithmetic coding";  break; -	case M_SOF13: process = "Differential sequential, arithmetic coding";  break; -	case M_SOF14: process = "Differential progressive, arithmetic coding"; break; -	case M_SOF15: process = "Differential lossless, arithmetic coding";  break; -	default:      process = "Unknown";  break; -    } -} - -/* -   Describes format descriptor -*/ -static int ExifBytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8}; -#define NUM_FORMATS EXIF_FMT_DOUBLE - -/* -   Describes tag values -*/ - -#define TAG_EXIF_OFFSET       0x8769 -#define TAG_INTEROP_OFFSET    0xa005 - -#define TAG_COMPRESSION       0x0103 - -#define TAG_MAKE              0x010F -#define TAG_MODEL             0x0110 -#define TAG_ORIENTATION       0x0112 - -#define TAG_SOFTWARE          0x0131 - -/* Olympus specific tags */ -#define TAG_SPECIALMODE       0x0200 -#define TAG_JPEGQUAL          0x0201 -#define TAG_MACRO             0x0202 -#define TAG_DIGIZOOM          0x0204 -#define TAG_SOFTWARERELEASE   0x0207 -#define TAG_PICTINFO          0x0208 -#define TAG_CAMERAID          0x0209 -/* end Olympus specific tags */ - -#define TAG_COPYRIGHT         0x8298 - -#define TAG_EXPOSURETIME      0x829A -#define TAG_FNUMBER           0x829D - -#define TAG_GPSINFO           0x8825 -#define TAG_ISOSPEED          0x8827 -#define TAG_EXIFVERSION       0x9000 - -#define TAG_SHUTTERSPEED      0x9201 -#define TAG_APERTURE          0x9202 -#define TAG_MAXAPERTURE       0x9205 -#define TAG_FOCALLENGTH       0x920A - -#define TAG_DATETIME_ORIGINAL 0x9003 -#define TAG_USERCOMMENT       0x9286 - -#define TAG_SUBJECT_DISTANCE  0x9206 -#define TAG_LIGHT_SOURCE      0x9208 -#define TAG_FLASH             0x9209 - -#define TAG_FOCALPLANEXRES    0xa20E -#define TAG_FOCALPLANEUNITS   0xa210 -#define TAG_IMAGEWIDTH        0xA002 - -struct ExifTag { -    unsigned short Tag; -    char *Desc; -	void (*Func)(); -}; - - - -/* Convert a 16 bit unsigned value from file's native byte order */ -static int -Get16u(void *Short, int MotorolaOrder) -{ -    if (MotorolaOrder) { -        return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1]; -    } else { -        return (((uchar *)Short)[1] << 8) | ((uchar *)Short)[0]; -    } -} - -/* Convert a 32 bit signed value from file's native byte order */ -static int -Get32s(void *Long, int MotorolaOrder) -{ -    if (MotorolaOrder) { -        return  ((( char *)Long)[0] << 24) | (((uchar *)Long)[1] << 16) -			| (((uchar *)Long)[2] << 8 ) | (((uchar *)Long)[3] << 0 ); -    } else { -        return  ((( char *)Long)[3] << 24) | (((uchar *)Long)[2] << 16) -			| (((uchar *)Long)[1] << 8 ) | (((uchar *)Long)[0] << 0 ); -    } -} - -/* Convert a 32 bit unsigned value from file's native byte order */ -static unsigned -Get32u(void *Long, int MotorolaOrder) -{ -    return (unsigned)Get32s(Long, MotorolaOrder) & 0xffffffff; -} - - -/* Evaluate number, be it int, rational, or float from directory. */ -static double -ConvertAnyFormat(void *ValuePtr, int Format, int MotorolaOrder) -{ -    double Value; -    Value = 0; - -    switch(Format) { -	case EXIF_FMT_SBYTE:     Value = *(signed char *)ValuePtr;  break; -	case EXIF_FMT_BYTE:      Value = *(uchar *)ValuePtr;        break; - -	case EXIF_FMT_USHORT:    Value = Get16u(ValuePtr,MotorolaOrder);          break; -	case EXIF_FMT_ULONG:     Value = Get32u(ValuePtr,MotorolaOrder);          break; - -	case EXIF_FMT_URATIONAL: -	case EXIF_FMT_SRATIONAL:  -		{ -			int Num,Den; -			Num = Get32s(ValuePtr,MotorolaOrder); -			Den = Get32s(4+(char *)ValuePtr,MotorolaOrder); -			if (Den == 0) { -				Value = 0; -			} else { -				Value = (double)Num/Den; -			} -			break; -		} - -	case EXIF_FMT_SSHORT:    Value = (signed short)Get16u(ValuePtr,MotorolaOrder);  break; -	case EXIF_FMT_SLONG:     Value = Get32s(ValuePtr,MotorolaOrder);                break; - -        /* Not sure if this is correct (never seen float used in Exif format) */ -	case EXIF_FMT_SINGLE:    Value = (double)*(float *)ValuePtr;      break; -	case EXIF_FMT_DOUBLE:    Value = *(double *)ValuePtr;             break; -    } -    return Value; -} - -/* Evaluate number, be it int, rational, or float from directory. */ -static char -ConvertAnyFormat2(void *ValuePtr, int ByteCount, int Format, int MotorolaOrder, exif_rec_data_t *data_p) -{ -	char *str, *p; -	char r_type; -	unsigned char c; -	static char hexdigits[] = "0123456789ABCDEF"; - -    switch(Format) { -	case EXIF_FMT_STRING: -		data_p->s = exif_strndup(ValuePtr, ByteCount); -		r_type = 's'; -		break; - -	case EXIF_FMT_SBYTE: -		data_p->l = (long)*(signed char *)ValuePtr; -		r_type = 'l'; -		break; - -	case EXIF_FMT_BYTE: -		data_p->l = (long)*(uchar *)ValuePtr; -		r_type = 'l'; -        break; - -	case EXIF_FMT_USHORT: -		data_p->l = (long)Get16u(ValuePtr,MotorolaOrder); -		r_type = 'l'; -		break; -	case EXIF_FMT_ULONG: -		data_p->l = (long)Get32u(ValuePtr,MotorolaOrder); -		r_type = 'l'; -		break; - -	case EXIF_FMT_URATIONAL: -	case EXIF_FMT_SRATIONAL:  -		{ -			int Num,Den; -			data_p->r.num = Get32s(ValuePtr,MotorolaOrder); -			data_p->r.denom = Get32s(4+(char *)ValuePtr,MotorolaOrder); -			r_type = 'r'; -			break; -		} - -	case EXIF_FMT_SSHORT: -		data_p->l = (signed short)Get16u(ValuePtr,MotorolaOrder); -		r_type = 'l'; -		break; -	case EXIF_FMT_SLONG: -		data_p->l = (long)Get32s(ValuePtr,MotorolaOrder); -		r_type = 'l'; -		break; - -        /* Not sure if this is correct (never seen float used in Exif format) */ -	case EXIF_FMT_SINGLE: -		data_p->f = *(float *)ValuePtr; -		r_type = 'f'; -		break; - -	case EXIF_FMT_DOUBLE: -		data_p->g = *(double *)ValuePtr; -		r_type = 'f'; -		break; - -	default: -		/* unknown type */ -		p = str = (*exif_malloc_fn)(ByteCount*2 + 1); -		while (ByteCount--) { -			c = *(unsigned char *)ValuePtr++; -			*p++ = hexdigits[c / 16]; -			*p++ = hexdigits[c % 16]; -		} -		*p++ = '\0'; -		data_p->s = str; -		r_type = 's'; -		break; -    } -    return r_type; -} - - -static void -ProcessFocalPlaneUnits(ImageInfoType *ImageInfo, -					   void *ValuePtr, -					   int ByteCount, -					   int Format, -					   struct ExifTag *tag_p) -{ -    exif_rec_data_t rd; -	float FocalPlaneUnits; - -	switch((int)ConvertAnyFormat(ValuePtr, Format, ImageInfo->MotorolaOrder)) { -	case 1: -		FocalPlaneUnits = 25.4; -		break; /* inch */ -	case 2:  -		/* According to the information I was using, 2 means meters. -		   But looking at the Canon PowerShot's files, inches is the only -		   sensible value. */ -		FocalPlaneUnits = 25.4; -		break; - -	case 3: -		FocalPlaneUnits = 10; -		break;  /* centimeter */ -	case 4: -		FocalPlaneUnits = 1; -		break;  /* milimeter  */ -	case 5: -		FocalPlaneUnits = .001; -		break;  /* micrometer */ -	} - -	rd.f = FocalPlaneUnits; -	exif_append_data(&ImageInfo->d, -					 "FocalPlaneUnits", -					 'f', -					 Format, -					 &rd); -} - -static void -ProcessVersion(ImageInfoType *ImageInfo, -				   void *ValuePtr, -				   int ByteCount, -				   int Format, -				   struct ExifTag *tag_p) -{ -    exif_rec_data_t rd; -	rd.s = exif_strndup(ValuePtr, ByteCount); -	exif_append_data(&ImageInfo->d, -					 tag_p->Desc, -					 's', -					 Format, -					 &rd); -} - -static void -ProcessUserComment(ImageInfoType *ImageInfo, -				   void *_ValuePtr, -				   int ByteCount, -				   int Format, -				   struct ExifTag *tag_p) -{ -	char *ValuePtr = (char *)_ValuePtr; -    exif_rec_data_t rd; -	int a; - -	/* Olympus has this padded with trailing spaces.  Remove these first. */ -	for (a=ByteCount;;) { -		a--; -		if ((ValuePtr)[a] == ' ') { -			(ValuePtr)[a] = '\0'; -		} else { -			break; -		} -		if (a == 0) break; -	} - -	/* Copy the comment */ -	if (memcmp(ValuePtr, "ASCII",5) == 0) { -		for (a=5;a<10;a++) { -			int c; -			c = (ValuePtr)[a]; -			if (c != '\0' && c != ' ') { -				rd.s = exif_strndup(a+ValuePtr, ByteCount - a); -				exif_append_data(&ImageInfo->d, -								 "UserComment", -								 's', -								 Format, -								 &rd); -				break; -			} -		} -                     -	} else { -		rd.s = exif_strndup(ValuePtr, ByteCount); -		exif_append_data(&ImageInfo->d, -						 "UserComment", -						 's', -						 Format, -						 &rd); -	} -} - -static void -ProcessShutterSpeed(ImageInfoType *ImageInfo, -					void *ValuePtr, -					int ByteCount, -					int Format, -					struct ExifTag *tag_p) -{ -    exif_rec_data_t rd; -	char rec_type; - -	rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format, -								 ImageInfo->MotorolaOrder, -								 &rd); -	exif_append_data(&ImageInfo->d, -					 tag_p->Desc, -					 rec_type, -					 Format, -					 &rd); - -	/* Convert shutter speed value to shutter speed; -	 * shutter speed is 1/(2**ShutterSpeedValue) -     */ -	rd.r.denom = (int)pow(2.0, ((double)rd.r.num)/((double)rd.r.denom)); -	rd.r.num = 1; -	exif_append_data(&ImageInfo->d, -					 "ShutterSpeed", -					 'r', -					 EXIF_FMT_COMPUTED, -					 &rd); -	 -} - -static void -ProcessAperture(ImageInfoType *ImageInfo, -				void *ValuePtr, -				int ByteCount, -				int Format, -				struct ExifTag *tag_p) -{ -    exif_rec_data_t rd; -	char rec_type; -	double fstop; -	char label[32]; - -	rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format, -								 ImageInfo->MotorolaOrder, -								 &rd); -	exif_append_data(&ImageInfo->d, -					 tag_p->Desc, -					 rec_type, -					 Format, -					 &rd); - -	if (exif_find_record(ImageInfo->d, "FNumber") == NULL) { -		/* Convert aperture to F-stop. */ -		fstop = pow(sqrt(2), ((double)rd.r.num)/((double)rd.r.denom)); -		sprintf(label, "f%.1g", fstop); -		rd.s = (char*)strdup(label); -		exif_append_data(&ImageInfo->d, -						 "FNumber", -						 's', -						 EXIF_FMT_COMPUTED, -						 &rd); -	} -} - -static void -ProcessCanonMakerNote(ImageInfoType *ImageInfo, -				 void *ValuePtr, -				 int ByteCount, -				 int Format, -				 struct ExifTag *tag_p, -				 char *OffsetBase) -{ -	 -	/* This is for the Canon MakerNote. */ -	/* XXX - go by value of Maker tag. */ -    exif_rec_data_t rd; -	char rec_type; -	unsigned long n_dir, tag, format, components, offset; -	char label[32]; -	void *OffsetPtr; - -	n_dir = Get16u(ValuePtr, ImageInfo->MotorolaOrder); -	ValuePtr += 2; -	while (n_dir--) { -		tag = Get16u(ValuePtr, ImageInfo->MotorolaOrder); -		ValuePtr += 2; -		format = Get16u(ValuePtr, ImageInfo->MotorolaOrder); -		ValuePtr += 2; -		components = Get32u(ValuePtr, ImageInfo->MotorolaOrder); -		ValuePtr += 4; -		offset = Get32u(ValuePtr, ImageInfo->MotorolaOrder); -        ByteCount = components * ExifBytesPerFormat[format]; -		if (ByteCount > 4) { -			OffsetPtr = OffsetBase + offset; -		} else { -			OffsetPtr = ValuePtr; -		} -		ValuePtr += 4; -		rec_type = ConvertAnyFormat2(OffsetPtr, ByteCount, format, -									 ImageInfo->MotorolaOrder, -									 &rd); -		sprintf(label, "MakerNote%04x", tag); -		exif_append_data(&ImageInfo->d, -						 label, -						 rec_type, -						 format, -						 &rd); -		 -	} -} - - -struct MakerNote { -	char *Make; -	void (*Func)(); -}; - -static struct MakerNote -MakerProcessors[] = { -	{"Canon", ProcessCanonMakerNote}, -    {NULL, NULL} -}; - -static void -ProcessMakerNote(ImageInfoType *ImageInfo, -				 void *ValuePtr, -				 int ByteCount, -				 int Format, -				 struct ExifTag *tag_p, -				 char *OffsetBase) -{ -	struct MakerNote *mn_p; -	exif_record_t *rec_p; - -	rec_p = exif_find_record(ImageInfo->d, "Make"); -	if (rec_p == NULL) { -		return; -	} - -	for(mn_p = &MakerProcessors[0]; mn_p->Make != NULL; mn_p++) { -		if (strcmp(mn_p->Make, rec_p->rec_data.s) == 0) { -			(*mn_p->Func)(ImageInfo, ValuePtr, ByteCount, Format, tag_p, OffsetBase); -			break; -		} -	} -} - -static struct ExifTag -TagTable[] = { -	{   0x0001, "InteroperabilityIndex"}, -	{   0x0002, "InteroperabilityVersion", ProcessVersion}, -	{	0x0100,	"ImageWidth"}, -	{	0x0101,	"ImageLength"}, -	{	0x0102,	"BitsPerSample"}, -	{	0x0103,	"Compression"}, -	{	0x0106,	"PhotometricInterpretation"}, -	{	0x010A,	"FillOrder"}, -	{	0x010D,	"DocumentName"}, -	{	0x010E,	"ImageDescription"}, -	{	0x010F,	"Make"}, -	{	0x0110,	"Model"}, -	{	0x0111,	"StripOffsets"}, -	{	0x0112,	"Orientation"}, -	{	0x0115,	"SamplesPerPixel"}, -	{	0x0116,	"RowsPerStrip"}, -	{	0x0117,	"StripByteCounts"}, -	{	0x011A,	"XResolution"}, -	{	0x011B,	"YResolution"}, -	{	0x011C,	"PlanarConfiguration"}, -	{	0x0128,	"ResolutionUnit"}, -	{	0x012D,	"TransferFunction"}, -	{	0x0131,	"Software"}, -	{	0x0132,	"DateTime"}, -	{	0x013B,	"Artist"}, -	{	0x013E,	"WhitePoint"}, -	{	0x013F,	"PrimaryChromaticities"}, -	{	0x0156,	"TransferRange"}, -	{	0x0200,	"JPEGProc"}, -	{	0x0201,	"JPEGInterchangeFormat"}, -	{	0x0202,	"JPEGInterchangeFormatLength"}, -	{	0x0211,	"YCbCrCoefficients"}, -	{	0x0212,	"YCbCrSubSampling"}, -	{	0x0213,	"YCbCrPositioning"}, -	{	0x0214,	"ReferenceBlackWhite"}, -	{   0x1000, "RelatedImageFileFormat"}, -	{   0x1001, "RelatedImageWidth"}, -	{   0x1002, "RelatedImageLength"}, -	{	0x828D,	"CFARepeatPatternDim"}, -	{	0x828E,	"CFAPattern"}, -	{	0x828F,	"BatteryLevel"}, -	{	0x8298,	"Copyright"}, -	{	0x829A,	"ExposureTime"}, -	{	0x829D,	"FNumber"}, -	{	0x83BB,	"IPTC/NAA"}, -	{	0x8769,	"ExifOffset"}, -	{	0x8773,	"InterColorProfile"}, -	{	0x8822,	"ExposureProgram"}, -	{	0x8824,	"SpectralSensitivity"}, -	{	0x8825,	"GPSInfo"}, -	{	0x8827,	"ISOSpeedRatings"}, -	{	0x8828,	"OECF"}, -	{	0x9000,	"ExifVersion", ProcessVersion}, -	{	0x9003,	"DateTimeOriginal"}, -	{	0x9004,	"DateTimeDigitized"}, -	{	0x9101,	"ComponentsConfiguration"}, -	{	0x9102,	"CompressedBitsPerPixel"}, -	{	0x9201,	"ShutterSpeedValue", ProcessShutterSpeed}, -	{	0x9202,	"ApertureValue", ProcessAperture}, -	{	0x9203,	"BrightnessValue"}, -	{	0x9204,	"ExposureBiasValue"}, -	{	0x9205,	"MaxApertureValue", ProcessAperture}, -	{	0x9206,	"SubjectDistance"}, -	{	0x9207,	"MeteringMode"}, -	{	0x9208,	"LightSource"}, -	{	0x9209,	"Flash"}, -	{	0x920A,	"FocalLength"}, -	{	0x927C,	"MakerNote", ProcessMakerNote}, -	{	0x9286,	"UserComment", ProcessUserComment}, -	{	0x9290,	"SubSecTime"}, -	{	0x9291,	"SubSecTimeOriginal"}, -	{	0x9292,	"SubSecTimeDigitized"}, -	{	0xA000,	"FlashPixVersion", ProcessVersion}, -	{	0xA001,	"ColorSpace"}, -	{	0xA002,	"ExifImageWidth"}, -	{	0xA003,	"ExifImageLength"}, -	{	0xA005,	"InteroperabilityOffset"}, -	{	0xA20B,	"FlashEnergy"},			        /* 0x920B in TIFF/EP */ -	{	0xA20C,	"SpatialFrequencyResponse"},	/* 0x920C    -  -    */ -	{	0xA20E,	"FocalPlaneXResolution"},    	/* 0x920E    -  -    */ -	{	0xA20F,	"FocalPlaneYResolution"},	    /* 0x920F    -  -    */ -	{	0xA210,	"FocalPlaneResolutionUnit", ProcessFocalPlaneUnits}, -	                                            /* 0x9210    -  -    */ -	{	0xA214,	"SubjectLocation"},		        /* 0x9214    -  -    */ -	{	0xA215,	"ExposureIndex"},		        /* 0x9215    -  -    */ -	{	0xA217,	"SensingMethod"},		        /* 0x9217    -  -    */ -	{	0xA300,	"FileSource"}, -	{	0xA301,	"SceneType"}, -	{        0, NULL} -} ; - - - -/* Process one of the nested EXIF directories. */ -static int -ProcessExifDir(ImageInfoType *ImageInfo, char *DirStart, char *OffsetBase, unsigned ExifLength, char *LastExifRefd) -{ -    int de; -    int a; -    int NumDirEntries; -    exif_rec_data_t rd; -	char rec_type; -	char label[32]; - -    NumDirEntries = Get16u(DirStart, ImageInfo->MotorolaOrder); - -    if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength)) { -		exif_error("Illegally sized directory"); -		return FALSE; -    } - - -    for (de=0;de<NumDirEntries;de++) { -        int Tag, Format, Components; -        char *ValuePtr; -        int ByteCount; -        char *DirEntry; -		struct ExifTag *tag_p; - -        DirEntry = DirStart+2+12*de; - -        Tag = Get16u(DirEntry, ImageInfo->MotorolaOrder); -        Format = Get16u(DirEntry+2, ImageInfo->MotorolaOrder); -        Components = Get32u(DirEntry+4, ImageInfo->MotorolaOrder); - -        if ((Format-1) >= NUM_FORMATS) { -            /* (-1) catches illegal zero case as unsigned underflows to positive large. */ -			exif_error("Illegal format code in EXIF dir"); -			return FALSE; -        } - -        ByteCount = Components * ExifBytesPerFormat[Format]; - -        if (ByteCount > 4) { -            unsigned OffsetVal; -            OffsetVal = Get32u(DirEntry+8, ImageInfo->MotorolaOrder); -            /* If its bigger than 4 bytes, the dir entry contains an offset. */ -            if (OffsetVal+ByteCount > ExifLength) { -                /* Bogus pointer offset and / or bytecount value */ -				/*                printf("Offset %d bytes %d ExifLen %d\n",OffsetVal, ByteCount, ExifLength); */ - -				exif_error("Illegal pointer offset value in EXIF"); -				return FALSE; -            } -            ValuePtr = OffsetBase+OffsetVal; -        } else { -            /* 4 bytes or less and value is in the dir entry itself */ -            ValuePtr = DirEntry+8; -        } - -        if (LastExifRefd < ValuePtr+ByteCount) { -            /*  -			   Keep track of last byte in the exif header that was actually referenced. -               That way, we know where the discardable thumbnail data begins. -			*/ -            LastExifRefd = ValuePtr+ByteCount; -        } - -        if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET) { -            char *SubdirStart; -            SubdirStart = OffsetBase + Get32u(ValuePtr, ImageInfo->MotorolaOrder); -            if (SubdirStart < OffsetBase || SubdirStart > OffsetBase+ExifLength) { -				exif_error("Illegal subdirectory link"); -				return FALSE; -            } -            ProcessExifDir(ImageInfo, SubdirStart, OffsetBase, ExifLength, LastExifRefd); -            continue; -        } - -		/* Search through tag table */ -		for (tag_p = &TagTable[0]; tag_p->Desc != NULL; tag_p++) { -			if (tag_p->Tag == Tag) { -				if (tag_p->Func != NULL) { -					(*tag_p->Func)(ImageInfo, ValuePtr, ByteCount, Format, tag_p, OffsetBase); -				} else { -					rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format, -												 ImageInfo->MotorolaOrder, -												 &rd); -					exif_append_data(&ImageInfo->d, -									 tag_p->Desc, -									 rec_type, -									 Format, -									 &rd); -				} -				break; -			} -		} -		if (tag_p->Desc == NULL) { -			rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format, -										 ImageInfo->MotorolaOrder, -										 &rd); -			sprintf(label, "0x%04x", Tag); -			exif_append_data(&ImageInfo->d, -							 label, -							 rec_type, -							 Format, -							 &rd); -		} -	} -    return TRUE; -} - -/*  -   Process an EXIF marker -   Describes all the drivel that most digital cameras include... -*/ -static int -process_EXIF (ImageInfoType *ImageInfo, char *CharBuf, unsigned int length, char *LastExifRefd) -{ -	int cc; -	exif_rec_data_t rd; -	LastExifRefd = CharBuf; - -	{   /* Check the EXIF header component */ -		static const uchar ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; -		if (memcmp(CharBuf+2, ExifHeader,6)) { -			exif_error("Incorrect Exif header"); -			return FALSE; -		} -	} - -	if (memcmp(CharBuf+8,"II",2) == 0) { -		ImageInfo->MotorolaOrder = 0; -	} else { -		if (memcmp(CharBuf+8,"MM",2) == 0) { -			ImageInfo->MotorolaOrder = 1; -		} else { -			exif_error("Invalid Exif alignment marker."); -			return FALSE; -		} -	} - -	/* Check the next two values for correctness. */ -	if (Get16u(CharBuf+10,ImageInfo->MotorolaOrder) != 0x2a -		|| Get32u(CharBuf+12,ImageInfo->MotorolaOrder) != 0x08) { -		exif_error("Invalid Exif start (1, NULL)"); -		return FALSE; -	} - -	/* First directory starts 16 bytes in.  Offsets start at 8 bytes in. */ -	cc = ProcessExifDir(ImageInfo, CharBuf+16, CharBuf+8, length-6, LastExifRefd); -	if (cc != TRUE) { -		return cc; -	} -	return TRUE; -} -  -/* Parse the marker stream until SOS or EOI is seen; */ -static int  -scan_JPEG_header (ImageInfoType *ImageInfo, FILE *infile, Section_t *Sections, int *SectionsRead, int ReadAll, char *LastExifRefd) -{ -    int a; -    int HaveCom = FALSE; - -    a = fgetc(infile); -    if (a != 0xff || fgetc(infile) != M_SOI) { -        return FALSE; -    } - -    for(*SectionsRead=0;*SectionsRead < 19;) { -        int itemlen; -        int marker = 0; -        int ll,lh, got; -        uchar *Data; - -        for (a=0;a<7;a++) { -            marker = fgetc(infile); -            if (marker != 0xff) break; -        } -        if (marker == 0xff) { -            /* 0xff is legal padding, but if we get that many, something's wrong. */ -			exif_error("too many padding bytes!"); -			return FALSE; -        } - -        Sections[*SectionsRead].Type = marker; -   -        /* Read the length of the section. */ -        lh = fgetc(infile); -        ll = fgetc(infile); - -        itemlen = (lh << 8) | ll; - -        if (itemlen < 2) { -			exif_error("invalid marker"); -			return FALSE; -        } - -        Sections[*SectionsRead].Size = itemlen; - -        Data = (uchar *)(*exif_malloc_fn)(itemlen+1); /* Add 1 to allow sticking a 0 at the end. */ -        Sections[*SectionsRead].Data = Data; - -        /* Store first two pre-read bytes. */ -        Data[0] = (uchar)lh; -        Data[1] = (uchar)ll; - -        got = fread(Data+2, 1, itemlen-2, infile); /* Read the whole section. */ -        if (got != itemlen-2) { -			exif_error("reading from file"); -			return FALSE; -        } -        *SectionsRead += 1; - -        switch(marker) { -		case M_SOS:   /* stop before hitting compressed data  */ -			/* If reading entire image is requested, read the rest of the data. */ -			if (ReadAll) { -				int cp, ep, size; -				/* Determine how much file is left. */ -				cp = ftell(infile); -				fseek(infile, 0, SEEK_END); -				ep = ftell(infile); -				fseek(infile, cp, SEEK_SET); - -				size = ep-cp; -				Data = (uchar *)(*exif_malloc_fn)(size); -				if (Data == NULL) { -					exif_error("could not allocate data for entire image"); -					return FALSE; -				} - -				got = fread(Data, 1, size, infile); -				if (got != size) { -					exif_error("could not read the rest of the image"); -					return FALSE; -				} - -				Sections[*SectionsRead].Data = Data; -				Sections[*SectionsRead].Size = size; -				Sections[*SectionsRead].Type = PSEUDO_IMAGE_MARKER; -				(*SectionsRead)++; -				/* -				 *HaveAll = 1; -				 */ -			} -			return TRUE; - -		case M_EOI:   /* in case it's a tables-only JPEG stream */ -			exif_error("No image in jpeg!"); -			return FALSE; - -		case M_COM: /* Comment section */ -			if (HaveCom) { -				(*SectionsRead) -= 1; -				(*exif_free_fn)(Sections[*SectionsRead].Data); -			} else { -				process_COM(ImageInfo, Data, itemlen); -				HaveCom = TRUE; -			} -			break; - -		case M_EXIF: -			if (*SectionsRead <= 2) { -				/* Seen files from some 'U-lead' software with Vivitar scanner -				   that uses marker 31 later in the file (no clue what for!) */ -				process_EXIF(ImageInfo, (char *)Data, itemlen, LastExifRefd); -			} -			break; - -		case M_SOF0:  -		case M_SOF1:  -		case M_SOF2:  -		case M_SOF3:  -		case M_SOF5:  -		case M_SOF6:  -		case M_SOF7:  -		case M_SOF9:  -		case M_SOF10: -		case M_SOF11: -		case M_SOF13: -		case M_SOF14: -		case M_SOF15: -			process_SOFn(ImageInfo, Data, marker); -			break; -		default: -			/* skip any other marker silently. */ -			break; -        } -    } -    return TRUE; -} - -/*  -   Discard read data. -*/ -static void -DiscardData(Section_t *Sections, int *SectionsRead) -{ -    int a; -    for (a=0;a<*SectionsRead-1;a++) { -        (*exif_free_fn)(Sections[a].Data); -    } -    *SectionsRead = 0; -} - -/*  -   Read image data. -*/ -static int -ReadJpegFile(ImageInfoType *ImageInfo, Section_t *Sections,  -			 int *SectionsRead, int fd,  -			 int ReadAll, char *LastExifRefd) -{ -    FILE *infile; -    int ret; -	char *tmp; -	char **p_argv; -	int p_argc; - -    infile = fdopen(fd, "rb"); /* Unix ignores 'b', windows needs it. */ - -    if (infile == NULL) { -		exif_error("Unable to open '%s'", ImageInfo->filename); -		return FALSE; -    } - -    /* Start with an empty image information structure. */ -    memset(ImageInfo, 0, sizeof(*ImageInfo)); -    memset(Sections, 0, sizeof(*Sections)); - -    ImageInfo->d = exif_alloc(); - -    /* Scan the JPEG headers. */ -    ret = scan_JPEG_header(ImageInfo, infile, Sections, SectionsRead, ReadAll, LastExifRefd); -    if (!ret) { -		exif_error("Invalid Jpeg file: '%s'",ImageInfo->filename); -		return FALSE; -    } - -    fclose(infile); - -    return ret; -} - -static int -read_jpeg_exif(ImageInfoType *ImageInfo, int fd, int ReadAll) -{ -	Section_t Sections[20]; -	int SectionsRead; -	char *LastExifRefd=NULL; -	int ret; -	int thumbsize=0; - -	ret = ReadJpegFile(ImageInfo, Sections, &SectionsRead, fd, ReadAll, LastExifRefd);  -#if 0 -	/* -	 * Thought this might pick out the embedded thumbnail, but it doesn't work.   -RL -     */ -	for (i=0;i<SectionsRead-1;i++) { -		if (Sections[i].Type == M_EXIF) { -			thumbsize = Sections[i].Size; -			if(thumbsize>0) { -				ImageInfo->Thumbnail = (*exif_malloc_fn)(thumbsize+5); -				ImageInfo->ThumbnailSize = thumbsize; -				ImageInfo->Thumbnail[0] = 0xff; -				ImageInfo->Thumbnail[1] = 0xd8; -				ImageInfo->Thumbnail[2] = 0xff; -				memcpy(ImageInfo->Thumbnail+4, Sections[i].Data, thumbsize+4); -			} -		} -	} -#endif -    if (ret != FALSE) { -        DiscardData(Sections, &SectionsRead); -    } -	return(ret); -} - -exif_data_t * -exif_parse_fd(int fd) -{ -	ImageInfoType ImageInfo; - -	ImageInfo.filename = "<file stream>"; -	if (read_jpeg_exif(&ImageInfo, fd, 1) != TRUE) { -		return NULL; -	} -	return ImageInfo.d; -} - -exif_data_t * -exif_parse_file(const char *filename) -{ -	ImageInfoType ImageInfo; -	int fd; -	 -	ImageInfo.filename = filename; -	fd = open(filename, O_RDONLY); -	if (fd < 0) { -		return NULL; -	} - -	if (read_jpeg_exif(&ImageInfo, fd, 1) != TRUE) { -		return NULL; -	} -	return ImageInfo.d; -} - -void -exif_free_data(struct exif_data *d) -{ -	int i; -	for (i=0; i<d->n_recs; i++) { -		(*exif_free_fn)(d->recs[i].rec_name); -		if (d->recs[i].rec_type == 's') { -			(*exif_free_fn)(d->recs[i].rec_data.s); -		} -	} -	(*exif_free_fn)(d); -} - -void -exif_init(void *(*malloc_fn)(int), -		  void (*free_fn)(void *), -		  void *(*realloc_fn)(void *, int)) -{ -	if (malloc_fn == NULL) { -		malloc_fn = (void *(*)(int))malloc; -	} -	exif_malloc_fn = malloc_fn; -	if (free_fn == NULL) { -		free_fn = (void (*)(void *))free; -	} -	exif_free_fn = free_fn; -	if (realloc_fn == NULL) { -		realloc_fn = (void *(*)(void *, int))realloc; -	} -	exif_realloc_fn = realloc_fn; -} - -extern exif_record_t * -exif_find_record(exif_data_t *d, const char *rec_name) -{ -	int i; -	for (i=0; i<d->n_recs; i++) { -		if (strcmp(d->recs[i].rec_name, rec_name) == 0) { -			return &d->recs[i]; -		} -	} -	return NULL; -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ - - diff --git a/src/libexif/exif.h b/src/libexif/exif.h deleted file mode 100644 index 32f0a6d..0000000 --- a/src/libexif/exif.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - -Copyright © 2000 Curtis Galloway - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -*/ - -typedef struct exif_rational { -  int      num; -  unsigned denom; -} exif_rational_t; - -typedef union { -  long            l; -  float           f; -  double          g; -  char *          s; -  exif_rational_t r; -} exif_rec_data_t; - -typedef struct exif_record { -  char *           rec_name; -  char             rec_type; -  int              exif_format; -  exif_rec_data_t  rec_data; -} exif_record_t; - -typedef struct exif_data { -  int           n_recs; -  int           n_alloc; -  exif_record_t recs[0]; -} exif_data_t; - - -/* EXIF data formats */ - -#define EXIF_FMT_COMPUTED  -1 /* Not in raw data */ -#define EXIF_FMT_BYTE       1  -#define EXIF_FMT_STRING     2 -#define EXIF_FMT_USHORT     3 -#define EXIF_FMT_ULONG      4 -#define EXIF_FMT_URATIONAL  5 -#define EXIF_FMT_SBYTE      6 -#define EXIF_FMT_UNDEFINED  7 -#define EXIF_FMT_SSHORT     8 -#define EXIF_FMT_SLONG      9 -#define EXIF_FMT_SRATIONAL 10 -#define EXIF_FMT_SINGLE    11 -#define EXIF_FMT_DOUBLE    12 - -extern void -exif_init(void *(*malloc_fn)(int), -	  void (*free_fn)(void *), -	  void *(*realloc_fn)(void *, int)); - -extern exif_data_t * -exif_parse_fd(int fd); - -extern exif_data_t * -exif_parse_file(const char *filename); - -extern void -exif_free_data(exif_data_t *d); - -extern exif_record_t * -exif_find_record(exif_data_t *d, const char *rec_name); - - diff --git a/src/libexif/fuji/exif-mnote-data-fuji.c b/src/libexif/fuji/exif-mnote-data-fuji.c new file mode 100644 index 0000000..b7b311b --- /dev/null +++ b/src/libexif/fuji/exif-mnote-data-fuji.c @@ -0,0 +1,297 @@ +/* exif-mnote-data-fuji.c + * + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful,  + * but WITHOUT ANY WARRANTY; without even the implied warranty of  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.  + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <stdlib.h> +#include <string.h> + + +#include <config.h> +#include <libexif/exif-byte-order.h> +#include <libexif/exif-utils.h> + +#include "exif-mnote-data-fuji.h" + +struct _MNoteFujiDataPrivate { +	ExifByteOrder order; +}; + +static void +exif_mnote_data_fuji_clear (ExifMnoteDataFuji *n) +{ +	ExifMnoteData *d = (ExifMnoteData *) n; +	unsigned int i; + +	if (!n) return; + +	if (n->entries) { +		for (i = 0; i < n->count; i++) +			if (n->entries[i].data) { +				exif_mem_free (d->mem, n->entries[i].data); +				n->entries[i].data = NULL; +			} +		exif_mem_free (d->mem, n->entries); +		n->entries = NULL; +		n->count = 0; +	} +} + +static void +exif_mnote_data_fuji_free (ExifMnoteData *n) +{ +	if (!n) return; + +	exif_mnote_data_fuji_clear ((ExifMnoteDataFuji *) n); +} + +static char * +exif_mnote_data_fuji_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen) +{ +	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d; + +	if (!d || !val) return NULL; +	if (i > n->count -1) return NULL; +	exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji", +		  "Querying value for tag '%s'...", +		  mnote_fuji_tag_get_name (n->entries[i].tag)); +	return mnote_fuji_entry_get_value (&n->entries[i], val, maxlen); +} + +static void +exif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf, +			   unsigned int *buf_size) +{ +	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) ne; +	size_t i, o, s, doff; +	unsigned char *t; +	size_t ts; + +	if (!n || !buf || !buf_size) return; + +	/* +	 * Allocate enough memory for all entries and the number +	 * of entries. +	 */ +	*buf_size = 8 + 4 + 2 + n->count * 12 + 4; +	*buf = exif_mem_alloc (ne->mem, *buf_size); +	if (!*buf) { +		*buf_size = 0; +		return; +	} + +	/* +	 * Header: "FUJIFILM" and 4 bytes offset to the first entry. +	 * As the first entry will start right thereafter, the offset is 12. +	 */ +	memcpy (*buf, "FUJIFILM", 8); +	exif_set_long (*buf + 8, n->order, 12); + +	/* Save the number of entries */ +	exif_set_short (*buf + 8 + 4, n->order, (ExifShort) n->count); +	 +	/* Save each entry */ +	for (i = 0; i < n->count; i++) { +		o = 8 + 4 + 2 + i * 12; +		exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag); +		exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format); +		exif_set_long  (*buf + o + 4, n->order, n->entries[i].components); +		o += 8; +		s = exif_format_get_size (n->entries[i].format) * +						n->entries[i].components; +		if (s > 65536) { +			/* Corrupt data: EXIF data size is limited to the +			 * maximum size of a JPEG segment (64 kb). +			 */ +			continue; +		} +		if (s > 4) { +			ts = *buf_size + s; + +			/* Ensure even offsets. Set padding bytes to 0. */ +			if (s & 1) ts += 1; +			t = exif_mem_realloc (ne->mem, *buf, ts); +			if (!t) { +				return; +			} +			*buf = t; +			*buf_size = ts; +			doff = *buf_size - s; +			if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; } +			exif_set_long (*buf + o, n->order, doff); +		} else +			doff = o; + +		/* +		 * Write the data. Fill unneeded bytes with 0. Do not +		 * crash if data is NULL. +		 */ +		if (!n->entries[i].data) memset (*buf + doff, 0, s); +		else memcpy (*buf + doff, n->entries[i].data, s); +	} +} + +static void +exif_mnote_data_fuji_load (ExifMnoteData *en, +	const unsigned char *buf, unsigned int buf_size) +{ +	ExifMnoteDataFuji *n = (ExifMnoteDataFuji*) en; +	ExifLong c; +	size_t i, o, s, datao = 6 + n->offset; +	MnoteFujiEntry *t; + +	if (!n || !buf || !buf_size || (buf_size < datao + 12)) return; + +	/* Read the number of entries and remove old ones. */ +	n->order = EXIF_BYTE_ORDER_INTEL; +	datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL); +	c = exif_get_short (buf + datao, EXIF_BYTE_ORDER_INTEL); +	datao += 2; +	exif_mnote_data_fuji_clear (n); + +	/* Parse the entries */ +	for (i = 0; i < c; i++) { +		o = datao + 12 * i; +		if (datao + 12 > buf_size) return; + +		t = exif_mem_realloc (en->mem, n->entries, +				sizeof (MnoteFujiEntry) * (i + 1)); +		if (!t) return; +		n->count = i + 1; +		n->entries = t; +		memset (&n->entries[i], 0, sizeof (MnoteFujiEntry)); +		n->entries[i].tag        = exif_get_short (buf + o, n->order); +		n->entries[i].format     = exif_get_short (buf + o + 2, n->order); +		n->entries[i].components = exif_get_long (buf + o + 4, n->order); +		n->entries[i].order      = n->order; + +		/* +		 * Size? If bigger than 4 bytes, the actual data is not +		 * in the entry but somewhere else (offset). +		 */ +		s = exif_format_get_size (n->entries[i].format) * n->entries[i].components; +		if (!s) return; +		o += 8; +		if (s > 4) o = exif_get_long (buf + o, n->order) + 6 + n->offset; +		if (o + s > buf_size) return; + +		/* Sanity check */ +		n->entries[i].data = exif_mem_alloc (en->mem, s); +		if (!n->entries[i].data) return; +		n->entries[i].size = s; +		memcpy (n->entries[i].data, buf + o, s); +	} +} + +static unsigned int +exif_mnote_data_fuji_count (ExifMnoteData *n) +{ +	return n ? ((ExifMnoteDataFuji *) n)->count : 0; +} + +static unsigned int +exif_mnote_data_fuji_get_id (ExifMnoteData *d, unsigned int n) +{ +	ExifMnoteDataFuji *note = (ExifMnoteDataFuji *) d; + +	if (!note) return 0; +	if (note->count <= n) return 0; +	return note->entries[n].tag; +} + +static const char * +exif_mnote_data_fuji_get_name (ExifMnoteData *d, unsigned int i) +{ +	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d; + +	if (!n) return NULL; +	if (i >= n->count) return NULL; +	return mnote_fuji_tag_get_name (n->entries[i].tag); +} + +static const char * +exif_mnote_data_fuji_get_title (ExifMnoteData *d, unsigned int i) +{ +	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d; +	 +	if (!n) return NULL; +	if (i >= n->count) return NULL; +        return mnote_fuji_tag_get_title (n->entries[i].tag); +} + +static const char * +exif_mnote_data_fuji_get_description (ExifMnoteData *d, unsigned int i) +{ +	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d; +	 +	if (!n) return NULL; +	if (i >= n->count) return NULL; +        return mnote_fuji_tag_get_description (n->entries[i].tag); +} + +static void +exif_mnote_data_fuji_set_byte_order (ExifMnoteData *d, ExifByteOrder o) +{ +	ExifByteOrder o_orig; +	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d; +	unsigned int i; + +	if (!n) return; + +	o_orig = n->order; +	n->order = o; +	for (i = 0; i < n->count; i++) { +		n->entries[i].order = o; +		exif_array_set_byte_order (n->entries[i].format, n->entries[i].data, +				n->entries[i].components, o_orig, o); +	} +} + +static void +exif_mnote_data_fuji_set_offset (ExifMnoteData *n, unsigned int o) +{ +	if (n) ((ExifMnoteDataFuji *) n)->offset = o; +} + +ExifMnoteData * +exif_mnote_data_fuji_new (ExifMem *mem) +{ +	ExifMnoteData *d; + +	if (!mem) return NULL; + +	d = exif_mem_alloc (mem, sizeof (ExifMnoteDataFuji)); +	if (!d) return NULL; + +	exif_mnote_data_construct (d, mem); + +	/* Set up function pointers */ +	d->methods.free            = exif_mnote_data_fuji_free; +	d->methods.set_byte_order  = exif_mnote_data_fuji_set_byte_order; +	d->methods.set_offset      = exif_mnote_data_fuji_set_offset; +	d->methods.load            = exif_mnote_data_fuji_load; +	d->methods.save            = exif_mnote_data_fuji_save; +	d->methods.count           = exif_mnote_data_fuji_count; +	d->methods.get_id          = exif_mnote_data_fuji_get_id; +	d->methods.get_name        = exif_mnote_data_fuji_get_name; +	d->methods.get_title       = exif_mnote_data_fuji_get_title; +	d->methods.get_description = exif_mnote_data_fuji_get_description; +	d->methods.get_value       = exif_mnote_data_fuji_get_value; + +	return d; +} diff --git a/src/libexif/fuji/exif-mnote-data-fuji.h b/src/libexif/fuji/exif-mnote-data-fuji.h new file mode 100644 index 0000000..298193a --- /dev/null +++ b/src/libexif/fuji/exif-mnote-data-fuji.h @@ -0,0 +1,43 @@ +/* exif-mnote-data-fuji.h + * + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful,  + * but WITHOUT ANY WARRANTY; without even the implied warranty of  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.  + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __MNOTE_FUJI_CONTENT_H__ +#define __MNOTE_FUJI_CONTENT_H__ + +#include <libexif/exif-mnote-data.h> + +typedef struct _ExifMnoteDataFuji        ExifMnoteDataFuji; + +#include <libexif/exif-mnote-data-priv.h> +#include <libexif/fuji/mnote-fuji-entry.h> + +struct _ExifMnoteDataFuji { +	ExifMnoteData parent; + +	MnoteFujiEntry *entries; +	unsigned int count; + +	ExifByteOrder order; +	unsigned int offset; +}; + +ExifMnoteData *exif_mnote_data_fuji_new (ExifMem *); + +#endif /* __MNOTE_FUJI_CONTENT_H__ */ diff --git a/src/libexif/fuji/mnote-fuji-entry.c b/src/libexif/fuji/mnote-fuji-entry.c new file mode 100644 index 0000000..ea978ac --- /dev/null +++ b/src/libexif/fuji/mnote-fuji-entry.c @@ -0,0 +1,306 @@ +/* mnote-fuji-entry.c + * + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful,  + * but WITHOUT ANY WARRANTY; without even the implied warranty of  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.  + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <config.h> + +#include <libexif/i18n.h> + +#include "mnote-fuji-entry.h" + +#define CF(format,target,v,maxlen)                              \ +{                                                               \ +        if (format != target) {                                 \ +                snprintf (v, maxlen,	                        \ +                        _("Invalid format '%s', "               \ +                        "expected '%s'."),                      \ +                        exif_format_get_name (format),          \ +                        exif_format_get_name (target));         \ +                break;                                          \ +        }                                                       \ +} + +#define CC(number,target,v,maxlen)                                      \ +{                                                                       \ +        if (number != target) {                                         \ +                snprintf (v, maxlen,                                    \ +                        _("Invalid number of components (%i, "          \ +                        "expected %i)."), (int) number, (int) target);  \ +                break;                                                  \ +        }                                                               \ +} + +static const struct { +	ExifTag tag; +	struct { +		int index; +		const char *string; +	} elem[22]; +} items[] = { +#ifndef NO_VERBOSE_TAG_DATA +  { MNOTE_FUJI_TAG_SHARPNESS, +    { {1, N_("Softest")}, +      {2, N_("Soft")}, +      {3, N_("Normal")}, +      {4, N_("Hard")}, +      {5, N_("Hardest")}, +      {0x0082, N_("Medium soft")}, +      {0x0084, N_("Medium hard")}, +      {0x8000, N_("Film simulation mode")}, +      {0xFFFF, N_("Off")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_WHITE_BALANCE, +    { {0, N_("Auto")}, +      {0x100, N_("Daylight")}, +      {0x200, N_("Cloudy")}, +      {0x300, N_("Daylight-color fluorescent")}, +      {0x301, N_("DayWhite-color fluorescent")}, +      {0x302, N_("White fluorescent")}, +      {0x400, N_("Incandescent")}, +      {0x500, N_("Flash")}, +      {0xF00, N_("Custom")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_COLOR, +    { {0, N_("Standard")}, +      {0x0080, N_("Medium high")}, +      {0x0100, N_("High")}, +      {0x0180, N_("Medium low")}, +      {0x0200, N_("Original")}, +      {0x0300, N_("Black & white")}, +      {0x8000, N_("Film simulation mode")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_TONE, +    { {0, N_("Standard")}, +      {0x0080, N_("Medium hard")}, +      {0x0100, N_("Hard")}, +      {0x0180, N_("Medium soft")}, +      {0x0200, N_("Original")}, +      {0x8000, N_("Film simulation mode")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_FLASH_MODE, +    { {0, N_("Auto")}, +      {1, N_("On")}, +      {2, N_("Off")}, +      {3, N_("Red-eye reduction")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_MACRO, +    { {0, N_("Off")}, +      {1, N_("On")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_FOCUS_MODE, +    { {0, N_("Auto")}, +      {1, N_("Manual")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_SLOW_SYNC, +    { {0, N_("Off")}, +      {1, N_("On")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_PICTURE_MODE, +    { {0, N_("Auto")}, +      {1, N_("Portrait")}, +      {2, N_("Landscape")}, +      {4, N_("Sports")}, +      {5, N_("Night")}, +      {6, N_("Program AE")}, +      {7, N_("Natural photo")}, +      {8, N_("Vibration reduction")}, +      {0x000A, N_("Sunset")}, +      {0x000B, N_("Museum")}, +      {0x000C, N_("Party")}, +      {0x000D, N_("Flower")}, +      {0x000E, N_("Text")}, +      {0x000F, N_("NP & flash")}, +      {0x0010, N_("Beach")}, +      {0x0011, N_("Snow")}, +      {0x0012, N_("Fireworks")}, +      {0x0013, N_("Underwater")}, +      {0x0100, N_("Aperture priority AE")}, +      {0x0200, N_("Shutter priority AE")}, +      {0x0300, N_("Manual exposure")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_CONT_TAKING, +    { {0, N_("Off")}, +      {1, N_("On")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_FINEPIX_COLOR, +    { {0x00, N_("F-Standard")}, +      {0x10, N_("F-Chrome")}, +      {0x30, N_("F-B&W")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_BLUR_CHECK, +    { {0, N_("No blur")}, +      {1, N_("Blur warning")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_FOCUS_CHECK, +    { {0, N_("Focus good")}, +      {1, N_("Out of focus")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_AUTO_EXPOSURE_CHECK, +    { {0, N_("AE good")}, +      {1, N_("Over exposed")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_DYNAMIC_RANGE, +    { {1, N_("Standard")}, +      {3, N_("Wide")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_FILM_MODE, +    { {0, N_("F0/Standard")}, +      {0x0100, N_("F1/Studio portrait")}, +      {0x0110, N_("F1a/Professional portrait")}, +      {0x0120, N_("F1b/Professional portrait")}, +      {0x0130, N_("F1c/Professional portrait")}, +      {0x0200, N_("F2/Fujichrome")}, +      {0x0300, N_("F3/Studio portrait Ex")}, +      {0x0400, N_("F4/Velvia")}, +      {0, NULL}}}, +  { MNOTE_FUJI_TAG_DYNAMIC_RANGE_SETTING, +    { {0, N_("Auto (100-400%)")}, +      {1, N_("RAW")}, +      {0x0100, N_("Standard (100%)")}, +      {0x0200, N_("Wide1 (230%)")}, +      {0x0201, N_("Wide2 (400%)")}, +      {0x8000, N_("Film simulation mode")}, +      {0, NULL}}}, +#endif +  {0, {{0, NULL}}} +}; + + +char * +mnote_fuji_entry_get_value (MnoteFujiEntry *entry, +			      char *val, unsigned int maxlen) +{ +	ExifLong  vl; +	ExifSLong vsl; +	ExifShort vs, vs2; +	ExifRational vr; +	ExifSRational vsr; +	int i, j; + +	if (!entry) return (NULL); + +	memset (val, 0, maxlen); +	maxlen--; + +	switch (entry->tag) { +	  case MNOTE_FUJI_TAG_VERSION: +		CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen); +		CC (entry->components, 4, val, maxlen); +		memcpy (val, entry->data, MIN(maxlen, entry->size)); +		break; +	  case MNOTE_FUJI_TAG_SHARPNESS: +	  case MNOTE_FUJI_TAG_WHITE_BALANCE: +	  case MNOTE_FUJI_TAG_COLOR: +  	  case MNOTE_FUJI_TAG_TONE: +	  case MNOTE_FUJI_TAG_FLASH_MODE: +	  case MNOTE_FUJI_TAG_MACRO: +	  case MNOTE_FUJI_TAG_FOCUS_MODE: +	  case MNOTE_FUJI_TAG_SLOW_SYNC: +	  case MNOTE_FUJI_TAG_PICTURE_MODE: +	  case MNOTE_FUJI_TAG_CONT_TAKING: +	  case MNOTE_FUJI_TAG_FINEPIX_COLOR: +	  case MNOTE_FUJI_TAG_BLUR_CHECK: +	  case MNOTE_FUJI_TAG_FOCUS_CHECK: +	  case MNOTE_FUJI_TAG_AUTO_EXPOSURE_CHECK: +	  case MNOTE_FUJI_TAG_DYNAMIC_RANGE: +	  case MNOTE_FUJI_TAG_FILM_MODE: +	  case MNOTE_FUJI_TAG_DYNAMIC_RANGE_SETTING: +		CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen); +		CC (entry->components, 1, val, maxlen); +		vs = exif_get_short (entry->data, entry->order); + +		/* search the tag */ +		for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++); +		if (!items[i].tag) { +			snprintf (val, maxlen, +				  _("Internal error (unknown value %i)"), vs); +		  	break; +		} + +		/* find the value */ +		for (j = 0; items[i].elem[j].string && +		    (items[i].elem[j].index < vs); j++); +		if (items[i].elem[j].index != vs) { +			snprintf (val, maxlen, +				  _("Internal error (unknown value %i)"), vs); +			break; +		} +		strncpy (val, _(items[i].elem[j].string), maxlen); +		break; +	  case MNOTE_FUJI_TAG_FOCUS_POINT: +		CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen); +		CC (entry->components, 2, val, maxlen); +		vs = exif_get_short (entry->data, entry->order); +		vs2 = exif_get_short (entry->data+2, entry->order); +		snprintf (val, maxlen, "%i, %i", vs, vs2); +		break; +	  case MNOTE_FUJI_TAG_MIN_FOCAL_LENGTH: +	  case MNOTE_FUJI_TAG_MAX_FOCAL_LENGTH: +		CF (entry->format, EXIF_FORMAT_RATIONAL, val, maxlen); +		CC (entry->components, 1, val, maxlen); +		vr = exif_get_rational (entry->data, entry->order); +		if (!vr.denominator) break; +		snprintf (val, maxlen, _("%2.2f mm"), (double) vr.numerator / +			  vr.denominator); +		break; + +	default: +		switch (entry->format) { +		case EXIF_FORMAT_ASCII: +		  strncpy (val, (char *)entry->data, MIN(maxlen, entry->size)); +		  break; +		case EXIF_FORMAT_SHORT: +		  vs = exif_get_short (entry->data, entry->order); +		  snprintf (val, maxlen, "%i", vs); +		  break; +		case EXIF_FORMAT_LONG: +		  vl = exif_get_long (entry->data, entry->order); +		  snprintf (val, maxlen, "%lu", (long unsigned) vl); +		  break; +		case EXIF_FORMAT_SLONG: +		  vsl = exif_get_slong (entry->data, entry->order); +		  snprintf (val, maxlen, "%li", (long int) vsl); +		  break; +		case EXIF_FORMAT_RATIONAL: +		  vr = exif_get_rational (entry->data, entry->order); +		  if (!vr.denominator) break; +		  snprintf (val, maxlen, "%2.4f", (double) vr.numerator / +						    vr.denominator); +		  break; +		case EXIF_FORMAT_SRATIONAL: +		  vsr = exif_get_srational (entry->data, entry->order); +		  if (!vsr.denominator) break; +		  snprintf (val, maxlen, "%2.4f", (double) vsr.numerator / +			  vsr.denominator); +		  break; +		case EXIF_FORMAT_UNDEFINED: +		default: +		  snprintf (val, maxlen, _("%i bytes unknown data"), + 			  entry->size); +		  break; +		} +		break; +	} + +	return (val); +} diff --git a/src/libexif/fuji/mnote-fuji-entry.h b/src/libexif/fuji/mnote-fuji-entry.h new file mode 100644 index 0000000..322d2d2 --- /dev/null +++ b/src/libexif/fuji/mnote-fuji-entry.h @@ -0,0 +1,45 @@ +/* mnote-fuji-entry.h + * + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful,  + * but WITHOUT ANY WARRANTY; without even the implied warranty of  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.  + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __MNOTE_FUJI_ENTRY_H__ +#define __MNOTE_FUJI_ENTRY_H__ + +#include <libexif/exif-format.h> +#include <libexif/fuji/mnote-fuji-tag.h> + +typedef struct _MnoteFujiEntry        MnoteFujiEntry; +typedef struct _MnoteFujiEntryPrivate MnoteFujiEntryPrivate; + +#include <libexif/fuji/exif-mnote-data-fuji.h> + +struct _MnoteFujiEntry { +	MnoteFujiTag tag; +	ExifFormat format; +	unsigned long components; + +	unsigned char *data; +	unsigned int size; + +	ExifByteOrder order; +}; + +char *mnote_fuji_entry_get_value (MnoteFujiEntry *entry, char *val, unsigned int maxlen); + +#endif /* __MNOTE_FUJI_ENTRY_H__ */ diff --git a/src/libexif/fuji/mnote-fuji-tag.c b/src/libexif/fuji/mnote-fuji-tag.c new file mode 100644 index 0000000..bff33d8 --- /dev/null +++ b/src/libexif/fuji/mnote-fuji-tag.c @@ -0,0 +1,105 @@ +/* mnote-fuji-tag.c + * + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful,  + * but WITHOUT ANY WARRANTY; without even the implied warranty of  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.  + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <stdlib.h> + +#include <config.h> +#include <libexif/i18n.h> + +#include "mnote-fuji-tag.h" + + +static struct { +	MnoteFujiTag tag; +	const char *name; +	const char *title; +	const char *description; +} table[] = { +#ifndef NO_VERBOSE_TAG_STRINGS +	{MNOTE_FUJI_TAG_VERSION, "Version", N_("Maker Note Version"), ""}, +	{MNOTE_FUJI_TAG_SERIAL_NUMBER, "SerialNumber", N_("Serial Number"), N_("This number is unique, it contains the date of manufacture.")}, +	{MNOTE_FUJI_TAG_QUALITY, "Quality", N_("Quality"), ""}, +	{MNOTE_FUJI_TAG_SHARPNESS, "Sharpness", N_("Sharpness"), ""}, +	{MNOTE_FUJI_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance"), ""}, +	{MNOTE_FUJI_TAG_COLOR, "ChromaticitySaturation", N_("Chromaticity Saturation"), ""}, +	{MNOTE_FUJI_TAG_TONE, "Contrast", N_("Contrast"), ""}, +	{MNOTE_FUJI_TAG_FLASH_MODE, "FlashMode", N_("Flash Mode"), ""}, +	{MNOTE_FUJI_TAG_FLASH_STRENGTH, "FlashStrength", N_("Flash Firing Strength Compensation"), ""}, +	{MNOTE_FUJI_TAG_MACRO, "MacroMode", N_("Macro mode"), ""}, +	{MNOTE_FUJI_TAG_FOCUS_MODE, "FocusingMode", N_("Focusing Mode"), ""}, +	{MNOTE_FUJI_TAG_FOCUS_POINT, "FocusPoint", N_("Focus Point"), ""}, +	{MNOTE_FUJI_TAG_SLOW_SYNC, "SlowSynchro", N_("Slow Synchro Mode"), ""}, +	{MNOTE_FUJI_TAG_PICTURE_MODE, "PictureMode", N_("Picture Mode"), ""}, +	{MNOTE_FUJI_TAG_CONT_TAKING, "ContinuousTaking", N_("Continuous Taking"), ""}, +	{MNOTE_FUJI_TAG_SEQUENCE_NUMBER, "ContinuousSequence", N_("Continuous Sequence Number"), ""}, +	{MNOTE_FUJI_TAG_FINEPIX_COLOR, "FinePixColor", N_("FinePix Color"), ""}, +	{MNOTE_FUJI_TAG_BLUR_CHECK, "BlurCheck", N_("Blur Check"), ""}, +	{MNOTE_FUJI_TAG_FOCUS_CHECK, "AutoFocusCheck", N_("Auto Focus Check"), ""}, +	{MNOTE_FUJI_TAG_AUTO_EXPOSURE_CHECK, "AutoExposureCheck", N_("Auto Exposure Check"), ""}, +	{MNOTE_FUJI_TAG_DYNAMIC_RANGE, "DynamicRange", N_("Dynamic Range"), ""}, +	{MNOTE_FUJI_TAG_FILM_MODE, "FilmMode", N_("Film simulation Mode"), ""}, +	{MNOTE_FUJI_TAG_DYNAMIC_RANGE_SETTING, "DRangeMode", N_("Dynamic Range Wide Mode"), ""}, +	{MNOTE_FUJI_TAG_DEV_DYNAMIC_RANGE_SETTING, "DevDRangeMode", N_("Development Dynamic Range Wide Mode"), ""}, +	{MNOTE_FUJI_TAG_MIN_FOCAL_LENGTH, "MinFocalLen", N_("Minimum Focal Length"), ""}, +	{MNOTE_FUJI_TAG_MAX_FOCAL_LENGTH, "MaxFocalLen", N_("Maximum Focal Length"), ""}, +	{MNOTE_FUJI_TAG_MAX_APERT_AT_MIN_FOC, "MaxApertAtMinFoc", N_("Maximum Aperture at Minimum Focal"), ""}, +	{MNOTE_FUJI_TAG_MAX_APERT_AT_MAX_FOC, "MaxApertAtMaxFoc", N_("Maximum Aperture at Maximum Focal"), ""}, +	{MNOTE_FUJI_TAG_FILE_SOURCE, "FileSource", N_("File Source"), ""}, +	{MNOTE_FUJI_TAG_ORDER_NUMBER, "OrderNumber", N_("Order Number"), ""}, +	{MNOTE_FUJI_TAG_FRAME_NUMBER, "FrameNumber", N_("Frame Number"), ""}, +#endif +	{0, NULL, NULL, NULL} +}; + +const char * +mnote_fuji_tag_get_name (MnoteFujiTag t) +{ +	unsigned int i; + +	for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) +		if (table[i].tag == t) return (table[i].name); +	return NULL; +} + +const char * +mnote_fuji_tag_get_title (MnoteFujiTag t) +{ +	unsigned int i; + +	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); +	for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) +		if (table[i].tag == t) return (_(table[i].title)); +	return NULL; +} + +const char * +mnote_fuji_tag_get_description (MnoteFujiTag t) +{ +	unsigned int i; + +	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); +	for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) +		if (table[i].tag == t) { +			if (!*table[i].description) +				return ""; +			return (_(table[i].description)); +		} +	return NULL; +} diff --git a/src/libexif/fuji/mnote-fuji-tag.h b/src/libexif/fuji/mnote-fuji-tag.h new file mode 100644 index 0000000..7ddde34 --- /dev/null +++ b/src/libexif/fuji/mnote-fuji-tag.h @@ -0,0 +1,92 @@ +/* mnote-fuji-tag.h + * + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful,  + * but WITHOUT ANY WARRANTY; without even the implied warranty of  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.  + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __MNOTE_FUJI_TAG_H__ +#define __MNOTE_FUJI_TAG_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <libexif/exif-data.h> + +enum _MnoteFujiTag { +	MNOTE_FUJI_TAG_VERSION                  = 0x0000, +	MNOTE_FUJI_TAG_SERIAL_NUMBER            = 0x0010, +	MNOTE_FUJI_TAG_QUALITY                  = 0x1000, +	MNOTE_FUJI_TAG_SHARPNESS                = 0x1001, +	MNOTE_FUJI_TAG_WHITE_BALANCE            = 0x1002, +	MNOTE_FUJI_TAG_COLOR                    = 0x1003, +	MNOTE_FUJI_TAG_TONE                     = 0x1004, +	MNOTE_FUJI_TAG_UNKNOWN_1006             = 0x1006, +	MNOTE_FUJI_TAG_UNKNOWN_1007             = 0x1007, +	MNOTE_FUJI_TAG_UNKNOWN_1008             = 0x1008, +	MNOTE_FUJI_TAG_UNKNOWN_1009             = 0x1009, +	MNOTE_FUJI_TAG_UNKNOWN_100A             = 0x100A, +	MNOTE_FUJI_TAG_UNKNOWN_100B             = 0x100B, +	MNOTE_FUJI_TAG_FLASH_MODE               = 0x1010, +	MNOTE_FUJI_TAG_FLASH_STRENGTH           = 0x1011, +	MNOTE_FUJI_TAG_MACRO                    = 0x1020, +	MNOTE_FUJI_TAG_FOCUS_MODE               = 0x1021, +	MNOTE_FUJI_TAG_UNKNOWN_1022             = 0x1022, +	MNOTE_FUJI_TAG_FOCUS_POINT              = 0x1023, +	MNOTE_FUJI_TAG_UNKNOWN_1024             = 0x1024, +	MNOTE_FUJI_TAG_UNKNOWN_1025             = 0x1025, +	MNOTE_FUJI_TAG_SLOW_SYNC                = 0x1030, +	MNOTE_FUJI_TAG_PICTURE_MODE             = 0x1031, +	MNOTE_FUJI_TAG_UNKNOWN_1032             = 0x1032, +	MNOTE_FUJI_TAG_CONT_TAKING              = 0x1100, +	MNOTE_FUJI_TAG_SEQUENCE_NUMBER          = 0x1101, +	MNOTE_FUJI_TAG_UNKNOWN_1200             = 0x1200, +	MNOTE_FUJI_TAG_FINEPIX_COLOR            = 0x1210, +	MNOTE_FUJI_TAG_BLUR_CHECK               = 0x1300, +	MNOTE_FUJI_TAG_FOCUS_CHECK              = 0x1301, +	MNOTE_FUJI_TAG_AUTO_EXPOSURE_CHECK      = 0x1302, +	MNOTE_FUJI_TAG_UNKNOWN_1303             = 0x1303, +	MNOTE_FUJI_TAG_DYNAMIC_RANGE            = 0x1400, +	MNOTE_FUJI_TAG_FILM_MODE                = 0x1401, +	MNOTE_FUJI_TAG_DYNAMIC_RANGE_SETTING    = 0x1402, +	MNOTE_FUJI_TAG_DEV_DYNAMIC_RANGE_SETTING= 0x1403, +	MNOTE_FUJI_TAG_MIN_FOCAL_LENGTH         = 0x1404, +	MNOTE_FUJI_TAG_MAX_FOCAL_LENGTH         = 0x1405, +	MNOTE_FUJI_TAG_MAX_APERT_AT_MIN_FOC     = 0x1406, +	MNOTE_FUJI_TAG_MAX_APERT_AT_MAX_FOC     = 0x1407, +	MNOTE_FUJI_TAG_UNKNOWN_1408             = 0x1408, +	MNOTE_FUJI_TAG_UNKNOWN_1409             = 0x1409, +	MNOTE_FUJI_TAG_UNKNOWN_140A             = 0x140A, +	MNOTE_FUJI_TAG_UNKNOWN_1410             = 0x1410, +	MNOTE_FUJI_TAG_UNKNOWN_1421             = 0x1421, +	MNOTE_FUJI_TAG_UNKNOWN_4100             = 0x4100, +	MNOTE_FUJI_TAG_UNKNOWN_4800             = 0x4800, +	MNOTE_FUJI_TAG_FILE_SOURCE              = 0x8000, +	MNOTE_FUJI_TAG_ORDER_NUMBER             = 0x8002, +	MNOTE_FUJI_TAG_FRAME_NUMBER             = 0x8003 +}; +typedef enum _MnoteFujiTag MnoteFujiTag; + +const char *mnote_fuji_tag_get_name        (MnoteFujiTag tag); +const char *mnote_fuji_tag_get_title       (MnoteFujiTag tag); +const char *mnote_fuji_tag_get_description (MnoteFujiTag tag); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MNOTE_FUJI_TAG_H__ */ diff --git a/src/libexif/i18n.h b/src/libexif/i18n.h index 6d08e3c..289435c 100644 --- a/src/libexif/i18n.h +++ b/src/libexif/i18n.h @@ -35,6 +35,7 @@  #else  #  define textdomain(String) (String)  #  define gettext(String) (String) +#  define ngettext(String1,String2,Count) (Count==1?String1:String2)  #  define dgettext(Domain,Message) (Message)  #  define dcgettext(Domain,Message,Type) (Message)  #ifdef __WATCOMC__ diff --git a/src/libexif/olympus/exif-mnote-data-olympus.c b/src/libexif/olympus/exif-mnote-data-olympus.c index 02794c5..200a276 100644 --- a/src/libexif/olympus/exif-mnote-data-olympus.c +++ b/src/libexif/olympus/exif-mnote-data-olympus.c @@ -1,6 +1,6 @@  /* exif-mnote-data-olympus.c   * - * Copyright © 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net> + * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -71,13 +71,25 @@ exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val,  	return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);  } + + + +/**  + * @brief save the MnoteData from ne to buf + *  + * @param ne extract the data from this structure  + * @param *buf write the mnoteData to this buffer (buffer will be allocated) + * @param buf_size the size of the buffer + */  static void  exif_mnote_data_olympus_save (ExifMnoteData *ne,  		unsigned char **buf, unsigned int *buf_size)  {  	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne; -	unsigned int i, o, s, doff, base = 0, o2 = 6; -	int datao = 0; +	size_t i, o, s, doff, base = 0, o2 = 6 + 2; +	size_t datao = 0; +	unsigned char *t; +	size_t ts;  	if (!n || !buf || !buf_size) return; @@ -86,29 +98,49 @@ exif_mnote_data_olympus_save (ExifMnoteData *ne,  	 */  	*buf_size = 6 + 2 + 2 + n->count * 12;  	switch (n->version) { -	case 0: /* Olympus */ +	case olympusV1: +	case sanyoV1:  		*buf = exif_mem_alloc (ne->mem, *buf_size);  		if (!*buf) return;  		/* Write the header and the number of entries. */ -		strcpy (*buf, "OLYMP"); -		o2 += 2; +		strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":"OLYMP"); +		exif_set_short (*buf + 6, n->order, (ExifShort) 1);  		datao = n->offset;  		break; -	case 1: /* Nikon v1 */ +	case olympusV2: +		*buf_size += 8-6 + 4; +		*buf = exif_mem_alloc (ne->mem, *buf_size); +		if (!*buf) return; + +		/* Write the header and the number of entries. */ +		strcpy ((char *)*buf, "OLYMPUS"); +		exif_set_short (*buf + 8, n->order, (ExifShort) ( +			(n->order == EXIF_BYTE_ORDER_INTEL) ? +			('I' << 8) | 'I' : +			('M' << 8) | 'M')); +		exif_set_short (*buf + 10, n->order, (ExifShort) 3); +		o2 += 4; +		break; +	case nikonV1:   		base = MNOTE_NIKON1_TAG_BASE; -		*buf_size -= 8; + +		/* v1 has offsets based to main IFD, not makernote IFD */ +		datao += n->offset + 10; +		/* subtract the size here, so the increment in the next case will not harm us */ +		*buf_size -= 8 + 2;  		/* Fall through */ -	case 2: /* Nikon v2 */ -		*buf_size += 8; +	case nikonV2:  +		*buf_size += 8 + 2; +		*buf_size += 4; /* Next IFD pointer */  		*buf = exif_mem_alloc (ne->mem, *buf_size);  		if (!*buf) return;  		/* Write the header and the number of entries. */ -		strcpy (*buf, "Nikon"); +		strcpy ((char *)*buf, "Nikon");  		(*buf)[6] = n->version; -		o2 += 2; *buf_size += 2; -		if (n->version == 2) { + +		if (n->version == nikonV2) {  			exif_set_short (*buf + 10, n->order, (ExifShort) (  				(n->order == EXIF_BYTE_ORDER_INTEL) ?  				('I' << 8) | 'I' : @@ -117,8 +149,13 @@ exif_mnote_data_olympus_save (ExifMnoteData *ne,  			exif_set_long (*buf + 14, n->order, (ExifShort) 8);  			o2 += 2 + 8;  		} -		datao = -10; +		datao -= 10; +		/* Reset next IFD pointer */ +		exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);  		break; + +	default: +		return;  	}  	exif_set_short (*buf + o2, n->order, (ExifShort) n->count); @@ -136,12 +173,20 @@ exif_mnote_data_olympus_save (ExifMnoteData *ne,  		o += 8;  		s = exif_format_get_size (n->entries[i].format) *  						n->entries[i].components; +		if (s > 65536) { +			/* Corrupt data: EXIF data size is limited to the +			 * maximum size of a JPEG segment (64 kb). +			 */ +			continue; +		}  		if (s > 4) {  			doff = *buf_size; -			*buf_size += s; -			*buf = exif_mem_realloc (ne->mem, *buf, -						 sizeof (char) * *buf_size); -			if (!*buf) return; +			ts = *buf_size + s; +			t = exif_mem_realloc (ne->mem, *buf, +						 sizeof (char) * ts); +			if (!t) return; +			*buf = t; +			*buf_size = ts;  			exif_set_long (*buf + o, n->order, datao + doff);  		} else  			doff = o; @@ -162,7 +207,7 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,  {  	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;  	ExifShort c; -	unsigned int i, s, o, o2 = 0, datao = 6, base = 0; +	size_t i, s, o, o2 = 0, datao = 6, base = 0;  	if (!n || !buf) return; @@ -174,6 +219,9 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,  	 * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the  	 * number of entries, and 12 for one entry.  	 * +	 * Sanyo format is identical and uses identical tags except that +	 * header starts with "SANYO". +	 *  	 * Nikon headers start with "Nikon" (6 bytes including '\0'),   	 * version number (1 or 2).  	 *  @@ -185,13 +233,46 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,  	 * lastly 0x2A.  	 */  	if (buf_size - n->offset < 22) return; -	if (!memcmp (buf + o2, "OLYMP", 5)) { +	if (!memcmp (buf + o2, "OLYMP", 6) || !memcmp (buf + o2, "SANYO", 6)) {  		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", -			"Parsing Olympus maker note..."); +			"Parsing Olympus/Sanyo maker note v1...");  		/* The number of entries is at position 8. */ -		n->version = 0; +		if (!memcmp (buf + o2, "SANYO", 6)) +			n->version = sanyoV1; +		else +			n->version = olympusV1; +		if (buf[o2 + 6] == 1) +			n->order = EXIF_BYTE_ORDER_INTEL; +		else if (buf[o2 + 6 + 1] == 1) +			n->order = EXIF_BYTE_ORDER_MOTOROLA;  		o2 += 8; +		if (o2 >= buf_size) return; +		c = exif_get_short (buf + o2, n->order); +		if ((!(c & 0xFF)) && (c > 0x500)) { +			if (n->order == EXIF_BYTE_ORDER_INTEL) { +				n->order = EXIF_BYTE_ORDER_MOTOROLA; +			} else { +				n->order = EXIF_BYTE_ORDER_INTEL; +			} +		} + +	} else if (!memcmp (buf + o2, "OLYMPUS", 8)) { +		/* Olympus S760, S770 */ +		datao = o2; +		o2 += 8; +		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", +			"Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...", +			buf[o2], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]); + +		if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I')) +			n->order = EXIF_BYTE_ORDER_INTEL; +		else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M')) +			n->order = EXIF_BYTE_ORDER_MOTOROLA; + +		/* The number of entries is at position 8+4. */ +		n->version = olympusV2; +		o2 += 4;  	} else if (!memcmp (buf + o2, "Nikon", 6)) {  		o2 += 6; @@ -199,8 +280,7 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,  			"Parsing Nikon maker note (0x%02x, %02x, %02x, "  			"%02x, %02x, %02x, %02x, %02x)...",  			buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],  -			buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);  - +			buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);  		/* The first byte is the version. */  		if (o2 >= buf_size) return;  		n->version = buf[o2]; @@ -210,12 +290,22 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,  		o2 += 1;  		switch (n->version) { -		case 1: +		case nikonV1:  			base = MNOTE_NIKON1_TAG_BASE; +			/* Fix endianness, if needed */ +			if (o2 >= buf_size) return; +			c = exif_get_short (buf + o2, n->order); +			if ((!(c & 0xFF)) && (c > 0x500)) { +				if (n->order == EXIF_BYTE_ORDER_INTEL) { +					n->order = EXIF_BYTE_ORDER_MOTOROLA; +				} else { +					n->order = EXIF_BYTE_ORDER_INTEL; +				} +			}  			break; -		case 2: +		case nikonV2:  			/* Skip 2 unknown bytes (00 00). */  			o2 += 2; @@ -226,9 +316,9 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,  			 */  			datao = o2;  			if (o2 >= buf_size) return; -			if (!strncmp (&buf[o2], "II", 2)) +			if (!strncmp ((char *)&buf[o2], "II", 2))  				n->order = EXIF_BYTE_ORDER_INTEL; -			else if (!strncmp (&buf[o2], "MM", 2)) +			else if (!strncmp ((char *)&buf[o2], "MM", 2))  				n->order = EXIF_BYTE_ORDER_MOTOROLA;  			else {  				exif_log (en->log, EXIF_LOG_CODE_DEBUG, @@ -254,7 +344,9 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,  			return;  		}  	} else if (!memcmp (buf + o2, "\0\x1b", 2)) { -		n->version = 2; +		n->version = nikonV2; +		/* 00 1b is # of entries in Motorola order - the rest should also be in MM order */ +		n->order = EXIF_BYTE_ORDER_MOTOROLA;  	} else {  		return;  	} @@ -347,7 +439,7 @@ exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)  	if (!n) return NULL;  	if (i >= n->count) return NULL; -        return mnote_olympus_tag_get_title (n->entries[i].tag); +        return mnote_olympus_tag_get_description (n->entries[i].tag);  }  static void diff --git a/src/libexif/olympus/exif-mnote-data-olympus.h b/src/libexif/olympus/exif-mnote-data-olympus.h index b9b4209..4d55cab 100644 --- a/src/libexif/olympus/exif-mnote-data-olympus.h +++ b/src/libexif/olympus/exif-mnote-data-olympus.h @@ -1,6 +1,6 @@  /* mnote-olympus-data.h   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -26,6 +26,9 @@  #include <libexif/exif-byte-order.h>  #include <libexif/exif-mem.h> +enum OlympusVersion {nikonV1 = 1, nikonV2 = 2, olympusV1 = 3, olympusV2 = 4, sanyoV1 = 5 }; + +  typedef struct _ExifMnoteDataOlympus ExifMnoteDataOlympus;  struct _ExifMnoteDataOlympus { diff --git a/src/libexif/olympus/mnote-olympus-entry.c b/src/libexif/olympus/mnote-olympus-entry.c index 1eff6fe..1e9e1e2 100644 --- a/src/libexif/olympus/mnote-olympus-entry.c +++ b/src/libexif/olympus/mnote-olympus-entry.c @@ -1,6 +1,6 @@  /* mnote-olympus-entry.c   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -42,6 +42,19 @@          }                                                       \  } +#define CF2(format,target1,target2,v,maxlen)                    \ +{                                                               \ +        if ((format != target1) && (format != target2)) {       \ +                snprintf (v, maxlen,	                        \ +                        _("Invalid format '%s', "               \ +                        "expected '%s' or '%s'."),              \ +                        exif_format_get_name (format),          \ +                        exif_format_get_name (target1),         \ +                        exif_format_get_name (target2));        \ +                break;                                          \ +        }                                                       \ +} +  #define CC(number,target,v,maxlen)                                      \  {                                                                       \          if (number != target) {                                         \ @@ -54,7 +67,7 @@  #define CC2(number,t1,t2,v,maxlen)                                      \  {                                                                       \ -	if ((number != t1) && (number != t2)) {                         \ +	if ((number < t1) || (number > t2)) {                           \  		snprintf (v, maxlen,                                    \  			_("Invalid number of components (%i, "          \  			"expected %i or %i)."), (int) number,		\ @@ -63,7 +76,7 @@  	}                                                               \  } -static struct { +static const struct {  	ExifTag tag;      ExifFormat fmt;  	struct { @@ -71,6 +84,7 @@ static struct {  		const char *string;  	} elem[10];  } items[] = { +#ifndef NO_VERBOSE_TAG_DATA    { MNOTE_NIKON_TAG_LENSTYPE, EXIF_FORMAT_BYTE,      { {0, N_("AF non D Lens")},        {1, N_("Manual")}, @@ -116,7 +130,7 @@ static struct {      { {0, N_("Auto")},        {1, N_("Preset")},        {2, N_("Daylight")}, -      {3, N_("Incandescense")}, +      {3, N_("Incandescence")},        {4, N_("Fluorescence")},        {5, N_("Cloudy")},        {6, N_("SpeedLight")}, @@ -129,14 +143,25 @@ static struct {      { {1, N_("SQ")},        {2, N_("HQ")},        {3, N_("SHQ")}, +      {4, N_("RAW")}, +      {5, N_("SQ1")}, +      {6, N_("SQ2")}, +      {17, N_("Standard")}, +      {529, N_("High")},        {0, NULL}}},    { MNOTE_OLYMPUS_TAG_MACRO, EXIF_FORMAT_SHORT,      { {0, N_("No")},        {1, N_("Yes")}, +      {2, N_("Super Macro")},        {0, NULL}}}, -  { MNOTE_OLYMPUS_TAG_DIGIZOOM, EXIF_FORMAT_SHORT, -    { {0, N_("1x")}, -      {2, N_("2x")}, +  { MNOTE_OLYMPUS_TAG_BWMODE, EXIF_FORMAT_SHORT, +    { {0, N_("No")}, +      {1, N_("Yes")}, +      {0, NULL}}}, +  { MNOTE_OLYMPUS_TAG_ONETOUCHWB, EXIF_FORMAT_SHORT, +    { {0, N_("Off")}, +      {1, N_("On")}, +      {2, N_("On (Preset)")},        {0, NULL}}},    { MNOTE_OLYMPUS_TAG_FLASHMODE, EXIF_FORMAT_SHORT,      { {0, N_("Auto")}, @@ -144,21 +169,73 @@ static struct {        {2, N_("Fill")},        {3, N_("Off")},        {0, NULL}}}, +  { MNOTE_OLYMPUS_TAG_FLASHDEVICE, EXIF_FORMAT_SHORT, +    { {0, N_("None")}, +      {1, N_("Internal")}, +      {4, N_("External")}, +      {5, N_("Internal + External")}, +      {0, NULL}}}, +  { MNOTE_OLYMPUS_TAG_FOCUSRANGE, EXIF_FORMAT_SHORT, +    { {0, N_("Normal")}, +      {1, N_("Macro")}, +      {0, NULL}}}, +  { MNOTE_OLYMPUS_TAG_MANFOCUS, EXIF_FORMAT_SHORT, +    { {0, N_("Auto")}, +      {1, N_("Manual")}, +      {0, NULL}}},    { MNOTE_OLYMPUS_TAG_SHARPNESS, EXIF_FORMAT_SHORT,      { {0, N_("Normal")},        {1, N_("Hard")},        {2, N_("Soft")},        {0, NULL}}}, +  { MNOTE_OLYMPUS_TAG_EXTERNALFLASHBOUNCE, EXIF_FORMAT_SHORT, +    { {0, N_("No")}, +      {1, N_("Yes")}, +      {0, NULL}}},    { MNOTE_OLYMPUS_TAG_CONTRAST, EXIF_FORMAT_SHORT,      { {0, N_("Hard")},        {1, N_("Normal")},        {2, N_("Soft")},        {0, NULL}}}, -  { MNOTE_OLYMPUS_TAG_MANFOCUS, EXIF_FORMAT_SHORT, +  { MNOTE_OLYMPUS_TAG_PREVIEWIMAGEVALID, EXIF_FORMAT_LONG, +    { {0, N_("No")}, +      {1, N_("Yes")}, +      {0, NULL}}}, +  { MNOTE_OLYMPUS_TAG_CCDSCANMODE, EXIF_FORMAT_SHORT, +    { {0, N_("Interlaced")}, +      {1, N_("Progressive")}, +      {0, NULL}}}, +  { MNOTE_SANYO_TAG_SEQUENTIALSHOT, EXIF_FORMAT_SHORT, +    { {0, N_("None")}, +      {1, N_("Standard")}, +      {2, N_("Best")}, +      {3, N_("Adjust Exposure")}, +      {0, NULL}}}, +  { MNOTE_SANYO_TAG_RECORDSHUTTERRELEASE, EXIF_FORMAT_SHORT, +    { {0, N_("Record while down")}, +      {1, N_("Press start, press stop")}, +      {0, NULL}}}, +  { MNOTE_SANYO_TAG_RESAVED, EXIF_FORMAT_SHORT,      { {0, N_("No")},        {1, N_("Yes")},        {0, NULL}}}, -  { 0, } +  { MNOTE_SANYO_TAG_SCENESELECT, EXIF_FORMAT_SHORT, +    { {0, N_("Off")}, +      {1, N_("Sport")}, +      {2, N_("TV")}, +      {3, N_("Night")}, +      {4, N_("User 1")}, +      {5, N_("User 2")}, +      {6, N_("Lamp")}, +      {0, NULL}}}, +  { MNOTE_SANYO_TAG_SEQUENCESHOTINTERVAL, EXIF_FORMAT_SHORT, +    { {0, N_("5 frames/sec")}, +      {1, N_("10 frames/sec")}, +      {2, N_("15 frames/sec")}, +      {3, N_("20 frames/sec")}, +      {0, NULL}}}, +#endif +  { 0, 0, { { 0, NULL } } }  };  char * @@ -167,7 +244,8 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  	char         buf[30];  	ExifLong     vl;  	ExifShort    vs = 0; -	ExifRational vr; +	ExifRational vr, vr2; +	ExifSRational vsr;  	int          i, j;  	double       r, b; @@ -177,7 +255,8 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  	memset (v, 0, maxlen);  	maxlen--; -	if ((!entry->data) && (entry->components > 0)) return (v); +	if ((!entry->data) && (entry->components > 0))  +		return (v);  	switch (entry->tag) { @@ -212,7 +291,7 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m                  //vl =  exif_get_long (entry->data  , entry->order);                  //printf("-> 0x%04x\n",entry->data);                  //printf("-> 0x%s<\n",entry->data - 0); -                memcpy(v, entry->data ,entry->components); +                memcpy(v, entry->data, MIN(maxlen, entry->size));                  //snprintf (v, maxlen, "%s<",  ( entry->data - 9  );                  break;  	case MNOTE_NIKON_TAG_COLORMODE: @@ -225,21 +304,43 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  	case MNOTE_NIKON_TAG_FLASHMODE:  	case MNOTE_NIKON_TAG_IMAGEADJUSTMENT:  	case MNOTE_NIKON_TAG_ADAPTER: -                CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen); -                memcpy(v, entry->data, MIN (maxlen, entry->components)); -                break; +	case MNOTE_NIKON_TAG_SATURATION2: +		CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen); +		memcpy(v, entry->data, MIN (maxlen, entry->size)); +		break;  	case MNOTE_NIKON_TAG_TOTALPICTURES: -                CF (entry->format, EXIF_FORMAT_LONG, v, maxlen); -                CC (entry->components, 1, v, maxlen); -                vl =  exif_get_long (entry->data, entry->order); -                snprintf (v, maxlen, "%lu",  (long unsigned int) vl ); -                break; +		CF (entry->format, EXIF_FORMAT_LONG, v, maxlen); +		CC (entry->components, 1, v, maxlen); +		vl =  exif_get_long (entry->data, entry->order); +		snprintf (v, maxlen, "%lu",  (long unsigned int) vl ); +		break; +	case MNOTE_NIKON_TAG_LENS_FSTOPS: +	case MNOTE_NIKON_TAG_EXPOSUREDIFF: { +		unsigned char a,b,c,d; +		CF (entry->format, EXIF_FORMAT_UNDEFINED, v, maxlen); +		CC (entry->components, 4, v, maxlen); +		vl =  exif_get_long (entry->data, entry->order); +		a = (vl>>24)&0xff; b = (vl>>16)&0xff; c = (vl>>8)&0xff; d = (vl)&0xff; +		snprintf (v, maxlen, "%.1f",  c?(float)a*((float)b/(float)c):0 ); +		break; +	} +	case MNOTE_NIKON_TAG_FLASHEXPCOMPENSATION: +	case MNOTE_NIKON_TAG_FLASHEXPOSUREBRACKETVAL: +		CF (entry->format, EXIF_FORMAT_UNDEFINED, v, maxlen); +		CC (entry->components, 4, v, maxlen); +		vl =  exif_get_long (entry->data, entry->order); +		snprintf (v, maxlen, "%.1f",  ((long unsigned int) vl>>24)/6.0 ); +		break; +	case MNOTE_NIKON_TAG_SATURATION:  	case MNOTE_NIKON_TAG_WHITEBALANCEFINE: -                CF (entry->format, EXIF_FORMAT_SSHORT, v, maxlen); -                CC (entry->components, 1, v, maxlen); -                vs = exif_get_short (entry->data, entry->order); -                snprintf (v, maxlen, "%hd", vs); -                break; +	case MNOTE_NIKON_TAG_HUE: +	case MNOTE_OLYMPUS_TAG_SENSORTEMPERATURE: +	case MNOTE_OLYMPUS_TAG_LENSTEMPERATURE: +		CF (entry->format, EXIF_FORMAT_SSHORT, v, maxlen); +		CC (entry->components, 1, v, maxlen); +		vs = exif_get_short (entry->data, entry->order); +		snprintf (v, maxlen, "%hd", vs); +		break;  	case MNOTE_NIKON_TAG_WHITEBALANCERB:  		CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);  		CC (entry->components, 4, v, maxlen); @@ -248,7 +349,7 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  		vr = exif_get_rational (entry->data+8, entry->order);  		b = (double)vr.numerator / vr.denominator;  		//printf("numerator %li, denominator %li\n", vr.numerator, vr.denominator); -		snprintf (v, maxlen, "Red Correction %f, Blue Correction %f", r,b); +		snprintf (v, maxlen, _("Red Correction %f, Blue Correction %f"), r,b);  		break;  	case MNOTE_NIKON_TAG_MANUALFOCUSDISTANCE:  		CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen); @@ -256,31 +357,69 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  		vr = exif_get_rational (entry->data, entry->order);  		if (vr.numerator) {  			r = (double)vr.numerator / vr.denominator; -			snprintf (v, maxlen, "%2.2f meters", r); +			snprintf (v, maxlen, _("%2.2f meters"), r);  		} else {  			strncpy (v, _("No manual focus selection"), maxlen);  		}  		break; -	case MNOTE_NIKON_TAG_DIGITALZOOM: -	case MNOTE_NIKON1_TAG_DIGITALZOOM: +	case MNOTE_NIKON_TAG_SENSORPIXELSIZE:  		CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen); -		CC (entry->components, 1, v, maxlen); +		CC (entry->components, 2, v, maxlen);  		vr = exif_get_rational (entry->data, entry->order); +		vr2 = exif_get_rational (entry->data+8, entry->order);  		r = (double)vr.numerator / vr.denominator; -		snprintf (v, maxlen, "%2.2f", r); +		b = (double)vr2.numerator / vr2.denominator; +		snprintf (v, maxlen, "%2.2f x %2.2f um", r, b); +		break; +	case MNOTE_NIKON_TAG_BRACKETING: +		CF2 (entry->format, EXIF_FORMAT_BYTE, EXIF_FORMAT_SHORT, v, maxlen); +		CC (entry->components, 1, v, maxlen); +		if (EXIF_FORMAT_SHORT == entry->format) { +			vs = exif_get_short (entry->data, entry->order); +		} else { +			vs = entry->data[0]; +		} +		snprintf (v, maxlen, "%hd", vs);  		break;  	case MNOTE_NIKON_TAG_AFFOCUSPOSITION:  		CF (entry->format, EXIF_FORMAT_UNDEFINED, v, maxlen);  		CC (entry->components, 4, v, maxlen);  		switch (  *( entry->data+1)  ) { -		  	case  0: strncpy (v, "AF Position: Center", maxlen); break; -		  	case  1: strncpy (v, "AF Position: Top", maxlen); break; -		  	case  2: strncpy (v, "AF Position: Bottom", maxlen); break; -		  	case  3: strncpy (v, "AF Position: Left", maxlen); break; -		  	case  4: strncpy (v, "AF Position: Right", maxlen); break; -		  	default: strncpy (v, "Unknown AF Position", maxlen); +		  	case  0: strncpy (v, _("AF Position: Center"), maxlen); break; +		  	case  1: strncpy (v, _("AF Position: Top"), maxlen); break; +		  	case  2: strncpy (v, _("AF Position: Bottom"), maxlen); break; +		  	case  3: strncpy (v, _("AF Position: Left"), maxlen); break; +		  	case  4: strncpy (v, _("AF Position: Right"), maxlen); break; +			case  5: strncpy (v, _("AF Position: Upper-left"), maxlen); break; +		  	case  6: strncpy (v, _("AF Position: Upper-right"), maxlen); break; +		  	case  7: strncpy (v, _("AF Position: Lower-left"), maxlen); break; +		  	case  8: strncpy (v, _("AF Position: Lower-right"), maxlen); break; +		  	case  9: strncpy (v, _("AF Position: Far Left"), maxlen); break; +		  	case  10: strncpy (v, _("AF Position: Far Right"), maxlen); break; +		  	default: strncpy (v, _("Unknown AF Position"), maxlen);  		}       		break; +	case MNOTE_OLYMPUS_TAG_FLASHDEVICE: +		CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen); +		CC (entry->components, 2, v, maxlen); +		vs = exif_get_short(entry->data, entry->order); +		/* search for the tag */ +		for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++) +			; +		if (!items[i].tag) { +		  	snprintf (v, maxlen, _("Internal error (unknown value %hi)"), vs); +		  	break; +		} +		CF (entry->format, items[i].fmt, v, maxlen); +		/* find the value */ +		for (j = 0; items[i].elem[j].string && +			    (items[i].elem[j].index < vs); j++); +		if (items[i].elem[j].index != vs) { +			snprintf (v, maxlen, _("Unknown value %hi"), vs); +			break; +		} +		strncpy (v, _(items[i].elem[j].string), maxlen); +		break;  	case MNOTE_OLYMPUS_TAG_DIGIZOOM:  		if (entry->format == EXIF_FORMAT_RATIONAL) {  			CC (entry->components, 1, v, maxlen); @@ -304,17 +443,21 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  	case MNOTE_NIKON1_TAG_CONVERTER:  	case MNOTE_OLYMPUS_TAG_QUALITY:  	case MNOTE_OLYMPUS_TAG_MACRO: +	case MNOTE_OLYMPUS_TAG_BWMODE: +	case MNOTE_OLYMPUS_TAG_ONETOUCHWB:  	case MNOTE_OLYMPUS_TAG_FLASHMODE: +	case MNOTE_OLYMPUS_TAG_FOCUSRANGE: +	case MNOTE_OLYMPUS_TAG_MANFOCUS:  	case MNOTE_OLYMPUS_TAG_SHARPNESS: +	case MNOTE_OLYMPUS_TAG_EXTERNALFLASHBOUNCE:  	case MNOTE_OLYMPUS_TAG_CONTRAST: -	case MNOTE_OLYMPUS_TAG_MANFOCUS: -		/* search the tag */ -		for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++); -		if (!items[i].tag) { -		  	strncpy (v, "Internal error", maxlen); -		  	break; -		} -		CF (entry->format, items[i].fmt, v, maxlen); +	case MNOTE_OLYMPUS_TAG_PREVIEWIMAGEVALID: +	case MNOTE_OLYMPUS_TAG_CCDSCANMODE: +	case MNOTE_SANYO_TAG_SEQUENTIALSHOT: +	case MNOTE_SANYO_TAG_RECORDSHUTTERRELEASE: +	case MNOTE_SANYO_TAG_RESAVED: +	case MNOTE_SANYO_TAG_SCENESELECT: +	case MNOTE_SANYO_TAG_SEQUENCESHOTINTERVAL:  		CC (entry->components, 1, v, maxlen);  		switch (entry->format) {  		case EXIF_FORMAT_BYTE: @@ -328,16 +471,48 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  			vs = 0;  			break;  		} +		/* search for the tag */ +		for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++) +			; +		if (!items[i].tag) { +		  	snprintf (v, maxlen, _("Internal error (unknown value %hi)"), vs); +		  	break; +		} +		CF (entry->format, items[i].fmt, v, maxlen);  		/* find the value */  		for (j = 0; items[i].elem[j].string &&  			    (items[i].elem[j].index < vs); j++);  		if (items[i].elem[j].index != vs) { -			snprintf (v, maxlen, "Unknown value %hi", vs); +			snprintf (v, maxlen, _("Unknown value %hi"), vs); +			break; +		} +		strncpy (v, _(items[i].elem[j].string), maxlen); +		break; +	case MNOTE_OLYMPUS_TAG_NOISEREDUCTION: +	case MNOTE_SANYO_TAG_WIDERANGE: +	case MNOTE_SANYO_TAG_COLORADJUSTMENTMODE: +	case MNOTE_SANYO_TAG_QUICKSHOT: +	case MNOTE_SANYO_TAG_SELFTIMER: +	case MNOTE_SANYO_TAG_VOICEMEMO: +	case MNOTE_SANYO_TAG_FLICKERREDUCE: +	case MNOTE_SANYO_TAG_OPTICALZOOM: +	case MNOTE_SANYO_TAG_DIGITALZOOM: +	case MNOTE_SANYO_TAG_LIGHTSOURCESPECIAL: +		CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen); +		CC (entry->components, 1, v, maxlen); +		vs = exif_get_short (entry->data, entry->order); +		switch (vs) { +		case 0: +			strncpy (v, _("Off"), maxlen); +			break; +		case 1: +			strncpy (v, _("On"), maxlen); +			break; +		default: +			strncpy (v, _("Unknown"), maxlen);  			break;  		} -		strncpy (v, items[i].elem[j].string, maxlen);  		break; -  	case MNOTE_NIKON_TAG_LENS:  		CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen);  		CC (entry->components, 4, v, maxlen); @@ -356,17 +531,6 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  			snprintf (v, maxlen, "%ld-%ldmm 1:%3.1f - %3.1f",a,b,c,d);  		}  		break; -	case MNOTE_NIKON1_TAG_FOCUS: -		CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen); -		CC (entry->components, 1, v, maxlen); -		vr = exif_get_rational (entry->data, entry->order); -		if (!vr.denominator) { -			strncpy (v, _("Infinite"), maxlen); -		} else { -			r = (double)vr.numerator / vr.denominator; -			snprintf (v, maxlen, "%2.2f", r); -		} -		break;  	/* Olympus */  	case MNOTE_OLYMPUS_TAG_MODE: @@ -412,37 +576,47 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  			strncat (v, buf, maxlen - strlen (v));  		}  		break; -	case MNOTE_OLYMPUS_TAG_UNKNOWN_1: -		CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen); -		CC (entry->components, 1, v, maxlen); -		strncpy (v, _("Unknown tag."), maxlen); -		break; -	case MNOTE_OLYMPUS_TAG_UNKNOWN_2: -		CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen); -		CC (entry->components, 1, v, maxlen); -		break; -	case MNOTE_OLYMPUS_TAG_UNKNOWN_3: +	case MNOTE_OLYMPUS_TAG_LENSDISTORTION:  		CF (entry->format, EXIF_FORMAT_SSHORT, v, maxlen); -		CC (entry->components, 1, v, maxlen); +		CC (entry->components, 6, v, maxlen); +		for (i=0; i < (int)entry->components; ++i) { +			vs = exif_get_sshort (entry->data+2*i, entry->order); +			sprintf (buf, "%hd ", vs); +			strncat (v, buf, maxlen - strlen (v)); +		} +		break; +	case MNOTE_OLYMPUS_TAG_COLORCONTROL: +		CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen); +		CC (entry->components, 6, v, maxlen); +		for (i=0; i < (int)entry->components; ++i) { +			vs = exif_get_short (entry->data+2*i, entry->order); +			sprintf (buf, "%hu ", vs); +			strncat (v, buf, maxlen - strlen (v)); +		}  		break;  	case MNOTE_OLYMPUS_TAG_VERSION:  		CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen);  		CC2 (entry->components, 5, 8, v, maxlen); -		strncpy (v, entry->data, MIN (maxlen, entry->size)); +		strncpy (v, (char *)entry->data, MIN (maxlen, entry->size)); +		break; +	case MNOTE_OLYMPUS_TAG_SERIALNUMBER2: +		CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen); +		strncpy (v, (char *)entry->data, MIN (maxlen, entry->size));  		break;  	case MNOTE_OLYMPUS_TAG_INFO:  		CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen); -		CC2 (entry->components, 52, 53, v, maxlen); -		strncpy (v, entry->data, MIN (maxlen, entry->size)); +		CC2 (entry->components, 52, 60, v, maxlen); +		strncpy (v, (char *)entry->data, MIN (maxlen, entry->size));  		break;  	case MNOTE_OLYMPUS_TAG_ID:  		CF (entry->format, EXIF_FORMAT_UNDEFINED, v, maxlen);  		CC (entry->components, 32, v, maxlen); -		strncpy (v, entry->data, MIN (maxlen, entry->size)); +		strncpy (v, (char *)entry->data, MIN (maxlen, entry->size));  		break;  	case MNOTE_OLYMPUS_TAG_UNKNOWN_4:  		CF (entry->format, EXIF_FORMAT_LONG, v, maxlen);  		CC (entry->components, 30, v, maxlen); +		/* TODO: display me */  		break;  	case MNOTE_OLYMPUS_TAG_FOCUSDIST:  		CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen); @@ -493,7 +667,7 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  					break;  				}  				if (colorTemp) { -					snprintf (v, maxlen, "Manual: %liK", colorTemp); +					snprintf (v, maxlen, _("Manual: %liK"), colorTemp);  				}  				else {  					strncpy (v, _("Manual: Unknown"), maxlen); @@ -509,24 +683,75 @@ mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int m  			break;  		}  		break; +	case MNOTE_OLYMPUS_TAG_REDBALANCE: +	case MNOTE_OLYMPUS_TAG_BLUEBALANCE: +		CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen); +		CC (entry->components, 2, v, maxlen); +		vs = exif_get_short (entry->data, entry->order); +		snprintf (v, maxlen, "%hu ", vs); +		vs = exif_get_short (entry->data + 2, entry->order); +		sprintf (buf, "%hu", vs); +		strncat (v, buf, maxlen - strlen (v)); +		break; +	case MNOTE_OLYMPUS_TAG_BLACKLEVEL: +	case MNOTE_NIKON_TAG_IMAGEBOUNDARY: +		CC (entry->components, 4, v, maxlen); +		/* Fall through to COLORMATRIX */ +	case MNOTE_OLYMPUS_TAG_COLORMATRIX: +		CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen); +		if (entry->tag == MNOTE_OLYMPUS_TAG_COLORMATRIX) +			CC (entry->components, 9, v, maxlen); +		for (i=0; i < (int)entry->components; ++i) { +			vs = exif_get_short (entry->data+2*i, entry->order); +			sprintf (buf, "%hu ", vs); +			strncat (v, buf, maxlen - strlen (v)); +		} +		break; +	case MNOTE_NIKON1_TAG_FOCUS: +	case MNOTE_NIKON_TAG_DIGITALZOOM: +	case MNOTE_NIKON1_TAG_DIGITALZOOM: +	case MNOTE_OLYMPUS_TAG_FOCALPLANEDIAGONAL: +		CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen); +		/* Fall through to default handler for display */  	default:  		switch (entry->format) {  		case EXIF_FORMAT_ASCII: -			strncpy (v, entry->data, -				 MIN (maxlen, entry->components)); +			strncpy (v, (char *)entry->data, MIN (maxlen, entry->size));  			break;  		case EXIF_FORMAT_SHORT: +			CC (entry->components, 1, v, maxlen);  			vs = exif_get_short (entry->data, entry->order); -			snprintf (v, maxlen, "%hi", vs); +			snprintf (v, maxlen, "%hu", vs);  			break;  		case EXIF_FORMAT_LONG: +			CC (entry->components, 1, v, maxlen);  			vl = exif_get_long (entry->data, entry->order);  			snprintf (v, maxlen, "%li", (long int) vl);  			break; +		case EXIF_FORMAT_RATIONAL: +			CC (entry->components, 1, v, maxlen); +			vr = exif_get_rational (entry->data, entry->order); +			if (!vr.denominator) { +				strncpy (v, _("Infinite"), maxlen); +			} else { +				r = (double)vr.numerator / vr.denominator; +				snprintf (v, maxlen, "%2.3f", r); +			} +			break; +		case EXIF_FORMAT_SRATIONAL: +			CC (entry->components, 1, v, maxlen); +			vsr = exif_get_srational (entry->data, entry->order); +			if (!vsr.denominator) { +				strncpy (v, _("Infinite"), maxlen); +			} else { +				r = (double)vsr.numerator / vsr.denominator; +				snprintf (v, maxlen, "%2.3f", r); +			} +			break;  		case EXIF_FORMAT_UNDEFINED:  		default: -			snprintf (v, maxlen, _("%li bytes unknown data: "), -				  (long int) entry->size); +			snprintf (v, maxlen, _("%i bytes unknown data: "), +				  entry->size);  			for (i = 0; i < (int)entry->size; i++) {  				sprintf (buf, "%02x", entry->data[i]);  				strncat (v, buf, maxlen - strlen (v)); diff --git a/src/libexif/olympus/mnote-olympus-entry.h b/src/libexif/olympus/mnote-olympus-entry.h index a725228..9526bad 100644 --- a/src/libexif/olympus/mnote-olympus-entry.h +++ b/src/libexif/olympus/mnote-olympus-entry.h @@ -1,6 +1,6 @@  /* mnote-olympus-entry.h   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public diff --git a/src/libexif/olympus/mnote-olympus-tag.c b/src/libexif/olympus/mnote-olympus-tag.c index b7beacd..37a6bdc 100644 --- a/src/libexif/olympus/mnote-olympus-tag.c +++ b/src/libexif/olympus/mnote-olympus-tag.c @@ -1,6 +1,6 @@  /* mnote-olympus-tag.c:   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -26,99 +26,163 @@  #include <stdlib.h> -static struct { +static const struct {  	MnoteOlympusTag tag;  	const char *name;  	const char *title;  	const char *description;  } table[] = { - +#ifndef NO_VERBOSE_TAG_STRINGS  	/* Nikon v2 */ -	{MNOTE_NIKON_TAG_FIRMWARE,     "Firmware", N_("Firmware Version"), NULL}, -	{MNOTE_NIKON_TAG_ISO,          "ISO", N_("ISO Setting"), NULL}, -	{MNOTE_NIKON_TAG_COLORMODE1,   "COLORMODE1", N_("Colormode (?)"), NULL}, -	{MNOTE_NIKON_TAG_QUALITY,      "QUALITY", N_("Quality"), NULL}, -	{MNOTE_NIKON_TAG_WHITEBALANCE, "WHITEBALANCE", N_("Whitebalance"), NULL}, -	{MNOTE_NIKON_TAG_SHARPENING,   "SHARPENING",   N_("Image Sharpening"), NULL}, -	{MNOTE_NIKON_TAG_FOCUSMODE,    "FOCUSMODE",   N_("Focus Mode"), NULL}, -	{MNOTE_NIKON_TAG_FLASHSETTING, "FLASHSETTING",   N_("Flash Setting"), NULL}, -	{MNOTE_NIKON_TAG_FLASHMODE,    "FLASHMODE",    N_("Flash Mode"), NULL}, -	{MNOTE_NIKON_TAG_WHITEBALANCEFINE,"WHITEBALANCEFINE",N_("Whitebalance fine ajustment"), NULL}, -	{MNOTE_NIKON_TAG_WHITEBALANCERB,  "WHITEBALANCERB", N_("Whitebalance RB"), NULL}, +	{MNOTE_NIKON_TAG_FIRMWARE,     "Firmware", N_("Firmware Version"), ""}, +	{MNOTE_NIKON_TAG_ISO,          "ISO", N_("ISO Setting"), ""}, +	{MNOTE_NIKON_TAG_COLORMODE1,   "COLORMODE1", N_("Colormode (?)"), ""}, +	{MNOTE_NIKON_TAG_QUALITY,      "QUALITY", N_("Quality"), ""}, +	{MNOTE_NIKON_TAG_WHITEBALANCE, "WHITEBALANCE", N_("Whitebalance"), ""}, +	{MNOTE_NIKON_TAG_SHARPENING,   "SHARPENING",   N_("Image Sharpening"), ""}, +	{MNOTE_NIKON_TAG_FOCUSMODE,    "FOCUSMODE",   N_("Focus Mode"), ""}, +	{MNOTE_NIKON_TAG_FLASHSETTING, "FLASHSETTING",   N_("Flash Setting"), ""}, +	{MNOTE_NIKON_TAG_FLASHMODE,    "FLASHMODE",    N_("Flash Mode"), ""}, +	{MNOTE_NIKON_TAG_WHITEBALANCEFINE,"WHITEBALANCEFINE",N_("Whitebalance fine adjustment"), ""}, +	{MNOTE_NIKON_TAG_WHITEBALANCERB,  "WHITEBALANCERB", N_("Whitebalance RB"), ""},  	{MNOTE_NIKON_TAG_UNKNOWN_0X000D,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_ISOSELECTION,    "ISOSELECTION", N_("Isoselection"), NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X0011,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_EXPOSUREDIFF,    "EXPOSUREDIFF", N_("Exposurediff ?"), NULL}, -	{MNOTE_NIKON_TAG_FLASHCOMPENSATION, "FLASHCOMPENSATION", N_("Flashcompensation ?"), NULL}, -	{MNOTE_NIKON_TAG_ISO2,            "ISO", N_("ISO Setting"), NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X0016,  NULL, NULL, NULL}, +	{MNOTE_NIKON_TAG_ISOSELECTION,    "ISOSELECTION", N_("Isoselection"), ""}, +	{MNOTE_NIKON_TAG_PREVIEWIMAGE,    "PREVIEWIMAGE", N_("Preview Image"), ""}, +	{MNOTE_NIKON_TAG_EXPOSUREDIFF,    "EXPOSUREDIFF", N_("Exposurediff ?"), ""}, +	{MNOTE_NIKON_TAG_FLASHEXPCOMPENSATION, "FLASHEXPCOMPENSATION", N_("Flash exposure compensation"), ""}, +	{MNOTE_NIKON_TAG_ISO2,            "ISO", N_("ISO Setting"), ""}, +	{MNOTE_NIKON_TAG_IMAGEBOUNDARY,   "IMAGEBOUNDARY", N_("Image Boundary"), ""},  	{MNOTE_NIKON_TAG_UNKNOWN_0X0017,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X0018,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X0019,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_IMAGEADJUSTMENT, "ImageAdjustment", N_("Image Adjustment"), NULL}, -	{MNOTE_NIKON_TAG_TONECOMPENSATION, "TONECOMPENSATION", N_("Tonecompensation"), NULL}, -	{MNOTE_NIKON_TAG_ADAPTER,         "Adapter", N_("Adapter"), NULL}, -	{MNOTE_NIKON_TAG_LENSTYPE,        "LENSTYPE", N_("Lenstype"), NULL}, -	{MNOTE_NIKON_TAG_LENS,            "LENS", N_("Lens"), NULL}, -	{MNOTE_NIKON_TAG_MANUALFOCUSDISTANCE, "MANUALFOCUSDISTANCE", N_("Manual Focus Distance"), NULL}, -	{MNOTE_NIKON_TAG_DIGITALZOOM,     "DigitalZoom", N_("Digital Zoom"), NULL}, -	{MNOTE_NIKON_TAG_FLASHUSED,       "FLASHUSED", N_("Flash used"), NULL}, -	{MNOTE_NIKON_TAG_AFFOCUSPOSITION, "AFFOCUSPOSITION", N_("AF Focus position"), NULL}, -	{MNOTE_NIKON_TAG_BRACKETING,      "BRACKETING", N_("Bracketing"), NULL}, +	{MNOTE_NIKON_TAG_FLASHEXPOSUREBRACKETVAL,  "FLASHEXPOSUREBRACKETVAL", N_("Flash exposure bracket value"), ""}, +	{MNOTE_NIKON_TAG_EXPOSUREBRACKETVAL,  "EXPOSUREBRACKETVAL", N_("Exposure bracket value"), ""}, +	{MNOTE_NIKON_TAG_IMAGEADJUSTMENT, "ImageAdjustment", N_("Image Adjustment"), ""}, +	{MNOTE_NIKON_TAG_TONECOMPENSATION, "TONECOMPENSATION", N_("Tonecompensation"), ""}, +	{MNOTE_NIKON_TAG_ADAPTER,         "ADAPTER", N_("Adapter"), ""}, +	{MNOTE_NIKON_TAG_LENSTYPE,        "LENSTYPE", N_("Lenstype"), ""}, +	{MNOTE_NIKON_TAG_LENS,            "LENS", N_("Lens"), ""}, +	{MNOTE_NIKON_TAG_MANUALFOCUSDISTANCE, "MANUALFOCUSDISTANCE", N_("Manual Focus Distance"), ""}, +	{MNOTE_NIKON_TAG_DIGITALZOOM,     "DigitalZoom", N_("Digital Zoom"), ""}, +	{MNOTE_NIKON_TAG_FLASHUSED,       "FLASHUSED", N_("Flash used"), ""}, +	{MNOTE_NIKON_TAG_AFFOCUSPOSITION, "AFFOCUSPOSITION", N_("AF Focus position"), ""}, +	{MNOTE_NIKON_TAG_BRACKETING,      "BRACKETING", N_("Bracketing"), ""},  	{MNOTE_NIKON_TAG_UNKNOWN_0X008A,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X008B,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_CURVE,           "CURVE,", N_("Contrast curve"), NULL}, -	{MNOTE_NIKON_TAG_COLORMODE,       "COLORMODE,", N_("Colormode"), NULL}, -	{MNOTE_NIKON_TAG_LIGHTYPE,        "LIGHTYPE,", N_("Lightype"), NULL}, +	{MNOTE_NIKON_TAG_LENS_FSTOPS,     "LENSFSTOPS", N_("Lens F stops"), ""}, +	{MNOTE_NIKON_TAG_CURVE,           "CURVE,", N_("Contrast curve"), ""}, +	{MNOTE_NIKON_TAG_COLORMODE,       "COLORMODE,", N_("Colormode"), ""}, +	{MNOTE_NIKON_TAG_LIGHTTYPE,       "LIGHTTYPE,", N_("Lighttype"), ""},  	{MNOTE_NIKON_TAG_UNKNOWN_0X0091,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_HUE,             "Hue,", N_("Hue Adjustment"), NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X0094,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_NOISEREDUCTION,  "NOISEREDUCTION,", N_("Noisereduction"), NULL}, +	{MNOTE_NIKON_TAG_HUE,             "HUE", N_("Hue Adjustment"), ""}, +	{MNOTE_NIKON_TAG_SATURATION,      "SATURATION", N_("Saturation"), ""}, +	{MNOTE_NIKON_TAG_NOISEREDUCTION,  "NOISEREDUCTION,", N_("Noisereduction"), ""},  	{MNOTE_NIKON_TAG_UNKNOWN_0X0097,  NULL, NULL, NULL},  	{MNOTE_NIKON_TAG_UNKNOWN_0X0098,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X009A,  NULL, NULL, NULL}, +	{MNOTE_NIKON_TAG_SENSORPIXELSIZE, "SENSORPIXELSIZE", N_("Sensor pixel size"), ""},  	{MNOTE_NIKON_TAG_UNKNOWN_0X009B,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X00A0,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X00A2,  NULL, NULL, NULL}, +	{MNOTE_NIKON_TAG_SERIALNUMBER,    "SERIALNUMBER", N_("Serial number"), ""}, +	{MNOTE_NIKON_TAG_IMAGE_DATASIZE,  "IMAGEDATASIZE", N_("Image datasize"), N_("Size of compressed image data in bytes.")},  	{MNOTE_NIKON_TAG_UNKNOWN_0X00A3,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_TOTALPICTURES,   "TOTALPICTURES,", N_("Total number of pictures taken"), NULL}, +	{MNOTE_NIKON_TAG_TOTALPICTURES,   "TOTALPICTURES,", N_("Total number of pictures taken"), ""},  	{MNOTE_NIKON_TAG_UNKNOWN_0X00A8,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_OPTIMIZATION,    "OPTIMIZATION,", N_("Optimize Image"), NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X00AA,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_UNKNOWN_0X00AB,  NULL, NULL, NULL}, -	{MNOTE_NIKON_TAG_CAPTUREEDITORDATA, "CAPTUREEDITORDATA", N_("Capture Editor Data"), NULL}, -	{MNOTE_NIKON_TAG_CAPTUREEDITORVER, "CAPTUREEDITORVER", N_("Capture Editor Version"), NULL}, +	{MNOTE_NIKON_TAG_OPTIMIZATION,    "OPTIMIZATION,", N_("Optimize Image"), ""}, +	{MNOTE_NIKON_TAG_SATURATION,      "SATURATION", N_("Saturation"), ""}, +	{MNOTE_NIKON_TAG_VARIPROGRAM,     "VARIPROGRAM", N_("Vari Program"), ""}, +	{MNOTE_NIKON_TAG_CAPTUREEDITORDATA, "CAPTUREEDITORDATA", N_("Capture Editor Data"), ""}, +	{MNOTE_NIKON_TAG_CAPTUREEDITORVER, "CAPTUREEDITORVER", N_("Capture Editor Version"), ""},  	{MNOTE_NIKON_TAG_UNKNOWN_0X0E0E,  NULL, NULL, NULL},  	{MNOTE_NIKON_TAG_UNKNOWN_0X0E10,  NULL, NULL, NULL},  	{MNOTE_NIKON1_TAG_UNKNOWN_0X0002, NULL, NULL, NULL}, -	{MNOTE_NIKON1_TAG_QUALITY,        "QUALITY", N_("Quality"), NULL}, -	{MNOTE_NIKON1_TAG_COLORMODE,      "COLORMODE,", N_("Colormode"), NULL}, -	{MNOTE_NIKON1_TAG_IMAGEADJUSTMENT, "ImageAdjustment", N_("Image Adjustment"), NULL}, -	{MNOTE_NIKON1_TAG_CCDSENSITIVITY, "CCDSensitivity", N_("CCD Sensitivity"), NULL}, -	{MNOTE_NIKON1_TAG_WHITEBALANCE,   "WhiteBalance", N_("Whitebalance"), NULL}, -	{MNOTE_NIKON1_TAG_FOCUS,          "Focus", N_("Focus"), NULL}, +	{MNOTE_NIKON1_TAG_QUALITY,        "QUALITY", N_("Quality"), ""}, +	{MNOTE_NIKON1_TAG_COLORMODE,      "COLORMODE,", N_("Colormode"), ""}, +	{MNOTE_NIKON1_TAG_IMAGEADJUSTMENT, "ImageAdjustment", N_("Image Adjustment"), ""}, +	{MNOTE_NIKON1_TAG_CCDSENSITIVITY, "CCDSensitivity", N_("CCD Sensitivity"), ""}, +	{MNOTE_NIKON1_TAG_WHITEBALANCE,   "WhiteBalance", N_("Whitebalance"), ""}, +	{MNOTE_NIKON1_TAG_FOCUS,          "Focus", N_("Focus"), ""},  	{MNOTE_NIKON1_TAG_UNKNOWN_0X0009, NULL, NULL, NULL}, -	{MNOTE_NIKON1_TAG_DIGITALZOOM,    "DigitalZoom", N_("Digital Zoom"), NULL}, -	{MNOTE_NIKON1_TAG_CONVERTER,      "Converter", N_("Converter"), NULL}, +	{MNOTE_NIKON1_TAG_DIGITALZOOM,    "DigitalZoom", N_("Digital Zoom"), ""}, +	{MNOTE_NIKON1_TAG_CONVERTER,      "Converter", N_("Converter"), ""}, -	/* Olympus */ -	{MNOTE_OLYMPUS_TAG_MODE, "Mode", N_("Speed/Sequence/Panorama direction"), NULL}, -	{MNOTE_OLYMPUS_TAG_QUALITY, "Quality", N_("Quality"), NULL}, -	{MNOTE_OLYMPUS_TAG_MACRO, "Macro", N_("Macro"), NULL}, -	{MNOTE_OLYMPUS_TAG_UNKNOWN_1, NULL, NULL, NULL}, -	{MNOTE_OLYMPUS_TAG_DIGIZOOM, "DigiZoom", N_("Digital Zoom"), NULL}, -	{MNOTE_OLYMPUS_TAG_UNKNOWN_2, NULL, NULL, NULL}, -	{MNOTE_OLYMPUS_TAG_UNKNOWN_3, NULL, NULL, NULL}, -	{MNOTE_OLYMPUS_TAG_VERSION, "FirmwareVersion", N_("Firmware version"), NULL}, -	{MNOTE_OLYMPUS_TAG_INFO, "Info", N_("Info"), NULL}, -	{MNOTE_OLYMPUS_TAG_ID, "CameraID", N_("Camera ID"), NULL}, +	/* Olympus & some Sanyo */ +	{MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE, "ThumbnailImage", N_("Thumbnail Image"), ""}, +	{MNOTE_OLYMPUS_TAG_MODE, "Mode", N_("Speed/Sequence/Panorama direction"), ""}, +	{MNOTE_OLYMPUS_TAG_QUALITY, "Quality", N_("Quality"), ""}, +	{MNOTE_OLYMPUS_TAG_MACRO, "Macro", N_("Macro"), ""}, +	{MNOTE_OLYMPUS_TAG_BWMODE, "BWMode", N_("B&W Mode"), ""}, +	{MNOTE_OLYMPUS_TAG_DIGIZOOM, "DigiZoom", N_("Digital Zoom"), ""}, +	{MNOTE_OLYMPUS_TAG_FOCALPLANEDIAGONAL, "FocalPlaneDiagonal", N_("Focal Plane Diagonal"), ""}, +	{MNOTE_OLYMPUS_TAG_LENSDISTORTION, "LensDistortionParams", N_("Lens Distortion Parameters"), ""}, +	{MNOTE_OLYMPUS_TAG_VERSION, "FirmwareVersion", N_("Firmware version"), ""}, +	{MNOTE_OLYMPUS_TAG_INFO, "Info", N_("Info"), ""}, +	{MNOTE_OLYMPUS_TAG_ID, "CameraID", N_("Camera ID"), ""}, +	{MNOTE_OLYMPUS_TAG_PRECAPTUREFRAMES, "PreCaptureFrames", N_("Precapture Frames"), ""}, +	{MNOTE_OLYMPUS_TAG_WHITEBOARD, "WhiteBoard", N_("White Board"), ""}, +	{MNOTE_OLYMPUS_TAG_ONETOUCHWB, "OneTouchWB", N_("One Touch White Balance"), ""}, +	{MNOTE_OLYMPUS_TAG_WHITEBALANCEBRACKET, "WhiteBalanceBracket", N_("White Balance Bracket"), ""}, +	{MNOTE_OLYMPUS_TAG_WHITEBALANCEBIAS, "WhiteBalanceBias", N_("White Balance Bias"), ""}, +	{MNOTE_OLYMPUS_TAG_UNKNOWN_5, NULL, NULL, NULL},  	{MNOTE_OLYMPUS_TAG_UNKNOWN_4, NULL, NULL, NULL}, -	{MNOTE_OLYMPUS_TAG_FLASHMODE, "FlashMode", N_("Flash Mode"), NULL}, -	{MNOTE_OLYMPUS_TAG_FOCUSDIST, "ManualFocusDistance", N_("Manual Focus Distance"), NULL}, -	{MNOTE_OLYMPUS_TAG_SHARPNESS, "Sharpness", N_("Sharpness Setting"), NULL}, -	{MNOTE_OLYMPUS_TAG_WBALANCE, "WhiteBalance", N_("White Balance Setting"), NULL}, -	{MNOTE_OLYMPUS_TAG_CONTRAST, "Contrast", N_("Contrast Setting"), NULL}, -	{MNOTE_OLYMPUS_TAG_MANFOCUS, "ManualFocus", N_("Manual Focus"), NULL}, +	{MNOTE_OLYMPUS_TAG_SHUTTERSPEED, "ShutterSpeed", N_("Shutter Speed"), ""}, +	{MNOTE_OLYMPUS_TAG_ISOVALUE, "ISOValue", N_("ISO Value"), ""}, +	{MNOTE_OLYMPUS_TAG_APERTUREVALUE, "ApertureValue", N_("Aperture Value"), ""}, +	{MNOTE_OLYMPUS_TAG_BRIGHTNESSVALUE, "BrightnessValue", N_("Brightness Value"), ""}, +	{MNOTE_OLYMPUS_TAG_FLASHMODE, "FlashMode", N_("Flash Mode"), ""}, +	{MNOTE_OLYMPUS_TAG_FLASHDEVICE, "FlashDevice", N_("Flash Device"), ""}, +	{MNOTE_OLYMPUS_TAG_EXPOSURECOMP, "ExposureCompensation", N_("Exposure Compensation"), ""}, +	{MNOTE_OLYMPUS_TAG_SENSORTEMPERATURE, "SensorTemperature", N_("Sensor Temperature"), ""}, +	{MNOTE_OLYMPUS_TAG_LENSTEMPERATURE, "LensTemperature", N_("Lens Temperature"), ""}, +	{MNOTE_OLYMPUS_TAG_LIGHTCONDITION, "LightCondition", N_("Light Condition"), ""}, +	{MNOTE_OLYMPUS_TAG_FOCUSRANGE, "FocusRange", N_("Focus Range"), ""}, +	{MNOTE_OLYMPUS_TAG_MANFOCUS, "FocusMode", N_("Focus Mode"), "Automatic or manual focusing mode"}, +	{MNOTE_OLYMPUS_TAG_FOCUSDIST, "ManualFocusDistance", N_("Manual Focus Distance"), ""}, +	{MNOTE_OLYMPUS_TAG_ZOOMSTEPCOUNT, "ZoomStepCount", N_("Zoom Step Count"), ""}, +	{MNOTE_OLYMPUS_TAG_FOCUSSTEPCOUNT, "FocusStepCount", N_("Focus Step Count"), ""}, +	{MNOTE_OLYMPUS_TAG_SHARPNESS, "Sharpness", N_("Sharpness Setting"), ""}, +	{MNOTE_OLYMPUS_TAG_FLASHCHARGELEVEL, "FlashChargeLevel", N_("Flash Charge Level"), ""}, +	{MNOTE_OLYMPUS_TAG_COLORMATRIX, "ColorMatrix", N_("Color Matrix"), ""}, +	{MNOTE_OLYMPUS_TAG_BLACKLEVEL, "BlackLevel", N_("Black Level"), ""}, +	{MNOTE_OLYMPUS_TAG_WBALANCE, "WhiteBalance", N_("White Balance Setting"), ""}, +	{MNOTE_OLYMPUS_TAG_REDBALANCE, "RedBalance", N_("Red Balance"), ""}, +	{MNOTE_OLYMPUS_TAG_BLUEBALANCE, "BlueBalance", N_("Blue Balance"), ""}, +	{MNOTE_OLYMPUS_TAG_COLORMATRIXNUMBER, "ColorMatrixNumber", N_("Color Matrix Number"), ""}, +	{MNOTE_OLYMPUS_TAG_SERIALNUMBER2, "SerialNumber", N_("Serial Number"), ""}, +	{MNOTE_OLYMPUS_TAG_FLASHEXPOSURECOMP, "FlashExposureComp", N_("Flash Exposure Comp"), ""}, +	{MNOTE_OLYMPUS_TAG_INTERNALFLASHTABLE, "InternalFlashTable", N_("Internal Flash Table"), ""}, +	{MNOTE_OLYMPUS_TAG_EXTERNALFLASHGVALUE, "ExternalFlashGValue", N_("External Flash G Value"), ""}, +	{MNOTE_OLYMPUS_TAG_EXTERNALFLASHBOUNCE, "ExternalFlashBounce", N_("External Flash Bounce"), ""}, +	{MNOTE_OLYMPUS_TAG_EXTERNALFLASHZOOM, "ExternalFlashZoom", N_("External Flash Zoom"), ""}, +	{MNOTE_OLYMPUS_TAG_EXTERNALFLASHMODE, "ExternalFlashMode", N_("External Flash Mode"), ""}, +	{MNOTE_OLYMPUS_TAG_CONTRAST, "Contrast", N_("Contrast Setting"), ""}, +	{MNOTE_OLYMPUS_TAG_SHARPNESSFACTOR, "SharpnessFactor", N_("Sharpness Factor"), ""}, +	{MNOTE_OLYMPUS_TAG_COLORCONTROL, "ColorControl", N_("Color Control"), ""}, +	{MNOTE_OLYMPUS_TAG_IMAGEWIDTH, "OlympusImageWidth", N_("Olympus Image Width"), ""}, +	{MNOTE_OLYMPUS_TAG_IMAGEHEIGHT, "OlympusImageHeight", N_("Olympus Image Height"), ""}, +	{MNOTE_OLYMPUS_TAG_SCENEDETECT, "SceneDetect", N_("Scene Detect"), ""}, +	{MNOTE_OLYMPUS_TAG_COMPRESSIONRATIO, "CompressionRatio", N_("Compression Ratio"), ""}, +	{MNOTE_OLYMPUS_TAG_PREVIEWIMAGEVALID, "PreviewImageValid", N_("Preview Image Valid"), ""}, +	{MNOTE_OLYMPUS_TAG_AFRESULT, "AFResult", N_("AF Result"), ""}, +	{MNOTE_OLYMPUS_TAG_CCDSCANMODE, "CCDScanMode", N_("CCD Scan Mode"), ""}, +	{MNOTE_OLYMPUS_TAG_NOISEREDUCTION, "NoiseReduction", N_("Noise Reduction"), ""}, +	{MNOTE_OLYMPUS_TAG_INFINITYLENSSTEP, "InfinityLensStep", N_("Infinity Lens Step"), ""}, +	{MNOTE_OLYMPUS_TAG_NEARLENSSTEP, "NearLensStep", N_("Near Lens Step"), ""}, +	{MNOTE_OLYMPUS_TAG_LIGHTVALUECENTER, "LightValueCenter", N_("Light Value Center"), ""}, +	{MNOTE_OLYMPUS_TAG_LIGHTVALUEPERIPHERY, "LightValuePeriphery", N_("Light Value Periphery"), ""}, + +	/* Sanyo */ +	{MNOTE_SANYO_TAG_SEQUENTIALSHOT, "SequentialShot", N_("Sequential Shot"), ""}, +	{MNOTE_SANYO_TAG_WIDERANGE, "WideRange", N_("Wide Range"), ""}, +	{MNOTE_SANYO_TAG_COLORADJUSTMENTMODE, "ColorAdjustmentMode", N_("Color Adjustment Mode"), ""}, +	{MNOTE_SANYO_TAG_QUICKSHOT, "QuickShot", N_("Quick Shot"), ""}, +	{MNOTE_SANYO_TAG_SELFTIMER, "SelfTimer", N_("Self Timer"), ""}, +	{MNOTE_SANYO_TAG_VOICEMEMO, "VoiceMemo", N_("Voice Memo"), ""}, +	{MNOTE_SANYO_TAG_RECORDSHUTTERRELEASE, "RecordShutterRelease", N_("Record Shutter Release"), ""}, +	{MNOTE_SANYO_TAG_FLICKERREDUCE, "FlickerReduce", N_("Flicker Reduce"), ""}, +	{MNOTE_SANYO_TAG_OPTICALZOOM, "OpticalZoom", N_("Optical Zoom"), ""}, +	{MNOTE_SANYO_TAG_DIGITALZOOM, "DigitalZoom", N_("Digital Zoom"), ""}, +	{MNOTE_SANYO_TAG_LIGHTSOURCESPECIAL, "LightSourceSpecial", N_("Light Source Special"), ""}, +	{MNOTE_SANYO_TAG_RESAVED, "Resaved", N_("Resaved"), ""}, +	{MNOTE_SANYO_TAG_SCENESELECT, "SceneSelect", N_("Scene Select"), ""}, +	{MNOTE_SANYO_TAG_MANUALFOCUSDISTANCE, "ManualFocusDistance", N_("Manual Focus Distance"), ""}, +	{MNOTE_SANYO_TAG_SEQUENCESHOTINTERVAL, "SequenceShotInterval", N_("Sequence Shot Interval"), ""}, +#endif  	{0, NULL, NULL, NULL}  }; @@ -150,6 +214,10 @@ mnote_olympus_tag_get_description (MnoteOlympusTag t)  	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);  	for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) -		if (table[i].tag == t) return (_(table[i].description)); +		if (table[i].tag == t) { +			if (!table[i].description || !*table[i].description) +				return ""; +			return (_(table[i].description)); +		}  	return NULL;  } diff --git a/src/libexif/olympus/mnote-olympus-tag.h b/src/libexif/olympus/mnote-olympus-tag.h index 22278ac..9ec08a6 100644 --- a/src/libexif/olympus/mnote-olympus-tag.h +++ b/src/libexif/olympus/mnote-olympus-tag.h @@ -1,6 +1,6 @@  /* mnote-olympus-tag.h   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -42,13 +42,13 @@ enum _MnoteOlympusTag {  	MNOTE_NIKON_TAG_UNKNOWN_0X000D          = 0x000d,  	MNOTE_NIKON_TAG_EXPOSUREDIFF            = 0x000e,  	MNOTE_NIKON_TAG_ISOSELECTION            = 0x000f, -	MNOTE_NIKON_TAG_UNKNOWN_0X0011          = 0x0011, -	MNOTE_NIKON_TAG_FLASHCOMPENSATION       = 0x0012, +	MNOTE_NIKON_TAG_PREVIEWIMAGE            = 0x0011, +	MNOTE_NIKON_TAG_FLASHEXPCOMPENSATION    = 0x0012,  	MNOTE_NIKON_TAG_ISO2                    = 0x0013, -	MNOTE_NIKON_TAG_UNKNOWN_0X0016          = 0x0016, +	MNOTE_NIKON_TAG_IMAGEBOUNDARY           = 0x0016,  	MNOTE_NIKON_TAG_UNKNOWN_0X0017          = 0x0017, -	MNOTE_NIKON_TAG_UNKNOWN_0X0018          = 0x0018, -	MNOTE_NIKON_TAG_UNKNOWN_0X0019          = 0x0019, +	MNOTE_NIKON_TAG_FLASHEXPOSUREBRACKETVAL = 0x0018, +	MNOTE_NIKON_TAG_EXPOSUREBRACKETVAL      = 0x0019,  	MNOTE_NIKON_TAG_IMAGEADJUSTMENT         = 0x0080,  	MNOTE_NIKON_TAG_TONECOMPENSATION        = 0x0081,  	MNOTE_NIKON_TAG_ADAPTER                 = 0x0082, @@ -60,26 +60,26 @@ enum _MnoteOlympusTag {  	MNOTE_NIKON_TAG_AFFOCUSPOSITION         = 0x0088,  	MNOTE_NIKON_TAG_BRACKETING              = 0x0089,  	MNOTE_NIKON_TAG_UNKNOWN_0X008A          = 0x008a, -	MNOTE_NIKON_TAG_UNKNOWN_0X008B          = 0x008b, +	MNOTE_NIKON_TAG_LENS_FSTOPS             = 0x008b,  	MNOTE_NIKON_TAG_CURVE                   = 0x008c,  	MNOTE_NIKON_TAG_COLORMODE               = 0x008d, -	MNOTE_NIKON_TAG_LIGHTYPE                = 0x0090, +	MNOTE_NIKON_TAG_LIGHTTYPE               = 0x0090,  	MNOTE_NIKON_TAG_UNKNOWN_0X0091          = 0x0091,  	MNOTE_NIKON_TAG_HUE                     = 0x0092, -	MNOTE_NIKON_TAG_UNKNOWN_0X0094          = 0x0094, +	MNOTE_NIKON_TAG_SATURATION              = 0x0094,  	MNOTE_NIKON_TAG_NOISEREDUCTION          = 0x0095,  	MNOTE_NIKON_TAG_UNKNOWN_0X0097          = 0x0097,  	MNOTE_NIKON_TAG_UNKNOWN_0X0098          = 0x0098, -	MNOTE_NIKON_TAG_UNKNOWN_0X009A          = 0x009a, +	MNOTE_NIKON_TAG_SENSORPIXELSIZE         = 0x009a,  	MNOTE_NIKON_TAG_UNKNOWN_0X009B          = 0x009b, -	MNOTE_NIKON_TAG_UNKNOWN_0X00A0          = 0x00a0, -	MNOTE_NIKON_TAG_UNKNOWN_0X00A2          = 0x00a2, +	MNOTE_NIKON_TAG_SERIALNUMBER            = 0x00a0, +	MNOTE_NIKON_TAG_IMAGE_DATASIZE          = 0x00a2,  	MNOTE_NIKON_TAG_UNKNOWN_0X00A3          = 0x00a3,  	MNOTE_NIKON_TAG_TOTALPICTURES           = 0x00a7,  	MNOTE_NIKON_TAG_UNKNOWN_0X00A8          = 0x00a8,  	MNOTE_NIKON_TAG_OPTIMIZATION            = 0x00a9, -	MNOTE_NIKON_TAG_UNKNOWN_0X00AA          = 0x00aa, -	MNOTE_NIKON_TAG_UNKNOWN_0X00AB          = 0x00ab, +	MNOTE_NIKON_TAG_SATURATION2             = 0x00aa, +	MNOTE_NIKON_TAG_VARIPROGRAM             = 0x00ab,  	MNOTE_NIKON_TAG_CAPTUREEDITORDATA       = 0x0e01,  	MNOTE_NIKON_TAG_CAPTUREEDITORVER	= 0x0e09,  	MNOTE_NIKON_TAG_UNKNOWN_0X0E0E		= 0x0e0e, @@ -98,27 +98,95 @@ enum _MnoteOlympusTag {  	MNOTE_NIKON1_TAG_DIGITALZOOM            = 0x000a + MNOTE_NIKON1_TAG_BASE,  	MNOTE_NIKON1_TAG_CONVERTER              = 0x000b + MNOTE_NIKON1_TAG_BASE, -	/* Olympus */ -	MNOTE_OLYMPUS_TAG_MODE		= 0x0200, -	MNOTE_OLYMPUS_TAG_QUALITY	= 0x0201, -	MNOTE_OLYMPUS_TAG_MACRO		= 0x0202, -	MNOTE_OLYMPUS_TAG_UNKNOWN_1	= 0x0203, -	MNOTE_OLYMPUS_TAG_DIGIZOOM	= 0x0204, -	MNOTE_OLYMPUS_TAG_UNKNOWN_2	= 0x0205, -	MNOTE_OLYMPUS_TAG_UNKNOWN_3	= 0x0206, -	MNOTE_OLYMPUS_TAG_VERSION	= 0x0207, -	MNOTE_OLYMPUS_TAG_INFO		= 0x0208, -	MNOTE_OLYMPUS_TAG_ID		= 0x0209, -	MNOTE_OLYMPUS_TAG_UNKNOWN_4	= 0x0f04, -	MNOTE_OLYMPUS_TAG_FLASHMODE	= 0x1004, -	MNOTE_OLYMPUS_TAG_MANFOCUS	= 0x100b, -	MNOTE_OLYMPUS_TAG_FOCUSDIST	= 0x100c, -	MNOTE_OLYMPUS_TAG_SHARPNESS	= 0x100f, -	MNOTE_OLYMPUS_TAG_WBALANCE	= 0x1015, -	MNOTE_OLYMPUS_TAG_CONTRAST	= 0x1029 +	/* Olympus and some Sanyo */ +	MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE	= 0x0100, +	MNOTE_OLYMPUS_TAG_MODE			= 0x0200, +	MNOTE_OLYMPUS_TAG_QUALITY		= 0x0201, +	MNOTE_OLYMPUS_TAG_MACRO			= 0x0202, +	MNOTE_OLYMPUS_TAG_BWMODE		= 0x0203, +	MNOTE_OLYMPUS_TAG_DIGIZOOM		= 0x0204, +	MNOTE_OLYMPUS_TAG_FOCALPLANEDIAGONAL	= 0x0205, +	MNOTE_OLYMPUS_TAG_LENSDISTORTION	= 0x0206, +	MNOTE_OLYMPUS_TAG_VERSION		= 0x0207, +	MNOTE_OLYMPUS_TAG_INFO			= 0x0208, +	MNOTE_OLYMPUS_TAG_ID			= 0x0209, +	MNOTE_OLYMPUS_TAG_PRECAPTUREFRAMES	= 0x0300, +	MNOTE_OLYMPUS_TAG_WHITEBOARD		= 0x0301, +	MNOTE_OLYMPUS_TAG_ONETOUCHWB		= 0x0302, +	MNOTE_OLYMPUS_TAG_WHITEBALANCEBRACKET	= 0x0303, +	MNOTE_OLYMPUS_TAG_WHITEBALANCEBIAS	= 0x0304, +	MNOTE_OLYMPUS_TAG_UNKNOWN_5		= 0x0f00, +	MNOTE_OLYMPUS_TAG_UNKNOWN_4		= 0x0f04, +	MNOTE_OLYMPUS_TAG_SHUTTERSPEED		= 0x1000, +	MNOTE_OLYMPUS_TAG_ISOVALUE		= 0x1001, +	MNOTE_OLYMPUS_TAG_APERTUREVALUE		= 0x1002, +	MNOTE_OLYMPUS_TAG_BRIGHTNESSVALUE	= 0x1003, +	MNOTE_OLYMPUS_TAG_FLASHMODE		= 0x1004, +	MNOTE_OLYMPUS_TAG_FLASHDEVICE		= 0x1005, +	MNOTE_OLYMPUS_TAG_EXPOSURECOMP		= 0x1006, +	MNOTE_OLYMPUS_TAG_SENSORTEMPERATURE	= 0x1007, +	MNOTE_OLYMPUS_TAG_LENSTEMPERATURE	= 0x1008, +	MNOTE_OLYMPUS_TAG_LIGHTCONDITION	= 0x1009, +	MNOTE_OLYMPUS_TAG_FOCUSRANGE		= 0x100a, +	MNOTE_OLYMPUS_TAG_MANFOCUS		= 0x100b, +	MNOTE_OLYMPUS_TAG_FOCUSDIST		= 0x100c, +	MNOTE_OLYMPUS_TAG_ZOOMSTEPCOUNT		= 0x100d, +	MNOTE_OLYMPUS_TAG_FOCUSSTEPCOUNT	= 0x100e, +	MNOTE_OLYMPUS_TAG_SHARPNESS		= 0x100f, +	MNOTE_OLYMPUS_TAG_FLASHCHARGELEVEL	= 0x1010, +	MNOTE_OLYMPUS_TAG_COLORMATRIX		= 0x1011, +	MNOTE_OLYMPUS_TAG_BLACKLEVEL		= 0x1012, +	MNOTE_OLYMPUS_TAG_WBALANCE		= 0x1015, +	MNOTE_OLYMPUS_TAG_REDBALANCE		= 0x1017, +	MNOTE_OLYMPUS_TAG_BLUEBALANCE		= 0x1018, +	MNOTE_OLYMPUS_TAG_COLORMATRIXNUMBER	= 0x1019, +	MNOTE_OLYMPUS_TAG_SERIALNUMBER2		= 0x101a, +	MNOTE_OLYMPUS_TAG_FLASHEXPOSURECOMP	= 0x1023, +	MNOTE_OLYMPUS_TAG_INTERNALFLASHTABLE	= 0x1024, +	MNOTE_OLYMPUS_TAG_EXTERNALFLASHGVALUE	= 0x1025, +	MNOTE_OLYMPUS_TAG_EXTERNALFLASHBOUNCE	= 0x1026, +	MNOTE_OLYMPUS_TAG_EXTERNALFLASHZOOM	= 0x1027, +	MNOTE_OLYMPUS_TAG_EXTERNALFLASHMODE	= 0x1028, +	MNOTE_OLYMPUS_TAG_CONTRAST		= 0x1029, +	MNOTE_OLYMPUS_TAG_SHARPNESSFACTOR	= 0x102a, +	MNOTE_OLYMPUS_TAG_COLORCONTROL		= 0x102b, +	MNOTE_OLYMPUS_TAG_IMAGEWIDTH		= 0x102e, +	MNOTE_OLYMPUS_TAG_IMAGEHEIGHT		= 0x102f, +	MNOTE_OLYMPUS_TAG_SCENEDETECT		= 0x1030, +	MNOTE_OLYMPUS_TAG_COMPRESSIONRATIO	= 0x1034, +	MNOTE_OLYMPUS_TAG_PREVIEWIMAGEVALID	= 0x1035, +	MNOTE_OLYMPUS_TAG_AFRESULT		= 0x1038, +	MNOTE_OLYMPUS_TAG_CCDSCANMODE		= 0x1039, +	MNOTE_OLYMPUS_TAG_NOISEREDUCTION	= 0x103a, +	MNOTE_OLYMPUS_TAG_INFINITYLENSSTEP	= 0x103b, +	MNOTE_OLYMPUS_TAG_NEARLENSSTEP		= 0x103c, +	MNOTE_OLYMPUS_TAG_LIGHTVALUECENTER	= 0x103d, +	MNOTE_OLYMPUS_TAG_LIGHTVALUEPERIPHERY	= 0x103e, + +	/* Sanyo */ +	MNOTE_SANYO_TAG_SEQUENTIALSHOT		= 0x020e, +	MNOTE_SANYO_TAG_WIDERANGE		= 0x020f, +	MNOTE_SANYO_TAG_COLORADJUSTMENTMODE	= 0x0210, +	MNOTE_SANYO_TAG_QUICKSHOT		= 0x0213, +	MNOTE_SANYO_TAG_SELFTIMER		= 0x0214, +	MNOTE_SANYO_TAG_VOICEMEMO		= 0x0216, +	MNOTE_SANYO_TAG_RECORDSHUTTERRELEASE	= 0x0217, +	MNOTE_SANYO_TAG_FLICKERREDUCE		= 0x0218, +	MNOTE_SANYO_TAG_OPTICALZOOM		= 0x0219, +	MNOTE_SANYO_TAG_DIGITALZOOM		= 0x021b, +	MNOTE_SANYO_TAG_LIGHTSOURCESPECIAL	= 0x021d, +	MNOTE_SANYO_TAG_RESAVED			= 0x021e, +	MNOTE_SANYO_TAG_SCENESELECT		= 0x021f, +	MNOTE_SANYO_TAG_MANUALFOCUSDISTANCE	= 0x0223, +	MNOTE_SANYO_TAG_SEQUENCESHOTINTERVAL	= 0x0224  };  typedef enum _MnoteOlympusTag MnoteOlympusTag; +/* Don't use these definitions. They are here for compatibility only. */ +#define MNOTE_OLYMPUS_TAG_UNKNOWN_1	MNOTE_OLYMPUS_TAG_BWMODE +#define MNOTE_OLYMPUS_TAG_UNKNOWN_2	MNOTE_OLYMPUS_TAG_FOCALPLANEDIAGONAL +#define MNOTE_OLYMPUS_TAG_UNKNOWN_3	MNOTE_OLYMPUS_TAG_LENSDISTORTION +  const char *mnote_olympus_tag_get_name        (MnoteOlympusTag tag);  const char *mnote_olympus_tag_get_title       (MnoteOlympusTag tag);  const char *mnote_olympus_tag_get_description (MnoteOlympusTag tag); diff --git a/src/libexif/pentax/exif-mnote-data-pentax.c b/src/libexif/pentax/exif-mnote-data-pentax.c index cc2cc12..0d17d62 100644 --- a/src/libexif/pentax/exif-mnote-data-pentax.c +++ b/src/libexif/pentax/exif-mnote-data-pentax.c @@ -1,6 +1,6 @@  /* exif-mnote-data-pentax.c   * - * Copyright © 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net> + * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -73,41 +73,67 @@ exif_mnote_data_pentax_load (ExifMnoteData *en,  		const unsigned char *buf, unsigned int buf_size)  {  	ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) en; -	unsigned int i, o, s; +	size_t i, o, s, datao = 6 + n->offset, base = 0;  	ExifShort c;  	/* Number of entries */ -	if (buf_size < 2) return; -	c = exif_get_short (buf + 6 + n->offset, n->order); +	if (buf_size < datao + (4 + 2) + 2) return; +	if (!memcmp(buf + datao, "AOC", 4)) { +		if ((buf[datao + 4] == 'I') && (buf[datao + 5] == 'I')) { +			n->version = pentaxV3; +			n->order = EXIF_BYTE_ORDER_INTEL; +		} else if ((buf[datao + 4] == 'M') && (buf[datao + 5] == 'M')) { +			n->version = pentaxV3; +			n->order = EXIF_BYTE_ORDER_MOTOROLA; +		} else { +			/* Uses Casio v2 tags */ +			n->version = pentaxV2; +		} +		datao += 4 + 2; +		base = MNOTE_PENTAX2_TAG_BASE; +	} if (!memcmp(buf + datao, "QVC", 4)) { +		n->version = casioV2; +		base = MNOTE_CASIO2_TAG_BASE; +		datao += 4 + 2; +	} else { +		n->version = pentaxV1; +	} +	c = exif_get_short (buf + datao, n->order);  	n->entries = exif_mem_alloc (en->mem, sizeof (MnotePentaxEntry) * c);  	if (!n->entries) return;  	for (i = 0; i < c; i++) { -	    o = 6 + 2 + n->offset + 12 * i; -	    if (o + 8 > buf_size) return; - -	    n->count = i + 1; -	    n->entries[i].tag        = exif_get_short (buf + o + 0, n->order); -	    n->entries[i].format     = exif_get_short (buf + o + 2, n->order); -	    n->entries[i].components = exif_get_long  (buf + o + 4, n->order); -	    n->entries[i].order      = n->order; - -            /* -             * Size? If bigger than 4 bytes, the actual data is not -             * in the entry but somewhere else (offset). -             */ -            s = exif_format_get_size (n->entries[i].format) * +		o = datao + 2 + 12 * i; +		if (o + 8 > buf_size) return; + +		n->count = i + 1; +		n->entries[i].tag        = exif_get_short (buf + o + 0, n->order) + base; +		n->entries[i].format     = exif_get_short (buf + o + 2, n->order); +		n->entries[i].components = exif_get_long  (buf + o + 4, n->order); +		n->entries[i].order      = n->order; + +		/* +		 * Size? If bigger than 4 bytes, the actual data is not +		 * in the entry but somewhere else (offset). +		 */ +		s = exif_format_get_size (n->entries[i].format) *                                        n->entries[i].components; -            if (!s) return; -            o += 8; -            if (s > 4) o = exif_get_long (buf + o, n->order) + 6; -            if (o + s > buf_size) return; +		if (s > 65536) { +			/* Corrupt data: EXIF data size is limited to the +			 * maximum size of a JPEG segment (64 kb).  +			 */ +			continue; +		} +		if (!s) return; +		o += 8; +		if (s > 4) o = exif_get_long (buf + o, n->order) + 6; +		if (o + s > buf_size) return; -            /* Sanity check */ -            n->entries[i].data = exif_mem_alloc (en->mem, sizeof (char) * s); -            if (!n->entries[i].data) return; -            n->entries[i].size = s; -            memcpy (n->entries[i].data, buf + o, s); +		/* Sanity check */ +		n->entries[i].data = exif_mem_alloc (en->mem, s); +		if (!n->entries[i].data) return; +		n->entries[i].size = s; +		memcpy (n->entries[i].data, buf + o, s);          }  } diff --git a/src/libexif/pentax/exif-mnote-data-pentax.h b/src/libexif/pentax/exif-mnote-data-pentax.h index c04bc41..62f9739 100644 --- a/src/libexif/pentax/exif-mnote-data-pentax.h +++ b/src/libexif/pentax/exif-mnote-data-pentax.h @@ -1,6 +1,6 @@  /* exif-mnote-data-pentax.h   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -27,6 +27,8 @@  #include <libexif/pentax/mnote-pentax-entry.h>  #include <libexif/exif-mem.h> +enum PentaxVersion {pentaxV1 = 1, pentaxV2 = 2, pentaxV3 = 4, casioV2 = 4 }; +  typedef struct _ExifMnoteDataPentax ExifMnoteDataPentax;  struct _ExifMnoteDataPentax { @@ -37,6 +39,8 @@ struct _ExifMnoteDataPentax {  	ExifByteOrder order;  	unsigned int offset; + +	enum PentaxVersion version;  };  ExifMnoteData *exif_mnote_data_pentax_new (ExifMem *); diff --git a/src/libexif/pentax/mnote-pentax-entry.c b/src/libexif/pentax/mnote-pentax-entry.c index 3469f22..ac15108 100644 --- a/src/libexif/pentax/mnote-pentax-entry.c +++ b/src/libexif/pentax/mnote-pentax-entry.c @@ -1,6 +1,6 @@  /* mnote-pentax-entry.c   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -34,37 +34,50 @@  #define CF(format,target,v,maxlen)                              \  {                                                               \ -        if (format != target) {                                 \ -                snprintf (v, maxlen,	                        \ -                        _("Invalid format '%s', "               \ -                        "expected '%s'."),                      \ -                        exif_format_get_name (format),          \ -                        exif_format_get_name (target));         \ -                break;                                          \ -        }                                                       \ +	if (format != target) {                                 \ +		snprintf (v, maxlen,	                        \ +			_("Invalid format '%s', "               \ +			"expected '%s'."),                      \ +			exif_format_get_name (format),          \ +			exif_format_get_name (target));         \ +		break;                                          \ +	}                                                       \  }  #define CC(number,target,v,maxlen)                                      \  {                                                                       \ -        if (number != target) {                                         \ -                snprintf (v, maxlen,                                    \ -                        _("Invalid number of components (%i, "          \ -                        "expected %i)."), (int) number, (int) target);  \ -                break;                                                  \ -        }                                                               \ +	if (number != target) {                                         \ +		snprintf (v, maxlen,                                    \ +			_("Invalid number of components (%i, "          \ +			"expected %i)."), (int) number, (int) target);  \ +		break;                                                  \ +	}                                                               \  } -static struct { +#define CC2(number,t1,t2,v,maxlen)                                      \ +{                                                                       \ +	if ((number != t1) && (number != t2)) {                         \ +		snprintf (v, maxlen,                                    \ +			_("Invalid number of components (%i, "          \ +			"expected %i or %i)."), (int) number,		\ +			(int) t1, (int) t2);  				\ +		break;                                                  \ +	}                                                               \ +} + +static const struct {  	ExifTag tag;  	struct {  		int index;  		const char *string; -	} elem[7]; +	} elem[33];  } items[] = { +#ifndef NO_VERBOSE_TAG_DATA    { MNOTE_PENTAX_TAG_MODE,      { {0, N_("Auto")},        {1, N_("Night-scene")},        {2, N_("Manual")}, +      {4, N_("Multi-exposure")},        {0, NULL}}},    { MNOTE_PENTAX_TAG_QUALITY,      { {0, N_("Good")}, @@ -114,6 +127,181 @@ static struct {        {2, N_("Black & White")},        {3, N_("Sepia")},        {0, NULL}}}, +  { MNOTE_PENTAX2_TAG_MODE, +    { {0, N_("Auto")}, +      {1, N_("Night-scene")}, +      {2, N_("Manual")}, +      {4, N_("Multi-exposure")}, +      {0, NULL}}}, +  { MNOTE_PENTAX2_TAG_QUALITY, +    { {0, N_("Good")}, +      {1, N_("Better")}, +      {2, N_("Best")}, +      {3, N_("TIFF")}, +      {4, N_("RAW")}, +      {0, NULL}}}, +  { MNOTE_PENTAX2_TAG_IMAGE_SIZE, +    { {0, "640x480"}, +      {1, N_("Full")}, +      {2, "1024x768"}, +      {3, "1280x960"}, +      {4, "1600x1200"}, +      {5, "2048x1536"}, +      {8, N_("2560x1920 or 2304x1728")}, +      {9, "3072x2304"}, +      {10, "3264x2448"}, +      {19, "320x240"}, +      {20, "2288x1712"}, +      {21, "2592x1944"}, +      {22, N_("2304x1728 or 2592x1944")}, +      {23, "3056x2296"}, +      {25, N_("2816x2212 or 2816x2112")}, +      {27, "3648x2736"}, +      {36, "3008x2008"}, +      {0, NULL}}}, +  { MNOTE_PENTAX2_TAG_PICTURE_MODE, +    { {0, N_("Program")}, +      {2, N_("Program AE")}, +      {3, N_("Manual")}, +      {5, N_("Portrait")}, +      {6, N_("Landscape")}, +      {8, N_("Sport")}, +      {9, N_("Night Scene")}, +      {11, N_("Soft")}, +      {12, N_("Surf & Snow")}, +      {13, N_("Sunset or Candlelight")}, +      {14, N_("Autumn")}, +      {15, N_("Macro")}, +      {17, N_("Fireworks")}, +      {18, N_("Text")}, +      {19, N_("Panorama")}, +      {30, N_("Self Portrait")}, +      {31, N_("Illustrations")}, +      {33, N_("Digital Filter")}, +      {37, N_("Museum")}, +      {38, N_("Food")}, +      {40, N_("Green Mode")}, +      {49, N_("Light Pet")}, +      {50, N_("Dark Pet")}, +      {51, N_("Medium Pet")}, +      {53, N_("Underwater")}, +      {54, N_("Candlelight")}, +      {55, N_("Natural Skin Tone")}, +      {56, N_("Synchro Sound Record")}, +      {58, N_("Frame Composite")}, +      {0, NULL}}}, +  { MNOTE_PENTAX2_TAG_FLASH_MODE, +    { {0x0000, N_("Auto, Did not fire")}, +      {0x0001, N_("Off")}, +      {0x0003, N_("Auto, Did not fire, Red-eye reduction")}, +      {0x0100, N_("Auto, Fired")}, +      {0x0102, N_("On")}, +      {0x0103, N_("Auto, Fired, Red-eye reduction")}, +      {0x0104, N_("On, Red-eye reduction")}, +      {0x0105, N_("On, Wireless")}, +      {0x0108, N_("On, Soft")}, +      {0x0109, N_("On, Slow-sync")}, +      {0x010a, N_("On, Slow-sync, Red-eye reduction")}, +      {0x010b, N_("On, Trailing-curtain Sync")}, +      {0, NULL}}}, +  { MNOTE_PENTAX2_TAG_FOCUS_MODE, +    { {0, N_("Normal")}, +      {1, N_("Macro")}, +      {2, N_("Infinity")}, +      {3, N_("Manual")}, +      {5, N_("Pan Focus")}, +      {16, N_("AF-S")}, +      {17, N_("AF-C")}, +      {0, NULL}}}, +  { MNOTE_PENTAX2_TAG_AFPOINT_SELECTED, +    { {1, N_("Upper-left")}, +      {2, N_("Top")}, +      {3, N_("Upper-right")}, +      {4, N_("Left")}, +      {5, N_("Mid-left")}, +      {6, N_("Center")}, +      {7, N_("Mid-right")}, +      {8, N_("Right")}, +      {9, N_("Lower-left")}, +      {10, N_("Bottom")}, +      {11, N_("Lower-right")}, +      {0xfffe, N_("Fixed Center")}, +      {0xffff, N_("Auto")}, +      {0, NULL}}}, +  { MNOTE_PENTAX2_TAG_AUTO_AFPOINT, +    { {0, N_("Multiple")}, +      {1, N_("Top-left")}, +      {2, N_("Top-center")}, +      {3, N_("Top-right")}, +      {4, N_("Left")}, +      {5, N_("Center")}, +      {6, N_("Right")}, +      {7, N_("Bottom-left")}, +      {8, N_("Bottom-center")}, +      {9, N_("Bottom-right")}, +      {0xffff, N_("None")}, +      {0, NULL}}}, +  { MNOTE_PENTAX2_TAG_WHITE_BALANCE, +    { {0, N_("Auto")}, +      {1, N_("Daylight")}, +      {2, N_("Shade")}, +      {3, N_("Fluorescent")}, +      {4, N_("Tungsten")}, +      {5, N_("Manual")}, +      {6, N_("Daylight Fluorescent")}, +      {7, N_("Daywhite Fluorescent")}, +      {8, N_("White Fluorescent")}, +      {9, N_("Flash")}, +      {10, N_("Cloudy")}, +      {0xfffe, N_("Unknown")}, +      {0xffff, N_("User Selected")}, +      {0, NULL}}}, +  {MNOTE_CASIO2_TAG_BESTSHOT_MODE,  +    { {0, N_("Off")}, +      {1, N_("On")}, +      {0, NULL}}}, +#endif +  {0, {{0, NULL}}} +}; + +/* Two-component values */ +static const struct { +	ExifTag tag; +	struct { +		int index1, index2; +		const char *string; +	} elem[39]; +} items2[] = { +#ifndef NO_VERBOSE_TAG_DATA +  { MNOTE_PENTAX2_TAG_IMAGE_SIZE, +    { {0, 0, "2304x1728"}, +      {4, 0, "1600x1200"}, +      {5, 0, "2048x1536"}, +      {8, 0, "2560x1920"}, +      {34, 0, "1536x1024"}, +      {36, 0, N_("3008x2008 or 3040x2024")}, +      {37, 0, "3008x2000"}, +      {35, 1, "2400x1600"}, +      {32, 2, "960x480"}, +      {33, 2, "1152x768"}, +      {34, 2, "1536x1024"}, +      {0,  0, NULL}}}, +  { MNOTE_PENTAX2_TAG_PICTURE_MODE, +    { {0,   0, N_("Auto")}, +      {5,   0, N_("Portrait")}, +      {53,  0, N_("Underwater")}, +      {255, 0, N_("Digital Filter?")}, +      {5,   1, N_("Portrait")}, +      {9,   1, N_("Night Scene")}, +      {13,  1, N_("Candlelight")}, +      {15,  1, N_("Macro")}, +      {53,  1, N_("Underwater")}, +      {0,   2, N_("Program AE")}, +      {5,   2, N_("Portrait")}, +      {6,   2, N_("Landscape")}, +      {0,   0, NULL}}}, +#endif +  {0, {{0, 0, NULL}}}  };  char * @@ -121,7 +309,7 @@ mnote_pentax_entry_get_value (MnotePentaxEntry *entry,  			      char *val, unsigned int maxlen)  {  	ExifLong vl; -	ExifShort vs; +	ExifShort vs, vs2;  	int i = 0, j = 0;  	if (!entry) return (NULL); @@ -140,26 +328,63 @@ mnote_pentax_entry_get_value (MnotePentaxEntry *entry,  	  case MNOTE_PENTAX_TAG_SATURATION:  	  case MNOTE_PENTAX_TAG_ISO_SPEED:  	  case MNOTE_PENTAX_TAG_COLOR: +	  case MNOTE_PENTAX2_TAG_MODE: +	  case MNOTE_PENTAX2_TAG_QUALITY: +	  case MNOTE_PENTAX2_TAG_FLASH_MODE: +	  case MNOTE_PENTAX2_TAG_FOCUS_MODE: +	  case MNOTE_PENTAX2_TAG_AFPOINT_SELECTED: +	  case MNOTE_PENTAX2_TAG_AUTO_AFPOINT: +	  case MNOTE_PENTAX2_TAG_WHITE_BALANCE: +	  case MNOTE_PENTAX2_TAG_PICTURE_MODE: +	  case MNOTE_PENTAX2_TAG_IMAGE_SIZE: +	  case MNOTE_CASIO2_TAG_BESTSHOT_MODE:  		CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen); -		CC (entry->components, 1, val, maxlen); -		vs = exif_get_short (entry->data, entry->order); +		CC2 (entry->components, 1, 2, val, maxlen); +		if (entry->components == 1) { +			vs = exif_get_short (entry->data, entry->order); -		/* search the tag */ -		for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++); -		if (!items[i].tag) { -		  	strncpy (val, "Internal error", maxlen); -		  	break; -		} +			/* search the tag */ +			for (i = 0; (items[i].tag && items[i].tag != entry->tag); i++); +			if (!items[i].tag) { +				snprintf (val, maxlen, +					  _("Internal error (unknown value %i)"), vs); +			  	break; +			} -		/* find the value */ -		for (j = 0; items[i].elem[j].string && +			/* find the value */ +			for (j = 0; items[i].elem[j].string &&  			    (items[i].elem[j].index < vs); j++); -		if (items[i].elem[j].index != vs) { -			snprintf (val, maxlen, -				  "Internal error (unknown value %i)", vs); -			break; +			if (items[i].elem[j].index != vs) { +				snprintf (val, maxlen, +					  _("Internal error (unknown value %i)"), vs); +				break; +			} +			strncpy (val, _(items[i].elem[j].string), maxlen); +		} else { +			/* Two-component values */ +			CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen); +			CC2 (entry->components, 1, 2, val, maxlen); +			vs = exif_get_short (entry->data, entry->order); +			vs2 = exif_get_short (entry->data+2, entry->order) << 16; + +			/* search the tag */ +			for (i = 0; (items2[i].tag && items2[i].tag != entry->tag); i++); +			if (!items2[i].tag) { +				snprintf (val, maxlen, +					  _("Internal error (unknown value %i %i)"), vs, vs2); +			  	break; +			} + +			/* find the value */ +			for (j = 0; items2[i].elem[j].string && ((items2[i].elem[j].index2 < vs2) +				|| ((items2[i].elem[j].index2 == vs2) && (items2[i].elem[j].index1 < vs))); j++); +			if ((items2[i].elem[j].index1 != vs) || (items2[i].elem[j].index2 != vs2)) { +				snprintf (val, maxlen, +					  _("Internal error (unknown value %i %i)"), vs, vs2); +				break; +			} +			strncpy (val, _(items2[i].elem[j].string), maxlen);  		} -		snprintf (val, maxlen, "%s", items[i].elem[j].string);  		break;  	case MNOTE_PENTAX_TAG_ZOOM: @@ -171,23 +396,23 @@ mnote_pentax_entry_get_value (MnotePentaxEntry *entry,  	case MNOTE_PENTAX_TAG_PRINTIM:  		CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen);  		CC (entry->components, 124, val, maxlen); -		snprintf (val, maxlen, "%li bytes unknown data", -			  entry->components); +		snprintf (val, maxlen, _("%i bytes unknown data"), +			entry->size);  		break;  	case MNOTE_PENTAX_TAG_TZ_CITY:  		CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen);  		CC (entry->components, 4, val, maxlen); -		snprintf (val, entry->components, "%s", entry->data); +		strncpy (val, (char*)entry->data, MIN(maxlen, entry->size));  		break;  	case MNOTE_PENTAX_TAG_TZ_DST:  		CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen);  		CC (entry->components, 4, val, maxlen); -		snprintf (val, entry->components, "%s", entry->data); +		strncpy (val, (char*)entry->data, MIN(maxlen, entry->size));  		break;  	default:  		switch (entry->format) {  		case EXIF_FORMAT_ASCII: -		  strncpy (val, entry->data, MIN(maxlen, entry->components)); +		  strncpy (val, (char *)entry->data, MIN(maxlen, entry->size));  		  break;  		case EXIF_FORMAT_SHORT:  		  vs = exif_get_short (entry->data, entry->order); @@ -199,8 +424,8 @@ mnote_pentax_entry_get_value (MnotePentaxEntry *entry,  		  break;  		case EXIF_FORMAT_UNDEFINED:  		default: -		  snprintf (val, maxlen, "%li bytes unknown data", -			    entry->components); +		  snprintf (val, maxlen, _("%i bytes unknown data"), +			  entry->size);  		  break;  		}  		break; diff --git a/src/libexif/pentax/mnote-pentax-entry.h b/src/libexif/pentax/mnote-pentax-entry.h index 628d5dd..a7025e6 100644 --- a/src/libexif/pentax/mnote-pentax-entry.h +++ b/src/libexif/pentax/mnote-pentax-entry.h @@ -1,6 +1,6 @@  /* mnote-pentax-entry.h   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public diff --git a/src/libexif/pentax/mnote-pentax-tag.c b/src/libexif/pentax/mnote-pentax-tag.c index 76823a4..dd06cd9 100644 --- a/src/libexif/pentax/mnote-pentax-tag.c +++ b/src/libexif/pentax/mnote-pentax-tag.c @@ -1,6 +1,6 @@  /* mnote-pentax-tag.c:   * - * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net> + * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -25,39 +25,53 @@  #include <libexif/i18n.h> -static struct { +static const struct {  	MnotePentaxTag tag;  	const char *name;  	const char *title;  	const char *description;  } table[] = { -	{MNOTE_PENTAX_TAG_MODE, "Mode", N_("Capture Mode"), NULL}, -	{MNOTE_PENTAX_TAG_QUALITY, "Quality", N_("Quality Level"), NULL}, -	{MNOTE_PENTAX_TAG_FOCUS, "Focus", N_("Focus Mode"), NULL}, -	{MNOTE_PENTAX_TAG_FLASH, "Flash", N_("Flash Mode"), NULL}, +#ifndef NO_VERBOSE_TAG_STRINGS +	{MNOTE_PENTAX_TAG_MODE, "Mode", N_("Capture Mode"), ""}, +	{MNOTE_PENTAX_TAG_QUALITY, "Quality", N_("Quality Level"), ""}, +	{MNOTE_PENTAX_TAG_FOCUS, "Focus", N_("Focus Mode"), ""}, +	{MNOTE_PENTAX_TAG_FLASH, "Flash", N_("Flash Mode"), ""},  	{MNOTE_PENTAX_TAG_UNKNOWN_05, NULL, NULL, NULL},  	{MNOTE_PENTAX_TAG_UNKNOWN_06, NULL, NULL, NULL}, -	{MNOTE_PENTAX_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance"), NULL}, +	{MNOTE_PENTAX_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance"), ""},  	{MNOTE_PENTAX_TAG_UNKNOWN_08, NULL, NULL, NULL},  	{MNOTE_PENTAX_TAG_UNKNOWN_09, NULL, NULL, NULL},  	{MNOTE_PENTAX_TAG_ZOOM, "Zoom", N_("Zoom"), NULL}, -	{MNOTE_PENTAX_TAG_SHARPNESS, "Sharpness", N_("Sharpness"), NULL}, -	{MNOTE_PENTAX_TAG_CONTRAST, "Contrast", N_("Contrast"), NULL}, -	{MNOTE_PENTAX_TAG_SATURATION, "Saturation", N_("Saturation"), NULL}, +	{MNOTE_PENTAX_TAG_SHARPNESS, "Sharpness", N_("Sharpness"), ""}, +	{MNOTE_PENTAX_TAG_CONTRAST, "Contrast", N_("Contrast"), ""}, +	{MNOTE_PENTAX_TAG_SATURATION, "Saturation", N_("Saturation"), ""},  	{MNOTE_PENTAX_TAG_UNKNOWN_14, NULL, NULL, NULL},  	{MNOTE_PENTAX_TAG_UNKNOWN_15, NULL, NULL, NULL},  	{MNOTE_PENTAX_TAG_UNKNOWN_16, NULL, NULL, NULL},  	{MNOTE_PENTAX_TAG_UNKNOWN_17, NULL, NULL, NULL},  	{MNOTE_PENTAX_TAG_UNKNOWN_18, NULL, NULL, NULL},  	{MNOTE_PENTAX_TAG_UNKNOWN_19, NULL, NULL, NULL}, -	{MNOTE_PENTAX_TAG_ISO_SPEED, "ISOSpeed", N_("ISOSpeed"), NULL}, +	{MNOTE_PENTAX_TAG_ISO_SPEED, "ISOSpeed", N_("ISOSpeed"), ""},  	{MNOTE_PENTAX_TAG_UNKNOWN_21, NULL, NULL, NULL}, -	{MNOTE_PENTAX_TAG_COLOR, "Color", N_("Color"), NULL}, +	{MNOTE_PENTAX_TAG_COLOR, "Color", N_("Colors"), ""},  	{MNOTE_PENTAX_TAG_UNKNOWN_24, NULL, NULL, NULL},  	{MNOTE_PENTAX_TAG_UNKNOWN_25, NULL, NULL, NULL}, -	{MNOTE_PENTAX_TAG_PRINTIM, "PrintIM", N_("PrintIM Settings"), NULL}, -	{MNOTE_PENTAX_TAG_TZ_CITY, "TimeZone", N_("TimeZone"), NULL}, -	{MNOTE_PENTAX_TAG_TZ_DST, "DaylightSavings", N_("DaylightSavings"), NULL}, +	{MNOTE_PENTAX_TAG_PRINTIM, "PrintIM", N_("PrintIM Settings"), ""}, +	{MNOTE_PENTAX_TAG_TZ_CITY, "TimeZone", N_("Time Zone"), ""}, +	{MNOTE_PENTAX_TAG_TZ_DST, "DaylightSavings", N_("Daylight Savings"), ""}, +	{MNOTE_PENTAX2_TAG_MODE, "Mode", N_("Capture Mode"), ""}, +	{MNOTE_PENTAX2_TAG_QUALITY, "Quality", N_("Quality Level"), ""}, +	{MNOTE_PENTAX2_TAG_IMAGE_SIZE, "ImageSize", N_("Image Size"), ""}, +	{MNOTE_PENTAX2_TAG_PICTURE_MODE, "PictureMode", N_("PictureMode"), ""}, +	{MNOTE_PENTAX2_TAG_FLASH_MODE, "FlashMode", N_("Flash Mode"), ""}, +	{MNOTE_PENTAX2_TAG_FOCUS_MODE, "FocusMode", N_("Focus Mode"), ""}, +	{MNOTE_PENTAX2_TAG_AFPOINT_SELECTED, "AFPointSelected", N_("AF Point Selected"), ""}, +	{MNOTE_PENTAX2_TAG_AUTO_AFPOINT, "AutoAFPoint", N_("Auto AF Point"), ""}, +	{MNOTE_PENTAX2_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance"), ""}, +	{MNOTE_CASIO2_TAG_OBJECT_DISTANCE, "ObjectDistance", N_("Object Distance"), N_("Distance of photographed object in millimeters.")}, +	{MNOTE_CASIO2_TAG_TIME_ZONE, "TimeZone", N_("Time Zone"), ""}, +	{MNOTE_CASIO2_TAG_BESTSHOT_MODE, "BestshotMode", N_("Bestshot mode"), ""}, +#endif  	{0, NULL, NULL, NULL}  }; @@ -89,6 +103,10 @@ mnote_pentax_tag_get_description (MnotePentaxTag t)  	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);  	for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) -		if (table[i].tag == t) return (_(table[i].description)); +		if (table[i].tag == t) { +			if (!table[i].description || !*table[i].description) +				return ""; +			return (_(table[i].description)); +		}  	return NULL;  } diff --git a/src/libexif/pentax/mnote-pentax-tag.h b/src/libexif/pentax/mnote-pentax-tag.h index a261102..872222b 100644 --- a/src/libexif/pentax/mnote-pentax-tag.h +++ b/src/libexif/pentax/mnote-pentax-tag.h @@ -1,6 +1,6 @@  /* mnote-pentax-tag.h   * - * Copyright © 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net> + * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>   *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -59,7 +59,86 @@ enum _MnotePentaxTag {  	MNOTE_PENTAX_TAG_UNKNOWN_25	= 0x0019,  	MNOTE_PENTAX_TAG_PRINTIM	= 0x0e00,  	MNOTE_PENTAX_TAG_TZ_CITY	= 0x1000, -	MNOTE_PENTAX_TAG_TZ_DST		= 0x1001 +	MNOTE_PENTAX_TAG_TZ_DST		= 0x1001, + +	/* Pentax v2, v3: real values + our proprietary base to distinguish from v1 */ +	MNOTE_PENTAX2_TAG_BASE              = 0x4000, +	MNOTE_PENTAX2_TAG_MODE		    = 0x0001 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_PREVIEW_SIZE      = 0x0002 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_PREVIEW_LENGTH    = 0x0003 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_PREVIEW_START     = 0x0004 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_MODEL_ID          = 0x0005 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_DATE              = 0x0006 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_TIME              = 0x0007 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_QUALITY           = 0x0008 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_IMAGE_SIZE        = 0x0009 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_PICTURE_MODE      = 0x000b + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_FLASH_MODE        = 0x000c + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_FOCUS_MODE        = 0x000d + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_AFPOINT_SELECTED  = 0x000e + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_AUTO_AFPOINT      = 0x000f + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_FOCUS_POSITION    = 0x0010 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_EXPOSURE_TIME     = 0x0012 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_FNUMBER           = 0x0013 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_ISO               = 0x0014 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_EXPOSURE_COMPENSATION = 0x0016 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_METERING_MODE     = 0x0017 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_AUTO_BRACKETING   = 0x0018 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_WHITE_BALANCE     = 0x0019 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_WHITE_BALANCE_MODE= 0x001a + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_BLUE_BALANCE      = 0x001b + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_RED_BALANCE       = 0x001c + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_FOCAL_LENGTH      = 0x001d + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_DIGITAL_ZOOM      = 0x001e + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_SATURATION        = 0x001f + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_CONTRAST          = 0x0020 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_SHARPNESS         = 0x0021 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_WORLDTIME_LOCATION = 0x0022 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_HOMETOWN_CITY     = 0x0023 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_DESTINATION_CITY  = 0x0024 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_HOMETOWN_DST      = 0x0025 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_DESTINATION_DST   = 0x0026 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_FRAME_NUMBER      = 0x0029 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_IMAGE_PROCESSING  = 0x0032 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_PICTURE_MODE2     = 0x0033 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_DRIVE_MODE        = 0x0034 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_COLOR_SPACE       = 0x0037 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_IMAGE_AREA_OFFSET = 0x0038 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_RAW_IMAGE_SIZE    = 0x0039 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_AFPOINTS_USED     = 0x003c + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_LENS_TYPE         = 0x003f + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_CAMERA_TEMPERATURE = 0x0047 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_NOISE_REDUCTION   = 0x0049 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_FLASH_EXPOSURE_COMP = 0x004d + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_IMAGE_TONE        = 0x004f + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_SHAKE_REDUCTION_INFO = 0x005c + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_BLACK_POINT       = 0x0200 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_WHITE_POINT       = 0x0201 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_AE_INFO           = 0x0206 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_LENS_INFO         = 0x0207 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_FLASH_INFO        = 0x0208 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_CAMERA_INFO       = 0x0215 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_BATTERY_INFO      = 0x0216 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_HOMETOWN_CITY_CODE = 0x1000 + MNOTE_PENTAX2_TAG_BASE, +	MNOTE_PENTAX2_TAG_DESTINATION_CITY_CODE = 0x1001 + MNOTE_PENTAX2_TAG_BASE, + +	/* Casio v2: some Casio v2 tags match Pentax v2 tags */ +	MNOTE_CASIO2_TAG_BASE               = MNOTE_PENTAX2_TAG_BASE, +	MNOTE_CASIO2_TAG_PREVIEW_START      = 0x2000 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_WHITE_BALANCE_BIAS = 0x2011 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_WHITE_BALANCE      = 0x2012 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_OBJECT_DISTANCE    = 0x2022 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_FLASH_DISTANCE     = 0x2034 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_RECORD_MODE        = 0x3000 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_SELF_TIMER         = 0x3001 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_QUALITY            = 0x3002 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_FOCUS_MODE         = 0x3003 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_TIME_ZONE          = 0x3006 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_BESTSHOT_MODE      = 0x3007 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_CCS_ISO_SENSITIVITY = 0x3014 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_COLOR_MODE         = 0x3015 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_ENHANCEMENT        = 0x3016 + MNOTE_CASIO2_TAG_BASE, +	MNOTE_CASIO2_TAG_FINER              = 0x3017 + MNOTE_CASIO2_TAG_BASE  };  typedef enum _MnotePentaxTag MnotePentaxTag;  | 
