diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-08 16:01:05 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-08 16:01:05 +0000 |
commit | 75d1a629c40ea6cbf38c30e394b98efdeb25a737 (patch) | |
tree | 2ae62feee162969a870e440544b9e48ce221c31a | |
parent | e4175f8393fb98b852234304b756a25c045f5b0f (diff) | |
parent | 4d201c8e365b56e6559d71d8c96749676a6ca99c (diff) | |
download | libexif-aml_tz2_305400100.tar.gz |
Snap for 8426163 from 4d201c8e365b56e6559d71d8c96749676a6ca99c to mainline-tzdata2-releaseandroid-mainline-12.0.0_r112aml_tz2_305400500aml_tz2_305400300aml_tz2_305400100aml_tz2_304500300aml_tz2_303900110aml_tz2_303900102aml_tz2_303800002aml_tz2_303800001aml_tz2_303200001android12-mainline-tzdata2-releaseaml_tz2_305400100
Change-Id: Iaac7efdf866a643f8a27c00dc1d6f81070ef2f27
33 files changed, 6001 insertions, 53 deletions
@@ -16,54 +16,8 @@ // WARNING: this makefile builds a shared library. Do not ever make it build // a static library or otherwise statically link libexif with your code. -package { - default_applicable_licenses: ["external_libexif_license"], -} - -// Added automatically by a large-scale-change that took the approach of -// 'apply every license found to every target'. While this makes sure we respect -// every license restriction, it may not be entirely correct. -// -// e.g. GPL in an MIT project might only apply to the contrib/ directory. -// -// Please consider splitting the single license below into multiple licenses, -// taking care not to lose any license_kind information, and overriding the -// default license using the 'licenses: [...]' property on targets as needed. -// -// For unused files, consider creating a 'fileGroup' with "//visibility:private" -// to attach the license to, and including a comment whether the files may be -// used in the current project. -// -// large-scale-change included anything that looked like it might be a license -// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc. -// -// Please consider removing redundant or irrelevant files from 'license_text:'. -// See: http://go/android-license-faq -license { - name: "external_libexif_license", - visibility: [":__subpackages__"], - license_kinds: [ - "SPDX-license-identifier-Apache-2.0", - "SPDX-license-identifier-BSD", - "SPDX-license-identifier-FSFAP", - "SPDX-license-identifier-GPL", - "SPDX-license-identifier-LGPL", - "SPDX-license-identifier-LGPL-2.1", - "SPDX-license-identifier-LGPL-3.0", - "SPDX-license-identifier-MIT", - "legacy_notice", - "legacy_permissive", - "legacy_unencumbered", - ], - license_text: [ - "COPYING", - "NOTICE", - ], -} - cc_library_shared { name: "libexif", - host_supported: true, vendor_available: true, vndk: { enabled: true, @@ -82,6 +36,18 @@ cc_library_shared { "libexif/exif-mnote-data.c", "libexif/exif-tag.c", "libexif/exif-utils.c", + "libexif/canon/exif-mnote-data-canon.c", + "libexif/canon/mnote-canon-entry.c", + "libexif/canon/mnote-canon-tag.c", + "libexif/olympus/exif-mnote-data-olympus.c", + "libexif/olympus/mnote-olympus-tag.c", + "libexif/olympus/mnote-olympus-entry.c", + "libexif/fuji/exif-mnote-data-fuji.c", + "libexif/fuji/mnote-fuji-entry.c", + "libexif/fuji/mnote-fuji-tag.c", + "libexif/pentax/exif-mnote-data-pentax.c", + "libexif/pentax/mnote-pentax-entry.c", + "libexif/pentax/mnote-pentax-tag.c", ], shared_libs: [ @@ -104,7 +70,7 @@ cc_library_shared { sanitize: { integer_overflow: true, - blocklist: "libexif_blocklist.txt", + blacklist: "libexif_blacklist.txt", }, } diff --git a/METADATA b/METADATA deleted file mode 100644 index 6d8601b..0000000 --- a/METADATA +++ /dev/null @@ -1,3 +0,0 @@ -third_party { - license_type: RESTRICTED -} diff --git a/README.android b/README.android index 7d0393c..e207a69 100644 --- a/README.android +++ b/README.android @@ -3,4 +3,3 @@ Note: - do not statically link to it - do not upgrade to LGPLv3 -- Much of EXIF reading capability removed to reduce library scope diff --git a/libexif/canon/Makefile-files b/libexif/canon/Makefile-files new file mode 100644 index 0000000..ef7ee2b --- /dev/null +++ b/libexif/canon/Makefile-files @@ -0,0 +1,7 @@ +# -*- Makefile -*- +noinst_LTLIBRARIES += libmnote-canon.la +libmnote_canon_la_SOURCES = \ + canon/exif-mnote-data-canon.c canon/exif-mnote-data-canon.h \ + canon/mnote-canon-entry.c canon/mnote-canon-entry.h \ + canon/mnote-canon-tag.c canon/mnote-canon-tag.h +libmnote_canon_la_LIBADD = $(LTLIBINTL) diff --git a/libexif/canon/exif-mnote-data-canon.c b/libexif/canon/exif-mnote-data-canon.c new file mode 100644 index 0000000..3a0778c --- /dev/null +++ b/libexif/canon/exif-mnote-data-canon.c @@ -0,0 +1,407 @@ +/* exif-mnote-data-canon.c + * + * 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 + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include <config.h> +#include "exif-mnote-data-canon.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <libexif/exif-byte-order.h> +#include <libexif/exif-utils.h> +#include <libexif/exif-data.h> + +#define DEBUG + +#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize )) + +static void +exif_mnote_data_canon_clear (ExifMnoteDataCanon *n) +{ + ExifMnoteData *d = (ExifMnoteData *) n; + unsigned int i; + + if (!n) return; + + if (n->entries) { + for (i = 0; i < n->count; i++) + if (n->entries[i].data) { + exif_mem_free (d->mem, n->entries[i].data); + n->entries[i].data = NULL; + } + exif_mem_free (d->mem, n->entries); + n->entries = NULL; + n->count = 0; + } +} + +static void +exif_mnote_data_canon_free (ExifMnoteData *n) +{ + if (!n) return; + + exif_mnote_data_canon_clear ((ExifMnoteDataCanon *) n); +} + +static 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 *dc = (ExifMnoteDataCanon *) note; + unsigned int m, s; + + 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 +exif_mnote_data_canon_set_byte_order (ExifMnoteData *d, ExifByteOrder o) +{ + ExifByteOrder o_orig; + ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) d; + unsigned int i; + + if (!n) return; + + o_orig = n->order; + n->order = o; + for (i = 0; i < n->count; i++) { + n->entries[i].order = o; + exif_array_set_byte_order (n->entries[i].format, n->entries[i].data, + n->entries[i].components, o_orig, o); + } +} + +static void +exif_mnote_data_canon_set_offset (ExifMnoteData *n, unsigned int o) +{ + if (n) ((ExifMnoteDataCanon *) n)->offset = o; +} + +static void +exif_mnote_data_canon_save (ExifMnoteData *ne, + unsigned char **buf, unsigned int *buf_size) +{ + ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne; + 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 = 2 + n->count * 12 + 4; + *buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size); + if (!*buf) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", *buf_size); + return; + } + + /* Save the number of entries */ + exif_set_short (*buf, n->order, (ExifShort) n->count); + + /* Save each entry */ + for (i = 0; i < n->count; i++) { + o = 2 + i * 12; + exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag); + exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format); + exif_set_long (*buf + o + 4, n->order, + n->entries[i].components); + o += 8; + s = exif_format_get_size (n->entries[i].format) * + n->entries[i].components; + if (s > 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, + sizeof (char) * ts); + if (!t) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", ts); + 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); + } else + doff = o; + + /* + * Write the data. Fill unneeded bytes with 0. Do not + * crash if data is NULL. + */ + if (!n->entries[i].data) memset (*buf + doff, 0, s); + else memcpy (*buf + doff, n->entries[i].data, s); + if (s < 4) memset (*buf + doff + s, 0, (4 - s)); + } +} + +/* XXX + * FIXME: exif_mnote_data_canon_load() may fail and there is no + * semantics to express that. + * See bug #1054323 for details, especially the comment by liblit + * after it has supposedly been fixed: + * + * https://sourceforge.net/tracker/?func=detail&aid=1054323&group_id=12272&atid=112272 + * Unfortunately, the "return" statements aren't commented at + * all, so it isn't trivial to find out what is a normal + * return, and what is a reaction to an error condition. + */ + +static void +exif_mnote_data_canon_load (ExifMnoteData *ne, + const unsigned char *buf, unsigned int buf_size) +{ + ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne; + ExifShort c; + size_t i, tcount, o, datao; + + if (!n || !buf || !buf_size) { + exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteCanon", "Short MakerNote"); + return; + } + datao = 6 + n->offset; + + if (CHECKOVERFLOW(datao, buf_size, 2)) { + exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteCanon", "Short MakerNote"); + return; + } + + /* Read the number of tags */ + c = exif_get_short (buf + datao, n->order); + datao += 2; + + /* Remove any old entries */ + exif_mnote_data_canon_clear (n); + + /* Reserve enough space for all the possible MakerNote tags */ + n->entries = exif_mem_alloc (ne->mem, sizeof (MnoteCanonEntry) * c); + if (!n->entries) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", sizeof (MnoteCanonEntry) * c); + return; + } + + /* Parse the entries */ + tcount = 0; + for (i = c, o = datao; i; --i, o += 12) { + size_t s; + + memset(&n->entries[tcount], 0, sizeof(MnoteCanonEntry)); + if (CHECKOVERFLOW(o,buf_size,12)) { + exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteCanon", "Short MakerNote"); + break; + } + + n->entries[tcount].tag = exif_get_short (buf + o, n->order); + n->entries[tcount].format = exif_get_short (buf + o + 2, n->order); + n->entries[tcount].components = exif_get_long (buf + o + 4, n->order); + n->entries[tcount].order = n->order; + + exif_log (ne->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteCanon", + "Loading entry 0x%x ('%s')...", n->entries[tcount].tag, + mnote_canon_tag_get_name (n->entries[tcount].tag)); + + /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection, + * we will check the buffer sizes closer later. */ + if ( exif_format_get_size (n->entries[tcount].format) && + buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components + ) { + exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteCanon", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components); + continue; + } + + /* + * 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[tcount].format) * + n->entries[tcount].components; + n->entries[tcount].size = s; + if (!s) { + exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteCanon", + "Invalid zero-length tag size"); + continue; + + } else { + size_t dataofs = o + 8; + if (s > 4) dataofs = exif_get_long (buf + dataofs, n->order) + 6; + + if (CHECKOVERFLOW(dataofs, buf_size, s)) { + exif_log (ne->log, EXIF_LOG_CODE_DEBUG, + "ExifMnoteCanon", + "Tag data past end of buffer (%zu > %u)", + dataofs + s, buf_size); + continue; + } + + n->entries[tcount].data = exif_mem_alloc (ne->mem, s); + if (!n->entries[tcount].data) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", s); + continue; + } + memcpy (n->entries[tcount].data, buf + dataofs, s); + } + + /* Tag was successfully parsed */ + ++tcount; + } + /* Store the count of successfully parsed tags */ + n->count = tcount; +} + +static unsigned int +exif_mnote_data_canon_count (ExifMnoteData *n) +{ + 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 i) +{ + ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) d; + unsigned int m; + + 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 *dc = (ExifMnoteDataCanon *) note; + unsigned int m, s; + + 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 *dc = (ExifMnoteDataCanon *) note; + unsigned int m, s; + + 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 *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); +} + +int +exif_mnote_data_canon_identify (const ExifData *ed, const ExifEntry *e) +{ + char value[8]; + ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE); + if (!em) + return 0; + return !strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon"); +} + +ExifMnoteData * +exif_mnote_data_canon_new (ExifMem *mem, ExifDataOption o) +{ + ExifMnoteData *d; + ExifMnoteDataCanon *dc; + + if (!mem) return NULL; + + d = exif_mem_alloc (mem, sizeof (ExifMnoteDataCanon)); + if (!d) + return NULL; + + memset(d, 0, sizeof(ExifMnoteDataCanon)); + + exif_mnote_data_construct (d, mem); + + /* Set up function pointers */ + d->methods.free = exif_mnote_data_canon_free; + d->methods.set_byte_order = exif_mnote_data_canon_set_byte_order; + d->methods.set_offset = exif_mnote_data_canon_set_offset; + d->methods.load = exif_mnote_data_canon_load; + d->methods.save = exif_mnote_data_canon_save; + d->methods.count = exif_mnote_data_canon_count; + d->methods.get_id = exif_mnote_data_canon_get_id; + d->methods.get_name = exif_mnote_data_canon_get_name; + d->methods.get_title = exif_mnote_data_canon_get_title; + d->methods.get_description = exif_mnote_data_canon_get_description; + d->methods.get_value = exif_mnote_data_canon_get_value; + + dc = (ExifMnoteDataCanon*)d; + dc->options = o; + return d; +} diff --git a/libexif/canon/exif-mnote-data-canon.h b/libexif/canon/exif-mnote-data-canon.h new file mode 100644 index 0000000..2a1cc87 --- /dev/null +++ b/libexif/canon/exif-mnote-data-canon.h @@ -0,0 +1,58 @@ +/* exif-mnote-data-canon.h + * + * 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 + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __EXIF_MNOTE_DATA_CANON_H__ +#define __EXIF_MNOTE_DATA_CANON_H__ + +#include <libexif/exif-byte-order.h> +#include <libexif/exif-mnote-data.h> +#include <libexif/exif-mnote-data-priv.h> +#include <libexif/exif-mem.h> +#include <libexif/exif-data.h> + +typedef struct _ExifMnoteDataCanon ExifMnoteDataCanon; + +#include <libexif/canon/mnote-canon-entry.h> + +struct _ExifMnoteDataCanon { + ExifMnoteData parent; + + MnoteCanonEntry *entries; + unsigned int count; + + ExifByteOrder order; + unsigned int offset; + + ExifDataOption options; +}; + +/*! Detect if MakerNote is recognized as one handled by the Canon module. + * + * \param[in] ed image #ExifData to identify as as a Canon type + * \param[in] e #ExifEntry for EXIF_TAG_MAKER_NOTE, from within ed but + * duplicated here for convenience + * \return 0 if not recognized, nonzero if recognized. The specific nonzero + * value returned may identify a subtype unique within this module. + */ +int exif_mnote_data_canon_identify (const ExifData *ed, const ExifEntry *e); + +ExifMnoteData *exif_mnote_data_canon_new (ExifMem *mem, ExifDataOption o); + +#endif /* __EXIF_MNOTE_DATA_CANON_H__ */ diff --git a/libexif/canon/mnote-canon-entry.c b/libexif/canon/mnote-canon-entry.c new file mode 100644 index 0000000..b92f69c --- /dev/null +++ b/libexif/canon/mnote-canon-entry.c @@ -0,0 +1,762 @@ +/* mnote-canon-entry.c + * + * 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 + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "mnote-canon-entry.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <libexif/exif-format.h> +#include <libexif/exif-utils.h> +#include <libexif/i18n.h> + +/* #define DEBUG */ + +#define CF(format,target,v,maxlen) \ +{ \ + if (format != target) { \ + snprintf (v, maxlen, \ + _("Invalid format '%s', " \ + "expected '%s'."), \ + exif_format_get_name (format), \ + exif_format_get_name (target)); \ + break; \ + } \ +} + +#define CC(number,target,v,maxlen) \ +{ \ + if (number != target) { \ + snprintf (v, maxlen, \ + _("Invalid number of components (%i, " \ + "expected %i)."), (int) number, (int) target); \ + break; \ + } \ +} +#define CC2(number,t1,t2,v,maxlen) \ +{ \ + if ((number != t1) && (number != t2)) { \ + snprintf (v, maxlen, \ + _("Invalid number of components (%i, " \ + "expected %i or %i)."), (int) number, \ + (int) t1, (int) t2); \ + break; \ + } \ +} + +#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, 37, N_("Canon EF 35-80mm f/4-5.6")}, + {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, 52, N_("Canon EF-S 18-55mm f/3.5-5.6 IS II")}, + {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")}, + {21, 251, N_("Canon EF 70-200mm f/2.8L IS II 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 set 1")}, + {7, 11, N_("PC set 2")}, + {7, 12, N_("PC set 3")}, + {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, _(", "), 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, unsigned int t, char *val, unsigned int maxlen) +{ + char buf[128]; + ExifLong vl; + ExifShort vs, n; + unsigned char *data; + double d; + + if (!entry) + return NULL; + + 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; + if (t >= n) return NULL; + CC (entry->components, n, val, maxlen); + 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 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 22: + case 23: + case 24: + snprintf (val, maxlen, "%u", vs); + break; + case 25: + case 26: + snprintf (val, maxlen, "%.2f", apex_value_to_aperture (vs / 32.0)); + break; + case 28: + canon_search_table_bitfield(entries_settings_1, t, vs, val, maxlen); + break; + case 34: + snprintf (val, maxlen, "%.2f", vs / 10.0); + break; + case 35: + case 36: + snprintf (val, maxlen, "%u", vs); + break; + 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 2: + case 3: + snprintf (val, maxlen, _("%.2f mm"), vs * 25.4 / 1000); + break; + default: + canon_search_table_value (entries_focal_length, t, vs, val, maxlen); + } + break; + + case MNOTE_CANON_TAG_SETTINGS_2: + 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); + 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"), (ExifSShort)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/%i"),(int)(1.0 / d)); + else + snprintf (val, maxlen, "%i", (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; + } + 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_OWNER: + CC (entry->components, 32, val, 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); Can also be 22 */ + strncpy (val, (char *)data, MIN (entry->size, maxlen)); + break; + + case MNOTE_CANON_TAG_IMAGE_NUMBER: + CF (entry->format, EXIF_FORMAT_LONG, val, maxlen); + CC (entry->components, 1, val, maxlen); + vl = exif_get_long (data, entry->order); + snprintf (val, maxlen, "%03lu-%04lu", + (unsigned long) vl/10000, + (unsigned long) vl%10000); + break; + + case MNOTE_CANON_TAG_SERIAL_NUMBER: + CF (entry->format, EXIF_FORMAT_LONG, val, maxlen); + CC (entry->components, 1, val, maxlen); + vl = exif_get_long (data, entry->order); + snprintf (val, maxlen, "%04X-%05d", (int)vl>>16,(int)vl&0xffff); + break; + + case MNOTE_CANON_TAG_CUSTOM_FUNCS: + CF (entry->format, EXIF_FORMAT_SHORT, val, maxlen); + n = exif_get_short (data, entry->order) / 2; + if (t >= n) return NULL; + CC (entry->components, n, val, maxlen); + 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); + data+=2; + printf ("Value%d=%d\n", i, vs); + } + else if (entry->format == EXIF_FORMAT_LONG) + for(i=0;i<entry->components;i++) { + vl = exif_get_long (data, entry->order); + data+=4; + printf ("Value%d=%d\n", i, vs); + } + else if (entry->format == EXIF_FORMAT_ASCII) + strncpy (val, data, MIN (entry->size, maxlen)); + } +#endif + break; + } + return val; +} diff --git a/libexif/canon/mnote-canon-entry.h b/libexif/canon/mnote-canon-entry.h new file mode 100644 index 0000000..a4d4499 --- /dev/null +++ b/libexif/canon/mnote-canon-entry.h @@ -0,0 +1,44 @@ +/* mnote-canon-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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __MNOTE_CANON_ENTRY_H__ +#define __MNOTE_CANON_ENTRY_H__ + +#include <libexif/exif-format.h> +#include <libexif/exif-byte-order.h> +#include <libexif/canon/mnote-canon-tag.h> + +typedef struct _MnoteCanonEntry MnoteCanonEntry; + +struct _MnoteCanonEntry { + MnoteCanonTag tag; + ExifFormat format; + unsigned long components; + + unsigned char *data; + unsigned int size; + + ExifByteOrder order; +}; + +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/libexif/canon/mnote-canon-tag.c b/libexif/canon/mnote-canon-tag.c new file mode 100644 index 0000000..3cacfa6 --- /dev/null +++ b/libexif/canon/mnote-canon-tag.c @@ -0,0 +1,201 @@ +/* mnote-canon-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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include <config.h> +#include "mnote-canon-tag.h" + +#include <stdlib.h> + +#include <libexif/i18n.h> + +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; /* 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; + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) + if (table[i].tag == t) return (_(table[i].title)); + return NULL; +} + +const char * +mnote_canon_tag_get_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; + + for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) + if (table[i].tag == t) { + if (!table[i].description || !*table[i].description) + return ""; + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + return _(table[i].description); + } + return NULL; +} diff --git a/libexif/canon/mnote-canon-tag.h b/libexif/canon/mnote-canon-tag.h new file mode 100644 index 0000000..0c7d9aa --- /dev/null +++ b/libexif/canon/mnote-canon-tag.h @@ -0,0 +1,59 @@ +/* mnote-canon-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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __MNOTE_CANON_TAG_H__ +#define __MNOTE_CANON_TAG_H__ + +#include <libexif/exif-data.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +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, + MNOTE_CANON_TAG_OWNER = 0x9, + MNOTE_CANON_TAG_UNKNOWN_10 = 0xa, + MNOTE_CANON_TAG_SERIAL_NUMBER = 0xc, + MNOTE_CANON_TAG_UNKNOWN_13 = 0xd, + MNOTE_CANON_TAG_CUSTOM_FUNCS = 0xf, + MNOTE_CANON_TAG_COLOR_INFORMATION = 0xa0 +}; +typedef enum _MnoteCanonTag MnoteCanonTag; + +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 +} +#endif /* __cplusplus */ + +#endif /* __MNOTE_CANON_TAG_H__ */ diff --git a/libexif/exif-data.c b/libexif/exif-data.c index 3ad2bb4..5a7763b 100644 --- a/libexif/exif-data.c +++ b/libexif/exif-data.c @@ -30,6 +30,11 @@ #include <libexif/i18n.h> #include <libexif/exif-system.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 <inttypes.h> #include <stdlib.h> #include <stdio.h> @@ -744,8 +749,29 @@ interpret_maker_note(ExifData *data, const unsigned char *d, unsigned int ds) if (!e) return; - /** Maker note detection removed **/ - + if ((mnoteid = exif_mnote_data_olympus_identify (data, e)) != 0) { + exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, + "ExifData", "Olympus MakerNote variant type %d", mnoteid); + data->priv->md = exif_mnote_data_olympus_new (data->priv->mem); + + } else if ((mnoteid = exif_mnote_data_canon_identify (data, e)) != 0) { + exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, + "ExifData", "Canon MakerNote variant type %d", mnoteid); + data->priv->md = exif_mnote_data_canon_new (data->priv->mem, data->priv->options); + + } else if ((mnoteid = exif_mnote_data_fuji_identify (data, e)) != 0) { + exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, + "ExifData", "Fuji MakerNote variant type %d", mnoteid); + data->priv->md = exif_mnote_data_fuji_new (data->priv->mem); + + /* NOTE: Must do Pentax detection last because some of the + * heuristics are pretty general. */ + } else if ((mnoteid = exif_mnote_data_pentax_identify (data, e)) != 0) { + exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, + "ExifData", "Pentax MakerNote variant type %d", mnoteid); + data->priv->md = exif_mnote_data_pentax_new (data->priv->mem); + } + /* * If we are able to interpret the maker note, do so. */ diff --git a/libexif/fuji/Makefile-files b/libexif/fuji/Makefile-files new file mode 100644 index 0000000..3a520b3 --- /dev/null +++ b/libexif/fuji/Makefile-files @@ -0,0 +1,7 @@ +# -*- Makefile -*- +noinst_LTLIBRARIES += libmnote-fuji.la +libmnote_fuji_la_SOURCES = \ + fuji/mnote-fuji-entry.c fuji/mnote-fuji-entry.h \ + fuji/exif-mnote-data-fuji.c fuji/exif-mnote-data-fuji.h \ + fuji/mnote-fuji-tag.c fuji/mnote-fuji-tag.h +libmnote_fuji_la_LIBADD = $(LTLIBINTL) diff --git a/libexif/fuji/exif-mnote-data-fuji.c b/libexif/fuji/exif-mnote-data-fuji.c new file mode 100644 index 0000000..ce70bb6 --- /dev/null +++ b/libexif/fuji/exif-mnote-data-fuji.c @@ -0,0 +1,363 @@ +/* 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 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" + +#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize )) + +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, tcount, o, datao; + + if (!n || !buf || !buf_size) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataFuji", "Short MakerNote"); + return; + } + datao = 6 + n->offset; + if (CHECKOVERFLOW(datao, buf_size, 12)) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataFuji", "Short MakerNote"); + return; + } + + n->order = EXIF_BYTE_ORDER_INTEL; + datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL); + if (CHECKOVERFLOW(datao, buf_size, 2)) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataFuji", "Short MakerNote"); + return; + } + + /* Read the number of tags */ + c = exif_get_short (buf + datao, EXIF_BYTE_ORDER_INTEL); + datao += 2; + + /* Remove any old entries */ + exif_mnote_data_fuji_clear (n); + + /* Reserve enough space for all the possible MakerNote tags */ + n->entries = exif_mem_alloc (en->mem, sizeof (MnoteFujiEntry) * c); + if (!n->entries) { + EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", sizeof (MnoteFujiEntry) * c); + return; + } + + /* Parse all c entries, storing ones that are successfully parsed */ + tcount = 0; + for (i = c, o = datao; i; --i, o += 12) { + size_t s; + + memset(&n->entries[tcount], 0, sizeof(MnoteFujiEntry)); + if (CHECKOVERFLOW(o, buf_size, 12)) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataFuji", "Short MakerNote"); + break; + } + + n->entries[tcount].tag = exif_get_short (buf + o, n->order); + n->entries[tcount].format = exif_get_short (buf + o + 2, n->order); + n->entries[tcount].components = exif_get_long (buf + o + 4, n->order); + n->entries[tcount].order = n->order; + + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji", + "Loading entry 0x%x ('%s')...", n->entries[tcount].tag, + mnote_fuji_tag_get_name (n->entries[tcount].tag)); + + /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection, + * we will check the buffer sizes closer later. */ + if ( exif_format_get_size (n->entries[tcount].format) && + buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components + ) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataFuji", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components); + continue; + } + + /* + * 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[tcount].format) * n->entries[tcount].components; + n->entries[tcount].size = s; + if (s) { + size_t dataofs = o + 8; + if (s > 4) + /* The data in this case is merely a pointer */ + dataofs = exif_get_long (buf + dataofs, n->order) + 6 + n->offset; + if (CHECKOVERFLOW(dataofs, buf_size, s)) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataFuji", "Tag data past end of " + "buffer (%zu >= %u)", dataofs + s, buf_size); + continue; + } + + n->entries[tcount].data = exif_mem_alloc (en->mem, s); + if (!n->entries[tcount].data) { + EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", s); + continue; + } + memcpy (n->entries[tcount].data, buf + dataofs, s); + } + + /* Tag was successfully parsed */ + ++tcount; + } + /* Store the count of successfully parsed tags */ + n->count = tcount; +} + +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; +} + +int +exif_mnote_data_fuji_identify (const ExifData *ed, const ExifEntry *e) +{ + return ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8)); +} + +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; + + memset(d, 0, sizeof(ExifMnoteDataFuji)); + + 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/libexif/fuji/exif-mnote-data-fuji.h b/libexif/fuji/exif-mnote-data-fuji.h new file mode 100644 index 0000000..2a7cd3e --- /dev/null +++ b/libexif/fuji/exif-mnote-data-fuji.h @@ -0,0 +1,53 @@ +/* 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __MNOTE_FUJI_CONTENT_H__ +#define __MNOTE_FUJI_CONTENT_H__ + +#include <libexif/exif-mnote-data.h> +#include <libexif/exif-mnote-data-priv.h> +#include <libexif/exif-data.h> +#include <libexif/fuji/mnote-fuji-entry.h> + +typedef struct _ExifMnoteDataFuji ExifMnoteDataFuji; + +struct _ExifMnoteDataFuji { + ExifMnoteData parent; + + MnoteFujiEntry *entries; + unsigned int count; + + ExifByteOrder order; + unsigned int offset; +}; + +/*! Detect if MakerNote is recognized as one handled by the Fuji module. + * + * \param[in] ed image #ExifData to identify as as a Fuji type + * \param[in] e #ExifEntry for EXIF_TAG_MAKER_NOTE, from within ed but + * duplicated here for convenience + * \return 0 if not recognized, nonzero if recognized. The specific nonzero + * value returned may identify a subtype unique within this module. + */ +int exif_mnote_data_fuji_identify (const ExifData *ed, const ExifEntry *e); + +ExifMnoteData *exif_mnote_data_fuji_new (ExifMem *); + +#endif /* __MNOTE_FUJI_CONTENT_H__ */ diff --git a/libexif/fuji/mnote-fuji-entry.c b/libexif/fuji/mnote-fuji-entry.c new file mode 100644 index 0000000..0ca1634 --- /dev/null +++ b/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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 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 fluorescent")}, + {0x301, N_("Day white 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/libexif/fuji/mnote-fuji-entry.h b/libexif/fuji/mnote-fuji-entry.h new file mode 100644 index 0000000..a8395c5 --- /dev/null +++ b/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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 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/libexif/fuji/mnote-fuji-tag.c b/libexif/fuji/mnote-fuji-tag.c new file mode 100644 index 0000000..3b80597 --- /dev/null +++ b/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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include <stdlib.h> + +#include <config.h> +#include <libexif/i18n.h> + +#include "mnote-fuji-tag.h" + + +static const 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 and based on 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; + + for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) + if (table[i].tag == t) { + if (!table[i].description || !*table[i].description) + return ""; + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + return _(table[i].description); + } + return NULL; +} diff --git a/libexif/fuji/mnote-fuji-tag.h b/libexif/fuji/mnote-fuji-tag.h new file mode 100644 index 0000000..1d250e4 --- /dev/null +++ b/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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 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/libexif/olympus/Makefile-files b/libexif/olympus/Makefile-files new file mode 100644 index 0000000..b7b6b30 --- /dev/null +++ b/libexif/olympus/Makefile-files @@ -0,0 +1,7 @@ +# -*- Makefile -*- +noinst_LTLIBRARIES += libmnote-olympus.la +libmnote_olympus_la_SOURCES = \ + olympus/mnote-olympus-entry.c olympus/mnote-olympus-entry.h \ + olympus/exif-mnote-data-olympus.c olympus/exif-mnote-data-olympus.h \ + olympus/mnote-olympus-tag.c olympus/mnote-olympus-tag.h +libmnote_olympus_la_LIBADD = $(LTLIBINTL) diff --git a/libexif/olympus/exif-mnote-data-olympus.c b/libexif/olympus/exif-mnote-data-olympus.c new file mode 100644 index 0000000..f11616c --- /dev/null +++ b/libexif/olympus/exif-mnote-data-olympus.c @@ -0,0 +1,678 @@ +/* exif-mnote-data-olympus.c + * + * 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 + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include <config.h> +#include "exif-mnote-data-olympus.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include <libexif/exif-utils.h> +#include <libexif/exif-data.h> + +#define DEBUG + +/* Uncomment this to fix a problem with Sanyo MakerNotes. It's probably best + * not to in most cases because it seems to only affect the thumbnail tag + * which is duplicated in IFD 1, and fixing the offset could actually cause + * problems with other software that expects the broken form. + */ +/*#define EXIF_OVERCOME_SANYO_OFFSET_BUG */ + +#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize )) + +static enum OlympusVersion +exif_mnote_data_olympus_identify_variant (const unsigned char *buf, + unsigned int buf_size); + + +static void +exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n) +{ + ExifMnoteData *d = (ExifMnoteData *) n; + unsigned int i; + + if (!n) return; + + if (n->entries) { + for (i = 0; i < n->count; i++) + if (n->entries[i].data) { + exif_mem_free (d->mem, n->entries[i].data); + n->entries[i].data = NULL; + } + exif_mem_free (d->mem, n->entries); + n->entries = NULL; + n->count = 0; + } +} + +static void +exif_mnote_data_olympus_free (ExifMnoteData *n) +{ + if (!n) return; + + exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n); +} + +static char * +exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen) +{ + ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; + + if (!d || !val) return NULL; + if (i > n->count -1) return NULL; +/* + exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", + "Querying value for tag '%s'...", + mnote_olympus_tag_get_name (n->entries[i].tag)); +*/ + return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen); +} + + + + +/** + * @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; + 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; + + /* + * Allocate enough memory for all entries and the number of entries. + */ + *buf_size = 6 + 2 + 2 + n->count * 12; + switch (n->version) { + case olympusV1: + case sanyoV1: + case epsonV1: + *buf = exif_mem_alloc (ne->mem, *buf_size); + if (!*buf) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); + return; + } + + /* Write the header and the number of entries. */ + strcpy ((char *)*buf, n->version==sanyoV1?"SANYO": + (n->version==epsonV1?"EPSON":"OLYMP")); + exif_set_short (*buf + 6, n->order, (ExifShort) 1); + datao = n->offset; + break; + + case olympusV2: + *buf_size += 8-6 + 4; + *buf = exif_mem_alloc (ne->mem, *buf_size); + if (!*buf) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); + 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; + + /* 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 to nikonV2 handler */ + case nikonV2: + /* Write out V0 files in V2 format */ + case nikonV0: + *buf_size += 8 + 2; + *buf_size += 4; /* Next IFD pointer */ + *buf = exif_mem_alloc (ne->mem, *buf_size); + if (!*buf) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); + return; + } + + /* Write the header and the number of entries. */ + strcpy ((char *)*buf, "Nikon"); + (*buf)[6] = n->version; + + if (n->version != nikonV1) { + exif_set_short (*buf + 10, n->order, (ExifShort) ( + (n->order == EXIF_BYTE_ORDER_INTEL) ? + ('I' << 8) | 'I' : + ('M' << 8) | 'M')); + exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A); + exif_set_long (*buf + 14, n->order, (ExifShort) 8); + o2 += 2 + 8; + } + datao -= 10; + /* 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); + o2 += 2; + + /* Save each entry */ + for (i = 0; i < n->count; i++) { + o = o2 + i * 12; + exif_set_short (*buf + o + 0, n->order, + (ExifShort) (n->entries[i].tag - base)); + exif_set_short (*buf + o + 2, n->order, + (ExifShort) n->entries[i].format); + exif_set_long (*buf + o + 4, n->order, + n->entries[i].components); + o += 8; + s = exif_format_get_size (n->entries[i].format) * + n->entries[i].components; + if (s > 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; + ts = *buf_size + s; + t = exif_mem_realloc (ne->mem, *buf, + sizeof (char) * ts); + if (!t) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts); + return; + } + *buf = t; + *buf_size = ts; + exif_set_long (*buf + o, n->order, datao + doff); + } else + doff = o; + + /* Write the data. */ + if (n->entries[i].data) { + memcpy (*buf + doff, n->entries[i].data, s); + } else { + /* Most certainly damaged input file */ + memset (*buf + doff, 0, s); + } + } +} + +static void +exif_mnote_data_olympus_load (ExifMnoteData *en, + const unsigned char *buf, unsigned int buf_size) +{ + ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en; + ExifShort c; + size_t i, tcount, o, o2, datao = 6, base = 0; + + if (!n || !buf || !buf_size) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataOlympus", "Short MakerNote"); + return; + } + o2 = 6 + n->offset; /* Start of interesting data */ + + if (CHECKOVERFLOW(o2,buf_size,10)) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataOlympus", "Short MakerNote"); + return; + } + + /* + * Olympus headers start with "OLYMP" and need to have at least + * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the + * number of entries, and 12 for one entry. + * + * Sanyo format is identical and uses identical tags except that + * header starts with "SANYO". + * + * Epson format is identical and uses identical tags except that + * header starts with "EPSON". + * + * Nikon headers start with "Nikon" (6 bytes including '\0'), + * version number (1 or 2). + * + * Version 1 continues with 0, 1, 0, number_of_tags, + * or just with number_of_tags (models D1H, D1X...). + * + * Version 2 continues with an unknown byte (0 or 10), + * two unknown bytes (0), "MM" or "II", another byte 0 and + * lastly 0x2A. + */ + n->version = exif_mnote_data_olympus_identify_variant(buf+o2, buf_size-o2); + switch (n->version) { + case olympusV1: + case sanyoV1: + case epsonV1: + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", + "Parsing Olympus/Sanyo/Epson maker note v1..."); + + /* The number of entries is at position 8. */ + 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 + 2 > 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 olympusV2: + /* Olympus S760, S770 */ + datao = o2; + o2 += 8; + + if (CHECKOVERFLOW(o2,buf_size,4)) return; + 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. */ + o2 += 4; + break; + + case nikonV1: + o2 += 6; + if (o2 >= buf_size) return; + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", + "Parsing Nikon maker note v1 (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]); + + /* Skip version number */ + o2 += 1; + + /* Skip an unknown byte (00 or 0A). */ + o2 += 1; + + base = MNOTE_NIKON1_TAG_BASE; + /* Fix endianness, if needed */ + if (o2 + 2 > 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 nikonV2: + o2 += 6; + if (o2 >= buf_size) return; + if (CHECKOVERFLOW(o2,buf_size,12)) return; + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", + "Parsing Nikon maker note v2 (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]); + + /* Skip version number */ + o2 += 1; + + /* Skip an unknown byte (00 or 0A). */ + o2 += 1; + + /* Skip 2 unknown bytes (00 00). */ + o2 += 2; + + /* + * Byte order. From here the data offset + * gets calculated. + */ + datao = o2; + if (o2 >= buf_size) return; + if (!strncmp ((char *)&buf[o2], "II", 2)) + n->order = EXIF_BYTE_ORDER_INTEL; + else if (!strncmp ((char *)&buf[o2], "MM", 2)) + n->order = EXIF_BYTE_ORDER_MOTOROLA; + else { + exif_log (en->log, EXIF_LOG_CODE_DEBUG, + "ExifMnoteDataOlympus", "Unknown " + "byte order '%c%c'", buf[o2], + buf[o2 + 1]); + return; + } + o2 += 2; + + /* Skip 2 unknown bytes (00 2A). */ + o2 += 2; + + /* Go to where the number of entries is. */ + if (o2 + 4 > buf_size) return; + o2 = datao + exif_get_long (buf + o2, n->order); + break; + + case nikonV0: + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", + "Parsing Nikon maker note v0 (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]); + /* 00 1b is # of entries in Motorola order - the rest should also be in MM order */ + n->order = EXIF_BYTE_ORDER_MOTOROLA; + break; + + default: + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", + "Unknown Olympus variant %i.", n->version); + return; + } + + /* Sanity check the offset */ + + if (CHECKOVERFLOW(o2,buf_size,2)) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteOlympus", "Short MakerNote"); + return; + } + + /* Read the number of tags */ + c = exif_get_short (buf + o2, n->order); + o2 += 2; + + /* Remove any old entries */ + exif_mnote_data_olympus_clear (n); + + /* Reserve enough space for all the possible MakerNote tags */ + n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c); + if (!n->entries) { + EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c); + return; + } + + /* Parse all c entries, storing ones that are successfully parsed */ + tcount = 0; + for (i = c, o = o2; i; --i, o += 12) { + size_t s; + + memset(&n->entries[tcount], 0, sizeof(MnoteOlympusEntry)); + if (CHECKOVERFLOW(o, buf_size, 12)) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteOlympus", "Short MakerNote"); + break; + } + + n->entries[tcount].tag = exif_get_short (buf + o, n->order) + base; + n->entries[tcount].format = exif_get_short (buf + o + 2, n->order); + n->entries[tcount].components = exif_get_long (buf + o + 4, n->order); + n->entries[tcount].order = n->order; + + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus", + "Loading entry 0x%x ('%s')...", n->entries[tcount].tag, + mnote_olympus_tag_get_name (n->entries[tcount].tag)); +/* exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus", + "0x%x %d %ld*(%d)", + n->entries[tcount].tag, + n->entries[tcount].format, + n->entries[tcount].components, + (int)exif_format_get_size(n->entries[tcount].format)); */ + + /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection, + * we will check the buffer sizes closer later. */ + if (exif_format_get_size (n->entries[tcount].format) && + buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components + ) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteOlympus", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components); + continue; + } + + /* + * 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[tcount].format) * + n->entries[tcount].components; + n->entries[tcount].size = s; + if (s) { + size_t dataofs = o + 8; + if (s > 4) { + /* The data in this case is merely a pointer */ + dataofs = exif_get_long (buf + dataofs, n->order) + datao; +#ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG + /* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when + * writing the offset for the MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE + * tag in its MakerNote. The offset is actually the absolute + * position in the file instead of the position within the IFD. + */ + if (dataofs > (buf_size - s) && n->version == sanyoV1) { + /* fix pointer */ + dataofs -= datao + 6; + exif_log (en->log, EXIF_LOG_CODE_DEBUG, + "ExifMnoteOlympus", + "Inconsistent thumbnail tag offset; attempting to recover"); + } +#endif + } + if (CHECKOVERFLOW(dataofs, buf_size, s)) { + exif_log (en->log, EXIF_LOG_CODE_DEBUG, + "ExifMnoteOlympus", + "Tag data past end of buffer (%zu > %u)", + dataofs + s, buf_size); + continue; + } + + n->entries[tcount].data = exif_mem_alloc (en->mem, s); + if (!n->entries[tcount].data) { + EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s); + continue; + } + memcpy (n->entries[tcount].data, buf + dataofs, s); + } + + /* Tag was successfully parsed */ + ++tcount; + } + /* Store the count of successfully parsed tags */ + n->count = tcount; +} + +static unsigned int +exif_mnote_data_olympus_count (ExifMnoteData *n) +{ + return n ? ((ExifMnoteDataOlympus *) n)->count : 0; +} + +static unsigned int +exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n) +{ + ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d; + + if (!note) return 0; + if (note->count <= n) return 0; + return note->entries[n].tag; +} + +static const char * +exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i) +{ + ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; + + if (!n) return NULL; + if (i >= n->count) return NULL; + return mnote_olympus_tag_get_name (n->entries[i].tag); +} + +static const char * +exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i) +{ + ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; + + if (!n) return NULL; + if (i >= n->count) return NULL; + return mnote_olympus_tag_get_title (n->entries[i].tag); +} + +static const char * +exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i) +{ + ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; + + if (!n) return NULL; + if (i >= n->count) return NULL; + return mnote_olympus_tag_get_description (n->entries[i].tag); +} + +static void +exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o) +{ + ExifByteOrder o_orig; + ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; + unsigned int i; + + if (!n) return; + + o_orig = n->order; + n->order = o; + for (i = 0; i < n->count; i++) { + n->entries[i].order = o; + exif_array_set_byte_order (n->entries[i].format, n->entries[i].data, + n->entries[i].components, o_orig, o); + } +} + +static void +exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o) +{ + if (n) ((ExifMnoteDataOlympus *) n)->offset = o; +} + +static enum OlympusVersion +exif_mnote_data_olympus_identify_variant (const unsigned char *buf, + unsigned int buf_size) +{ + /* Olympus, Nikon, Sanyo, Epson */ + if (buf_size >= 8) { + /* Match the terminating NUL character, too */ + if (!memcmp (buf, "OLYMPUS", 8)) + return olympusV2; + else if (!memcmp (buf, "OLYMP", 6)) + return olympusV1; + else if (!memcmp (buf, "SANYO", 6)) + return sanyoV1; + else if (!memcmp (buf, "EPSON", 6)) + return epsonV1; + else if (!memcmp (buf, "Nikon", 6)) { + switch (buf[6]) { + case 1: return nikonV1; + case 2: return nikonV2; + default: return 0; /* Unrecognized Nikon variant */ + } + } + } + + /* Another variant of Nikon */ + if ((buf_size >= 2) && (buf[0] == 0x00) && (buf[1] == 0x1b)) { + return nikonV0; + } + + return unrecognized; +} + +int +exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e) +{ + int variant = exif_mnote_data_olympus_identify_variant(e->data, e->size); + + if (variant == nikonV0) { + /* This variant needs some extra checking with the Make */ + char value[5]; + ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE); + variant = unrecognized; + + if (em) { + const char *v = exif_entry_get_value (em, value, sizeof(value)); + if (v && (!strncmp (v, "Nikon", sizeof(value)) || + !strncmp (v, "NIKON", sizeof(value)) )) + /* When saved, this variant will be written out like the + * alternative nikonV2 form above instead + */ + variant = nikonV0; + } + } + + return variant; +} + + +ExifMnoteData * +exif_mnote_data_olympus_new (ExifMem *mem) +{ + ExifMnoteData *d; + + if (!mem) return NULL; + + d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus)); + if (!d) return NULL; + + memset(d, 0, sizeof(ExifMnoteDataOlympus)); + + exif_mnote_data_construct (d, mem); + + /* Set up function pointers */ + d->methods.free = exif_mnote_data_olympus_free; + d->methods.set_byte_order = exif_mnote_data_olympus_set_byte_order; + d->methods.set_offset = exif_mnote_data_olympus_set_offset; + d->methods.load = exif_mnote_data_olympus_load; + d->methods.save = exif_mnote_data_olympus_save; + d->methods.count = exif_mnote_data_olympus_count; + d->methods.get_id = exif_mnote_data_olympus_get_id; + d->methods.get_name = exif_mnote_data_olympus_get_name; + d->methods.get_title = exif_mnote_data_olympus_get_title; + d->methods.get_description = exif_mnote_data_olympus_get_description; + d->methods.get_value = exif_mnote_data_olympus_get_value; + + return d; +} diff --git a/libexif/olympus/exif-mnote-data-olympus.h b/libexif/olympus/exif-mnote-data-olympus.h new file mode 100644 index 0000000..d08b0f4 --- /dev/null +++ b/libexif/olympus/exif-mnote-data-olympus.h @@ -0,0 +1,67 @@ +/* mnote-olympus-data.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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __MNOTE_OLYMPUS_CONTENT_H__ +#define __MNOTE_OLYMPUS_CONTENT_H__ + +#include <libexif/exif-mnote-data-priv.h> +#include <libexif/olympus/mnote-olympus-entry.h> +#include <libexif/exif-byte-order.h> +#include <libexif/exif-data.h> +#include <libexif/exif-mem.h> + +enum OlympusVersion { + unrecognized = 0, + nikonV1 = 1, + nikonV2 = 2, + olympusV1 = 3, + olympusV2 = 4, + sanyoV1 = 5, + epsonV1 = 6, + nikonV0 = 7 +}; + + +typedef struct _ExifMnoteDataOlympus ExifMnoteDataOlympus; + +struct _ExifMnoteDataOlympus { + ExifMnoteData parent; + + MnoteOlympusEntry *entries; + unsigned int count; + + ExifByteOrder order; + unsigned int offset; + enum OlympusVersion version; +}; + +/*! Detect if MakerNote is recognized as one handled by the Olympus module. + * + * \param[in] ed image #ExifData to identify as as an Olympus type + * \param[in] e #ExifEntry for EXIF_TAG_MAKER_NOTE, from within ed but + * duplicated here for convenience + * \return 0 if not recognized, nonzero if recognized. The specific nonzero + * value returned may identify a subtype unique within this module. + */ +int exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e); + +ExifMnoteData *exif_mnote_data_olympus_new (ExifMem *); + +#endif /* __MNOTE_OLYMPUS_CONTENT_H__ */ diff --git a/libexif/olympus/mnote-olympus-entry.c b/libexif/olympus/mnote-olympus-entry.c new file mode 100644 index 0000000..96c919d --- /dev/null +++ b/libexif/olympus/mnote-olympus-entry.c @@ -0,0 +1,827 @@ +/* mnote-olympus-entry.c + * + * Copyright (c) 2002-2009 Lutz Mueller <lutz@users.sourceforge.net> et. al. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include <config.h> +#include "mnote-olympus-entry.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <libexif/exif-format.h> +#include <libexif/exif-utils.h> +#include <libexif/exif-entry.h> +#include <libexif/i18n.h> + +#define CF(format,target,v,maxlen) \ +{ \ + if (format != target) { \ + snprintf (v, maxlen, \ + _("Invalid format '%s', " \ + "expected '%s'."), \ + exif_format_get_name (format), \ + exif_format_get_name (target)); \ + break; \ + } \ +} + +#define 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) { \ + snprintf (v, maxlen, \ + _("Invalid number of components (%i, " \ + "expected %i)."), (int) number, (int) target); \ + break; \ + } \ +} + +#define CC2(number,t1,t2,v,maxlen) \ +{ \ + if ((number < t1) || (number > t2)) { \ + snprintf (v, maxlen, \ + _("Invalid number of components (%i, " \ + "expected %i or %i)."), (int) number, \ + (int) t1, (int) t2); \ + break; \ + } \ +} + +#define R2L(n) ((n).denominator ? (long)(n).numerator/(n).denominator : 0L) +#define R2D(n) ((n).denominator ? (double)(n).numerator/(n).denominator : 0.0) + +static const struct { + ExifTag tag; + ExifFormat fmt; + struct { + int index; + const char *string; + } elem[24]; +} items[] = { +#ifndef NO_VERBOSE_TAG_DATA + { MNOTE_NIKON_TAG_LENSTYPE, EXIF_FORMAT_BYTE, + { {0, N_("AF non D lens")}, + {1, N_("Manual")}, + {2, N_("AF-D or AF-S lens")}, + {6, N_("AF-D G lens")}, + {10, N_("AF-D VR lens")}, + {14, N_("AF-D G VR lens")}, + {0, NULL}}}, + { MNOTE_NIKON_TAG_FLASHUSED, EXIF_FORMAT_BYTE, + { {0, N_("Flash did not fire")}, + {4, N_("Flash unit unknown")}, + {7, N_("Flash is external")}, + {9, N_("Flash is on camera")}, + {0, NULL}}}, + { MNOTE_NIKON1_TAG_QUALITY, EXIF_FORMAT_SHORT, + { {1, N_("VGA basic")}, + {2, N_("VGA normal")}, + {3, N_("VGA fine")}, + {4, N_("SXGA basic")}, + {5, N_("SXGA normal")}, + {6, N_("SXGA fine")}, + {10, N_("2 Mpixel basic")}, + {11, N_("2 Mpixel normal")}, + {12, N_("2 Mpixel fine")}, + {0, NULL}}}, + { MNOTE_NIKON1_TAG_COLORMODE, EXIF_FORMAT_SHORT, + { {1, N_("Color")}, + {2, N_("Monochrome")}, + {0, NULL}}}, + { MNOTE_NIKON1_TAG_IMAGEADJUSTMENT, EXIF_FORMAT_SHORT, + { {0, N_("Normal")}, + {1, N_("Bright+")}, + {2, N_("Bright-")}, + {3, N_("Contrast+")}, + {4, N_("Contrast-")}, + {0, NULL}}}, + { MNOTE_NIKON1_TAG_CCDSENSITIVITY, EXIF_FORMAT_SHORT, + { {0, N_("ISO 80")}, + {2, N_("ISO 160")}, + {4, N_("ISO 320")}, + {5, N_("ISO 100")}, + {0, NULL}}}, + { MNOTE_NIKON1_TAG_WHITEBALANCE, EXIF_FORMAT_SHORT, + { {0, N_("Auto")}, + {1, N_("Preset")}, + {2, N_("Daylight")}, + {3, N_("Incandescence")}, + {4, N_("Fluorescence")}, + {5, N_("Cloudy")}, + {6, N_("SpeedLight")}, + {0, NULL}}}, + { MNOTE_NIKON1_TAG_CONVERTER, EXIF_FORMAT_SHORT, + { {0, N_("No fisheye")}, + {1, N_("Fisheye on")}, + {0, NULL}}}, + { MNOTE_OLYMPUS_TAG_QUALITY, EXIF_FORMAT_SHORT, + { {1, N_("Normal, SQ")}, + {2, N_("Normal, HQ")}, + {3, N_("Normal, SHQ")}, + {4, N_("Normal, RAW")}, + {5, N_("Normal, SQ1")}, + {6, N_("Normal, SQ2")}, + {7, N_("Normal, super high")}, + {17, N_("Normal, standard")}, + {0x101, N_("Fine, SQ")}, + {0x102, N_("Fine, HQ")}, + {0x103, N_("Fine, SHQ")}, + {0x104, N_("Fine, RAW")}, + {0x105, N_("Fine, SQ1")}, + {0x106, N_("Fine, SQ2")}, + {0x107, N_("Fine, super high")}, + {0x201, N_("Super fine, SQ")}, + {0x202, N_("Super fine, HQ")}, + {0x203, N_("Super fine, SHQ")}, + {0x204, N_("Super fine, RAW")}, + {0x205, N_("Super fine, SQ1")}, + {0x206, N_("Super fine, SQ2")}, + {0x207, N_("Super fine, super high")}, + {0x211, N_("Super fine, 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_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")}, + {1, N_("Red-eye reduction")}, + {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_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_FOCUSMODE, EXIF_FORMAT_SHORT, + { {1, N_("Spot focus")}, + {2, N_("Normal focus")}, + {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}}}, + { MNOTE_SANYO_TAG_CCDSENSITIVITY, EXIF_FORMAT_SHORT, + { {0, N_("Auto")}, + {1, N_("ISO 50")}, + {3, N_("ISO 100")}, + {4, N_("ISO 200")}, + {5, N_("ISO 400")}, + {0, NULL}}}, + { 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 * +mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *v, unsigned int maxlen) +{ + char buf[30]; + ExifLong vl; + ExifShort vs = 0; + ExifSShort vss = 0; + ExifRational vr, vr2; + ExifSRational vsr; + int i, j; + double r, b; + + if (!entry) + return (NULL); + + memset (v, 0, maxlen); + maxlen--; + + if ((!entry->data) && (entry->components > 0)) + return (v); + + if ((!entry->data) && (entry->size > 0)) + return NULL; /* internal inconsistency error */ + + switch (entry->tag) { + + /* Nikon */ + case MNOTE_NIKON_TAG_FIRMWARE: + CF (entry->format, EXIF_FORMAT_UNDEFINED, v, maxlen); + CC (entry->components, 4, v, maxlen); + vl = exif_get_long (entry->data, entry->order); + if ((vl & 0xF0F0F0F0) == 0x30303030) { + memcpy (v, entry->data, MIN (maxlen, 4)); + } else { + snprintf (v, maxlen, "%04lx", (long unsigned int) vl); + } + break; + case MNOTE_NIKON_TAG_ISO: + CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen); + CC (entry->components, 2, v, maxlen); + /*vs = exif_get_short (entry->data, entry->order);*/ + vs = exif_get_short (entry->data + 2, entry->order); + snprintf (v, maxlen, "ISO %hd", vs); + break; + case MNOTE_NIKON_TAG_ISO2: + CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen); + CC (entry->components, 2, v, maxlen); + /*vs = exif_get_short (entry->data, entry->order);*/ + vs = exif_get_short (entry->data + 2, entry->order); + snprintf (v, maxlen, "ISO2 %hd", vs); + break; + case MNOTE_NIKON_TAG_QUALITY: + case MNOTE_NIKON_TAG_COLORMODE: + case MNOTE_NIKON_TAG_COLORMODE1: + case MNOTE_NIKON_TAG_WHITEBALANCE: + case MNOTE_NIKON_TAG_SHARPENING: + case MNOTE_NIKON_TAG_FOCUSMODE: + case MNOTE_NIKON_TAG_FLASHSETTING: + case MNOTE_NIKON_TAG_ISOSELECTION: + case MNOTE_NIKON_TAG_FLASHMODE: + case MNOTE_NIKON_TAG_IMAGEADJUSTMENT: + case MNOTE_NIKON_TAG_ADAPTER: + case MNOTE_NIKON_TAG_SATURATION2: + case MNOTE_EPSON_TAG_SOFTWARE: + CF (entry->format, EXIF_FORMAT_ASCII, v, maxlen); + memcpy(v, entry->data, MIN (maxlen, entry->size)); + break; + case MNOTE_NIKON_TAG_TOTALPICTURES: + case MNOTE_EPSON_TAG_IMAGE_WIDTH: + case MNOTE_EPSON_TAG_IMAGE_HEIGHT: + 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: + 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); + vr = exif_get_rational (entry->data, entry->order); + r = R2D(vr); + vr = exif_get_rational (entry->data+8, entry->order); + b = R2D(vr); + snprintf (v, maxlen, _("Red Correction %f, blue Correction %f"), r,b); + break; + case MNOTE_NIKON_TAG_MANUALFOCUSDISTANCE: + CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen); + CC (entry->components, 1, v, maxlen); + vr = exif_get_rational (entry->data, entry->order); + if (!vr.numerator || !vr.denominator) { + strncpy (v, _("No manual focus selection"), maxlen); + } else { + r = R2D(vr); + snprintf (v, maxlen, _("%2.2f meters"), r); + } + break; + case MNOTE_NIKON_TAG_SENSORPIXELSIZE: + CF (entry->format, EXIF_FORMAT_RATIONAL, 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 = R2D(vr); + b = R2D(vr2); + 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; + 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); + vr = exif_get_rational (entry->data, entry->order); + if (!vr.numerator || !vr.denominator) { + strncpy (v, _("None"), maxlen); + } else { + r = R2D(vr); + snprintf (v, maxlen, "%2.2f", r); + } + break; + } + /* fall through to handle SHORT version of this tag */ + case MNOTE_NIKON_TAG_LENSTYPE: + case MNOTE_NIKON_TAG_FLASHUSED: + case MNOTE_NIKON1_TAG_QUALITY: + case MNOTE_NIKON1_TAG_COLORMODE: + case MNOTE_NIKON1_TAG_IMAGEADJUSTMENT: + case MNOTE_NIKON1_TAG_CCDSENSITIVITY: + case MNOTE_NIKON1_TAG_WHITEBALANCE: + case MNOTE_NIKON1_TAG_CONVERTER: + case MNOTE_OLYMPUS_TAG_QUALITY: + case MNOTE_OLYMPUS_TAG_MACRO: + case MNOTE_OLYMPUS_TAG_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_PREVIEWIMAGEVALID: + case MNOTE_OLYMPUS_TAG_CCDSCANMODE: + case MNOTE_SANYO_TAG_SEQUENTIALSHOT: + case MNOTE_SANYO_TAG_FOCUSMODE: + case MNOTE_SANYO_TAG_RECORDSHUTTERRELEASE: + case MNOTE_SANYO_TAG_RESAVED: + case MNOTE_SANYO_TAG_CCDSENSITIVITY: + case MNOTE_SANYO_TAG_SCENESELECT: + case MNOTE_SANYO_TAG_SEQUENCESHOTINTERVAL: + CC (entry->components, 1, v, maxlen); + switch (entry->format) { + case EXIF_FORMAT_BYTE: + case EXIF_FORMAT_UNDEFINED: + vs = entry->data[0]; + break; + case EXIF_FORMAT_SHORT: + vs = exif_get_short(entry->data, entry->order); + break; + default: + vs = 0; + break; + } + /* 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_NOISEREDUCTION: + case MNOTE_SANYO_TAG_WIDERANGE: + case MNOTE_SANYO_TAG_COLORADJUSTMENTMODE: + case MNOTE_SANYO_TAG_QUICKSHOT: + 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: + sprintf (buf, _("Unknown %hu"), vs); + strncat (v, buf, maxlen - strlen (v)); + break; + } + break; + case MNOTE_SANYO_TAG_SELFTIMER: + 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; + case 2: + strncpy (v, _("2 sec."), maxlen); + break; + default: + sprintf (buf, _("Unknown %hu"), vs); + strncat (v, buf, maxlen - strlen (v)); + break; + } + break; + case MNOTE_NIKON_TAG_LENS: + CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen); + CC (entry->components, 4, v, maxlen); + { + double c,d; + unsigned long a,b; + vr = exif_get_rational (entry->data, entry->order); + a = R2L(vr); + vr = exif_get_rational (entry->data+8, entry->order); + b = R2L(vr); + vr = exif_get_rational (entry->data+16, entry->order); + c = R2D(vr); + vr = exif_get_rational (entry->data+24, entry->order); + d = R2D(vr); + snprintf (v, maxlen, "%ld-%ldmm 1:%3.1f - %3.1f",a,b,c,d); + } + break; + + /* Olympus */ + case MNOTE_OLYMPUS_TAG_MODE: + CF (entry->format, EXIF_FORMAT_LONG, v, maxlen); + CC (entry->components, 3, v, maxlen); + vl = exif_get_long (entry->data, entry->order); + switch (vl) { + case 0: + strncpy (v, _("Normal"), maxlen); + break; + case 1: + strncpy (v, _("Unknown"), maxlen); + break; + case 2: + strncpy (v, _("Fast"), maxlen); + break; + case 3: + strncpy (v, _("Panorama"), maxlen); + break; + default: + snprintf (v, maxlen, "%li", (long int) vl); + } + vl = exif_get_long (entry->data + 4, entry->order); + snprintf (buf, sizeof (buf), "/%li/", (long int) vl); + strncat (v, buf, maxlen - strlen (v)); + vl = exif_get_long (entry->data + 8, entry->order); + switch (vl) { + case 1: + strncat (v, _("Left to right"), maxlen - strlen (v)); + break; + case 2: + strncat (v, _("Right to left"), maxlen - strlen (v)); + break; + case 3: + strncat (v, _("Bottom to top"), maxlen - strlen (v)); + break; + case 4: + strncat (v, _("Top to bottom"), maxlen - strlen (v)); + break; + default: + snprintf (buf, sizeof (buf), "%li", + (long int) vl); + strncat (v, buf, maxlen - strlen (v)); + } + break; + case MNOTE_OLYMPUS_TAG_LENSDISTORTION: + if (entry->format == EXIF_FORMAT_SHORT) { + /* Epson uses a single SHORT here */ + CC (entry->components, 1, v, maxlen); + vs = exif_get_short (entry->data, entry->order); + sprintf (buf, "%hu", vs); + strncat (v, buf, maxlen - strlen (v)); + } else { + /* Others use an array of SSHORT here */ + CC (entry->components, 6, v, maxlen); + CF (entry->format, EXIF_FORMAT_SSHORT, v, maxlen); + for (i=0; i < (int)entry->components; ++i) { + vss = exif_get_sshort (entry->data+2*i, entry->order); + sprintf (buf, "%hd ", vss); + 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, (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, 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, (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); + for (i=0; i < (int)entry->components; ++i) { + vl = exif_get_long (entry->data+4*i, entry->order); + sprintf (buf, "%lu ", (unsigned long)vl); + strncat (v, buf, maxlen - strlen (v)); + } + break; + case MNOTE_OLYMPUS_TAG_FOCUSDIST: + CF (entry->format, EXIF_FORMAT_RATIONAL, v, maxlen); + CC (entry->components, 1, v, maxlen); + vr = exif_get_rational (entry->data, entry->order); + if (!vr.numerator || !vr.denominator) { + strncpy (v, _("Unknown"), maxlen); + } + else { + unsigned long tmp = vr.numerator / vr.denominator; + snprintf (v, maxlen, "%li mm", tmp); + } + break; + case MNOTE_OLYMPUS_TAG_WBALANCE: + CF (entry->format, EXIF_FORMAT_SHORT, v, maxlen); + CC (entry->components, 2, v, maxlen); + vs = exif_get_short (entry->data, entry->order); + switch (vs) { + case 1: + strncpy (v, _("Automatic"), maxlen); + break; + case 2: + { + ExifShort v2 = exif_get_short (entry->data + 2, entry->order); + unsigned long colorTemp = 0; + switch (v2) { + case 2: + colorTemp = 3000; + break; + case 3: + colorTemp = 3700; + break; + case 4: + colorTemp = 4000; + break; + case 5: + colorTemp = 4500; + break; + case 6: + colorTemp = 5500; + break; + case 7: + colorTemp = 6500; + break; + case 9: + colorTemp = 7500; + break; + } + if (colorTemp) { + snprintf (v, maxlen, _("Manual: %liK"), colorTemp); + } + else { + strncpy (v, _("Manual: unknown"), maxlen); + } + + } + break; + case 3: + strncpy (v, _("One-touch"), maxlen); + break; + default: + strncpy (v, _("Unknown"), maxlen); + break; + } + break; + 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, (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, "%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 = R2D(vr); + 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 = R2D(vsr); + snprintf (v, maxlen, "%2.3f", r); + } + break; + case EXIF_FORMAT_UNDEFINED: + default: + 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)); + } + break; + } + break; + } + + return (v); +} diff --git a/libexif/olympus/mnote-olympus-entry.h b/libexif/olympus/mnote-olympus-entry.h new file mode 100644 index 0000000..f1b0a98 --- /dev/null +++ b/libexif/olympus/mnote-olympus-entry.h @@ -0,0 +1,43 @@ +/* mnote-olympus-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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __MNOTE_OLYMPUS_ENTRY_H__ +#define __MNOTE_OLYMPUS_ENTRY_H__ + +#include <libexif/exif-format.h> +#include <libexif/exif-byte-order.h> +#include <libexif/olympus/mnote-olympus-tag.h> + +typedef struct _MnoteOlympusEntry MnoteOlympusEntry; + +struct _MnoteOlympusEntry { + MnoteOlympusTag tag; + ExifFormat format; + unsigned long components; + + unsigned char *data; + unsigned int size; + + ExifByteOrder order; +}; + +char *mnote_olympus_entry_get_value (MnoteOlympusEntry *entry, char *val, unsigned int maxlen); + +#endif /* __MNOTE_OLYMPUS_ENTRY_H__ */ diff --git a/libexif/olympus/mnote-olympus-tag.c b/libexif/olympus/mnote-olympus-tag.c new file mode 100644 index 0000000..3810352 --- /dev/null +++ b/libexif/olympus/mnote-olympus-tag.c @@ -0,0 +1,230 @@ +/* mnote-olympus-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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include <config.h> +#include "mnote-olympus-tag.h" + +#include <libexif/i18n.h> +#include <libexif/exif-utils.h> + +#include <stdlib.h> + +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"), ""}, + {MNOTE_NIKON_TAG_ISO, "ISO", N_("ISO Setting"), ""}, + {MNOTE_NIKON_TAG_COLORMODE1, "ColorMode1", N_("Color Mode (?)"), ""}, + {MNOTE_NIKON_TAG_QUALITY, "Quality", N_("Quality"), ""}, + {MNOTE_NIKON_TAG_WHITEBALANCE, "WhiteBalance", N_("White Balance"), ""}, + {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_("White Balance Fine Adjustment"), ""}, + {MNOTE_NIKON_TAG_WHITEBALANCERB, "WhiteBalanceRB", N_("White Balance RB"), ""}, + {MNOTE_NIKON_TAG_UNKNOWN_0X000D, NULL, NULL, NULL}, + {MNOTE_NIKON_TAG_ISOSELECTION, "ISOSelection", N_("ISO Selection"), ""}, + {MNOTE_NIKON_TAG_PREVIEWIMAGE_IFD_POINTER, "PreviewImage", N_("Preview Image IFD"), N_("Offset of the preview image directory (IFD) inside the file.")}, + {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_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_("Tone Compensation"), ""}, + {MNOTE_NIKON_TAG_ADAPTER, "Adapter", N_("Adapter"), ""}, + {MNOTE_NIKON_TAG_LENSTYPE, "LensType", N_("Lens Type"), ""}, + {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_LENS_FSTOPS, "LensFStops", N_("Lens F Stops"), ""}, + {MNOTE_NIKON_TAG_CURVE, "Curve,", N_("Contrast Curve"), ""}, + {MNOTE_NIKON_TAG_COLORMODE, "ColorMode,", N_("Color Mode"), ""}, + {MNOTE_NIKON_TAG_LIGHTTYPE, "LightType,", N_("Light Type"), ""}, + {MNOTE_NIKON_TAG_UNKNOWN_0X0091, NULL, NULL, NULL}, + {MNOTE_NIKON_TAG_HUE, "Hue", N_("Hue Adjustment"), ""}, + {MNOTE_NIKON_TAG_SATURATION, "Saturation", N_("Saturation"), ""}, + {MNOTE_NIKON_TAG_NOISEREDUCTION, "NoiseReduction,", N_("Noise Reduction"), ""}, + {MNOTE_NIKON_TAG_UNKNOWN_0X0097, NULL, NULL, NULL}, + {MNOTE_NIKON_TAG_UNKNOWN_0X0098, NULL, NULL, NULL}, + {MNOTE_NIKON_TAG_SENSORPIXELSIZE, "SensorPixelSize", N_("Sensor Pixel Size"), ""}, + {MNOTE_NIKON_TAG_UNKNOWN_0X009B, NULL, NULL, NULL}, + {MNOTE_NIKON_TAG_SERIALNUMBER, "SerialNumber", N_("Serial Number"), ""}, + {MNOTE_NIKON_TAG_IMAGE_DATASIZE, "ImageDataSize", N_("Image Data Size"), 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"), ""}, + {MNOTE_NIKON_TAG_UNKNOWN_0X00A8, NULL, NULL, 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"), ""}, + {MNOTE_NIKON1_TAG_COLORMODE, "ColorMode,", N_("Color Mode"), ""}, + {MNOTE_NIKON1_TAG_IMAGEADJUSTMENT, "ImageAdjustment", N_("Image Adjustment"), ""}, + {MNOTE_NIKON1_TAG_CCDSENSITIVITY, "CCDSensitivity", N_("CCD Sensitivity"), ""}, + {MNOTE_NIKON1_TAG_WHITEBALANCE, "WhiteBalance", N_("White Balance"), ""}, + {MNOTE_NIKON1_TAG_FOCUS, "Focus", N_("Focus"), ""}, + {MNOTE_NIKON1_TAG_UNKNOWN_0X0009, NULL, NULL, NULL}, + {MNOTE_NIKON1_TAG_DIGITALZOOM, "DigitalZoom", N_("Digital Zoom"), ""}, + {MNOTE_NIKON1_TAG_CONVERTER, "Converter", N_("Converter"), ""}, + + /* 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_("Black & White 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_DATADUMP, "DataDump", N_("Data Dump"), NULL}, + {MNOTE_OLYMPUS_TAG_UNKNOWN_4, NULL, NULL, 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_FOCUSMODE, "FocusMode", N_("Focus 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_CCDSENSITIVITY, "CCDSensitivity", N_("CCD Sensitivity"), ""}, + {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"), ""}, + + /* Epson */ + {MNOTE_EPSON_TAG_IMAGE_WIDTH, "EpsonImageWidth", N_("Epson Image Width"), ""}, + {MNOTE_EPSON_TAG_IMAGE_HEIGHT, "EpsonImageHeight", N_("Epson Image Height"), ""}, + {MNOTE_EPSON_TAG_SOFTWARE, "EpsonSoftware", N_("Epson Software Version"), ""}, +#endif + {0, NULL, NULL, NULL} +}; + +const char * +mnote_olympus_tag_get_name (MnoteOlympusTag t) +{ + unsigned int i; + + for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) + if (table[i].tag == t) return (table[i].name); + return NULL; +} + +const char * +mnote_olympus_tag_get_title (MnoteOlympusTag t) +{ + unsigned int i; + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) + if (table[i].tag == t) return (_(table[i].title)); + return NULL; +} + +const char * +mnote_olympus_tag_get_description (MnoteOlympusTag t) +{ + unsigned int i; + + for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) + if (table[i].tag == t) { + if (!table[i].description || !*table[i].description) + return ""; + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + return _(table[i].description); + } + return NULL; +} diff --git a/libexif/olympus/mnote-olympus-tag.h b/libexif/olympus/mnote-olympus-tag.h new file mode 100644 index 0000000..2c3de82 --- /dev/null +++ b/libexif/olympus/mnote-olympus-tag.h @@ -0,0 +1,229 @@ +/* mnote-olympus-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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __MNOTE_OLYMPUS_TAG_H__ +#define __MNOTE_OLYMPUS_TAG_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +enum _MnoteOlympusTag { + + /* Nikon v.2 */ + MNOTE_NIKON_TAG_FIRMWARE = 0x0001, + MNOTE_NIKON_TAG_ISO = 0x0002, + MNOTE_NIKON_TAG_COLORMODE1 = 0x0003, + MNOTE_NIKON_TAG_QUALITY = 0x0004, + MNOTE_NIKON_TAG_WHITEBALANCE = 0x0005, + MNOTE_NIKON_TAG_SHARPENING = 0x0006, + MNOTE_NIKON_TAG_FOCUSMODE = 0x0007, + MNOTE_NIKON_TAG_FLASHSETTING = 0x0008, + MNOTE_NIKON_TAG_FLASHMODE = 0x0009, + MNOTE_NIKON_TAG_WHITEBALANCEFINE = 0x000b, + MNOTE_NIKON_TAG_WHITEBALANCERB = 0x000c, + MNOTE_NIKON_TAG_UNKNOWN_0X000D = 0x000d, + MNOTE_NIKON_TAG_EXPOSUREDIFF = 0x000e, + MNOTE_NIKON_TAG_ISOSELECTION = 0x000f, + MNOTE_NIKON_TAG_PREVIEWIMAGE_IFD_POINTER= 0x0011, + MNOTE_NIKON_TAG_FLASHEXPCOMPENSATION = 0x0012, + MNOTE_NIKON_TAG_ISO2 = 0x0013, + MNOTE_NIKON_TAG_IMAGEBOUNDARY = 0x0016, + MNOTE_NIKON_TAG_UNKNOWN_0X0017 = 0x0017, + 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, + MNOTE_NIKON_TAG_LENSTYPE = 0x0083, + MNOTE_NIKON_TAG_LENS = 0x0084, + MNOTE_NIKON_TAG_MANUALFOCUSDISTANCE = 0x0085, + MNOTE_NIKON_TAG_DIGITALZOOM = 0x0086, + MNOTE_NIKON_TAG_FLASHUSED = 0x0087, + MNOTE_NIKON_TAG_AFFOCUSPOSITION = 0x0088, + MNOTE_NIKON_TAG_BRACKETING = 0x0089, + MNOTE_NIKON_TAG_UNKNOWN_0X008A = 0x008a, + MNOTE_NIKON_TAG_LENS_FSTOPS = 0x008b, + MNOTE_NIKON_TAG_CURVE = 0x008c, + MNOTE_NIKON_TAG_COLORMODE = 0x008d, + MNOTE_NIKON_TAG_LIGHTTYPE = 0x0090, + MNOTE_NIKON_TAG_UNKNOWN_0X0091 = 0x0091, + MNOTE_NIKON_TAG_HUE = 0x0092, + 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_SENSORPIXELSIZE = 0x009a, + MNOTE_NIKON_TAG_UNKNOWN_0X009B = 0x009b, + 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_SATURATION2 = 0x00aa, + MNOTE_NIKON_TAG_VARIPROGRAM = 0x00ab, + MNOTE_NIKON_TAG_CAPTUREEDITORDATA = 0x0e01, + MNOTE_NIKON_TAG_CAPTUREEDITORVER = 0x0e09, + MNOTE_NIKON_TAG_UNKNOWN_0X0E0E = 0x0e0e, + MNOTE_NIKON_TAG_UNKNOWN_0X0E10 = 0x0e10, + + /* Nikon v1: real values + our proprietary base to distinguish from v2 */ + MNOTE_NIKON1_TAG_BASE = 0x8000, + MNOTE_NIKON1_TAG_UNKNOWN_0X0002 = 0x0002 + MNOTE_NIKON1_TAG_BASE, + MNOTE_NIKON1_TAG_QUALITY = 0x0003 + MNOTE_NIKON1_TAG_BASE, + MNOTE_NIKON1_TAG_COLORMODE = 0x0004 + MNOTE_NIKON1_TAG_BASE, + MNOTE_NIKON1_TAG_IMAGEADJUSTMENT = 0x0005 + MNOTE_NIKON1_TAG_BASE, + MNOTE_NIKON1_TAG_CCDSENSITIVITY = 0x0006 + MNOTE_NIKON1_TAG_BASE, + MNOTE_NIKON1_TAG_WHITEBALANCE = 0x0007 + MNOTE_NIKON1_TAG_BASE, + MNOTE_NIKON1_TAG_FOCUS = 0x0008 + MNOTE_NIKON1_TAG_BASE, + MNOTE_NIKON1_TAG_UNKNOWN_0X0009 = 0x0009 + MNOTE_NIKON1_TAG_BASE, + MNOTE_NIKON1_TAG_DIGITALZOOM = 0x000a + MNOTE_NIKON1_TAG_BASE, + MNOTE_NIKON1_TAG_CONVERTER = 0x000b + MNOTE_NIKON1_TAG_BASE, + + /* Olympus 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_DATADUMP = 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, + + /* Epson */ + MNOTE_EPSON_TAG_IMAGE_WIDTH = 0x020b, + MNOTE_EPSON_TAG_IMAGE_HEIGHT = 0x020c, + MNOTE_EPSON_TAG_SOFTWARE = 0x020d, + + /* Sanyo */ + MNOTE_SANYO_TAG_SEQUENTIALSHOT = 0x020e, + MNOTE_SANYO_TAG_WIDERANGE = 0x020f, + MNOTE_SANYO_TAG_COLORADJUSTMENTMODE = 0x0210, + MNOTE_SANYO_TAG_FOCUSMODE = 0x0212, + 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_CCDSENSITIVITY = 0x021a, + 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 +#define MNOTE_OLYMPUS_TAG_UNKNOWN_5 MNOTE_OLYMPUS_TAG_DATADUMP +#define MNOTE_NIKON_TAG_PREVIEWIMAGE MNOTE_NIKON_TAG_PREVIEWIMAGE_IFD_POINTER + +/*! Return a textual name of the given tag within the Olympus-style MakerNote. + * The name is a short, unique, non-localized text string containing only + * US-ASCII alphanumeric characters. + * + * \param[in] tag Olympus-style MakerNote tag + * \return textual name of the tag, or NULL if the tag is unknown + */ +const char *mnote_olympus_tag_get_name (MnoteOlympusTag tag); + +/*! Return a textual title of the given tag within the Olympus-style MakerNote. + * The title is a short, localized description of the tag. + * + * \param[in] tag Olympus-style MakerNote tag + * \return textual title of the tag, or NULL if the tag is unknown + */ +const char *mnote_olympus_tag_get_title (MnoteOlympusTag tag); + +/*! Return a verbose textual description of the given tag within the + * Olympus-style MakerNote. + * The description is a verbose, localized description of the tag. + * + * \param[in] tag EXIF tag + * \return textual description of the tag, or NULL if the tag is unknown + */ +const char *mnote_olympus_tag_get_description (MnoteOlympusTag tag); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MNOTE_OLYMPUS_TAG_H__ */ diff --git a/libexif/pentax/Makefile-files b/libexif/pentax/Makefile-files new file mode 100644 index 0000000..bcc0ac5 --- /dev/null +++ b/libexif/pentax/Makefile-files @@ -0,0 +1,7 @@ +# -*- Makefile -*- +noinst_LTLIBRARIES += libmnote-pentax.la +libmnote_pentax_la_SOURCES = \ + pentax/mnote-pentax-entry.c pentax/mnote-pentax-entry.h \ + pentax/exif-mnote-data-pentax.c pentax/exif-mnote-data-pentax.h \ + pentax/mnote-pentax-tag.c pentax/mnote-pentax-tag.h +libmnote_pentax_la_LIBADD = $(LTLIBINTL) diff --git a/libexif/pentax/exif-mnote-data-pentax.c b/libexif/pentax/exif-mnote-data-pentax.c new file mode 100644 index 0000000..3676563 --- /dev/null +++ b/libexif/pentax/exif-mnote-data-pentax.c @@ -0,0 +1,464 @@ +/* exif-mnote-data-pentax.c + * + * 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 + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "exif-mnote-data-pentax.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include <libexif/exif-byte-order.h> +#include <libexif/exif-utils.h> + +#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize )) + +static void +exif_mnote_data_pentax_clear (ExifMnoteDataPentax *n) +{ + ExifMnoteData *d = (ExifMnoteData *) n; + unsigned int i; + + if (!n) return; + + if (n->entries) { + for (i = 0; i < n->count; i++) + if (n->entries[i].data) { + exif_mem_free (d->mem, n->entries[i].data); + n->entries[i].data = NULL; + } + exif_mem_free (d->mem, n->entries); + n->entries = NULL; + n->count = 0; + } +} + +static void +exif_mnote_data_pentax_free (ExifMnoteData *n) +{ + if (!n) return; + + exif_mnote_data_pentax_clear ((ExifMnoteDataPentax *) n); +} + +static char * +exif_mnote_data_pentax_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen) +{ + ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) d; + + if (!n) return NULL; + if (n->count <= i) return NULL; + return mnote_pentax_entry_get_value (&n->entries[i], val, maxlen); +} + +/** + * @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 final size of the buffer + */ +static void +exif_mnote_data_pentax_save (ExifMnoteData *ne, + unsigned char **buf, unsigned int *buf_size) +{ + ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) ne; + size_t i, + base = 0, /* internal MakerNote tag number offset */ + o2 = 4 + 2; /* offset to first tag entry, past header */ + size_t datao = n->offset; /* this MakerNote style uses offsets + based on main IFD, not makernote IFD */ + + if (!n || !buf || !buf_size) return; + + /* + * Allocate enough memory for header, the number of entries, entries, + * and next IFD pointer + */ + *buf_size = o2 + 2 + n->count * 12 + 4; + switch (n->version) { + case casioV2: + base = MNOTE_PENTAX2_TAG_BASE; + *buf = exif_mem_alloc (ne->mem, *buf_size); + if (!*buf) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); + return; + } + /* Write the magic header */ + strcpy ((char *)*buf, "QVC"); + exif_set_short (*buf + 4, n->order, (ExifShort) 0); + + break; + + case pentaxV3: + base = MNOTE_PENTAX2_TAG_BASE; + *buf = exif_mem_alloc (ne->mem, *buf_size); + if (!*buf) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); + return; + } + + /* Write the magic header */ + strcpy ((char *)*buf, "AOC"); + exif_set_short (*buf + 4, n->order, (ExifShort) ( + (n->order == EXIF_BYTE_ORDER_INTEL) ? + ('I' << 8) | 'I' : + ('M' << 8) | 'M')); + break; + + case pentaxV2: + base = MNOTE_PENTAX2_TAG_BASE; + *buf = exif_mem_alloc (ne->mem, *buf_size); + if (!*buf) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); + return; + } + + /* Write the magic header */ + strcpy ((char *)*buf, "AOC"); + exif_set_short (*buf + 4, n->order, (ExifShort) 0); + break; + + case pentaxV1: + /* It looks like this format doesn't have a magic header as + * such, just has a fixed number of entries equal to 0x001b */ + *buf_size -= 6; + o2 -= 6; + *buf = exif_mem_alloc (ne->mem, *buf_size); + if (!*buf) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); + return; + } + break; + + default: + /* internal error */ + return; + } + + /* Write the number of entries. */ + exif_set_short (*buf + o2, n->order, (ExifShort) n->count); + o2 += 2; + + /* Save each entry */ + for (i = 0; i < n->count; i++) { + size_t doff; /* offset to current data portion of tag */ + size_t s; + unsigned char *t; + size_t o = o2 + i * 12; /* current offset into output buffer */ + exif_set_short (*buf + o + 0, n->order, + (ExifShort) (n->entries[i].tag - base)); + exif_set_short (*buf + o + 2, n->order, + (ExifShort) n->entries[i].format); + exif_set_long (*buf + o + 4, n->order, + n->entries[i].components); + o += 8; + s = exif_format_get_size (n->entries[i].format) * + n->entries[i].components; + if (s > 65536) { + /* Corrupt data: EXIF data size is limited to the + * maximum size of a JPEG segment (64 kb). + */ + continue; + } + if (s > 4) { + size_t ts = *buf_size + s; + doff = *buf_size; + t = exif_mem_realloc (ne->mem, *buf, + sizeof (char) * ts); + if (!t) { + EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", ts); + return; + } + *buf = t; + *buf_size = ts; + exif_set_long (*buf + o, n->order, datao + doff); + } else + doff = o; + + /* Write the data. */ + if (n->entries[i].data) { + memcpy (*buf + doff, n->entries[i].data, s); + } else { + /* Most certainly damaged input file */ + memset (*buf + doff, 0, s); + } + } + + /* Sanity check the buffer size */ + if (*buf_size < (o2 + n->count * 12 + 4)) { + exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteDataPentax", + "Buffer overflow"); + } + + /* Reset next IFD pointer */ + exif_set_long (*buf + o2 + n->count * 12, n->order, 0); +} + +static void +exif_mnote_data_pentax_load (ExifMnoteData *en, + const unsigned char *buf, unsigned int buf_size) +{ + ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) en; + size_t i, tcount, o, datao, base = 0; + ExifShort c; + + if (!n || !buf || !buf_size) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataPentax", "Short MakerNote"); + return; + } + datao = 6 + n->offset; + if (CHECKOVERFLOW(datao, buf_size, 8)) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataPentax", "Short MakerNote"); + return; + } + + /* Detect variant of Pentax/Casio MakerNote found */ + 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; + } + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataPentax", + "Parsing Pentax maker note v%d...", (int)n->version); + datao += 4 + 2; + base = MNOTE_PENTAX2_TAG_BASE; + } else if (!memcmp(buf + datao, "QVC", 4)) { + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataPentax", + "Parsing Casio maker note v2..."); + n->version = casioV2; + base = MNOTE_CASIO2_TAG_BASE; + datao += 4 + 2; + } else { + /* probably assert(!memcmp(buf + datao, "\x00\x1b", 2)) */ + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataPentax", + "Parsing Pentax maker note v1..."); + n->version = pentaxV1; + } + + /* Read the number of tags */ + c = exif_get_short (buf + datao, n->order); + datao += 2; + + /* Remove any old entries */ + exif_mnote_data_pentax_clear (n); + + /* Reserve enough space for all the possible MakerNote tags */ + n->entries = exif_mem_alloc (en->mem, sizeof (MnotePentaxEntry) * c); + if (!n->entries) { + EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataPentax", sizeof (MnotePentaxEntry) * c); + return; + } + + /* Parse all c entries, storing ones that are successfully parsed */ + tcount = 0; + for (i = c, o = datao; i; --i, o += 12) { + size_t s; + + memset(&n->entries[tcount], 0, sizeof(MnotePentaxEntry)); + if (CHECKOVERFLOW(o,buf_size,12)) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataPentax", "Short MakerNote"); + break; + } + + n->entries[tcount].tag = exif_get_short (buf + o + 0, n->order) + base; + n->entries[tcount].format = exif_get_short (buf + o + 2, n->order); + n->entries[tcount].components = exif_get_long (buf + o + 4, n->order); + n->entries[tcount].order = n->order; + + exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnotePentax", + "Loading entry 0x%x ('%s')...", n->entries[tcount].tag, + mnote_pentax_tag_get_name (n->entries[tcount].tag)); + + /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection, + * we will check the buffer sizes closer later. */ + if ( exif_format_get_size (n->entries[tcount].format) && + buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components + ) { + exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, + "ExifMnoteDataPentax", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components); + break; + } + + /* + * 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[tcount].format) * + n->entries[tcount].components; + n->entries[tcount].size = s; + if (s) { + size_t dataofs = o + 8; + if (s > 4) + /* The data in this case is merely a pointer */ + dataofs = exif_get_long (buf + dataofs, n->order) + 6; + if (CHECKOVERFLOW(dataofs, buf_size, s)) { + exif_log (en->log, EXIF_LOG_CODE_DEBUG, + "ExifMnoteDataPentax", "Tag data past end " + "of buffer (%zu > %u)", dataofs + s, buf_size); + continue; + } + + n->entries[tcount].data = exif_mem_alloc (en->mem, s); + if (!n->entries[tcount].data) { + EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataPentax", s); + continue; + } + memcpy (n->entries[tcount].data, buf + dataofs, s); + } + + /* Tag was successfully parsed */ + ++tcount; + } + /* Store the count of successfully parsed tags */ + n->count = tcount; +} + +static unsigned int +exif_mnote_data_pentax_count (ExifMnoteData *n) +{ + return n ? ((ExifMnoteDataPentax *) n)->count : 0; +} + +static unsigned int +exif_mnote_data_pentax_get_id (ExifMnoteData *d, unsigned int n) +{ + ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d; + + if (!note) return 0; + if (note->count <= n) return 0; + return note->entries[n].tag; +} + +static const char * +exif_mnote_data_pentax_get_name (ExifMnoteData *d, unsigned int n) +{ + ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d; + + if (!note) return NULL; + if (note->count <= n) return NULL; + return mnote_pentax_tag_get_name (note->entries[n].tag); +} + +static const char * +exif_mnote_data_pentax_get_title (ExifMnoteData *d, unsigned int n) +{ + ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d; + + if (!note) return NULL; + if (note->count <= n) return NULL; + return mnote_pentax_tag_get_title (note->entries[n].tag); +} + +static const char * +exif_mnote_data_pentax_get_description (ExifMnoteData *d, unsigned int n) +{ + ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d; + + if (!note) return NULL; + if (note->count <= n) return NULL; + return mnote_pentax_tag_get_description (note->entries[n].tag); +} + +static void +exif_mnote_data_pentax_set_offset (ExifMnoteData *d, unsigned int o) +{ + if (d) ((ExifMnoteDataPentax *) d)->offset = o; +} + +static void +exif_mnote_data_pentax_set_byte_order (ExifMnoteData *d, ExifByteOrder o) +{ + ExifByteOrder o_orig; + ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) d; + unsigned int i; + + if (!n) return; + + o_orig = n->order; + n->order = o; + for (i = 0; i < n->count; i++) { + n->entries[i].order = o; + exif_array_set_byte_order (n->entries[i].format, n->entries[i].data, + n->entries[i].components, o_orig, o); + } +} + +int +exif_mnote_data_pentax_identify (const ExifData *ed, const ExifEntry *e) +{ + if ((e->size >= 8) && !memcmp (e->data, "AOC", 4)) { + if (((e->data[4] == 'I') && (e->data[5] == 'I')) || + ((e->data[4] == 'M') && (e->data[5] == 'M'))) + return pentaxV3; + else + /* Uses Casio v2 tags */ + return pentaxV2; + } + + if ((e->size >= 8) && !memcmp (e->data, "QVC", 4)) + return casioV2; + + /* This isn't a very robust test, so make sure it's done last */ + /* Maybe we should additionally check for a make of Asahi or Pentax */ + if ((e->size >= 2) && (e->data[0] == 0x00) && (e->data[1] == 0x1b)) + return pentaxV1; + + return 0; +} + +ExifMnoteData * +exif_mnote_data_pentax_new (ExifMem *mem) +{ + ExifMnoteData *d; + + if (!mem) return NULL; + + d = exif_mem_alloc (mem, sizeof (ExifMnoteDataPentax)); + if (!d) return NULL; + + memset(d, 0, sizeof(ExifMnoteDataPentax)); + + exif_mnote_data_construct (d, mem); + + /* Set up function pointers */ + d->methods.free = exif_mnote_data_pentax_free; + d->methods.set_byte_order = exif_mnote_data_pentax_set_byte_order; + d->methods.set_offset = exif_mnote_data_pentax_set_offset; + d->methods.load = exif_mnote_data_pentax_load; + d->methods.save = exif_mnote_data_pentax_save; + d->methods.count = exif_mnote_data_pentax_count; + d->methods.get_id = exif_mnote_data_pentax_get_id; + d->methods.get_name = exif_mnote_data_pentax_get_name; + d->methods.get_title = exif_mnote_data_pentax_get_title; + d->methods.get_description = exif_mnote_data_pentax_get_description; + d->methods.get_value = exif_mnote_data_pentax_get_value; + + return d; +} diff --git a/libexif/pentax/exif-mnote-data-pentax.h b/libexif/pentax/exif-mnote-data-pentax.h new file mode 100644 index 0000000..da9f79a --- /dev/null +++ b/libexif/pentax/exif-mnote-data-pentax.h @@ -0,0 +1,59 @@ +/* exif-mnote-data-pentax.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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __EXIF_MNOTE_DATA_PENTAX_H__ +#define __EXIF_MNOTE_DATA_PENTAX_H__ + +#include <libexif/exif-byte-order.h> +#include <libexif/exif-mnote-data.h> +#include <libexif/exif-mnote-data-priv.h> +#include <libexif/pentax/mnote-pentax-entry.h> +#include <libexif/exif-data.h> +#include <libexif/exif-mem.h> + +enum PentaxVersion {pentaxV1 = 1, pentaxV2 = 2, pentaxV3 = 3, casioV2 = 4 }; + +typedef struct _ExifMnoteDataPentax ExifMnoteDataPentax; + +struct _ExifMnoteDataPentax { + ExifMnoteData parent; + + MnotePentaxEntry *entries; + unsigned int count; + + ExifByteOrder order; + unsigned int offset; + + enum PentaxVersion version; +}; + +/*! Detect if MakerNote is recognized as one handled by the Pentax module. + * + * \param[in] ed image #ExifData to identify as as a Pentax type + * \param[in] e #ExifEntry for EXIF_TAG_MAKER_NOTE, from within ed but + * duplicated here for convenience + * \return 0 if not recognized, nonzero if recognized. The specific nonzero + * value returned may identify a subtype unique within this module. + */ +int exif_mnote_data_pentax_identify (const ExifData *ed, const ExifEntry *e); + +ExifMnoteData *exif_mnote_data_pentax_new (ExifMem *); + +#endif /* __EXIF_MNOTE_DATA_PENTAX_H__ */ diff --git a/libexif/pentax/mnote-pentax-entry.c b/libexif/pentax/mnote-pentax-entry.c new file mode 100644 index 0000000..dcb1560 --- /dev/null +++ b/libexif/pentax/mnote-pentax-entry.c @@ -0,0 +1,469 @@ +/* mnote-pentax-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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include <config.h> +#include "mnote-pentax-entry.h" + +#include <libexif/i18n.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <libexif/exif-format.h> +#include <libexif/exif-utils.h> +#include <libexif/exif-entry.h> + + +#define CF(format,target,v,maxlen) \ +{ \ + if (format != target) { \ + snprintf (v, maxlen, \ + _("Invalid format '%s', " \ + "expected '%s'."), \ + exif_format_get_name (format), \ + exif_format_get_name (target)); \ + break; \ + } \ +} + +#define CC(number,target,v,maxlen) \ +{ \ + if (number != target) { \ + snprintf (v, maxlen, \ + _("Invalid number of components (%i, " \ + "expected %i)."), (int) number, (int) target); \ + break; \ + } \ +} + +#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[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")}, + {1, N_("Better")}, + {2, N_("Best")},{0,NULL}}}, + { MNOTE_PENTAX_TAG_FOCUS, + { {2, N_("Custom")}, + {3, N_("Auto")}, + {0, NULL}}}, + { MNOTE_PENTAX_TAG_FLASH, + { {1, N_("Auto")}, + {2, N_("Flash on")}, + {4, N_("Flash off")}, + {6, N_("Red-eye reduction")}, + {0, NULL}}}, + { MNOTE_PENTAX_TAG_WHITE_BALANCE, + { {0, N_("Auto")}, + {1, N_("Daylight")}, + {2, N_("Shade")}, + {3, N_("Tungsten")}, + {4, N_("Fluorescent")}, + {5, N_("Manual")}, + {0, NULL}}}, + { MNOTE_PENTAX_TAG_SHARPNESS, + { {0, N_("Normal")}, + {1, N_("Soft")}, + {2, N_("Hard")}, + {0, NULL}}}, + { MNOTE_PENTAX_TAG_CONTRAST, + { {0, N_("Normal")}, + {1, N_("Low")}, + {2, N_("High")}, + {0, NULL}}}, + { MNOTE_PENTAX_TAG_SATURATION, + { {0, N_("Normal")}, + {1, N_("Low")}, + {2, N_("High")}, + {0, NULL}}}, + { MNOTE_PENTAX_TAG_ISO_SPEED, + { {10, N_("100")}, + {16, N_("200")}, + {100, N_("100")}, + {200, N_("200")}, + { 0, NULL}}}, + { MNOTE_PENTAX_TAG_COLOR, + { {1, N_("Full")}, + {2, N_("Black & white")}, + {3, N_("Sepia")}, + {0, NULL}}}, + { 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_("Day white 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 * +mnote_pentax_entry_get_value (MnotePentaxEntry *entry, + char *val, unsigned int maxlen) +{ + ExifLong vl; + ExifShort vs, vs2; + int i = 0, j = 0; + + if (!entry) return (NULL); + + memset (val, 0, maxlen); + maxlen--; + + switch (entry->tag) { + case MNOTE_PENTAX_TAG_MODE: + case MNOTE_PENTAX_TAG_QUALITY: + case MNOTE_PENTAX_TAG_FOCUS: + case MNOTE_PENTAX_TAG_FLASH: + case MNOTE_PENTAX_TAG_WHITE_BALANCE: + case MNOTE_PENTAX_TAG_SHARPNESS: + case MNOTE_PENTAX_TAG_CONTRAST: + case MNOTE_PENTAX_TAG_SATURATION: + case MNOTE_PENTAX_TAG_ISO_SPEED: + case MNOTE_PENTAX_TAG_COLOR: + 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); + 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) { + 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); + } 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); + } + break; + + case MNOTE_PENTAX_TAG_ZOOM: + CF (entry->format, EXIF_FORMAT_LONG, val, maxlen); + CC (entry->components, 1, val, maxlen); + vl = exif_get_long (entry->data, entry->order); + snprintf (val, maxlen, "%li", (long int) vl); + break; + case MNOTE_PENTAX_TAG_PRINTIM: + CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen); + CC (entry->components, 124, val, maxlen); + snprintf (val, maxlen, _("%i bytes unknown data"), + entry->size); + break; + case MNOTE_PENTAX_TAG_TZ_CITY: + case MNOTE_PENTAX_TAG_TZ_DST: + CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen); + CC (entry->components, 4, val, maxlen); + strncpy (val, (char*)entry->data, MIN(maxlen, entry->size)); + break; + case MNOTE_PENTAX2_TAG_DATE: + CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen); + CC (entry->components, 4, val, maxlen); + /* Note: format is UNDEFINED, not SHORT -> order is fixed: MOTOROLA */ + vs = exif_get_short (entry->data, EXIF_BYTE_ORDER_MOTOROLA); + snprintf (val, maxlen, "%i:%02i:%02i", vs, entry->data[2], entry->data[3]); + break; + case MNOTE_PENTAX2_TAG_TIME: + CF (entry->format, EXIF_FORMAT_UNDEFINED, val, maxlen); + CC2 (entry->components, 3, 4, val, maxlen); + snprintf (val, maxlen, "%02i:%02i:%02i", entry->data[0], entry->data[1], entry->data[2]); + break; + default: + switch (entry->format) { + case EXIF_FORMAT_ASCII: + strncpy (val, (char *)entry->data, MIN(maxlen, entry->size)); + break; + case EXIF_FORMAT_SHORT: + { + const unsigned char *data = entry->data; + size_t k, len = strlen(val), sizeleft; + + sizeleft = entry->size; + for(k=0; k<entry->components; k++) { + if (sizeleft < 2) + break; + vs = exif_get_short (data, entry->order); + snprintf (val+len, maxlen-len, "%i ", vs); + len = strlen(val); + data += 2; + sizeleft -= 2; + } + } + break; + case EXIF_FORMAT_LONG: + { + const unsigned char *data = entry->data; + size_t k, len = strlen(val), sizeleft; + + sizeleft = entry->size; + for(k=0; k<entry->components; k++) { + if (sizeleft < 4) + break; + vl = exif_get_long (data, entry->order); + snprintf (val+len, maxlen-len, "%li", (long int) vl); + len = strlen(val); + data += 4; + sizeleft -= 4; + } + } + break; + case EXIF_FORMAT_UNDEFINED: + default: + snprintf (val, maxlen, _("%i bytes unknown data"), + entry->size); + break; + } + break; + } + + return val; +} diff --git a/libexif/pentax/mnote-pentax-entry.h b/libexif/pentax/mnote-pentax-entry.h new file mode 100644 index 0000000..4547ec3 --- /dev/null +++ b/libexif/pentax/mnote-pentax-entry.h @@ -0,0 +1,43 @@ +/* mnote-pentax-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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __MNOTE_PENTAX_ENTRY_H__ +#define __MNOTE_PENTAX_ENTRY_H__ + +#include <libexif/exif-format.h> +#include <libexif/exif-byte-order.h> +#include <libexif/pentax/mnote-pentax-tag.h> + +typedef struct _MnotePentaxEntry MnotePentaxEntry; + +struct _MnotePentaxEntry { + MnotePentaxTag tag; + ExifFormat format; + unsigned long components; + + unsigned char *data; + unsigned int size; + + ExifByteOrder order; +}; + +char *mnote_pentax_entry_get_value (MnotePentaxEntry *entry, char *val, unsigned int maxlen); + +#endif /* __MNOTE_PENTAX_ENTRY_H__ */ diff --git a/libexif/pentax/mnote-pentax-tag.c b/libexif/pentax/mnote-pentax-tag.c new file mode 100644 index 0000000..740f135 --- /dev/null +++ b/libexif/pentax/mnote-pentax-tag.c @@ -0,0 +1,175 @@ +/* mnote-pentax-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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include <config.h> +#include "mnote-pentax-tag.h" + +#include <stdlib.h> + +#include <libexif/i18n.h> + +static const struct { + MnotePentaxTag tag; + const char *name; + const char *title; + const char *description; +} table[] = { +#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"), ""}, + {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"), ""}, + {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_("ISO Speed"), ""}, + {MNOTE_PENTAX_TAG_UNKNOWN_21, NULL, NULL, 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"), ""}, + {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_PREVIEW_SIZE, "PentaxPreviewSize", N_("Preview Size"), ""}, + {MNOTE_PENTAX2_TAG_PREVIEW_LENGTH, "PentaxPreviewLength", N_("Preview Length"), ""}, + {MNOTE_PENTAX2_TAG_PREVIEW_START, "PentaxPreviewStart", N_("Preview Start"), ""}, + {MNOTE_PENTAX2_TAG_MODEL_ID, "ModelID", N_("Model Identification"), ""}, + {MNOTE_PENTAX2_TAG_DATE, "Date", N_("Date"), ""}, + {MNOTE_PENTAX2_TAG_TIME, "Time", N_("Time"), ""}, + {MNOTE_PENTAX2_TAG_QUALITY, "Quality", N_("Quality Level"), ""}, + {MNOTE_PENTAX2_TAG_IMAGE_SIZE, "ImageSize", N_("Image Size"), ""}, + {MNOTE_PENTAX2_TAG_PICTURE_MODE, "PictureMode", N_("Picture Mode"), ""}, + {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_FOCUS_POSITION, "FocusPosition", N_("Focus Position"), ""}, + {MNOTE_PENTAX2_TAG_EXPOSURE_TIME, "ExposureTime", N_("Exposure Time"), ""}, + {MNOTE_PENTAX2_TAG_FNUMBER, "FNumber", N_("F-Number"), ""}, + {MNOTE_PENTAX2_TAG_ISO, "ISO", N_("ISO Number"), ""}, + {MNOTE_PENTAX2_TAG_EXPOSURE_COMPENSATION, "ExposureCompensation", N_("Exposure Compensation"), ""}, + {MNOTE_PENTAX2_TAG_METERING_MODE, "MeteringMode", N_("Metering Mode"), ""}, + {MNOTE_PENTAX2_TAG_AUTO_BRACKETING, "AutoBracketing", N_("Auto Bracketing"), ""}, + {MNOTE_PENTAX2_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance"), ""}, + {MNOTE_PENTAX2_TAG_WHITE_BALANCE_MODE, "WhiteBalanceMode", N_("White Balance Mode"), ""}, + {MNOTE_PENTAX2_TAG_BLUE_BALANCE, "BlueBalance", N_("Blue Balance"), ""}, + {MNOTE_PENTAX2_TAG_RED_BALANCE, "RedBalance", N_("Red Balance"), ""}, + {MNOTE_PENTAX2_TAG_FOCAL_LENGTH, "FocalLength", N_("Focal Length"), ""}, + {MNOTE_PENTAX2_TAG_DIGITAL_ZOOM, "DigitalZoom", N_("Digital Zoom"), ""}, + {MNOTE_PENTAX2_TAG_SATURATION, "Saturation", N_("Saturation"), ""}, + {MNOTE_PENTAX2_TAG_CONTRAST, "Contrast", N_("Contrast"), ""}, + {MNOTE_PENTAX2_TAG_SHARPNESS, "Sharpness", N_("Sharpness"), ""}, + {MNOTE_PENTAX2_TAG_WORLDTIME_LOCATION, "WorldTimeLocation", N_("World Time Location"), ""}, + {MNOTE_PENTAX2_TAG_HOMETOWN_CITY, "HometownCity", N_("Hometown City"), ""}, + {MNOTE_PENTAX2_TAG_DESTINATION_CITY, "DestinationCity", N_("Destination City"), ""}, + {MNOTE_PENTAX2_TAG_HOMETOWN_DST, "HometownDST,", N_("Hometown DST"), N_("Home Daylight Savings Time")}, + {MNOTE_PENTAX2_TAG_DESTINATION_DST, "DestinationDST", N_("Destination DST"), N_("Destination Daylight Savings Time")}, + {MNOTE_PENTAX2_TAG_FRAME_NUMBER, "FrameNumber", N_("Frame Number"), ""}, + {MNOTE_PENTAX2_TAG_IMAGE_PROCESSING, "ImageProcessing", N_("Image Processing"), ""}, + {MNOTE_PENTAX2_TAG_PICTURE_MODE2, "PictureMode2", N_("Picture Mode (2)"), ""}, + {MNOTE_PENTAX2_TAG_DRIVE_MODE, "DriveMode", N_("Drive Mode"), ""}, + {MNOTE_PENTAX2_TAG_COLOR_SPACE, "ColorSpace", N_("Color Space"), ""}, + {MNOTE_PENTAX2_TAG_IMAGE_AREA_OFFSET, "ImageAreaOffset", N_("Image Area Offset"), ""}, + {MNOTE_PENTAX2_TAG_RAW_IMAGE_SIZE, "RawImageSize", N_("Raw Image Size"), ""}, + {MNOTE_PENTAX2_TAG_AFPOINTS_USED, "AfPointsUsed,", N_("Autofocus Points Used"), ""}, + {MNOTE_PENTAX2_TAG_LENS_TYPE, "LensType", N_("Lens Type"), ""}, + {MNOTE_PENTAX2_TAG_CAMERA_TEMPERATURE, "CameraTemperature", N_("Camera Temperature"), ""}, + {MNOTE_PENTAX2_TAG_NOISE_REDUCTION, "NoiseReduction", N_("Noise Reduction"), ""}, + {MNOTE_PENTAX2_TAG_FLASH_EXPOSURE_COMP, "FlashExposureComp", N_("Flash Exposure Compensation"), ""}, + {MNOTE_PENTAX2_TAG_IMAGE_TONE, "ImageTone", N_("Image Tone"), ""}, + {MNOTE_PENTAX2_TAG_SHAKE_REDUCTION_INFO, "ShakeReductionInfo,", N_("Shake Reduction Info"), ""}, + {MNOTE_PENTAX2_TAG_BLACK_POINT, "BlackPoint", N_("Black Point"), ""}, + {MNOTE_PENTAX2_TAG_WHITE_POINT, "WhitePoint", N_("White Point"), ""}, + {MNOTE_PENTAX2_TAG_AE_INFO, "AEInfo", N_("AE Info"), ""}, + {MNOTE_PENTAX2_TAG_LENS_INFO, "LensInfo", N_("Lens Info"), ""}, + {MNOTE_PENTAX2_TAG_FLASH_INFO, "FlashInfo", N_("Flash Info"), ""}, + {MNOTE_PENTAX2_TAG_CAMERA_INFO, "CameraInfo", N_("Camera Info"), ""}, + {MNOTE_PENTAX2_TAG_BATTERY_INFO, "BatteryInfo", N_("Battery Info"), ""}, + {MNOTE_PENTAX2_TAG_HOMETOWN_CITY_CODE, "HometownCityCode", N_("Hometown City Code"), ""}, + {MNOTE_PENTAX2_TAG_DESTINATION_CITY_CODE, "DestinationCityCode", N_("Destination City Code"), ""}, + + {MNOTE_CASIO2_TAG_PREVIEW_START, "CasioPreviewStart", N_("Preview Start"), ""}, + {MNOTE_CASIO2_TAG_WHITE_BALANCE_BIAS, "WhiteBalanceBias", N_("White Balance Bias"), ""}, + {MNOTE_CASIO2_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_FLASH_DISTANCE, "FlashDistance", N_("Flash Distance"), ""}, + {MNOTE_CASIO2_TAG_RECORD_MODE, "RecordMode", N_("Record Mode"), ""}, + {MNOTE_CASIO2_TAG_SELF_TIMER, "SelfTimer", N_("Self-timer"), ""}, + {MNOTE_CASIO2_TAG_QUALITY, "CasioQuality", N_("Quality Level"), ""}, + {MNOTE_CASIO2_TAG_FOCUS_MODE, "CasioFocusMode", N_("Focus Mode"), ""}, + {MNOTE_CASIO2_TAG_TIME_ZONE, "TimeZone", N_("Time Zone"), ""}, + {MNOTE_CASIO2_TAG_BESTSHOT_MODE, "BestshotMode", N_("Bestshot Mode"), ""}, + {MNOTE_CASIO2_TAG_CCS_ISO_SENSITIVITY, "CCSISOSensitivity", N_("CCS ISO Sensitivity"), ""}, + {MNOTE_CASIO2_TAG_COLOR_MODE, "ColorMode", N_("Color Mode"), ""}, + {MNOTE_CASIO2_TAG_ENHANCEMENT, "Enhancement", N_("Enhancement"), ""}, + {MNOTE_CASIO2_TAG_FINER, "Finer", N_("Finer"), ""}, +#endif + {0, NULL, NULL, NULL} +}; + +const char * +mnote_pentax_tag_get_name (MnotePentaxTag t) +{ + unsigned int i; + + for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) + if (table[i].tag == t) return (table[i].name); + return NULL; +} + +const char * +mnote_pentax_tag_get_title (MnotePentaxTag t) +{ + unsigned int i; + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) + if (table[i].tag == t) return (_(table[i].title)); + return NULL; +} + +const char * +mnote_pentax_tag_get_description (MnotePentaxTag t) +{ + unsigned int i; + + for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) + if (table[i].tag == t) { + if (!table[i].description || !*table[i].description) + return ""; + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + return _(table[i].description); + } + return NULL; +} diff --git a/libexif/pentax/mnote-pentax-tag.h b/libexif/pentax/mnote-pentax-tag.h new file mode 100644 index 0000000..51b2aec --- /dev/null +++ b/libexif/pentax/mnote-pentax-tag.h @@ -0,0 +1,153 @@ +/* mnote-pentax-tag.h + * + * 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 + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __MNOTE_PENTAX_TAG_H__ +#define __MNOTE_PENTAX_TAG_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Missing features which are probably in the unknowns somewhere ... + * 1/ AF Area (Wide, Spot, Free) + * 2/ AE Metering (Multi segment, Centre-weighted, Spot) + * 3/ + */ + +enum _MnotePentaxTag { + MNOTE_PENTAX_TAG_MODE = 0x0001, + MNOTE_PENTAX_TAG_QUALITY = 0x0002, + MNOTE_PENTAX_TAG_FOCUS = 0x0003, + MNOTE_PENTAX_TAG_FLASH = 0x0004, + MNOTE_PENTAX_TAG_UNKNOWN_05 = 0x0005, + MNOTE_PENTAX_TAG_UNKNOWN_06 = 0x0006, + MNOTE_PENTAX_TAG_WHITE_BALANCE = 0x0007, + MNOTE_PENTAX_TAG_UNKNOWN_08 = 0x0008, + MNOTE_PENTAX_TAG_UNKNOWN_09 = 0x0009, + MNOTE_PENTAX_TAG_ZOOM = 0x000a, + MNOTE_PENTAX_TAG_SHARPNESS = 0x000b, + MNOTE_PENTAX_TAG_CONTRAST = 0x000c, + MNOTE_PENTAX_TAG_SATURATION = 0x000d, + MNOTE_PENTAX_TAG_UNKNOWN_14 = 0x000e, + MNOTE_PENTAX_TAG_UNKNOWN_15 = 0x000f, + MNOTE_PENTAX_TAG_UNKNOWN_16 = 0x0010, + MNOTE_PENTAX_TAG_UNKNOWN_17 = 0x0011, + MNOTE_PENTAX_TAG_UNKNOWN_18 = 0x0012, + MNOTE_PENTAX_TAG_UNKNOWN_19 = 0x0013, + MNOTE_PENTAX_TAG_ISO_SPEED = 0x0014, + MNOTE_PENTAX_TAG_UNKNOWN_21 = 0x0015, + MNOTE_PENTAX_TAG_COLOR = 0x0017, + MNOTE_PENTAX_TAG_UNKNOWN_24 = 0x0018, + MNOTE_PENTAX_TAG_UNKNOWN_25 = 0x0019, + MNOTE_PENTAX_TAG_PRINTIM = 0x0e00, + MNOTE_PENTAX_TAG_TZ_CITY = 0x1000, + MNOTE_PENTAX_TAG_TZ_DST = 0x1001, + + /* 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; + +const char *mnote_pentax_tag_get_name (MnotePentaxTag tag); +const char *mnote_pentax_tag_get_title (MnotePentaxTag tag); +const char *mnote_pentax_tag_get_description (MnotePentaxTag tag); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MNOTE_PENTAX_TAG_H__ */ diff --git a/libexif_blocklist.txt b/libexif_blacklist.txt index 2c838a7..2c838a7 100644 --- a/libexif_blocklist.txt +++ b/libexif_blacklist.txt |