summaryrefslogtreecommitdiff
path: root/libexif
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2012-07-12 20:34:34 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2012-07-12 20:34:34 +0000
commit0c6a5fa0d9719a40748d8726b4543f02f70518c1 (patch)
tree241f9ae619069ac5861d7621ade296102ab5de5d /libexif
downloadlibexif-tarball-0c6a5fa0d9719a40748d8726b4543f02f70518c1.tar.gz
Diffstat (limited to 'libexif')
-rw-r--r--libexif/Makefile.am67
-rw-r--r--libexif/Makefile.in856
-rw-r--r--libexif/_stdint.h2
-rw-r--r--libexif/canon/Makefile-files7
-rw-r--r--libexif/canon/exif-mnote-data-canon.c389
-rw-r--r--libexif/canon/exif-mnote-data-canon.h58
-rw-r--r--libexif/canon/mnote-canon-entry.c762
-rw-r--r--libexif/canon/mnote-canon-entry.h44
-rw-r--r--libexif/canon/mnote-canon-tag.c201
-rw-r--r--libexif/canon/mnote-canon-tag.h59
-rw-r--r--libexif/exif-byte-order.c39
-rw-r--r--libexif/exif-byte-order.h48
-rw-r--r--libexif/exif-content.c327
-rw-r--r--libexif/exif-content.h145
-rw-r--r--libexif/exif-data-type.h46
-rw-r--r--libexif/exif-data.c1276
-rw-r--r--libexif/exif-data.h265
-rw-r--r--libexif/exif-entry.c1748
-rw-r--r--libexif/exif-entry.h185
-rw-r--r--libexif/exif-format.c81
-rw-r--r--libexif/exif-format.h65
-rw-r--r--libexif/exif-ifd.c49
-rw-r--r--libexif/exif-ifd.h43
-rw-r--r--libexif/exif-loader.c434
-rw-r--r--libexif/exif-loader.h128
-rw-r--r--libexif/exif-log.c152
-rw-r--r--libexif/exif-log.h116
-rw-r--r--libexif/exif-mem.c99
-rw-r--r--libexif/exif-mem.h90
-rw-r--r--libexif/exif-mnote-data-priv.h86
-rw-r--r--libexif/exif-mnote-data.c158
-rw-r--r--libexif/exif-mnote-data.h122
-rw-r--r--libexif/exif-system.h32
-rw-r--r--libexif/exif-tag.c1180
-rw-r--r--libexif/exif-tag.h287
-rw-r--r--libexif/exif-utils.c253
-rw-r--r--libexif/exif-utils.h194
-rw-r--r--libexif/exif.h87
-rw-r--r--libexif/fuji/Makefile-files7
-rw-r--r--libexif/fuji/exif-mnote-data-fuji.c349
-rw-r--r--libexif/fuji/exif-mnote-data-fuji.h53
-rw-r--r--libexif/fuji/mnote-fuji-entry.c306
-rw-r--r--libexif/fuji/mnote-fuji-entry.h45
-rw-r--r--libexif/fuji/mnote-fuji-tag.c105
-rw-r--r--libexif/fuji/mnote-fuji-tag.h92
-rw-r--r--libexif/i18n.h52
-rw-r--r--libexif/libexif.sym129
-rw-r--r--libexif/olympus/Makefile-files7
-rw-r--r--libexif/olympus/exif-mnote-data-olympus.c659
-rw-r--r--libexif/olympus/exif-mnote-data-olympus.h67
-rw-r--r--libexif/olympus/mnote-olympus-entry.c827
-rw-r--r--libexif/olympus/mnote-olympus-entry.h43
-rw-r--r--libexif/olympus/mnote-olympus-tag.c230
-rw-r--r--libexif/olympus/mnote-olympus-tag.h229
-rw-r--r--libexif/pentax/Makefile-files7
-rw-r--r--libexif/pentax/exif-mnote-data-pentax.c449
-rw-r--r--libexif/pentax/exif-mnote-data-pentax.h59
-rw-r--r--libexif/pentax/mnote-pentax-entry.c459
-rw-r--r--libexif/pentax/mnote-pentax-entry.h43
-rw-r--r--libexif/pentax/mnote-pentax-tag.c175
-rw-r--r--libexif/pentax/mnote-pentax-tag.h153
61 files changed, 14725 insertions, 0 deletions
diff --git a/libexif/Makefile.am b/libexif/Makefile.am
new file mode 100644
index 0000000..dde00ac
--- /dev/null
+++ b/libexif/Makefile.am
@@ -0,0 +1,67 @@
+EXTRA_DIST =
+lib_LTLIBRARIES =
+noinst_LTLIBRARIES =
+
+include canon/Makefile-files
+include fuji/Makefile-files
+include olympus/Makefile-files
+include pentax/Makefile-files
+
+# The -no-undefined makes it possible to build DLLs for Windows,
+# or shared libraries for Tru64 or AIX (according to the autobook
+# chapter on "Portable Library Design"). It doesn't seem to hurt
+# elsewhere, so we can leave it in.
+lib_LTLIBRARIES += libexif.la
+libexif_la_LDFLAGS = \
+ -export-symbols $(srcdir)/libexif.sym \
+ -no-undefined -version-info @LIBEXIF_VERSION_INFO@
+libexif_la_SOURCES = \
+ exif-byte-order.c \
+ exif-content.c \
+ exif-data.c \
+ exif-entry.c \
+ exif-format.c \
+ exif-ifd.c \
+ exif-loader.c \
+ exif-log.c \
+ exif-mem.c \
+ exif-mnote-data.c \
+ exif-mnote-data-priv.h \
+ exif-tag.c \
+ exif-utils.c \
+ i18n.h
+libexif_la_DEPENDENCIES = \
+ $(srcdir)/libexif.sym \
+ libmnote-canon.la \
+ libmnote-fuji.la \
+ libmnote-olympus.la \
+ libmnote-pentax.la
+libexif_la_LIBADD = \
+ $(LTLIBINTL) \
+ libmnote-canon.la \
+ libmnote-fuji.la \
+ libmnote-olympus.la \
+ libmnote-pentax.la
+
+libexifincludedir = $(includedir)/libexif
+libexifinclude_HEADERS = \
+ exif-byte-order.h \
+ exif-content.h \
+ exif-data.h \
+ exif-data-type.h \
+ exif-entry.h \
+ exif-format.h \
+ exif-ifd.h \
+ exif-loader.h \
+ exif-log.h \
+ exif-mem.h \
+ exif-mnote-data.h \
+ exif-tag.h \
+ exif-utils.h \
+ _stdint.h
+
+EXTRA_DIST += exif-system.h exif.h
+
+EXTRA_DIST += libexif.sym
+
+DISTCLEANFILES = _stdint.h
diff --git a/libexif/Makefile.in b/libexif/Makefile.in
new file mode 100644
index 0000000..1156f64
--- /dev/null
+++ b/libexif/Makefile.in
@@ -0,0 +1,856 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(libexifinclude_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/canon/Makefile-files \
+ $(srcdir)/fuji/Makefile-files $(srcdir)/olympus/Makefile-files \
+ $(srcdir)/pentax/Makefile-files
+subdir = libexif
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4m/gp-check-shell-environment.m4 \
+ $(top_srcdir)/m4m/gp-config-msg.m4 \
+ $(top_srcdir)/m4m/gp-documentation.m4 \
+ $(top_srcdir)/m4m/gp-gettext-hack.m4 \
+ $(top_srcdir)/m4m/stdint.m4 $(top_srcdir)/auto-m4/gettext.m4 \
+ $(top_srcdir)/auto-m4/iconv.m4 $(top_srcdir)/auto-m4/lib-ld.m4 \
+ $(top_srcdir)/auto-m4/lib-link.m4 \
+ $(top_srcdir)/auto-m4/lib-prefix.m4 \
+ $(top_srcdir)/auto-m4/libtool.m4 \
+ $(top_srcdir)/auto-m4/ltoptions.m4 \
+ $(top_srcdir)/auto-m4/ltsugar.m4 \
+ $(top_srcdir)/auto-m4/ltversion.m4 \
+ $(top_srcdir)/auto-m4/lt~obsolete.m4 \
+ $(top_srcdir)/auto-m4/nls.m4 $(top_srcdir)/auto-m4/po.m4 \
+ $(top_srcdir)/auto-m4/progtest.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(libexifincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am_libexif_la_OBJECTS = exif-byte-order.lo exif-content.lo \
+ exif-data.lo exif-entry.lo exif-format.lo exif-ifd.lo \
+ exif-loader.lo exif-log.lo exif-mem.lo exif-mnote-data.lo \
+ exif-tag.lo exif-utils.lo
+libexif_la_OBJECTS = $(am_libexif_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+libexif_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libexif_la_LDFLAGS) $(LDFLAGS) -o $@
+libmnote_canon_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libmnote_canon_la_OBJECTS = exif-mnote-data-canon.lo \
+ mnote-canon-entry.lo mnote-canon-tag.lo
+libmnote_canon_la_OBJECTS = $(am_libmnote_canon_la_OBJECTS)
+libmnote_fuji_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libmnote_fuji_la_OBJECTS = mnote-fuji-entry.lo \
+ exif-mnote-data-fuji.lo mnote-fuji-tag.lo
+libmnote_fuji_la_OBJECTS = $(am_libmnote_fuji_la_OBJECTS)
+libmnote_olympus_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libmnote_olympus_la_OBJECTS = mnote-olympus-entry.lo \
+ exif-mnote-data-olympus.lo mnote-olympus-tag.lo
+libmnote_olympus_la_OBJECTS = $(am_libmnote_olympus_la_OBJECTS)
+libmnote_pentax_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libmnote_pentax_la_OBJECTS = mnote-pentax-entry.lo \
+ exif-mnote-data-pentax.lo mnote-pentax-tag.lo
+libmnote_pentax_la_OBJECTS = $(am_libmnote_pentax_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libexif_la_SOURCES) $(libmnote_canon_la_SOURCES) \
+ $(libmnote_fuji_la_SOURCES) $(libmnote_olympus_la_SOURCES) \
+ $(libmnote_pentax_la_SOURCES)
+DIST_SOURCES = $(libexif_la_SOURCES) $(libmnote_canon_la_SOURCES) \
+ $(libmnote_fuji_la_SOURCES) $(libmnote_olympus_la_SOURCES) \
+ $(libmnote_pentax_la_SOURCES)
+HEADERS = $(libexifinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOT = @DOT@
+DOXYGEN = @DOXYGEN@
+DOXYGEN_OUTPUT_DIR = @DOXYGEN_OUTPUT_DIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+HAVE_DOT = @HAVE_DOT@
+HTML_APIDOC_DIR = @HTML_APIDOC_DIR@
+HTML_APIDOC_INTERNALS_DIR = @HTML_APIDOC_INTERNALS_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXIF_AGE = @LIBEXIF_AGE@
+LIBEXIF_CURRENT = @LIBEXIF_CURRENT@
+LIBEXIF_CURRENT_MIN = @LIBEXIF_CURRENT_MIN@
+LIBEXIF_REVISION = @LIBEXIF_REVISION@
+LIBEXIF_VERSION_INFO = @LIBEXIF_VERSION_INFO@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = exif-system.h exif.h libexif.sym
+
+# The -no-undefined makes it possible to build DLLs for Windows,
+# or shared libraries for Tru64 or AIX (according to the autobook
+# chapter on "Portable Library Design"). It doesn't seem to hurt
+# elsewhere, so we can leave it in.
+lib_LTLIBRARIES = libexif.la
+
+# -*- Makefile -*-
+
+# -*- Makefile -*-
+
+# -*- Makefile -*-
+
+# -*- Makefile -*-
+noinst_LTLIBRARIES = libmnote-canon.la libmnote-fuji.la \
+ libmnote-olympus.la libmnote-pentax.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)
+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)
+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)
+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)
+libexif_la_LDFLAGS = \
+ -export-symbols $(srcdir)/libexif.sym \
+ -no-undefined -version-info @LIBEXIF_VERSION_INFO@
+
+libexif_la_SOURCES = \
+ exif-byte-order.c \
+ exif-content.c \
+ exif-data.c \
+ exif-entry.c \
+ exif-format.c \
+ exif-ifd.c \
+ exif-loader.c \
+ exif-log.c \
+ exif-mem.c \
+ exif-mnote-data.c \
+ exif-mnote-data-priv.h \
+ exif-tag.c \
+ exif-utils.c \
+ i18n.h
+
+libexif_la_DEPENDENCIES = \
+ $(srcdir)/libexif.sym \
+ libmnote-canon.la \
+ libmnote-fuji.la \
+ libmnote-olympus.la \
+ libmnote-pentax.la
+
+libexif_la_LIBADD = \
+ $(LTLIBINTL) \
+ libmnote-canon.la \
+ libmnote-fuji.la \
+ libmnote-olympus.la \
+ libmnote-pentax.la
+
+libexifincludedir = $(includedir)/libexif
+libexifinclude_HEADERS = \
+ exif-byte-order.h \
+ exif-content.h \
+ exif-data.h \
+ exif-data-type.h \
+ exif-entry.h \
+ exif-format.h \
+ exif-ifd.h \
+ exif-loader.h \
+ exif-log.h \
+ exif-mem.h \
+ exif-mnote-data.h \
+ exif-tag.h \
+ exif-utils.h \
+ _stdint.h
+
+DISTCLEANFILES = _stdint.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/canon/Makefile-files $(srcdir)/fuji/Makefile-files $(srcdir)/olympus/Makefile-files $(srcdir)/pentax/Makefile-files $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libexif/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu libexif/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libexif.la: $(libexif_la_OBJECTS) $(libexif_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libexif_la_LINK) -rpath $(libdir) $(libexif_la_OBJECTS) $(libexif_la_LIBADD) $(LIBS)
+libmnote-canon.la: $(libmnote_canon_la_OBJECTS) $(libmnote_canon_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libmnote_canon_la_OBJECTS) $(libmnote_canon_la_LIBADD) $(LIBS)
+libmnote-fuji.la: $(libmnote_fuji_la_OBJECTS) $(libmnote_fuji_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libmnote_fuji_la_OBJECTS) $(libmnote_fuji_la_LIBADD) $(LIBS)
+libmnote-olympus.la: $(libmnote_olympus_la_OBJECTS) $(libmnote_olympus_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libmnote_olympus_la_OBJECTS) $(libmnote_olympus_la_LIBADD) $(LIBS)
+libmnote-pentax.la: $(libmnote_pentax_la_OBJECTS) $(libmnote_pentax_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libmnote_pentax_la_OBJECTS) $(libmnote_pentax_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-byte-order.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-content.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-data.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-entry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-format.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-ifd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-loader.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-log.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-mem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-mnote-data-canon.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-mnote-data-fuji.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-mnote-data-olympus.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-mnote-data-pentax.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-mnote-data.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-tag.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exif-utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mnote-canon-entry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mnote-canon-tag.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mnote-fuji-entry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mnote-fuji-tag.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mnote-olympus-entry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mnote-olympus-tag.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mnote-pentax-entry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mnote-pentax-tag.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+exif-mnote-data-canon.lo: canon/exif-mnote-data-canon.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT exif-mnote-data-canon.lo -MD -MP -MF $(DEPDIR)/exif-mnote-data-canon.Tpo -c -o exif-mnote-data-canon.lo `test -f 'canon/exif-mnote-data-canon.c' || echo '$(srcdir)/'`canon/exif-mnote-data-canon.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/exif-mnote-data-canon.Tpo $(DEPDIR)/exif-mnote-data-canon.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='canon/exif-mnote-data-canon.c' object='exif-mnote-data-canon.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o exif-mnote-data-canon.lo `test -f 'canon/exif-mnote-data-canon.c' || echo '$(srcdir)/'`canon/exif-mnote-data-canon.c
+
+mnote-canon-entry.lo: canon/mnote-canon-entry.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mnote-canon-entry.lo -MD -MP -MF $(DEPDIR)/mnote-canon-entry.Tpo -c -o mnote-canon-entry.lo `test -f 'canon/mnote-canon-entry.c' || echo '$(srcdir)/'`canon/mnote-canon-entry.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mnote-canon-entry.Tpo $(DEPDIR)/mnote-canon-entry.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='canon/mnote-canon-entry.c' object='mnote-canon-entry.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mnote-canon-entry.lo `test -f 'canon/mnote-canon-entry.c' || echo '$(srcdir)/'`canon/mnote-canon-entry.c
+
+mnote-canon-tag.lo: canon/mnote-canon-tag.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mnote-canon-tag.lo -MD -MP -MF $(DEPDIR)/mnote-canon-tag.Tpo -c -o mnote-canon-tag.lo `test -f 'canon/mnote-canon-tag.c' || echo '$(srcdir)/'`canon/mnote-canon-tag.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mnote-canon-tag.Tpo $(DEPDIR)/mnote-canon-tag.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='canon/mnote-canon-tag.c' object='mnote-canon-tag.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mnote-canon-tag.lo `test -f 'canon/mnote-canon-tag.c' || echo '$(srcdir)/'`canon/mnote-canon-tag.c
+
+mnote-fuji-entry.lo: fuji/mnote-fuji-entry.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mnote-fuji-entry.lo -MD -MP -MF $(DEPDIR)/mnote-fuji-entry.Tpo -c -o mnote-fuji-entry.lo `test -f 'fuji/mnote-fuji-entry.c' || echo '$(srcdir)/'`fuji/mnote-fuji-entry.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mnote-fuji-entry.Tpo $(DEPDIR)/mnote-fuji-entry.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fuji/mnote-fuji-entry.c' object='mnote-fuji-entry.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mnote-fuji-entry.lo `test -f 'fuji/mnote-fuji-entry.c' || echo '$(srcdir)/'`fuji/mnote-fuji-entry.c
+
+exif-mnote-data-fuji.lo: fuji/exif-mnote-data-fuji.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT exif-mnote-data-fuji.lo -MD -MP -MF $(DEPDIR)/exif-mnote-data-fuji.Tpo -c -o exif-mnote-data-fuji.lo `test -f 'fuji/exif-mnote-data-fuji.c' || echo '$(srcdir)/'`fuji/exif-mnote-data-fuji.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/exif-mnote-data-fuji.Tpo $(DEPDIR)/exif-mnote-data-fuji.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fuji/exif-mnote-data-fuji.c' object='exif-mnote-data-fuji.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o exif-mnote-data-fuji.lo `test -f 'fuji/exif-mnote-data-fuji.c' || echo '$(srcdir)/'`fuji/exif-mnote-data-fuji.c
+
+mnote-fuji-tag.lo: fuji/mnote-fuji-tag.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mnote-fuji-tag.lo -MD -MP -MF $(DEPDIR)/mnote-fuji-tag.Tpo -c -o mnote-fuji-tag.lo `test -f 'fuji/mnote-fuji-tag.c' || echo '$(srcdir)/'`fuji/mnote-fuji-tag.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mnote-fuji-tag.Tpo $(DEPDIR)/mnote-fuji-tag.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fuji/mnote-fuji-tag.c' object='mnote-fuji-tag.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mnote-fuji-tag.lo `test -f 'fuji/mnote-fuji-tag.c' || echo '$(srcdir)/'`fuji/mnote-fuji-tag.c
+
+mnote-olympus-entry.lo: olympus/mnote-olympus-entry.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mnote-olympus-entry.lo -MD -MP -MF $(DEPDIR)/mnote-olympus-entry.Tpo -c -o mnote-olympus-entry.lo `test -f 'olympus/mnote-olympus-entry.c' || echo '$(srcdir)/'`olympus/mnote-olympus-entry.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mnote-olympus-entry.Tpo $(DEPDIR)/mnote-olympus-entry.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='olympus/mnote-olympus-entry.c' object='mnote-olympus-entry.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mnote-olympus-entry.lo `test -f 'olympus/mnote-olympus-entry.c' || echo '$(srcdir)/'`olympus/mnote-olympus-entry.c
+
+exif-mnote-data-olympus.lo: olympus/exif-mnote-data-olympus.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT exif-mnote-data-olympus.lo -MD -MP -MF $(DEPDIR)/exif-mnote-data-olympus.Tpo -c -o exif-mnote-data-olympus.lo `test -f 'olympus/exif-mnote-data-olympus.c' || echo '$(srcdir)/'`olympus/exif-mnote-data-olympus.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/exif-mnote-data-olympus.Tpo $(DEPDIR)/exif-mnote-data-olympus.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='olympus/exif-mnote-data-olympus.c' object='exif-mnote-data-olympus.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o exif-mnote-data-olympus.lo `test -f 'olympus/exif-mnote-data-olympus.c' || echo '$(srcdir)/'`olympus/exif-mnote-data-olympus.c
+
+mnote-olympus-tag.lo: olympus/mnote-olympus-tag.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mnote-olympus-tag.lo -MD -MP -MF $(DEPDIR)/mnote-olympus-tag.Tpo -c -o mnote-olympus-tag.lo `test -f 'olympus/mnote-olympus-tag.c' || echo '$(srcdir)/'`olympus/mnote-olympus-tag.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mnote-olympus-tag.Tpo $(DEPDIR)/mnote-olympus-tag.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='olympus/mnote-olympus-tag.c' object='mnote-olympus-tag.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mnote-olympus-tag.lo `test -f 'olympus/mnote-olympus-tag.c' || echo '$(srcdir)/'`olympus/mnote-olympus-tag.c
+
+mnote-pentax-entry.lo: pentax/mnote-pentax-entry.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mnote-pentax-entry.lo -MD -MP -MF $(DEPDIR)/mnote-pentax-entry.Tpo -c -o mnote-pentax-entry.lo `test -f 'pentax/mnote-pentax-entry.c' || echo '$(srcdir)/'`pentax/mnote-pentax-entry.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mnote-pentax-entry.Tpo $(DEPDIR)/mnote-pentax-entry.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pentax/mnote-pentax-entry.c' object='mnote-pentax-entry.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mnote-pentax-entry.lo `test -f 'pentax/mnote-pentax-entry.c' || echo '$(srcdir)/'`pentax/mnote-pentax-entry.c
+
+exif-mnote-data-pentax.lo: pentax/exif-mnote-data-pentax.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT exif-mnote-data-pentax.lo -MD -MP -MF $(DEPDIR)/exif-mnote-data-pentax.Tpo -c -o exif-mnote-data-pentax.lo `test -f 'pentax/exif-mnote-data-pentax.c' || echo '$(srcdir)/'`pentax/exif-mnote-data-pentax.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/exif-mnote-data-pentax.Tpo $(DEPDIR)/exif-mnote-data-pentax.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pentax/exif-mnote-data-pentax.c' object='exif-mnote-data-pentax.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o exif-mnote-data-pentax.lo `test -f 'pentax/exif-mnote-data-pentax.c' || echo '$(srcdir)/'`pentax/exif-mnote-data-pentax.c
+
+mnote-pentax-tag.lo: pentax/mnote-pentax-tag.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mnote-pentax-tag.lo -MD -MP -MF $(DEPDIR)/mnote-pentax-tag.Tpo -c -o mnote-pentax-tag.lo `test -f 'pentax/mnote-pentax-tag.c' || echo '$(srcdir)/'`pentax/mnote-pentax-tag.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mnote-pentax-tag.Tpo $(DEPDIR)/mnote-pentax-tag.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pentax/mnote-pentax-tag.c' object='mnote-pentax-tag.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mnote-pentax-tag.lo `test -f 'pentax/mnote-pentax-tag.c' || echo '$(srcdir)/'`pentax/mnote-pentax-tag.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-libexifincludeHEADERS: $(libexifinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libexifincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libexifincludedir)"
+ @list='$(libexifinclude_HEADERS)'; test -n "$(libexifincludedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libexifincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libexifincludedir)" || exit $$?; \
+ done
+
+uninstall-libexifincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libexifinclude_HEADERS)'; test -n "$(libexifincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(libexifincludedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(libexifincludedir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libexifincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ clean-noinstLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libexifincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES uninstall-libexifincludeHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-libLTLIBRARIES \
+ install-libexifincludeHEADERS install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-libLTLIBRARIES \
+ uninstall-libexifincludeHEADERS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libexif/_stdint.h b/libexif/_stdint.h
new file mode 100644
index 0000000..80ecf41
--- /dev/null
+++ b/libexif/_stdint.h
@@ -0,0 +1,2 @@
+/* This file is generated automatically by configure */
+#include <stdint.h>
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..eb53598
--- /dev/null
+++ b/libexif/canon/exif-mnote-data-canon.c
@@ -0,0 +1,389 @@
+/* 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
+
+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 ((datao + 2 < datao) || (datao + 2 < 2) || (datao + 2 > buf_size)) {
+ 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;
+ if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
+ 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));
+
+ /*
+ * 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 ((dataofs + s < s) || (dataofs + s < dataofs) || (dataofs + s > buf_size)) {
+ exif_log (ne->log, EXIF_LOG_CODE_DEBUG,
+ "ExifMnoteCanon",
+ "Tag data past end of buffer (%u > %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;
+
+ 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-byte-order.c b/libexif/exif-byte-order.c
new file mode 100644
index 0000000..05164e0
--- /dev/null
+++ b/libexif/exif-byte-order.c
@@ -0,0 +1,39 @@
+/* exif-byte-order.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 <libexif/exif-byte-order.h>
+#include <libexif/i18n.h>
+
+#include <stdlib.h>
+
+const char *
+exif_byte_order_get_name (ExifByteOrder order)
+{
+ switch (order) {
+ case EXIF_BYTE_ORDER_MOTOROLA:
+ return (_("Motorola"));
+ case EXIF_BYTE_ORDER_INTEL:
+ return (_("Intel"));
+ default:
+ return NULL;
+ }
+}
diff --git a/libexif/exif-byte-order.h b/libexif/exif-byte-order.h
new file mode 100644
index 0000000..10ded49
--- /dev/null
+++ b/libexif/exif-byte-order.h
@@ -0,0 +1,48 @@
+/*! \file exif-byte-order.h
+ * \brief Defines the ExifByteOrder enum and the associated functions.
+ */
+/*
+ * 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_BYTE_ORDER_H__
+#define __EXIF_BYTE_ORDER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*! Which byte order to use */
+typedef enum {
+ /*! Big-endian byte order */
+ EXIF_BYTE_ORDER_MOTOROLA,
+ /*! Little-endian byte order */
+ EXIF_BYTE_ORDER_INTEL
+} ExifByteOrder;
+
+/*! Return a short, localized, textual name for the given byte order.
+ * \param[in] order byte order
+ * \return localized textual name of the byte order
+ */
+const char *exif_byte_order_get_name (ExifByteOrder order);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_BYTE_ORDER_H__ */
diff --git a/libexif/exif-content.c b/libexif/exif-content.c
new file mode 100644
index 0000000..6d6c589
--- /dev/null
+++ b/libexif/exif-content.c
@@ -0,0 +1,327 @@
+/* exif-content.c
+ *
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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 <libexif/exif-content.h>
+#include <libexif/exif-system.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* unused constant
+ * static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+ */
+
+struct _ExifContentPrivate
+{
+ unsigned int ref_count;
+
+ ExifMem *mem;
+ ExifLog *log;
+};
+
+ExifContent *
+exif_content_new (void)
+{
+ ExifMem *mem = exif_mem_new_default ();
+ ExifContent *content = exif_content_new_mem (mem);
+
+ exif_mem_unref (mem);
+
+ return content;
+}
+
+ExifContent *
+exif_content_new_mem (ExifMem *mem)
+{
+ ExifContent *content;
+
+ if (!mem) return NULL;
+
+ content = exif_mem_alloc (mem, (ExifLong) sizeof (ExifContent));
+ if (!content)
+ return NULL;
+ content->priv = exif_mem_alloc (mem,
+ (ExifLong) sizeof (ExifContentPrivate));
+ if (!content->priv) {
+ exif_mem_free (mem, content);
+ return NULL;
+ }
+
+ content->priv->ref_count = 1;
+
+ content->priv->mem = mem;
+ exif_mem_ref (mem);
+
+ return content;
+}
+
+void
+exif_content_ref (ExifContent *content)
+{
+ content->priv->ref_count++;
+}
+
+void
+exif_content_unref (ExifContent *content)
+{
+ content->priv->ref_count--;
+ if (!content->priv->ref_count)
+ exif_content_free (content);
+}
+
+void
+exif_content_free (ExifContent *content)
+{
+ ExifMem *mem = (content && content->priv) ? content->priv->mem : NULL;
+ unsigned int i;
+
+ if (!content) return;
+
+ for (i = 0; i < content->count; i++)
+ exif_entry_unref (content->entries[i]);
+ exif_mem_free (mem, content->entries);
+
+ if (content->priv) {
+ exif_log_unref (content->priv->log);
+ }
+
+ exif_mem_free (mem, content->priv);
+ exif_mem_free (mem, content);
+ exif_mem_unref (mem);
+}
+
+void
+exif_content_dump (ExifContent *content, unsigned int indent)
+{
+ char buf[1024];
+ unsigned int i;
+
+ for (i = 0; i < 2 * indent; i++)
+ buf[i] = ' ';
+ buf[i] = '\0';
+
+ if (!content)
+ return;
+
+ printf ("%sDumping exif content (%u entries)...\n", buf,
+ content->count);
+ for (i = 0; i < content->count; i++)
+ exif_entry_dump (content->entries[i], indent + 1);
+}
+
+void
+exif_content_add_entry (ExifContent *c, ExifEntry *entry)
+{
+ ExifEntry **entries;
+ if (!c || !c->priv || !entry || entry->parent) return;
+
+ /* One tag can only be added once to an IFD. */
+ if (exif_content_get_entry (c, entry->tag)) {
+ exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "ExifContent",
+ "An attempt has been made to add "
+ "the tag '%s' twice to an IFD. This is against "
+ "specification.", exif_tag_get_name (entry->tag));
+ return;
+ }
+
+ entries = exif_mem_realloc (c->priv->mem,
+ c->entries, sizeof (ExifEntry*) * (c->count + 1));
+ if (!entries) return;
+ entry->parent = c;
+ entries[c->count++] = entry;
+ c->entries = entries;
+ exif_entry_ref (entry);
+}
+
+void
+exif_content_remove_entry (ExifContent *c, ExifEntry *e)
+{
+ unsigned int i;
+ ExifEntry **t, *temp;
+
+ if (!c || !c->priv || !e || (e->parent != c)) return;
+
+ /* Search the entry */
+ for (i = 0; i < c->count; i++)
+ if (c->entries[i] == e)
+ break;
+
+ if (i == c->count)
+ return;
+
+ /* Remove the entry */
+ temp = c->entries[c->count-1];
+ if (c->count > 1) {
+ t = exif_mem_realloc (c->priv->mem, c->entries,
+ sizeof(ExifEntry*) * (c->count - 1));
+ if (!t) {
+ return;
+ }
+ c->entries = t;
+ c->count--;
+ if (i != c->count) { /* we deallocated the last slot already */
+ memmove (&t[i], &t[i + 1], sizeof (ExifEntry*) * (c->count - i - 1));
+ t[c->count-1] = temp;
+ }
+ } else {
+ exif_mem_free (c->priv->mem, c->entries);
+ c->entries = NULL;
+ c->count = 0;
+ }
+ e->parent = NULL;
+ exif_entry_unref (e);
+}
+
+ExifEntry *
+exif_content_get_entry (ExifContent *content, ExifTag tag)
+{
+ unsigned int i;
+
+ if (!content)
+ return (NULL);
+
+ for (i = 0; i < content->count; i++)
+ if (content->entries[i]->tag == tag)
+ return (content->entries[i]);
+ return (NULL);
+}
+
+void
+exif_content_foreach_entry (ExifContent *content,
+ ExifContentForeachEntryFunc func, void *data)
+{
+ unsigned int i;
+
+ if (!content || !func)
+ return;
+
+ for (i = 0; i < content->count; i++)
+ func (content->entries[i], data);
+}
+
+void
+exif_content_log (ExifContent *content, ExifLog *log)
+{
+ if (!content || !content->priv || !log || content->priv->log == log)
+ return;
+
+ if (content->priv->log) exif_log_unref (content->priv->log);
+ content->priv->log = log;
+ exif_log_ref (log);
+}
+
+ExifIfd
+exif_content_get_ifd (ExifContent *c)
+{
+ if (!c || !c->parent) return EXIF_IFD_COUNT;
+
+ return
+ ((c)->parent->ifd[EXIF_IFD_EXIF] == (c)) ? EXIF_IFD_EXIF :
+ ((c)->parent->ifd[EXIF_IFD_0] == (c)) ? EXIF_IFD_0 :
+ ((c)->parent->ifd[EXIF_IFD_1] == (c)) ? EXIF_IFD_1 :
+ ((c)->parent->ifd[EXIF_IFD_GPS] == (c)) ? EXIF_IFD_GPS :
+ ((c)->parent->ifd[EXIF_IFD_INTEROPERABILITY] == (c)) ? EXIF_IFD_INTEROPERABILITY :
+ EXIF_IFD_COUNT;
+}
+
+static void
+fix_func (ExifEntry *e, void *UNUSED(data))
+{
+ exif_entry_fix (e);
+}
+
+/*!
+ * Check if this entry is unknown and if so, delete it.
+ * \note Be careful calling this function in a loop. Deleting an entry from
+ * an ExifContent changes the index of subsequent entries, as well as the
+ * total size of the entries array.
+ */
+static void
+remove_not_recorded (ExifEntry *e, void *UNUSED(data))
+{
+ ExifIfd ifd = exif_entry_get_ifd(e) ;
+ ExifContent *c = e->parent;
+ ExifDataType dt = exif_data_get_data_type (c->parent);
+ ExifTag t = e->tag;
+
+ if (exif_tag_get_support_level_in_ifd (t, ifd, dt) ==
+ EXIF_SUPPORT_LEVEL_NOT_RECORDED) {
+ exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
+ "Tag 0x%04x is not recorded in IFD '%s' and has therefore been "
+ "removed.", t, exif_ifd_get_name (ifd));
+ exif_content_remove_entry (c, e);
+ }
+
+}
+
+void
+exif_content_fix (ExifContent *c)
+{
+ ExifIfd ifd = exif_content_get_ifd (c);
+ ExifDataType dt;
+ ExifEntry *e;
+ unsigned int i, num;
+
+ if (!c)
+ return;
+
+ dt = exif_data_get_data_type (c->parent);
+
+ /*
+ * First of all, fix all existing entries.
+ */
+ exif_content_foreach_entry (c, fix_func, NULL);
+
+ /*
+ * Go through each tag and if it's not recorded, remove it. If one
+ * is removed, exif_content_foreach_entry() will skip the next entry,
+ * so if this happens do the loop again from the beginning to ensure
+ * they're all checked. This could be avoided if we stop relying on
+ * exif_content_foreach_entry but loop intelligently here.
+ */
+ do {
+ num = c->count;
+ exif_content_foreach_entry (c, remove_not_recorded, NULL);
+ } while (num != c->count);
+
+ /*
+ * Then check for non-existing mandatory tags and create them if needed
+ */
+ num = exif_tag_table_count();
+ for (i = 0; i < num; ++i) {
+ const ExifTag t = exif_tag_table_get_tag (i);
+ if (exif_tag_get_support_level_in_ifd (t, ifd, dt) ==
+ EXIF_SUPPORT_LEVEL_MANDATORY) {
+ if (exif_content_get_entry (c, t))
+ /* This tag already exists */
+ continue;
+ exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
+ "Tag '%s' is mandatory in IFD '%s' and has therefore been added.",
+ exif_tag_get_name_in_ifd (t, ifd), exif_ifd_get_name (ifd));
+ e = exif_entry_new ();
+ exif_content_add_entry (c, e);
+ exif_entry_initialize (e, t);
+ exif_entry_unref (e);
+ }
+ }
+}
diff --git a/libexif/exif-content.h b/libexif/exif-content.h
new file mode 100644
index 0000000..d912ccf
--- /dev/null
+++ b/libexif/exif-content.h
@@ -0,0 +1,145 @@
+/*! \file exif-content.h
+ * \brief Handling EXIF IFDs
+ */
+/*
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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_CONTENT_H__
+#define __EXIF_CONTENT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*! Holds all EXIF tags in a single IFD */
+typedef struct _ExifContent ExifContent;
+typedef struct _ExifContentPrivate ExifContentPrivate;
+
+#include <libexif/exif-tag.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-data.h>
+#include <libexif/exif-log.h>
+#include <libexif/exif-mem.h>
+
+struct _ExifContent
+{
+ ExifEntry **entries;
+ unsigned int count;
+
+ /*! Data containing this content */
+ ExifData *parent;
+
+ ExifContentPrivate *priv;
+};
+
+/* Lifecycle */
+ExifContent *exif_content_new (void);
+ExifContent *exif_content_new_mem (ExifMem *);
+void exif_content_ref (ExifContent *content);
+void exif_content_unref (ExifContent *content);
+void exif_content_free (ExifContent *content);
+
+/*! Add an EXIF tag to an IFD.
+ * If this tag already exists in the IFD, this function does nothing.
+ * \pre The "tag" member of the entry must be set on entry.
+ *
+ * \param[out] c IFD
+ * \param[in] entry EXIF entry to add
+ */
+void exif_content_add_entry (ExifContent *c, ExifEntry *entry);
+
+/*! Remove an EXIF tag from an IFD.
+ * If this tag does not exist in the IFD, this function does nothing.
+ *
+ * \param[out] c IFD
+ * \param[in] e EXIF entry to remove
+ */
+void exif_content_remove_entry (ExifContent *c, ExifEntry *e);
+
+/*! Return the #ExifEntry in this IFD corresponding to the given tag.
+ * This is a pointer into a member of the #ExifContent array and must NOT be
+ * freed or unrefed by the caller.
+ *
+ * \param[in] content EXIF content for an IFD
+ * \param[in] tag EXIF tag to return
+ * \return #ExifEntry of the tag, or NULL on error
+ */
+ExifEntry *exif_content_get_entry (ExifContent *content, ExifTag tag);
+
+/*! Fix the IFD to bring it into specification. Call #exif_entry_fix on
+ * each entry in this IFD to fix existing entries, create any new entries
+ * that are mandatory in this IFD but do not yet exist, and remove any
+ * entries that are not allowed in this IFD.
+ *
+ * \param[in,out] c EXIF content for an IFD
+ */
+void exif_content_fix (ExifContent *c);
+
+typedef void (* ExifContentForeachEntryFunc) (ExifEntry *, void *user_data);
+
+/*! Executes function on each EXIF tag in this IFD in turn.
+ * The tags will not necessarily be visited in numerical order.
+ *
+ * \param[in,out] content IFD over which to iterate
+ * \param[in] func function to call for each entry
+ * \param[in] user_data data to pass into func on each call
+ */
+void exif_content_foreach_entry (ExifContent *content,
+ ExifContentForeachEntryFunc func,
+ void *user_data);
+
+/*! Return the IFD number in which the given #ExifContent is found.
+ *
+ * \param[in] c an #ExifContent*
+ * \return IFD number, or #EXIF_IFD_COUNT on error
+ */
+ExifIfd exif_content_get_ifd (ExifContent *c);
+
+/*! Return a textual representation of the EXIF data for a tag.
+ *
+ * \param[in] c #ExifContent* for an IFD
+ * \param[in] t #ExifTag to return
+ * \param[out] v char* buffer in which to store value
+ * \param[in] m unsigned int length of the buffer v
+ * \return the v pointer, or NULL on error
+ */
+#define exif_content_get_value(c,t,v,m) \
+ (exif_content_get_entry (c,t) ? \
+ exif_entry_get_value (exif_content_get_entry (c,t),v,m) : NULL)
+
+/*! Dump contents of the IFD to stdout.
+ * This is intended for diagnostic purposes only.
+ *
+ * \param[in] content IFD data
+ * \param[in] indent how many levels deep to indent the data
+ */
+void exif_content_dump (ExifContent *content, unsigned int indent);
+
+/*! Set the log message object for this IFD.
+ *
+ * \param[in] content IFD
+ * \param[in] log #ExifLog*
+ */
+void exif_content_log (ExifContent *content, ExifLog *log);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_CONTENT_H__ */
diff --git a/libexif/exif-data-type.h b/libexif/exif-data-type.h
new file mode 100644
index 0000000..05d4f95
--- /dev/null
+++ b/libexif/exif-data-type.h
@@ -0,0 +1,46 @@
+/* exif-data-tag.h
+ *
+ * Copyright (c) 2005 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __EXIF_DATA_TYPE_H__
+#define __EXIF_DATA_TYPE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*! Represents the type of image data to which the EXIF data applies.
+ * The EXIF tags have different constraints depending on the type of
+ * image data.
+ */
+typedef enum {
+ EXIF_DATA_TYPE_UNCOMPRESSED_CHUNKY = 0,
+ EXIF_DATA_TYPE_UNCOMPRESSED_PLANAR,
+ EXIF_DATA_TYPE_UNCOMPRESSED_YCC,
+ EXIF_DATA_TYPE_COMPRESSED,
+ EXIF_DATA_TYPE_COUNT,
+
+ EXIF_DATA_TYPE_UNKNOWN = EXIF_DATA_TYPE_COUNT
+} ExifDataType;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_TAG_H__ */
diff --git a/libexif/exif-data.c b/libexif/exif-data.c
new file mode 100644
index 0000000..67df4db
--- /dev/null
+++ b/libexif/exif-data.c
@@ -0,0 +1,1276 @@
+/* exif-data.c
+ *
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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 <libexif/exif-mnote-data.h>
+#include <libexif/exif-data.h>
+#include <libexif/exif-ifd.h>
+#include <libexif/exif-mnote-data-priv.h>
+#include <libexif/exif-utils.h>
+#include <libexif/exif-loader.h>
+#include <libexif/exif-log.h>
+#include <libexif/i18n.h>
+#include <libexif/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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef JPEG_MARKER_SOI
+#define JPEG_MARKER_SOI 0xd8
+#undef JPEG_MARKER_APP0
+#define JPEG_MARKER_APP0 0xe0
+#undef JPEG_MARKER_APP1
+#define JPEG_MARKER_APP1 0xe1
+
+static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+
+struct _ExifDataPrivate
+{
+ ExifByteOrder order;
+
+ ExifMnoteData *md;
+
+ ExifLog *log;
+ ExifMem *mem;
+
+ unsigned int ref_count;
+
+ /* Temporarily used while loading data */
+ unsigned int offset_mnote;
+
+ ExifDataOption options;
+ ExifDataType data_type;
+};
+
+static void *
+exif_data_alloc (ExifData *data, unsigned int i)
+{
+ void *d;
+
+ if (!data || !i)
+ return NULL;
+
+ d = exif_mem_alloc (data->priv->mem, i);
+ if (d)
+ return d;
+
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", i);
+ return NULL;
+}
+
+ExifMnoteData *
+exif_data_get_mnote_data (ExifData *d)
+{
+ return (d && d->priv) ? d->priv->md : NULL;
+}
+
+ExifData *
+exif_data_new (void)
+{
+ ExifMem *mem = exif_mem_new_default ();
+ ExifData *d = exif_data_new_mem (mem);
+
+ exif_mem_unref (mem);
+
+ return d;
+}
+
+ExifData *
+exif_data_new_mem (ExifMem *mem)
+{
+ ExifData *data;
+ unsigned int i;
+
+ if (!mem)
+ return NULL;
+
+ data = exif_mem_alloc (mem, sizeof (ExifData));
+ if (!data)
+ return (NULL);
+ data->priv = exif_mem_alloc (mem, sizeof (ExifDataPrivate));
+ if (!data->priv) {
+ exif_mem_free (mem, data);
+ return (NULL);
+ }
+ data->priv->ref_count = 1;
+
+ data->priv->mem = mem;
+ exif_mem_ref (mem);
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++) {
+ data->ifd[i] = exif_content_new_mem (data->priv->mem);
+ if (!data->ifd[i]) {
+ exif_data_free (data);
+ return (NULL);
+ }
+ data->ifd[i]->parent = data;
+ }
+
+ /* Default options */
+#ifndef NO_VERBOSE_TAG_STRINGS
+ /*
+ * When the tag list is compiled away, setting this option prevents
+ * any tags from being loaded
+ */
+ exif_data_set_option (data, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS);
+#endif
+ exif_data_set_option (data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
+
+ /* Default data type: none */
+ exif_data_set_data_type (data, EXIF_DATA_TYPE_COUNT);
+
+ return (data);
+}
+
+ExifData *
+exif_data_new_from_data (const unsigned char *data, unsigned int size)
+{
+ ExifData *edata;
+
+ edata = exif_data_new ();
+ exif_data_load_data (edata, data, size);
+ return (edata);
+}
+
+static int
+exif_data_load_data_entry (ExifData *data, ExifEntry *entry,
+ const unsigned char *d,
+ unsigned int size, unsigned int offset)
+{
+ unsigned int s, doff;
+
+ entry->tag = exif_get_short (d + offset + 0, data->priv->order);
+ entry->format = exif_get_short (d + offset + 2, data->priv->order);
+ entry->components = exif_get_long (d + offset + 4, data->priv->order);
+
+ /* FIXME: should use exif_tag_get_name_in_ifd here but entry->parent
+ * has not been set yet
+ */
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Loading entry 0x%x ('%s')...", entry->tag,
+ exif_tag_get_name (entry->tag));
+
+ /* {0,1,2,4,8} x { 0x00000000 .. 0xffffffff }
+ * -> { 0x000000000 .. 0x7fffffff8 } */
+ s = exif_format_get_size(entry->format) * entry->components;
+ if ((s < entry->components) || (s == 0)){
+ return 0;
+ }
+
+ /*
+ * Size? If bigger than 4 bytes, the actual data is not
+ * in the entry but somewhere else (offset).
+ */
+ if (s > 4)
+ doff = exif_get_long (d + offset + 8, data->priv->order);
+ else
+ doff = offset + 8;
+
+ /* Sanity checks */
+ if ((doff + s < doff) || (doff + s < s) || (doff + s > size)) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Tag data past end of buffer (%u > %u)", doff+s, size);
+ return 0;
+ }
+
+ entry->data = exif_data_alloc (data, s);
+ if (entry->data) {
+ entry->size = s;
+ memcpy (entry->data, d + doff, s);
+ } else {
+ /* FIXME: What do our callers do if (entry->data == NULL)? */
+ EXIF_LOG_NO_MEMORY(data->priv->log, "ExifData", s);
+ }
+
+ /* If this is the MakerNote, remember the offset */
+ if (entry->tag == EXIF_TAG_MAKER_NOTE) {
+ if (!entry->data) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "MakerNote found with empty data");
+ } else if (entry->size > 6) {
+ exif_log (data->priv->log,
+ EXIF_LOG_CODE_DEBUG, "ExifData",
+ "MakerNote found (%02x %02x %02x %02x "
+ "%02x %02x %02x...).",
+ entry->data[0], entry->data[1], entry->data[2],
+ entry->data[3], entry->data[4], entry->data[5],
+ entry->data[6]);
+ }
+ data->priv->offset_mnote = doff;
+ }
+ return 1;
+}
+
+static void
+exif_data_save_data_entry (ExifData *data, ExifEntry *e,
+ unsigned char **d, unsigned int *ds,
+ unsigned int offset)
+{
+ unsigned int doff, s;
+ unsigned int ts;
+
+ if (!data || !data->priv)
+ return;
+
+ /*
+ * Each entry is 12 bytes long. The memory for the entry has
+ * already been allocated.
+ */
+ exif_set_short (*d + 6 + offset + 0,
+ data->priv->order, (ExifShort) e->tag);
+ exif_set_short (*d + 6 + offset + 2,
+ data->priv->order, (ExifShort) e->format);
+
+ if (!(data->priv->options & EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE)) {
+ /* If this is the maker note tag, update it. */
+ if ((e->tag == EXIF_TAG_MAKER_NOTE) && data->priv->md) {
+ /* TODO: this is using the wrong ExifMem to free e->data */
+ exif_mem_free (data->priv->mem, e->data);
+ e->data = NULL;
+ e->size = 0;
+ exif_mnote_data_set_offset (data->priv->md, *ds - 6);
+ exif_mnote_data_save (data->priv->md, &e->data, &e->size);
+ e->components = e->size;
+ }
+ }
+
+ exif_set_long (*d + 6 + offset + 4,
+ data->priv->order, e->components);
+
+ /*
+ * Size? If bigger than 4 bytes, the actual data is not in
+ * the entry but somewhere else.
+ */
+ s = exif_format_get_size (e->format) * e->components;
+ if (s > 4) {
+ unsigned char *t;
+ doff = *ds - 6;
+ ts = *ds + s;
+
+ /*
+ * According to the TIFF specification,
+ * the offset must be an even number. If we need to introduce
+ * a padding byte, we set it to 0.
+ */
+ if (s & 1)
+ ts++;
+ t = exif_mem_realloc (data->priv->mem, *d, ts);
+ if (!t) {
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts);
+ return;
+ }
+ *d = t;
+ *ds = ts;
+ exif_set_long (*d + 6 + offset + 8, data->priv->order, doff);
+ if (s & 1)
+ *(*d + *ds - 1) = '\0';
+
+ } else
+ doff = offset + 8;
+
+ /* Write the data. Fill unneeded bytes with 0. Do not crash with
+ * e->data is NULL */
+ if (e->data) {
+ memcpy (*d + 6 + doff, e->data, s);
+ } else {
+ memset (*d + 6 + doff, 0, s);
+ }
+ if (s < 4)
+ memset (*d + 6 + doff + s, 0, (4 - s));
+}
+
+static void
+exif_data_load_data_thumbnail (ExifData *data, const unsigned char *d,
+ unsigned int ds, ExifLong o, ExifLong s)
+{
+ /* Sanity checks */
+ if ((o + s < o) || (o + s < s) || (o + s > ds) || (o > ds)) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Bogus thumbnail offset (%u) or size (%u).",
+ o, s);
+ return;
+ }
+
+ if (data->data)
+ exif_mem_free (data->priv->mem, data->data);
+ if (!(data->data = exif_data_alloc (data, s))) {
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", s);
+ data->size = 0;
+ return;
+ }
+ data->size = s;
+ memcpy (data->data, d + o, s);
+}
+
+#undef CHECK_REC
+#define CHECK_REC(i) \
+if ((i) == ifd) { \
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \
+ "ExifData", "Recursive entry in IFD " \
+ "'%s' detected. Skipping...", \
+ exif_ifd_get_name (i)); \
+ break; \
+} \
+if (data->ifd[(i)]->count) { \
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \
+ "ExifData", "Attempt to load IFD " \
+ "'%s' multiple times detected. " \
+ "Skipping...", \
+ exif_ifd_get_name (i)); \
+ break; \
+}
+
+/*! Load data for an IFD.
+ *
+ * \param[in,out] data #ExifData
+ * \param[in] ifd IFD to load
+ * \param[in] d pointer to buffer containing raw IFD data
+ * \param[in] ds size of raw data in buffer at \c d
+ * \param[in] offset offset into buffer at \c d at which IFD starts
+ * \param[in] recursion_depth number of times this function has been
+ * recursively called without returning
+ */
+static void
+exif_data_load_data_content (ExifData *data, ExifIfd ifd,
+ const unsigned char *d,
+ unsigned int ds, unsigned int offset, unsigned int recursion_depth)
+{
+ ExifLong o, thumbnail_offset = 0, thumbnail_length = 0;
+ ExifShort n;
+ ExifEntry *entry;
+ unsigned int i;
+ ExifTag tag;
+
+ if (!data || !data->priv)
+ return;
+
+ /* check for valid ExifIfd enum range */
+ if ((((int)ifd) < 0) || ( ((int)ifd) >= EXIF_IFD_COUNT))
+ return;
+
+ if (recursion_depth > 30) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData",
+ "Deep recursion detected!");
+ return;
+ }
+
+ /* Read the number of entries */
+ if ((offset + 2 < offset) || (offset + 2 < 2) || (offset + 2 > ds)) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData",
+ "Tag data past end of buffer (%u > %u)", offset+2, ds);
+ return;
+ }
+ n = exif_get_short (d + offset, data->priv->order);
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Loading %hu entries...", n);
+ offset += 2;
+
+ /* Check if we have enough data. */
+ if (offset + 12 * n > ds) {
+ n = (ds - offset) / 12;
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Short data; only loading %hu entries...", n);
+ }
+
+ for (i = 0; i < n; i++) {
+
+ tag = exif_get_short (d + offset + 12 * i, data->priv->order);
+ switch (tag) {
+ case EXIF_TAG_EXIF_IFD_POINTER:
+ case EXIF_TAG_GPS_INFO_IFD_POINTER:
+ case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
+ o = exif_get_long (d + offset + 12 * i + 8,
+ data->priv->order);
+ /* FIXME: IFD_POINTER tags aren't marked as being in a
+ * specific IFD, so exif_tag_get_name_in_ifd won't work
+ */
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Sub-IFD entry 0x%x ('%s') at %u.", tag,
+ exif_tag_get_name(tag), o);
+ switch (tag) {
+ case EXIF_TAG_EXIF_IFD_POINTER:
+ CHECK_REC (EXIF_IFD_EXIF);
+ exif_data_load_data_content (data, EXIF_IFD_EXIF, d, ds, o, recursion_depth + 1);
+ break;
+ case EXIF_TAG_GPS_INFO_IFD_POINTER:
+ CHECK_REC (EXIF_IFD_GPS);
+ exif_data_load_data_content (data, EXIF_IFD_GPS, d, ds, o, recursion_depth + 1);
+ break;
+ case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
+ CHECK_REC (EXIF_IFD_INTEROPERABILITY);
+ exif_data_load_data_content (data, EXIF_IFD_INTEROPERABILITY, d, ds, o, recursion_depth + 1);
+ break;
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
+ thumbnail_offset = o;
+ if (thumbnail_offset && thumbnail_length)
+ exif_data_load_data_thumbnail (data, d,
+ ds, thumbnail_offset,
+ thumbnail_length);
+ break;
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
+ thumbnail_length = o;
+ if (thumbnail_offset && thumbnail_length)
+ exif_data_load_data_thumbnail (data, d,
+ ds, thumbnail_offset,
+ thumbnail_length);
+ break;
+ default:
+ return;
+ }
+ break;
+ default:
+
+ /*
+ * If we don't know the tag, don't fail. It could be that new
+ * versions of the standard have defined additional tags. Note that
+ * 0 is a valid tag in the GPS IFD.
+ */
+ if (!exif_tag_get_name_in_ifd (tag, ifd)) {
+
+ /*
+ * Special case: Tag and format 0. That's against specification
+ * (at least up to 2.2). But Photoshop writes it anyways.
+ */
+ if (!memcmp (d + offset + 12 * i, "\0\0\0\0", 4)) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Skipping empty entry at position %u in '%s'.", i,
+ exif_ifd_get_name (ifd));
+ break;
+ }
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Unknown tag 0x%04x (entry %u in '%s'). Please report this tag "
+ "to <libexif-devel@lists.sourceforge.net>.", tag, i,
+ exif_ifd_get_name (ifd));
+ if (data->priv->options & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS)
+ break;
+ }
+ entry = exif_entry_new_mem (data->priv->mem);
+ if (exif_data_load_data_entry (data, entry, d, ds,
+ offset + 12 * i))
+ exif_content_add_entry (data->ifd[ifd], entry);
+ exif_entry_unref (entry);
+ break;
+ }
+ }
+}
+
+static int
+cmp_func (const unsigned char *p1, const unsigned char *p2, ExifByteOrder o)
+{
+ ExifShort tag1 = exif_get_short (p1, o);
+ ExifShort tag2 = exif_get_short (p2, o);
+
+ return (tag1 < tag2) ? -1 : (tag1 > tag2) ? 1 : 0;
+}
+
+static int
+cmp_func_intel (const void *elem1, const void *elem2)
+{
+ return cmp_func ((const unsigned char *) elem1,
+ (const unsigned char *) elem2, EXIF_BYTE_ORDER_INTEL);
+}
+
+static int
+cmp_func_motorola (const void *elem1, const void *elem2)
+{
+ return cmp_func ((const unsigned char *) elem1,
+ (const unsigned char *) elem2, EXIF_BYTE_ORDER_MOTOROLA);
+}
+
+static void
+exif_data_save_data_content (ExifData *data, ExifContent *ifd,
+ unsigned char **d, unsigned int *ds,
+ unsigned int offset)
+{
+ unsigned int j, n_ptr = 0, n_thumb = 0;
+ ExifIfd i;
+ unsigned char *t;
+ unsigned int ts;
+
+ if (!data || !data->priv || !ifd || !d || !ds)
+ return;
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++)
+ if (ifd == data->ifd[i])
+ break;
+ if (i == EXIF_IFD_COUNT)
+ return; /* error */
+
+ /*
+ * Check if we need some extra entries for pointers or the thumbnail.
+ */
+ switch (i) {
+ case EXIF_IFD_0:
+
+ /*
+ * The pointer to IFD_EXIF is in IFD_0. The pointer to
+ * IFD_INTEROPERABILITY is in IFD_EXIF.
+ */
+ if (data->ifd[EXIF_IFD_EXIF]->count ||
+ data->ifd[EXIF_IFD_INTEROPERABILITY]->count)
+ n_ptr++;
+
+ /* The pointer to IFD_GPS is in IFD_0. */
+ if (data->ifd[EXIF_IFD_GPS]->count)
+ n_ptr++;
+
+ break;
+ case EXIF_IFD_1:
+ if (data->size)
+ n_thumb = 2;
+ break;
+ case EXIF_IFD_EXIF:
+ if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count)
+ n_ptr++;
+ default:
+ break;
+ }
+
+ /*
+ * Allocate enough memory for all entries
+ * and the number of entries.
+ */
+ ts = *ds + (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4);
+ t = exif_mem_realloc (data->priv->mem, *d, ts);
+ if (!t) {
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts);
+ return;
+ }
+ *d = t;
+ *ds = ts;
+
+ /* Save the number of entries */
+ exif_set_short (*d + 6 + offset, data->priv->order,
+ (ExifShort) (ifd->count + n_ptr + n_thumb));
+ offset += 2;
+
+ /*
+ * Save each entry. Make sure that no memcpys from NULL pointers are
+ * performed
+ */
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Saving %i entries (IFD '%s', offset: %i)...",
+ ifd->count, exif_ifd_get_name (i), offset);
+ for (j = 0; j < ifd->count; j++) {
+ if (ifd->entries[j]) {
+ exif_data_save_data_entry (data, ifd->entries[j], d, ds,
+ offset + 12 * j);
+ }
+ }
+
+ offset += 12 * ifd->count;
+
+ /* Now save special entries. */
+ switch (i) {
+ case EXIF_IFD_0:
+
+ /*
+ * The pointer to IFD_EXIF is in IFD_0.
+ * However, the pointer to IFD_INTEROPERABILITY is in IFD_EXIF,
+ * therefore, if IFD_INTEROPERABILITY is not empty, we need
+ * IFD_EXIF even if latter is empty.
+ */
+ if (data->ifd[EXIF_IFD_EXIF]->count ||
+ data->ifd[EXIF_IFD_INTEROPERABILITY]->count) {
+ exif_set_short (*d + 6 + offset + 0, data->priv->order,
+ EXIF_TAG_EXIF_IFD_POINTER);
+ exif_set_short (*d + 6 + offset + 2, data->priv->order,
+ EXIF_FORMAT_LONG);
+ exif_set_long (*d + 6 + offset + 4, data->priv->order,
+ 1);
+ exif_set_long (*d + 6 + offset + 8, data->priv->order,
+ *ds - 6);
+ exif_data_save_data_content (data,
+ data->ifd[EXIF_IFD_EXIF], d, ds, *ds - 6);
+ offset += 12;
+ }
+
+ /* The pointer to IFD_GPS is in IFD_0, too. */
+ if (data->ifd[EXIF_IFD_GPS]->count) {
+ exif_set_short (*d + 6 + offset + 0, data->priv->order,
+ EXIF_TAG_GPS_INFO_IFD_POINTER);
+ exif_set_short (*d + 6 + offset + 2, data->priv->order,
+ EXIF_FORMAT_LONG);
+ exif_set_long (*d + 6 + offset + 4, data->priv->order,
+ 1);
+ exif_set_long (*d + 6 + offset + 8, data->priv->order,
+ *ds - 6);
+ exif_data_save_data_content (data,
+ data->ifd[EXIF_IFD_GPS], d, ds, *ds - 6);
+ offset += 12;
+ }
+
+ break;
+ case EXIF_IFD_EXIF:
+
+ /*
+ * The pointer to IFD_INTEROPERABILITY is in IFD_EXIF.
+ * See note above.
+ */
+ if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count) {
+ exif_set_short (*d + 6 + offset + 0, data->priv->order,
+ EXIF_TAG_INTEROPERABILITY_IFD_POINTER);
+ exif_set_short (*d + 6 + offset + 2, data->priv->order,
+ EXIF_FORMAT_LONG);
+ exif_set_long (*d + 6 + offset + 4, data->priv->order,
+ 1);
+ exif_set_long (*d + 6 + offset + 8, data->priv->order,
+ *ds - 6);
+ exif_data_save_data_content (data,
+ data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds,
+ *ds - 6);
+ offset += 12;
+ }
+
+ break;
+ case EXIF_IFD_1:
+
+ /*
+ * Information about the thumbnail (if any) is saved in
+ * IFD_1.
+ */
+ if (data->size) {
+
+ /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT */
+ exif_set_short (*d + 6 + offset + 0, data->priv->order,
+ EXIF_TAG_JPEG_INTERCHANGE_FORMAT);
+ exif_set_short (*d + 6 + offset + 2, data->priv->order,
+ EXIF_FORMAT_LONG);
+ exif_set_long (*d + 6 + offset + 4, data->priv->order,
+ 1);
+ exif_set_long (*d + 6 + offset + 8, data->priv->order,
+ *ds - 6);
+ ts = *ds + data->size;
+ t = exif_mem_realloc (data->priv->mem, *d, ts);
+ if (!t) {
+ EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData",
+ ts);
+ return;
+ }
+ *d = t;
+ *ds = ts;
+ memcpy (*d + *ds - data->size, data->data, data->size);
+ offset += 12;
+
+ /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH */
+ exif_set_short (*d + 6 + offset + 0, data->priv->order,
+ EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
+ exif_set_short (*d + 6 + offset + 2, data->priv->order,
+ EXIF_FORMAT_LONG);
+ exif_set_long (*d + 6 + offset + 4, data->priv->order,
+ 1);
+ exif_set_long (*d + 6 + offset + 8, data->priv->order,
+ data->size);
+ offset += 12;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ /* Sort the directory according to TIFF specification */
+ qsort (*d + 6 + offset - (ifd->count + n_ptr + n_thumb) * 12,
+ (ifd->count + n_ptr + n_thumb), 12,
+ (data->priv->order == EXIF_BYTE_ORDER_INTEL) ? cmp_func_intel : cmp_func_motorola);
+
+ /* Correctly terminate the directory */
+ if (i == EXIF_IFD_0 && (data->ifd[EXIF_IFD_1]->count ||
+ data->size)) {
+
+ /*
+ * We are saving IFD 0. Tell where IFD 1 starts and save
+ * IFD 1.
+ */
+ exif_set_long (*d + 6 + offset, data->priv->order, *ds - 6);
+ exif_data_save_data_content (data, data->ifd[EXIF_IFD_1], d, ds,
+ *ds - 6);
+ } else
+ exif_set_long (*d + 6 + offset, data->priv->order, 0);
+}
+
+typedef enum {
+ EXIF_DATA_TYPE_MAKER_NOTE_NONE = 0,
+ EXIF_DATA_TYPE_MAKER_NOTE_CANON = 1,
+ EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS = 2,
+ EXIF_DATA_TYPE_MAKER_NOTE_PENTAX = 3,
+ EXIF_DATA_TYPE_MAKER_NOTE_NIKON = 4,
+ EXIF_DATA_TYPE_MAKER_NOTE_CASIO = 5,
+ EXIF_DATA_TYPE_MAKER_NOTE_FUJI = 6
+} ExifDataTypeMakerNote;
+
+/*! If MakerNote is recognized, load it.
+ *
+ * \param[in,out] data #ExifData
+ * \param[in] d pointer to raw EXIF data
+ * \param[in] ds length of data at d
+ */
+static void
+interpret_maker_note(ExifData *data, const unsigned char *d, unsigned int ds)
+{
+ int mnoteid;
+ ExifEntry* e = exif_data_get_entry (data, EXIF_TAG_MAKER_NOTE);
+ if (!e)
+ return;
+
+ 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.
+ */
+ if (data->priv->md) {
+ exif_mnote_data_log (data->priv->md, data->priv->log);
+ exif_mnote_data_set_byte_order (data->priv->md,
+ data->priv->order);
+ exif_mnote_data_set_offset (data->priv->md,
+ data->priv->offset_mnote);
+ exif_mnote_data_load (data->priv->md, d, ds);
+ }
+}
+
+#define LOG_TOO_SMALL \
+exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", \
+ _("Size of data too small to allow for EXIF data."));
+
+void
+exif_data_load_data (ExifData *data, const unsigned char *d_orig,
+ unsigned int ds)
+{
+ unsigned int l;
+ ExifLong offset;
+ ExifShort n;
+ const unsigned char *d = d_orig;
+ unsigned int len, fullds;
+
+ if (!data || !data->priv || !d || !ds)
+ return;
+
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Parsing %i byte(s) EXIF data...\n", ds);
+
+ /*
+ * It can be that the data starts with the EXIF header. If it does
+ * not, search the EXIF marker.
+ */
+ if (ds < 6) {
+ LOG_TOO_SMALL;
+ return;
+ }
+ if (!memcmp (d, ExifHeader, 6)) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Found EXIF header.");
+ } else {
+ while (ds >= 3) {
+ while (ds && (d[0] == 0xff)) {
+ d++;
+ ds--;
+ }
+
+ /* JPEG_MARKER_SOI */
+ if (ds && d[0] == JPEG_MARKER_SOI) {
+ d++;
+ ds--;
+ continue;
+ }
+
+ /* JPEG_MARKER_APP0 */
+ if (ds >= 3 && d[0] == JPEG_MARKER_APP0) {
+ d++;
+ ds--;
+ l = (d[0] << 8) | d[1];
+ if (l > ds)
+ return;
+ d += l;
+ ds -= l;
+ continue;
+ }
+
+ /* JPEG_MARKER_APP1 */
+ if (ds && d[0] == JPEG_MARKER_APP1)
+ break;
+
+ /* Unknown marker or data. Give up. */
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifData", _("EXIF marker not found."));
+ return;
+ }
+ if (ds < 3) {
+ LOG_TOO_SMALL;
+ return;
+ }
+ d++;
+ ds--;
+ len = (d[0] << 8) | d[1];
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "We have to deal with %i byte(s) of EXIF data.",
+ len);
+ d += 2;
+ ds -= 2;
+ }
+
+ /*
+ * Verify the exif header
+ * (offset 2, length 6).
+ */
+ if (ds < 6) {
+ LOG_TOO_SMALL;
+ return;
+ }
+ if (memcmp (d, ExifHeader, 6)) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifData", _("EXIF header not found."));
+ return;
+ }
+
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Found EXIF header.");
+
+ /* Sanity check the data length */
+ if (ds < 14)
+ return;
+
+ /* The JPEG APP1 section can be no longer than 64 KiB (including a
+ 16-bit length), so cap the data length to protect against overflow
+ in future offset calculations */
+ fullds = ds;
+ if (ds > 0xfffe)
+ ds = 0xfffe;
+
+ /* Byte order (offset 6, length 2) */
+ if (!memcmp (d + 6, "II", 2))
+ data->priv->order = EXIF_BYTE_ORDER_INTEL;
+ else if (!memcmp (d + 6, "MM", 2))
+ data->priv->order = EXIF_BYTE_ORDER_MOTOROLA;
+ else {
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifData", _("Unknown encoding."));
+ return;
+ }
+
+ /* Fixed value */
+ if (exif_get_short (d + 8, data->priv->order) != 0x002a)
+ return;
+
+ /* IFD 0 offset */
+ offset = exif_get_long (d + 10, data->priv->order);
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "IFD 0 at %i.", (int) offset);
+
+ /* Sanity check the offset, being careful about overflow */
+ if (offset > ds || offset + 6 + 2 > ds)
+ return;
+
+ /* Parse the actual exif data (usually offset 14 from start) */
+ exif_data_load_data_content (data, EXIF_IFD_0, d + 6, ds - 6, offset, 0);
+
+ /* IFD 1 offset */
+ n = exif_get_short (d + 6 + offset, data->priv->order);
+ if (offset + 6 + 2 + 12 * n + 4 > ds)
+ return;
+
+ offset = exif_get_long (d + 6 + offset + 2 + 12 * n, data->priv->order);
+ if (offset) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "IFD 1 at %i.", (int) offset);
+
+ /* Sanity check. */
+ if (offset > ds || offset + 6 > ds) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifData", "Bogus offset of IFD1.");
+ } else {
+ exif_data_load_data_content (data, EXIF_IFD_1, d + 6, ds - 6, offset, 0);
+ }
+ }
+
+ /*
+ * If we got an EXIF_TAG_MAKER_NOTE, try to interpret it. Some
+ * cameras use pointers in the maker note tag that point to the
+ * space between IFDs. Here is the only place where we have access
+ * to that data.
+ */
+ interpret_maker_note(data, d, fullds);
+
+ /* Fixup tags if requested */
+ if (data->priv->options & EXIF_DATA_OPTION_FOLLOW_SPECIFICATION)
+ exif_data_fix (data);
+}
+
+void
+exif_data_save_data (ExifData *data, unsigned char **d, unsigned int *ds)
+{
+ if (ds)
+ *ds = 0; /* This means something went wrong */
+
+ if (!data || !d || !ds)
+ return;
+
+ /* Header */
+ *ds = 14;
+ *d = exif_data_alloc (data, *ds);
+ if (!*d) {
+ *ds = 0;
+ return;
+ }
+ memcpy (*d, ExifHeader, 6);
+
+ /* Order (offset 6) */
+ if (data->priv->order == EXIF_BYTE_ORDER_INTEL) {
+ memcpy (*d + 6, "II", 2);
+ } else {
+ memcpy (*d + 6, "MM", 2);
+ }
+
+ /* Fixed value (2 bytes, offset 8) */
+ exif_set_short (*d + 8, data->priv->order, 0x002a);
+
+ /*
+ * IFD 0 offset (4 bytes, offset 10).
+ * We will start 8 bytes after the
+ * EXIF header (2 bytes for order, another 2 for the test, and
+ * 4 bytes for the IFD 0 offset make 8 bytes together).
+ */
+ exif_set_long (*d + 10, data->priv->order, 8);
+
+ /* Now save IFD 0. IFD 1 will be saved automatically. */
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Saving IFDs...");
+ exif_data_save_data_content (data, data->ifd[EXIF_IFD_0], d, ds,
+ *ds - 6);
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Saved %i byte(s) EXIF data.", *ds);
+}
+
+ExifData *
+exif_data_new_from_file (const char *path)
+{
+ ExifData *edata;
+ ExifLoader *loader;
+
+ loader = exif_loader_new ();
+ exif_loader_write_file (loader, path);
+ edata = exif_loader_get_data (loader);
+ exif_loader_unref (loader);
+
+ return (edata);
+}
+
+void
+exif_data_ref (ExifData *data)
+{
+ if (!data)
+ return;
+
+ data->priv->ref_count++;
+}
+
+void
+exif_data_unref (ExifData *data)
+{
+ if (!data)
+ return;
+
+ data->priv->ref_count--;
+ if (!data->priv->ref_count)
+ exif_data_free (data);
+}
+
+void
+exif_data_free (ExifData *data)
+{
+ unsigned int i;
+ ExifMem *mem = (data && data->priv) ? data->priv->mem : NULL;
+
+ if (!data)
+ return;
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++) {
+ if (data->ifd[i]) {
+ exif_content_unref (data->ifd[i]);
+ data->ifd[i] = NULL;
+ }
+ }
+
+ if (data->data) {
+ exif_mem_free (mem, data->data);
+ data->data = NULL;
+ }
+
+ if (data->priv) {
+ if (data->priv->log) {
+ exif_log_unref (data->priv->log);
+ data->priv->log = NULL;
+ }
+ if (data->priv->md) {
+ exif_mnote_data_unref (data->priv->md);
+ data->priv->md = NULL;
+ }
+ exif_mem_free (mem, data->priv);
+ exif_mem_free (mem, data);
+ }
+
+ exif_mem_unref (mem);
+}
+
+void
+exif_data_dump (ExifData *data)
+{
+ unsigned int i;
+
+ if (!data)
+ return;
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++) {
+ if (data->ifd[i] && data->ifd[i]->count) {
+ printf ("Dumping IFD '%s'...\n",
+ exif_ifd_get_name (i));
+ exif_content_dump (data->ifd[i], 0);
+ }
+ }
+
+ if (data->data) {
+ printf ("%i byte(s) thumbnail data available.", data->size);
+ if (data->size >= 4) {
+ printf ("0x%02x 0x%02x ... 0x%02x 0x%02x\n",
+ data->data[0], data->data[1],
+ data->data[data->size - 2],
+ data->data[data->size - 1]);
+ }
+ }
+}
+
+ExifByteOrder
+exif_data_get_byte_order (ExifData *data)
+{
+ if (!data)
+ return (0);
+
+ return (data->priv->order);
+}
+
+void
+exif_data_foreach_content (ExifData *data, ExifDataForeachContentFunc func,
+ void *user_data)
+{
+ unsigned int i;
+
+ if (!data || !func)
+ return;
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++)
+ func (data->ifd[i], user_data);
+}
+
+typedef struct _ByteOrderChangeData ByteOrderChangeData;
+struct _ByteOrderChangeData {
+ ExifByteOrder old, new;
+};
+
+static void
+entry_set_byte_order (ExifEntry *e, void *data)
+{
+ ByteOrderChangeData *d = data;
+
+ if (!e)
+ return;
+
+ exif_array_set_byte_order (e->format, e->data, e->components, d->old, d->new);
+}
+
+static void
+content_set_byte_order (ExifContent *content, void *data)
+{
+ exif_content_foreach_entry (content, entry_set_byte_order, data);
+}
+
+void
+exif_data_set_byte_order (ExifData *data, ExifByteOrder order)
+{
+ ByteOrderChangeData d;
+
+ if (!data || (order == data->priv->order))
+ return;
+
+ d.old = data->priv->order;
+ d.new = order;
+ exif_data_foreach_content (data, content_set_byte_order, &d);
+ data->priv->order = order;
+ if (data->priv->md)
+ exif_mnote_data_set_byte_order (data->priv->md, order);
+}
+
+void
+exif_data_log (ExifData *data, ExifLog *log)
+{
+ unsigned int i;
+
+ if (!data || !data->priv)
+ return;
+ exif_log_unref (data->priv->log);
+ data->priv->log = log;
+ exif_log_ref (log);
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++)
+ exif_content_log (data->ifd[i], log);
+}
+
+/* Used internally within libexif */
+ExifLog *exif_data_get_log (ExifData *);
+ExifLog *
+exif_data_get_log (ExifData *data)
+{
+ if (!data || !data->priv)
+ return NULL;
+ return data->priv->log;
+}
+
+static const struct {
+ ExifDataOption option;
+ const char *name;
+ const char *description;
+} exif_data_option[] = {
+ {EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS, N_("Ignore unknown tags"),
+ N_("Ignore unknown tags when loading EXIF data.")},
+ {EXIF_DATA_OPTION_FOLLOW_SPECIFICATION, N_("Follow specification"),
+ N_("Add, correct and remove entries to get EXIF data that follows "
+ "the specification.")},
+ {EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE, N_("Do not change maker note"),
+ N_("When loading and resaving Exif data, save the maker note unmodified."
+ " Be aware that the maker note can get corrupted.")},
+ {0, NULL, NULL}
+};
+
+const char *
+exif_data_option_get_name (ExifDataOption o)
+{
+ unsigned int i;
+
+ for (i = 0; exif_data_option[i].name; i++)
+ if (exif_data_option[i].option == o)
+ break;
+ return _(exif_data_option[i].name);
+}
+
+const char *
+exif_data_option_get_description (ExifDataOption o)
+{
+ unsigned int i;
+
+ for (i = 0; exif_data_option[i].description; i++)
+ if (exif_data_option[i].option == o)
+ break;
+ return _(exif_data_option[i].description);
+}
+
+void
+exif_data_set_option (ExifData *d, ExifDataOption o)
+{
+ if (!d)
+ return;
+
+ d->priv->options |= o;
+}
+
+void
+exif_data_unset_option (ExifData *d, ExifDataOption o)
+{
+ if (!d)
+ return;
+
+ d->priv->options &= ~o;
+}
+
+static void
+fix_func (ExifContent *c, void *UNUSED(data))
+{
+ switch (exif_content_get_ifd (c)) {
+ case EXIF_IFD_1:
+ if (c->parent->data)
+ exif_content_fix (c);
+ else if (c->count) {
+ exif_log (c->parent->priv->log, EXIF_LOG_CODE_DEBUG, "exif-data",
+ "No thumbnail but entries on thumbnail. These entries have been "
+ "removed.");
+ while (c->count) {
+ unsigned int cnt = c->count;
+ exif_content_remove_entry (c, c->entries[c->count - 1]);
+ if (cnt == c->count) {
+ /* safety net */
+ exif_log (c->parent->priv->log, EXIF_LOG_CODE_DEBUG, "exif-data",
+ "failed to remove last entry from entries.");
+ c->count--;
+ }
+ }
+ }
+ break;
+ default:
+ exif_content_fix (c);
+ }
+}
+
+void
+exif_data_fix (ExifData *d)
+{
+ exif_data_foreach_content (d, fix_func, NULL);
+}
+
+void
+exif_data_set_data_type (ExifData *d, ExifDataType dt)
+{
+ if (!d || !d->priv)
+ return;
+
+ d->priv->data_type = dt;
+}
+
+ExifDataType
+exif_data_get_data_type (ExifData *d)
+{
+ return (d && d->priv) ? d->priv->data_type : EXIF_DATA_TYPE_UNKNOWN;
+}
diff --git a/libexif/exif-data.h b/libexif/exif-data.h
new file mode 100644
index 0000000..eeee782
--- /dev/null
+++ b/libexif/exif-data.h
@@ -0,0 +1,265 @@
+/*! \file exif-data.h
+ * \brief Defines the ExifData type and the associated functions.
+ */
+/*
+ * \author Lutz Mueller <lutz@users.sourceforge.net>
+ * \date 2001-2005
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __EXIF_DATA_H__
+#define __EXIF_DATA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-data-type.h>
+#include <libexif/exif-ifd.h>
+#include <libexif/exif-log.h>
+#include <libexif/exif-tag.h>
+
+/*! Represents the entire EXIF data found in an image */
+typedef struct _ExifData ExifData;
+typedef struct _ExifDataPrivate ExifDataPrivate;
+
+#include <libexif/exif-content.h>
+#include <libexif/exif-mnote-data.h>
+#include <libexif/exif-mem.h>
+
+/*! Represents the entire EXIF data found in an image */
+struct _ExifData
+{
+ /*! Data for each IFD */
+ ExifContent *ifd[EXIF_IFD_COUNT];
+
+ /*! Pointer to thumbnail image, or NULL if not available */
+ unsigned char *data;
+
+ /*! Number of bytes in thumbnail image at \c data */
+ unsigned int size;
+
+ ExifDataPrivate *priv;
+};
+
+/*! Allocate a new #ExifData. The #ExifData contains an empty
+ * #ExifContent for each IFD and the default set of options,
+ * which has #EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS
+ * and #EXIF_DATA_OPTION_FOLLOW_SPECIFICATION set.
+ *
+ * \return allocated #ExifData, or NULL on error
+ */
+ExifData *exif_data_new (void);
+
+/*! Allocate a new #ExifData using the given memory allocator.
+ * The #ExifData contains an empty #ExifContent for each IFD and the default
+ * set of options, which has #EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS and
+ * #EXIF_DATA_OPTION_FOLLOW_SPECIFICATION set.
+ *
+ * \return allocated #ExifData, or NULL on error
+ */
+ExifData *exif_data_new_mem (ExifMem *);
+
+/*! Allocate a new #ExifData and load EXIF data from a JPEG file.
+ * Uses an #ExifLoader internally to do the loading.
+ *
+ * \param[in] path filename including path
+ * \return allocated #ExifData, or NULL on error
+ */
+ExifData *exif_data_new_from_file (const char *path);
+
+/*! Allocate a new #ExifData and load EXIF data from a memory buffer.
+ *
+ * \param[in] data pointer to raw JPEG or EXIF data
+ * \param[in] size number of bytes of data at data
+ * \return allocated #ExifData, or NULL on error
+ */
+ExifData *exif_data_new_from_data (const unsigned char *data,
+ unsigned int size);
+
+/*! Load the #ExifData structure from the raw JPEG or EXIF data in the given
+ * memory buffer. If the EXIF data contains a recognized MakerNote, it is
+ * loaded and stored as well for later retrieval by #exif_data_get_mnote_data.
+ * If the #EXIF_DATA_OPTION_FOLLOW_SPECIFICATION option has been set on this
+ * #ExifData, then the tags are automatically fixed after loading (by calling
+ * #exif_data_fix).
+ *
+ * \param[in,out] data EXIF data
+ * \param[in] d pointer to raw JPEG or EXIF data
+ * \param[in] size number of bytes of data at d
+ */
+void exif_data_load_data (ExifData *data, const unsigned char *d,
+ unsigned int size);
+
+/*! Store raw EXIF data representing the #ExifData structure into a memory
+ * buffer. The buffer is allocated by this function and must subsequently be
+ * freed by the caller using the matching free function as used by the #ExifMem
+ * in use by this #ExifData.
+ *
+ * \param[in] data EXIF data
+ * \param[out] d pointer to buffer pointer containing raw EXIF data on return
+ * \param[out] ds pointer to variable to hold the number of bytes of
+ * data at d, or set to 0 on error
+ */
+void exif_data_save_data (ExifData *data, unsigned char **d,
+ unsigned int *ds);
+
+void exif_data_ref (ExifData *data);
+void exif_data_unref (ExifData *data);
+void exif_data_free (ExifData *data);
+
+/*! Return the byte order in use by this EXIF structure.
+ *
+ * \param[in] data EXIF data
+ * \return byte order
+ */
+ExifByteOrder exif_data_get_byte_order (ExifData *data);
+
+/*! Set the byte order to use for this EXIF data. If any tags already exist
+ * (including MakerNote tags) they are are converted to the specified byte
+ * order.
+ *
+ * \param[in,out] data EXIF data
+ * \param[in] order byte order
+ */
+void exif_data_set_byte_order (ExifData *data, ExifByteOrder order);
+
+/*! Return the MakerNote data out of the EXIF data. Only certain
+ * MakerNote formats that are recognized by libexif are supported.
+ * The pointer references a member of the #ExifData structure and must NOT be
+ * freed by the caller.
+ *
+ * \param[in] d EXIF data
+ * \return MakerNote data, or NULL if not found or not supported
+ */
+ExifMnoteData *exif_data_get_mnote_data (ExifData *d);
+
+/*! Fix the EXIF data to bring it into specification. Call #exif_content_fix
+ * on each IFD to fix existing entries, create any new entries that are
+ * mandatory but do not yet exist, and remove any entries that are not
+ * allowed.
+ *
+ * \param[in,out] d EXIF data
+ */
+void exif_data_fix (ExifData *d);
+
+typedef void (* ExifDataForeachContentFunc) (ExifContent *, void *user_data);
+
+/*! Execute a function on each IFD in turn.
+ *
+ * \param[in] data EXIF data over which to iterate
+ * \param[in] func function to call for each entry
+ * \param[in] user_data data to pass into func on each call
+ */
+void exif_data_foreach_content (ExifData *data,
+ ExifDataForeachContentFunc func,
+ void *user_data);
+
+/*! Options to configure the behaviour of #ExifData */
+typedef enum {
+ /*! Act as though unknown tags are not present */
+ EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS = 1 << 0,
+
+ /*! Fix the EXIF tags to follow the spec */
+ EXIF_DATA_OPTION_FOLLOW_SPECIFICATION = 1 << 1,
+
+ /*! Leave the MakerNote alone, which could cause it to be corrupted */
+ EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE = 1 << 2
+} ExifDataOption;
+
+/*! Return a short textual description of the given #ExifDataOption.
+ *
+ * \param[in] o option
+ * \return localized textual description of the option
+ */
+const char *exif_data_option_get_name (ExifDataOption o);
+
+/*! Return a verbose textual description of the given #ExifDataOption.
+ *
+ * \param[in] o option
+ * \return verbose localized textual description of the option
+ */
+const char *exif_data_option_get_description (ExifDataOption o);
+
+/*! Set the given option on the given #ExifData.
+ *
+ * \param[in] d EXIF data
+ * \param[in] o option
+ */
+void exif_data_set_option (ExifData *d, ExifDataOption o);
+
+/*! Clear the given option on the given #ExifData.
+ *
+ * \param[in] d EXIF data
+ * \param[in] o option
+ */
+void exif_data_unset_option (ExifData *d, ExifDataOption o);
+
+/*! Set the data type for the given #ExifData.
+ *
+ * \param[in] d EXIF data
+ * \param[in] dt data type
+ */
+void exif_data_set_data_type (ExifData *d, ExifDataType dt);
+
+/*! Return the data type for the given #ExifData.
+ *
+ * \param[in] d EXIF data
+ * \return data type, or #EXIF_DATA_TYPE_UNKNOWN on error
+ */
+ExifDataType exif_data_get_data_type (ExifData *d);
+
+/*! Dump all EXIF data to stdout.
+ * This is intended for diagnostic purposes only.
+ *
+ * \param[in] data EXIF data
+ */
+void exif_data_dump (ExifData *data);
+
+/*! Set the log message object for all IFDs.
+ *
+ * \param[in] data EXIF data
+ * \param[in] log #ExifLog
+ */
+void exif_data_log (ExifData *data, ExifLog *log);
+
+/*! Return an #ExifEntry for the given tag if found in any IFD.
+ * Each IFD is searched in turn and the first containing a tag with
+ * this number is returned.
+ *
+ * \param[in] d #ExifData
+ * \param[in] t #ExifTag
+ * \return #ExifEntry* if found, else NULL if not found
+ */
+#define exif_data_get_entry(d,t) \
+ (exif_content_get_entry(d->ifd[EXIF_IFD_0],t) ? \
+ exif_content_get_entry(d->ifd[EXIF_IFD_0],t) : \
+ exif_content_get_entry(d->ifd[EXIF_IFD_1],t) ? \
+ exif_content_get_entry(d->ifd[EXIF_IFD_1],t) : \
+ exif_content_get_entry(d->ifd[EXIF_IFD_EXIF],t) ? \
+ exif_content_get_entry(d->ifd[EXIF_IFD_EXIF],t) : \
+ exif_content_get_entry(d->ifd[EXIF_IFD_GPS],t) ? \
+ exif_content_get_entry(d->ifd[EXIF_IFD_GPS],t) : \
+ exif_content_get_entry(d->ifd[EXIF_IFD_INTEROPERABILITY],t) ? \
+ exif_content_get_entry(d->ifd[EXIF_IFD_INTEROPERABILITY],t) : NULL)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_DATA_H__ */
diff --git a/libexif/exif-entry.c b/libexif/exif-entry.c
new file mode 100644
index 0000000..54a90a2
--- /dev/null
+++ b/libexif/exif-entry.c
@@ -0,0 +1,1748 @@
+/* exif-entry.c
+ *
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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 <libexif/exif-entry.h>
+#include <libexif/exif-ifd.h>
+#include <libexif/exif-utils.h>
+#include <libexif/i18n.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+struct _ExifEntryPrivate
+{
+ unsigned int ref_count;
+
+ ExifMem *mem;
+};
+
+/* This function is hidden in exif-data.c */
+ExifLog *exif_data_get_log (ExifData *);
+
+#ifndef NO_VERBOSE_TAG_STRINGS
+static void
+exif_entry_log (ExifEntry *e, ExifLogCode code, const char *format, ...)
+{
+ va_list args;
+ ExifLog *l = NULL;
+
+ if (e && e->parent && e->parent->parent)
+ l = exif_data_get_log (e->parent->parent);
+ va_start (args, format);
+ exif_logv (l, code, "ExifEntry", format, args);
+ va_end (args);
+}
+#else
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define exif_entry_log(...) do { } while (0)
+#elif defined(__GNUC__)
+#define exif_entry_log(x...) do { } while (0)
+#else
+#define exif_entry_log (void)
+#endif
+#endif
+
+static void *
+exif_entry_alloc (ExifEntry *e, unsigned int i)
+{
+ void *d;
+ ExifLog *l = NULL;
+
+ if (!e || !e->priv || !i) return NULL;
+
+ d = exif_mem_alloc (e->priv->mem, i);
+ if (d) return d;
+
+ if (e->parent && e->parent->parent)
+ l = exif_data_get_log (e->parent->parent);
+ EXIF_LOG_NO_MEMORY (l, "ExifEntry", i);
+ return NULL;
+}
+
+static void *
+exif_entry_realloc (ExifEntry *e, void *d_orig, unsigned int i)
+{
+ void *d;
+ ExifLog *l = NULL;
+
+ if (!e || !e->priv) return NULL;
+
+ if (!i) { exif_mem_free (e->priv->mem, d_orig); return NULL; }
+
+ d = exif_mem_realloc (e->priv->mem, d_orig, i);
+ if (d) return d;
+
+ if (e->parent && e->parent->parent)
+ l = exif_data_get_log (e->parent->parent);
+ EXIF_LOG_NO_MEMORY (l, "ExifEntry", i);
+ return NULL;
+}
+
+ExifEntry *
+exif_entry_new (void)
+{
+ ExifMem *mem = exif_mem_new_default ();
+ ExifEntry *e = exif_entry_new_mem (mem);
+
+ exif_mem_unref (mem);
+
+ return e;
+}
+
+ExifEntry *
+exif_entry_new_mem (ExifMem *mem)
+{
+ ExifEntry *e = NULL;
+
+ e = exif_mem_alloc (mem, sizeof (ExifEntry));
+ if (!e) return NULL;
+ e->priv = exif_mem_alloc (mem, sizeof (ExifEntryPrivate));
+ if (!e->priv) { exif_mem_free (mem, e); return NULL; }
+ e->priv->ref_count = 1;
+
+ e->priv->mem = mem;
+ exif_mem_ref (mem);
+
+ return e;
+}
+
+void
+exif_entry_ref (ExifEntry *e)
+{
+ if (!e) return;
+
+ e->priv->ref_count++;
+}
+
+void
+exif_entry_unref (ExifEntry *e)
+{
+ if (!e) return;
+
+ e->priv->ref_count--;
+ if (!e->priv->ref_count)
+ exif_entry_free (e);
+}
+
+void
+exif_entry_free (ExifEntry *e)
+{
+ if (!e) return;
+
+ if (e->priv) {
+ ExifMem *mem = e->priv->mem;
+ if (e->data)
+ exif_mem_free (mem, e->data);
+ exif_mem_free (mem, e->priv);
+ exif_mem_free (mem, e);
+ exif_mem_unref (mem);
+ }
+}
+
+/*! Get a value and convert it to an ExifShort.
+ * \bug Not all types are converted that could be converted and no indication
+ * is made when that occurs
+ */
+static inline ExifShort
+exif_get_short_convert (const unsigned char *buf, ExifFormat format,
+ ExifByteOrder order)
+{
+ switch (format) {
+ case EXIF_FORMAT_LONG:
+ return (ExifShort) exif_get_long (buf, order);
+ case EXIF_FORMAT_SLONG:
+ return (ExifShort) exif_get_slong (buf, order);
+ case EXIF_FORMAT_SHORT:
+ return (ExifShort) exif_get_short (buf, order);
+ case EXIF_FORMAT_SSHORT:
+ return (ExifShort) exif_get_sshort (buf, order);
+ case EXIF_FORMAT_BYTE:
+ case EXIF_FORMAT_SBYTE:
+ return (ExifShort) buf[0];
+ default:
+ /* Unsupported type */
+ return (ExifShort) 0;
+ }
+}
+
+void
+exif_entry_fix (ExifEntry *e)
+{
+ unsigned int i, newsize;
+ unsigned char *newdata;
+ ExifByteOrder o;
+ ExifRational r;
+ ExifSRational sr;
+
+ if (!e || !e->priv) return;
+
+ switch (e->tag) {
+
+ /* These tags all need to be of format SHORT. */
+ case EXIF_TAG_YCBCR_SUB_SAMPLING:
+ case EXIF_TAG_SUBJECT_AREA:
+ case EXIF_TAG_COLOR_SPACE:
+ case EXIF_TAG_PLANAR_CONFIGURATION:
+ case EXIF_TAG_SENSING_METHOD:
+ case EXIF_TAG_ORIENTATION:
+ case EXIF_TAG_YCBCR_POSITIONING:
+ case EXIF_TAG_PHOTOMETRIC_INTERPRETATION:
+ case EXIF_TAG_CUSTOM_RENDERED:
+ case EXIF_TAG_EXPOSURE_MODE:
+ case EXIF_TAG_WHITE_BALANCE:
+ case EXIF_TAG_SCENE_CAPTURE_TYPE:
+ case EXIF_TAG_GAIN_CONTROL:
+ case EXIF_TAG_SATURATION:
+ case EXIF_TAG_CONTRAST:
+ case EXIF_TAG_SHARPNESS:
+ case EXIF_TAG_ISO_SPEED_RATINGS:
+ switch (e->format) {
+ case EXIF_FORMAT_LONG:
+ case EXIF_FORMAT_SLONG:
+ case EXIF_FORMAT_BYTE:
+ case EXIF_FORMAT_SBYTE:
+ case EXIF_FORMAT_SSHORT:
+ if (!e->parent || !e->parent->parent) break;
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ _("Tag '%s' was of format '%s' (which is "
+ "against specification) and has been "
+ "changed to format '%s'."),
+ exif_tag_get_name_in_ifd(e->tag,
+ exif_entry_get_ifd(e)),
+ exif_format_get_name (e->format),
+ exif_format_get_name (EXIF_FORMAT_SHORT));
+
+ o = exif_data_get_byte_order (e->parent->parent);
+ newsize = e->components * exif_format_get_size (EXIF_FORMAT_SHORT);
+ newdata = exif_entry_alloc (e, newsize);
+ if (!newdata) {
+ exif_entry_log (e, EXIF_LOG_CODE_NO_MEMORY,
+ "Could not allocate %lu byte(s).", (unsigned long)newsize);
+ break;
+ }
+
+ for (i = 0; i < e->components; i++)
+ exif_set_short (
+ newdata + i *
+ exif_format_get_size (
+ EXIF_FORMAT_SHORT), o,
+ exif_get_short_convert (
+ e->data + i *
+ exif_format_get_size (e->format),
+ e->format, o));
+
+ exif_mem_free (e->priv->mem, e->data);
+ e->data = newdata;
+ e->size = newsize;
+ e->format = EXIF_FORMAT_SHORT;
+ break;
+ case EXIF_FORMAT_SHORT:
+ /* No conversion necessary */
+ break;
+ default:
+ exif_entry_log (e, EXIF_LOG_CODE_CORRUPT_DATA,
+ _("Tag '%s' is of format '%s' (which is "
+ "against specification) but cannot be changed "
+ "to format '%s'."),
+ exif_tag_get_name_in_ifd(e->tag,
+ exif_entry_get_ifd(e)),
+ exif_format_get_name (e->format),
+ exif_format_get_name (EXIF_FORMAT_SHORT));
+ break;
+ }
+ break;
+
+ /* All these tags need to be of format 'Rational'. */
+ case EXIF_TAG_FNUMBER:
+ case EXIF_TAG_APERTURE_VALUE:
+ case EXIF_TAG_EXPOSURE_TIME:
+ case EXIF_TAG_FOCAL_LENGTH:
+ switch (e->format) {
+ case EXIF_FORMAT_SRATIONAL:
+ if (!e->parent || !e->parent->parent) break;
+ o = exif_data_get_byte_order (e->parent->parent);
+ for (i = 0; i < e->components; i++) {
+ sr = exif_get_srational (e->data + i *
+ exif_format_get_size (
+ EXIF_FORMAT_SRATIONAL), o);
+ r.numerator = (ExifLong) sr.numerator;
+ r.denominator = (ExifLong) sr.denominator;
+ exif_set_rational (e->data + i *
+ exif_format_get_size (
+ EXIF_FORMAT_RATIONAL), o, r);
+ }
+ e->format = EXIF_FORMAT_RATIONAL;
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ _("Tag '%s' was of format '%s' (which is "
+ "against specification) and has been "
+ "changed to format '%s'."),
+ exif_tag_get_name_in_ifd(e->tag,
+ exif_entry_get_ifd(e)),
+ exif_format_get_name (EXIF_FORMAT_SRATIONAL),
+ exif_format_get_name (EXIF_FORMAT_RATIONAL));
+ break;
+ default:
+ break;
+ }
+ break;
+
+ /* All these tags need to be of format 'SRational'. */
+ case EXIF_TAG_EXPOSURE_BIAS_VALUE:
+ case EXIF_TAG_BRIGHTNESS_VALUE:
+ case EXIF_TAG_SHUTTER_SPEED_VALUE:
+ switch (e->format) {
+ case EXIF_FORMAT_RATIONAL:
+ if (!e->parent || !e->parent->parent) break;
+ o = exif_data_get_byte_order (e->parent->parent);
+ for (i = 0; i < e->components; i++) {
+ r = exif_get_rational (e->data + i *
+ exif_format_get_size (
+ EXIF_FORMAT_RATIONAL), o);
+ sr.numerator = (ExifLong) r.numerator;
+ sr.denominator = (ExifLong) r.denominator;
+ exif_set_srational (e->data + i *
+ exif_format_get_size (
+ EXIF_FORMAT_SRATIONAL), o, sr);
+ }
+ e->format = EXIF_FORMAT_SRATIONAL;
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ _("Tag '%s' was of format '%s' (which is "
+ "against specification) and has been "
+ "changed to format '%s'."),
+ exif_tag_get_name_in_ifd(e->tag,
+ exif_entry_get_ifd(e)),
+ exif_format_get_name (EXIF_FORMAT_RATIONAL),
+ exif_format_get_name (EXIF_FORMAT_SRATIONAL));
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case EXIF_TAG_USER_COMMENT:
+
+ /* Format needs to be UNDEFINED. */
+ if (e->format != EXIF_FORMAT_UNDEFINED) {
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ _("Tag 'UserComment' had invalid format '%s'. "
+ "Format has been set to 'undefined'."),
+ exif_format_get_name (e->format));
+ e->format = EXIF_FORMAT_UNDEFINED;
+ }
+
+ /* Some packages like Canon ZoomBrowser EX 4.5 store
+ only one zero byte followed by 7 bytes of rubbish */
+ if ((e->size >= 8) && (e->data[0] == 0)) {
+ memcpy(e->data, "\0\0\0\0\0\0\0\0", 8);
+ }
+
+ /* There need to be at least 8 bytes. */
+ if (e->size < 8) {
+ e->data = exif_entry_realloc (e, e->data, 8 + e->size);
+ if (!e->data) {
+ e->size = 0;
+ e->components = 0;
+ return;
+ }
+
+ /* Assume ASCII */
+ memmove (e->data + 8, e->data, e->size);
+ memcpy (e->data, "ASCII\0\0\0", 8);
+ e->size += 8;
+ e->components += 8;
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ _("Tag 'UserComment' has been expanded to at "
+ "least 8 bytes in order to follow the "
+ "specification."));
+ break;
+ }
+
+ /*
+ * If the first 8 bytes are empty and real data starts
+ * afterwards, let's assume ASCII and claim the 8 first
+ * bytes for the format specifyer.
+ */
+ for (i = 0; (i < e->size) && !e->data[i]; i++);
+ if (!i) for ( ; (i < e->size) && (e->data[i] == ' '); i++);
+ if ((i >= 8) && (i < e->size)) {
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ _("Tag 'UserComment' is not empty but does not "
+ "start with a format identifier. "
+ "This has been fixed."));
+ memcpy (e->data, "ASCII\0\0\0", 8);
+ break;
+ }
+
+ /*
+ * First 8 bytes need to follow the specification. If they don't,
+ * assume ASCII.
+ */
+ if (memcmp (e->data, "ASCII\0\0\0" , 8) &&
+ memcmp (e->data, "UNICODE\0" , 8) &&
+ memcmp (e->data, "JIS\0\0\0\0\0" , 8) &&
+ memcmp (e->data, "\0\0\0\0\0\0\0\0", 8)) {
+ e->data = exif_entry_realloc (e, e->data, 8 + e->size);
+ if (!e->data) {
+ e->size = 0;
+ e->components = 0;
+ break;
+ }
+
+ /* Assume ASCII */
+ memmove (e->data + 8, e->data, e->size);
+ memcpy (e->data, "ASCII\0\0\0", 8);
+ e->size += 8;
+ e->components += 8;
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ _("Tag 'UserComment' did not start with a "
+ "format identifier. This has been fixed."));
+ break;
+ }
+
+ break;
+ default:
+ break;
+ }
+}
+
+/*! Format the value of an ExifEntry for human display in a generic way.
+ * The output is localized. The formatting is independent of the tag number
+ * and is based entirely on the data type.
+ * \pre The ExifEntry is already a member of an ExifData.
+ * \param[in] e EXIF entry
+ * \param[out] val buffer in which to store value
+ * \param[in] maxlen one less than the length of the buffer val
+ */
+static void
+exif_entry_format_value(ExifEntry *e, char *val, size_t maxlen)
+{
+ ExifByte v_byte;
+ ExifShort v_short;
+ ExifSShort v_sshort;
+ ExifLong v_long;
+ ExifRational v_rat;
+ ExifSRational v_srat;
+ ExifSLong v_slong;
+ unsigned int i;
+ size_t len;
+ const ExifByteOrder o = exif_data_get_byte_order (e->parent->parent);
+
+ if (!e->size || !maxlen)
+ return;
+ ++maxlen; /* include the terminating NUL */
+ switch (e->format) {
+ case EXIF_FORMAT_UNDEFINED:
+ snprintf (val, maxlen, _("%i bytes undefined data"), e->size);
+ break;
+ case EXIF_FORMAT_BYTE:
+ case EXIF_FORMAT_SBYTE:
+ v_byte = e->data[0];
+ snprintf (val, maxlen, "0x%02x", v_byte);
+ len = strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_byte = e->data[i];
+ snprintf (val+len, maxlen-len, ", 0x%02x", v_byte);
+ len += strlen (val+len);
+ if (len >= maxlen-1) break;
+ }
+ break;
+ case EXIF_FORMAT_SHORT:
+ v_short = exif_get_short (e->data, o);
+ snprintf (val, maxlen, "%u", v_short);
+ len = strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_short = exif_get_short (e->data +
+ exif_format_get_size (e->format) * i, o);
+ snprintf (val+len, maxlen-len, ", %u", v_short);
+ len += strlen (val+len);
+ if (len >= maxlen-1) break;
+ }
+ break;
+ case EXIF_FORMAT_SSHORT:
+ v_sshort = exif_get_sshort (e->data, o);
+ snprintf (val, maxlen, "%i", v_sshort);
+ len = strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_sshort = exif_get_short (e->data +
+ exif_format_get_size (e->format) *
+ i, o);
+ snprintf (val+len, maxlen-len, ", %i", v_sshort);
+ len += strlen (val+len);
+ if (len >= maxlen-1) break;
+ }
+ break;
+ case EXIF_FORMAT_LONG:
+ v_long = exif_get_long (e->data, o);
+ snprintf (val, maxlen, "%lu", (unsigned long) v_long);
+ len = strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_long = exif_get_long (e->data +
+ exif_format_get_size (e->format) *
+ i, o);
+ snprintf (val+len, maxlen-len, ", %lu", (unsigned long) v_long);
+ len += strlen (val+len);
+ if (len >= maxlen-1) break;
+ }
+ break;
+ case EXIF_FORMAT_SLONG:
+ v_slong = exif_get_slong (e->data, o);
+ snprintf (val, maxlen, "%li", (long) v_slong);
+ len = strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_slong = exif_get_slong (e->data +
+ exif_format_get_size (e->format) * i, o);
+ snprintf (val+len, maxlen-len, ", %li", (long) v_slong);
+ len += strlen (val+len);
+ if (len >= maxlen-1) break;
+ }
+ break;
+ case EXIF_FORMAT_ASCII:
+ strncpy (val, (char *) e->data, MIN (maxlen-1, e->size));
+ val[MIN (maxlen-1, e->size)] = 0;
+ break;
+ case EXIF_FORMAT_RATIONAL:
+ len = 0;
+ for (i = 0; i < e->components; i++) {
+ if (i > 0) {
+ snprintf (val+len, maxlen-len, ", ");
+ len += strlen (val+len);
+ }
+ v_rat = exif_get_rational (
+ e->data + 8 * i, o);
+ if (v_rat.denominator) {
+ /*
+ * Choose the number of significant digits to
+ * display based on the size of the denominator.
+ * It is scaled so that denominators within the
+ * range 13..120 will show 2 decimal points.
+ */
+ int decimals = (int)(log10(v_rat.denominator)-0.08+1.0);
+ snprintf (val+len, maxlen-len, "%2.*f",
+ decimals,
+ (double) v_rat.numerator /
+ (double) v_rat.denominator);
+ } else
+ snprintf (val+len, maxlen-len, "%lu/%lu",
+ (unsigned long) v_rat.numerator,
+ (unsigned long) v_rat.denominator);
+ len += strlen (val+len);
+ if (len >= maxlen-1) break;
+ }
+ break;
+ case EXIF_FORMAT_SRATIONAL:
+ len = 0;
+ for (i = 0; i < e->components; i++) {
+ if (i > 0) {
+ snprintf (val+len, maxlen-len, ", ");
+ len += strlen (val+len);
+ }
+ v_srat = exif_get_srational (
+ e->data + 8 * i, o);
+ if (v_srat.denominator) {
+ int decimals = (int)(log10(fabs(v_srat.denominator))-0.08+1.0);
+ snprintf (val+len, maxlen-len, "%2.*f",
+ decimals,
+ (double) v_srat.numerator /
+ (double) v_srat.denominator);
+ } else
+ snprintf (val+len, maxlen-len, "%li/%li",
+ (long) v_srat.numerator,
+ (long) v_srat.denominator);
+ len += strlen (val+len);
+ if (len >= maxlen-1) break;
+ }
+ break;
+ case EXIF_FORMAT_DOUBLE:
+ case EXIF_FORMAT_FLOAT:
+ default:
+ snprintf (val, maxlen, _("%i bytes unsupported data type"),
+ e->size);
+ break;
+ }
+}
+
+void
+exif_entry_dump (ExifEntry *e, unsigned int indent)
+{
+ char buf[1024];
+ char value[1024];
+ unsigned int i;
+
+ for (i = 0; i < 2 * indent; i++)
+ buf[i] = ' ';
+ buf[i] = '\0';
+
+ if (!e)
+ return;
+
+ printf ("%sTag: 0x%x ('%s')\n", buf, e->tag,
+ exif_tag_get_name_in_ifd (e->tag, exif_entry_get_ifd(e)));
+ printf ("%s Format: %i ('%s')\n", buf, e->format,
+ exif_format_get_name (e->format));
+ printf ("%s Components: %i\n", buf, (int) e->components);
+ printf ("%s Size: %i\n", buf, e->size);
+ printf ("%s Value: %s\n", buf, exif_entry_get_value (e, value, sizeof(value)));
+}
+
+/*! Check if a string consists entirely of a single, repeated character.
+ * Up to first n bytes are checked.
+ *
+ * \param[in] data pointer of string to check
+ * \param[in] ch character to match
+ * \param[in] n maximum number of characters to match
+ *
+ * \return 0 if the string matches or is of zero length, nonzero otherwise
+ */
+static int
+match_repeated_char(const unsigned char *data, unsigned char ch, size_t n)
+{
+ int i;
+ for (i=n; i; --i, ++data) {
+ if (*data == 0) {
+ i = 0; /* all bytes before NUL matched */
+ break;
+ }
+ if (*data != ch)
+ break;
+ }
+ return i;
+}
+
+#define CF(entry,target,v,maxlen) \
+{ \
+ if (entry->format != target) { \
+ exif_entry_log (entry, EXIF_LOG_CODE_CORRUPT_DATA, \
+ _("The tag '%s' contains data of an invalid " \
+ "format ('%s', expected '%s')."), \
+ exif_tag_get_name (entry->tag), \
+ exif_format_get_name (entry->format), \
+ exif_format_get_name (target)); \
+ break; \
+ } \
+}
+
+#define CC(entry,target,v,maxlen) \
+{ \
+ if (entry->components != target) { \
+ exif_entry_log (entry, EXIF_LOG_CODE_CORRUPT_DATA, \
+ _("The tag '%s' contains an invalid number of " \
+ "components (%i, expected %i)."), \
+ exif_tag_get_name (entry->tag), \
+ (int) entry->components, (int) target); \
+ break; \
+ } \
+}
+
+static const struct {
+ ExifTag tag;
+ const char *strings[10];
+} list[] = {
+#ifndef NO_VERBOSE_TAG_DATA
+ { EXIF_TAG_PLANAR_CONFIGURATION,
+ { N_("Chunky format"), N_("Planar format"), NULL}},
+ { EXIF_TAG_SENSING_METHOD,
+ { "", N_("Not defined"), N_("One-chip color area sensor"),
+ N_("Two-chip color area sensor"), N_("Three-chip color area sensor"),
+ N_("Color sequential area sensor"), "", N_("Trilinear sensor"),
+ N_("Color sequential linear sensor"), NULL}},
+ { EXIF_TAG_ORIENTATION,
+ { "", N_("Top-left"), N_("Top-right"), N_("Bottom-right"),
+ N_("Bottom-left"), N_("Left-top"), N_("Right-top"),
+ N_("Right-bottom"), N_("Left-bottom"), NULL}},
+ { EXIF_TAG_YCBCR_POSITIONING,
+ { "", N_("Centered"), N_("Co-sited"), NULL}},
+ { EXIF_TAG_PHOTOMETRIC_INTERPRETATION,
+ { N_("Reversed mono"), N_("Normal mono"), N_("RGB"), N_("Palette"), "",
+ N_("CMYK"), N_("YCbCr"), "", N_("CieLAB"), NULL}},
+ { EXIF_TAG_CUSTOM_RENDERED,
+ { N_("Normal process"), N_("Custom process"), NULL}},
+ { EXIF_TAG_EXPOSURE_MODE,
+ { N_("Auto exposure"), N_("Manual exposure"), N_("Auto bracket"), NULL}},
+ { EXIF_TAG_WHITE_BALANCE,
+ { N_("Auto white balance"), N_("Manual white balance"), NULL}},
+ { EXIF_TAG_SCENE_CAPTURE_TYPE,
+ { N_("Standard"), N_("Landscape"), N_("Portrait"),
+ N_("Night scene"), NULL}},
+ { EXIF_TAG_GAIN_CONTROL,
+ { N_("Normal"), N_("Low gain up"), N_("High gain up"),
+ N_("Low gain down"), N_("High gain down"), NULL}},
+ { EXIF_TAG_SATURATION,
+ { N_("Normal"), N_("Low saturation"), N_("High saturation"), NULL}},
+ { EXIF_TAG_CONTRAST , {N_("Normal"), N_("Soft"), N_("Hard"), NULL}},
+ { EXIF_TAG_SHARPNESS, {N_("Normal"), N_("Soft"), N_("Hard"), NULL}},
+#endif
+ { 0, {NULL}}
+};
+
+static const struct {
+ ExifTag tag;
+ struct {
+ int index;
+ const char *values[4]; /*!< list of progressively shorter string
+ descriptions; the longest one that fits will be
+ selected */
+ } elem[25];
+} list2[] = {
+#ifndef NO_VERBOSE_TAG_DATA
+ { EXIF_TAG_METERING_MODE,
+ { { 0, {N_("Unknown"), NULL}},
+ { 1, {N_("Average"), N_("Avg"), NULL}},
+ { 2, {N_("Center-weighted average"), N_("Center-weight"), NULL}},
+ { 3, {N_("Spot"), NULL}},
+ { 4, {N_("Multi spot"), NULL}},
+ { 5, {N_("Pattern"), NULL}},
+ { 6, {N_("Partial"), NULL}},
+ {255, {N_("Other"), NULL}},
+ { 0, {NULL}}}},
+ { EXIF_TAG_COMPRESSION,
+ { {1, {N_("Uncompressed"), NULL}},
+ {5, {N_("LZW compression"), NULL}},
+ {6, {N_("JPEG compression"), NULL}},
+ {7, {N_("JPEG compression"), NULL}},
+ {8, {N_("Deflate/ZIP compression"), NULL}},
+ {32773, {N_("PackBits compression"), NULL}},
+ {0, {NULL}}}},
+ { EXIF_TAG_LIGHT_SOURCE,
+ { { 0, {N_("Unknown"), NULL}},
+ { 1, {N_("Daylight"), NULL}},
+ { 2, {N_("Fluorescent"), NULL}},
+ { 3, {N_("Tungsten incandescent light"), N_("Tungsten"), NULL}},
+ { 4, {N_("Flash"), NULL}},
+ { 9, {N_("Fine weather"), NULL}},
+ { 10, {N_("Cloudy weather"), N_("Cloudy"), NULL}},
+ { 11, {N_("Shade"), NULL}},
+ { 12, {N_("Daylight fluorescent"), NULL}},
+ { 13, {N_("Day white fluorescent"), NULL}},
+ { 14, {N_("Cool white fluorescent"), NULL}},
+ { 15, {N_("White fluorescent"), NULL}},
+ { 17, {N_("Standard light A"), NULL}},
+ { 18, {N_("Standard light B"), NULL}},
+ { 19, {N_("Standard light C"), NULL}},
+ { 20, {N_("D55"), NULL}},
+ { 21, {N_("D65"), NULL}},
+ { 22, {N_("D75"), NULL}},
+ { 24, {N_("ISO studio tungsten"),NULL}},
+ {255, {N_("Other"), NULL}},
+ { 0, {NULL}}}},
+ { EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT,
+ { {2, {N_("Inch"), N_("in"), NULL}},
+ {3, {N_("Centimeter"), N_("cm"), NULL}},
+ {0, {NULL}}}},
+ { EXIF_TAG_RESOLUTION_UNIT,
+ { {2, {N_("Inch"), N_("in"), NULL}},
+ {3, {N_("Centimeter"), N_("cm"), NULL}},
+ {0, {NULL}}}},
+ { EXIF_TAG_EXPOSURE_PROGRAM,
+ { {0, {N_("Not defined"), NULL}},
+ {1, {N_("Manual"), NULL}},
+ {2, {N_("Normal program"), N_("Normal"), NULL}},
+ {3, {N_("Aperture priority"), N_("Aperture"), NULL}},
+ {4, {N_("Shutter priority"),N_("Shutter"), NULL}},
+ {5, {N_("Creative program (biased toward depth of field)"),
+ N_("Creative"), NULL}},
+ {6, {N_("Creative program (biased toward fast shutter speed)"),
+ N_("Action"), NULL}},
+ {7, {N_("Portrait mode (for closeup photos with the background out "
+ "of focus)"), N_("Portrait"), NULL}},
+ {8, {N_("Landscape mode (for landscape photos with the background "
+ "in focus)"), N_("Landscape"), NULL}},
+ {0, {NULL}}}},
+ { EXIF_TAG_FLASH,
+ { {0x0000, {N_("Flash did not fire"), N_("No flash"), NULL}},
+ {0x0001, {N_("Flash fired"), N_("Flash"), N_("Yes"), NULL}},
+ {0x0005, {N_("Strobe return light not detected"), N_("Without strobe"),
+ NULL}},
+ {0x0007, {N_("Strobe return light detected"), N_("With strobe"), NULL}},
+ {0x0008, {N_("Flash did not fire"), NULL}}, /* Olympus E-330 */
+ {0x0009, {N_("Flash fired, compulsory flash mode"), NULL}},
+ {0x000d, {N_("Flash fired, compulsory flash mode, return light "
+ "not detected"), NULL}},
+ {0x000f, {N_("Flash fired, compulsory flash mode, return light "
+ "detected"), NULL}},
+ {0x0010, {N_("Flash did not fire, compulsory flash mode"), NULL}},
+ {0x0018, {N_("Flash did not fire, auto mode"), NULL}},
+ {0x0019, {N_("Flash fired, auto mode"), NULL}},
+ {0x001d, {N_("Flash fired, auto mode, return light not detected"),
+ NULL}},
+ {0x001f, {N_("Flash fired, auto mode, return light detected"), NULL}},
+ {0x0020, {N_("No flash function"),NULL}},
+ {0x0041, {N_("Flash fired, red-eye reduction mode"), NULL}},
+ {0x0045, {N_("Flash fired, red-eye reduction mode, return light "
+ "not detected"), NULL}},
+ {0x0047, {N_("Flash fired, red-eye reduction mode, return light "
+ "detected"), NULL}},
+ {0x0049, {N_("Flash fired, compulsory flash mode, red-eye reduction "
+ "mode"), NULL}},
+ {0x004d, {N_("Flash fired, compulsory flash mode, red-eye reduction "
+ "mode, return light not detected"), NULL}},
+ {0x004f, {N_("Flash fired, compulsory flash mode, red-eye reduction mode, "
+ "return light detected"), NULL}},
+ {0x0058, {N_("Flash did not fire, auto mode, red-eye reduction mode"), NULL}},
+ {0x0059, {N_("Flash fired, auto mode, red-eye reduction mode"), NULL}},
+ {0x005d, {N_("Flash fired, auto mode, return light not detected, "
+ "red-eye reduction mode"), NULL}},
+ {0x005f, {N_("Flash fired, auto mode, return light detected, "
+ "red-eye reduction mode"), NULL}},
+ {0x0000, {NULL}}}},
+ { EXIF_TAG_SUBJECT_DISTANCE_RANGE,
+ { {0, {N_("Unknown"), N_("?"), NULL}},
+ {1, {N_("Macro"), NULL}},
+ {2, {N_("Close view"), N_("Close"), NULL}},
+ {3, {N_("Distant view"), N_("Distant"), NULL}},
+ {0, {NULL}}}},
+ { EXIF_TAG_COLOR_SPACE,
+ { {1, {N_("sRGB"), NULL}},
+ {2, {N_("Adobe RGB"), NULL}},
+ {0xffff, {N_("Uncalibrated"), NULL}},
+ {0x0000, {NULL}}}},
+#endif
+ {0, { { 0, {NULL}}} }
+};
+
+const char *
+exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
+{
+ unsigned int i, j, k;
+ ExifShort v_short, v_short2, v_short3, v_short4;
+ ExifByte v_byte;
+ ExifRational v_rat;
+ ExifSRational v_srat;
+ char b[64];
+ const char *c;
+ ExifByteOrder o;
+ double d;
+ ExifEntry *entry;
+ static const struct {
+ char label[5];
+ char major, minor;
+ } versions[] = {
+ {"0110", 1, 1},
+ {"0120", 1, 2},
+ {"0200", 2, 0},
+ {"0210", 2, 1},
+ {"0220", 2, 2},
+ {"0221", 2, 21},
+ {"0230", 2, 3},
+ {"" , 0, 0}
+ };
+
+ /* FIXME: This belongs to somewhere else. */
+ /* libexif should use the default system locale.
+ * If an application specifically requires UTF-8, then we
+ * must give the application a way to tell libexif that.
+ *
+ * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ */
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+
+ if (!e || !e->parent || !e->parent->parent || !maxlen)
+ return val;
+
+ /* make sure the returned string is zero terminated */
+ memset (val, 0, maxlen);
+ maxlen--;
+ memset (b, 0, sizeof (b));
+
+ /* We need the byte order */
+ o = exif_data_get_byte_order (e->parent->parent);
+
+ /* Sanity check */
+ if (e->size != e->components * exif_format_get_size (e->format)) {
+ snprintf (val, maxlen, _("Invalid size of entry (%i, "
+ "expected %li x %i)."), e->size, e->components,
+ exif_format_get_size (e->format));
+ return val;
+ }
+
+ switch (e->tag) {
+ case EXIF_TAG_USER_COMMENT:
+
+ /*
+ * The specification says UNDEFINED, but some
+ * manufacturers don't care and use ASCII. If this is the
+ * case here, only refuse to read it if there is no chance
+ * of finding readable data.
+ */
+ if ((e->format != EXIF_FORMAT_ASCII) ||
+ (e->size <= 8) ||
+ ( memcmp (e->data, "ASCII\0\0\0" , 8) &&
+ memcmp (e->data, "UNICODE\0" , 8) &&
+ memcmp (e->data, "JIS\0\0\0\0\0", 8) &&
+ memcmp (e->data, "\0\0\0\0\0\0\0\0", 8)))
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+
+ /*
+ * Note that, according to the specification (V2.1, p 40),
+ * the user comment field does not have to be
+ * NULL terminated.
+ */
+ if ((e->size >= 8) && !memcmp (e->data, "ASCII\0\0\0", 8)) {
+ strncpy (val, (char *) e->data + 8, MIN (e->size - 8, maxlen));
+ break;
+ }
+ if ((e->size >= 8) && !memcmp (e->data, "UNICODE\0", 8)) {
+ strncpy (val, _("Unsupported UNICODE string"), maxlen);
+ /* FIXME: use iconv to convert into the locale encoding.
+ * EXIF 2.2 implies (but does not say) that this encoding is
+ * UCS-2.
+ */
+ break;
+ }
+ if ((e->size >= 8) && !memcmp (e->data, "JIS\0\0\0\0\0", 8)) {
+ strncpy (val, _("Unsupported JIS string"), maxlen);
+ /* FIXME: use iconv to convert into the locale encoding */
+ break;
+ }
+
+ /* Check if there is really some information in the tag. */
+ for (i = 0; (i < e->size) &&
+ (!e->data[i] || (e->data[i] == ' ')); i++);
+ if (i == e->size) break;
+
+ /*
+ * If we reach this point, the tag does not
+ * comply with the standard but seems to contain data.
+ * Print as much as possible.
+ */
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ _("Tag UserComment contains data but is "
+ "against specification."));
+ for (j = 0; (i < e->size) && (j < maxlen); i++, j++) {
+ exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
+ _("Byte at position %i: 0x%02x"), i, e->data[i]);
+ val[j] = isprint (e->data[i]) ? e->data[i] : '.';
+ }
+ break;
+
+ case EXIF_TAG_EXIF_VERSION:
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (e, 4, val, maxlen);
+ strncpy (val, _("Unknown Exif Version"), maxlen);
+ for (i = 0; *versions[i].label; i++) {
+ if (!memcmp (e->data, versions[i].label, 4)) {
+ snprintf (val, maxlen,
+ _("Exif Version %d.%d"),
+ versions[i].major,
+ versions[i].minor);
+ break;
+ }
+ }
+ break;
+ case EXIF_TAG_FLASH_PIX_VERSION:
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (e, 4, val, maxlen);
+ if (!memcmp (e->data, "0100", 4))
+ strncpy (val, _("FlashPix Version 1.0"), maxlen);
+ else if (!memcmp (e->data, "0101", 4))
+ strncpy (val, _("FlashPix Version 1.01"), maxlen);
+ else
+ strncpy (val, _("Unknown FlashPix Version"), maxlen);
+ break;
+ case EXIF_TAG_COPYRIGHT:
+ CF (e, EXIF_FORMAT_ASCII, val, maxlen);
+
+ /*
+ * First part: Photographer.
+ * Some cameras store a string like " " here. Ignore it.
+ * Remember that a corrupted tag might not be NUL-terminated
+ */
+ if (e->size && e->data && match_repeated_char(e->data, ' ', e->size))
+ strncpy (val, (char *) e->data, MIN (maxlen, e->size));
+ else
+ strncpy (val, _("[None]"), maxlen);
+ strncat (val, " ", maxlen - strlen (val));
+ strncat (val, _("(Photographer)"), maxlen - strlen (val));
+
+ /* Second part: Editor. */
+ strncat (val, " - ", maxlen - strlen (val));
+ k = 0;
+ if (e->size && e->data) {
+ const unsigned char *tagdata = memchr(e->data, 0, e->size);
+ if (tagdata++) {
+ int editor_ofs = tagdata - e->data;
+ int remaining = e->size - editor_ofs;
+ if (match_repeated_char(tagdata, ' ', remaining)) {
+ strncat (val, (const char*)tagdata, MIN (maxlen - strlen (val), remaining));
+ ++k;
+ }
+ }
+ }
+ if (!k)
+ strncat (val, _("[None]"), maxlen - strlen (val));
+ strncat (val, " ", maxlen - strlen (val));
+ strncat (val, _("(Editor)"), maxlen - strlen (val));
+
+ break;
+ case EXIF_TAG_FNUMBER:
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ snprintf (val, maxlen, "f/%.01f", d);
+ break;
+ case EXIF_TAG_APERTURE_VALUE:
+ case EXIF_TAG_MAX_APERTURE_VALUE:
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator || (0x80000000 == v_rat.numerator)) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ snprintf (val, maxlen, _("%.02f EV"), d);
+ snprintf (b, sizeof (b), _(" (f/%.01f)"), pow (2, d / 2.));
+ if (maxlen > strlen (val) + strlen (b))
+ strncat (val, b, maxlen - strlen (val));
+ break;
+ case EXIF_TAG_FOCAL_LENGTH:
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+
+ /*
+ * For calculation of the 35mm equivalent,
+ * Minolta cameras need a multiplier that depends on the
+ * camera model.
+ */
+ d = 0.;
+ entry = exif_content_get_entry (
+ e->parent->parent->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
+ if (entry && entry->data &&
+ !strncmp ((char *)entry->data, "Minolta", 7)) {
+ entry = exif_content_get_entry (
+ e->parent->parent->ifd[EXIF_IFD_0],
+ EXIF_TAG_MODEL);
+ if (entry && entry->data) {
+ if (!strncmp ((char *)entry->data, "DiMAGE 7", 8))
+ d = 3.9;
+ else if (!strncmp ((char *)entry->data, "DiMAGE 5", 8))
+ d = 4.9;
+ }
+ }
+ if (d)
+ snprintf (b, sizeof (b), _(" (35 equivalent: %d mm)"),
+ (int) (d * (double) v_rat.numerator /
+ (double) v_rat.denominator));
+
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ snprintf (val, maxlen, "%.1f mm", d);
+ if (maxlen > strlen (val) + strlen (b))
+ strncat (val, b, maxlen - strlen (val));
+ break;
+ case EXIF_TAG_SUBJECT_DISTANCE:
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ snprintf (val, maxlen, "%.1f m", d);
+ break;
+ case EXIF_TAG_EXPOSURE_TIME:
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ if (d < 1)
+ snprintf (val, maxlen, _("1/%i"), (int) (0.5 + 1. / d));
+ else
+ snprintf (val, maxlen, "%i", (int) d);
+ if (maxlen > strlen (val) + strlen (_(" sec.")))
+ strncat (val, _(" sec."), maxlen - strlen (val));
+ break;
+ case EXIF_TAG_SHUTTER_SPEED_VALUE:
+ CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_srat = exif_get_srational (e->data, o);
+ if (!v_srat.denominator) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+ d = (double) v_srat.numerator / (double) v_srat.denominator;
+ snprintf (val, maxlen, _("%.02f EV"), d);
+ d = 1. / pow (2, d);
+ if (d < 1)
+ snprintf (b, sizeof (b), _(" (1/%d sec.)"), (int) (1. / d));
+ else
+ snprintf (b, sizeof (b), _(" (%d sec.)"), (int) d);
+ strncat (val, b, maxlen - strlen (val));
+ break;
+ case EXIF_TAG_BRIGHTNESS_VALUE:
+ CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_srat = exif_get_srational (e->data, o);
+ if (!v_srat.denominator) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+ d = (double) v_srat.numerator / (double) v_srat.denominator;
+ snprintf (val, maxlen, _("%.02f EV"), d);
+ snprintf (b, sizeof (b), _(" (%.02f cd/m^2)"),
+ 1. / (M_PI * 0.3048 * 0.3048) * pow (2, d));
+ if (maxlen > strlen (val) + strlen (b))
+ strncat (val, b, maxlen - strlen (val));
+ break;
+ case EXIF_TAG_FILE_SOURCE:
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_byte = e->data[0];
+ if (v_byte == 3)
+ strncpy (val, _("DSC"), maxlen);
+ else
+ snprintf (val, maxlen, _("Internal error (unknown "
+ "value %i)"), v_byte);
+ break;
+ case EXIF_TAG_COMPONENTS_CONFIGURATION:
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (e, 4, val, maxlen);
+ for (i = 0; i < 4; i++) {
+ switch (e->data[i]) {
+ case 0: c = _("-"); break;
+ case 1: c = _("Y"); break;
+ case 2: c = _("Cb"); break;
+ case 3: c = _("Cr"); break;
+ case 4: c = _("R"); break;
+ case 5: c = _("G"); break;
+ case 6: c = _("B"); break;
+ default: c = _("Reserved"); break;
+ }
+ strncat (val, c, maxlen - strlen (val));
+ if (i < 3)
+ strncat (val, " ", maxlen - strlen (val));
+ }
+ break;
+ case EXIF_TAG_EXPOSURE_BIAS_VALUE:
+ CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_srat = exif_get_srational (e->data, o);
+ if (!v_srat.denominator) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+ d = (double) v_srat.numerator / (double) v_srat.denominator;
+ snprintf (val, maxlen, _("%.02f EV"), d);
+ break;
+ case EXIF_TAG_SCENE_TYPE:
+ CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_byte = e->data[0];
+ if (v_byte == 1)
+ strncpy (val, _("Directly photographed"), maxlen);
+ else
+ snprintf (val, maxlen, _("Internal error (unknown "
+ "value %i)"), v_byte);
+ break;
+ case EXIF_TAG_YCBCR_SUB_SAMPLING:
+ CF (e, EXIF_FORMAT_SHORT, val, maxlen);
+ CC (e, 2, val, maxlen);
+ v_short = exif_get_short (e->data, o);
+ v_short2 = exif_get_short (
+ e->data + exif_format_get_size (e->format),
+ o);
+ if ((v_short == 2) && (v_short2 == 1))
+ strncpy (val, _("YCbCr4:2:2"), maxlen);
+ else if ((v_short == 2) && (v_short2 == 2))
+ strncpy (val, _("YCbCr4:2:0"), maxlen);
+ else
+ snprintf (val, maxlen, "%u, %u", v_short, v_short2);
+ break;
+ case EXIF_TAG_SUBJECT_AREA:
+ CF (e, EXIF_FORMAT_SHORT, val, maxlen);
+ switch (e->components) {
+ case 2:
+ v_short = exif_get_short (e->data, o);
+ v_short2 = exif_get_short (e->data + 2, o);
+ snprintf (val, maxlen, "(x,y) = (%i,%i)",
+ v_short, v_short2);
+ break;
+ case 3:
+ v_short = exif_get_short (e->data, o);
+ v_short2 = exif_get_short (e->data + 2, o);
+ v_short3 = exif_get_short (e->data + 4, o);
+ snprintf (val, maxlen, _("Within distance %i of "
+ "(x,y) = (%i,%i)"), v_short3, v_short,
+ v_short2);
+ break;
+ case 4:
+ v_short = exif_get_short (e->data, o);
+ v_short2 = exif_get_short (e->data + 2, o);
+ v_short3 = exif_get_short (e->data + 4, o);
+ v_short4 = exif_get_short (e->data + 6, o);
+ snprintf (val, maxlen, _("Within rectangle "
+ "(width %i, height %i) around "
+ "(x,y) = (%i,%i)"), v_short3, v_short4,
+ v_short, v_short2);
+ break;
+ default:
+ snprintf (val, maxlen, _("Unexpected number "
+ "of components (%li, expected 2, 3, or 4)."),
+ e->components);
+ }
+ break;
+ case EXIF_TAG_GPS_VERSION_ID:
+ /* This is only valid in the GPS IFD */
+ CF (e, EXIF_FORMAT_BYTE, val, maxlen);
+ CC (e, 4, val, maxlen);
+ v_byte = e->data[0];
+ snprintf (val, maxlen, "%u", v_byte);
+ maxlen -= strlen (val);
+ for (i = 1; i < e->components; i++) {
+ v_byte = e->data[i];
+ snprintf (b, sizeof (b), ".%u", v_byte);
+ strncat (val, b, maxlen);
+ maxlen -= strlen (b);
+ if ((signed)maxlen <= 0) break;
+ }
+ break;
+ case EXIF_TAG_INTEROPERABILITY_VERSION:
+ /* a.k.a. case EXIF_TAG_GPS_LATITUDE: */
+ /* This tag occurs in EXIF_IFD_INTEROPERABILITY */
+ if (e->format == EXIF_FORMAT_UNDEFINED) {
+ strncpy (val, (char *) e->data, MIN (maxlen, e->size));
+ break;
+ }
+ /* EXIF_TAG_GPS_LATITUDE is the same numerically as
+ * EXIF_TAG_INTEROPERABILITY_VERSION but in EXIF_IFD_GPS
+ */
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ case EXIF_TAG_GPS_ALTITUDE_REF:
+ /* This is only valid in the GPS IFD */
+ CF (e, EXIF_FORMAT_BYTE, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_byte = e->data[0];
+ if (v_byte == 0)
+ strncpy (val, _("Sea level"), maxlen);
+ else if (v_byte == 1)
+ strncpy (val, _("Sea level reference"), maxlen);
+ else
+ snprintf (val, maxlen, _("Internal error (unknown "
+ "value %i)"), v_byte);
+ break;
+ case EXIF_TAG_GPS_TIME_STAMP:
+ /* This is only valid in the GPS IFD */
+ CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
+ CC (e, 3, val, maxlen);
+
+ v_rat = exif_get_rational (e->data, o);
+ if (!v_rat.denominator) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+ i = v_rat.numerator / v_rat.denominator;
+
+ v_rat = exif_get_rational (e->data +
+ exif_format_get_size (e->format),
+ o);
+ if (!v_rat.denominator) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+ j = v_rat.numerator / v_rat.denominator;
+
+ v_rat = exif_get_rational (e->data +
+ 2*exif_format_get_size (e->format),
+ o);
+ if (!v_rat.denominator) {
+ exif_entry_format_value(e, val, maxlen);
+ break;
+ }
+ d = (double) v_rat.numerator / (double) v_rat.denominator;
+ snprintf (val, maxlen, "%02u:%02u:%05.2f", i, j, d);
+ break;
+
+ case EXIF_TAG_METERING_MODE:
+ case EXIF_TAG_COMPRESSION:
+ case EXIF_TAG_LIGHT_SOURCE:
+ case EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT:
+ case EXIF_TAG_RESOLUTION_UNIT:
+ case EXIF_TAG_EXPOSURE_PROGRAM:
+ case EXIF_TAG_FLASH:
+ case EXIF_TAG_SUBJECT_DISTANCE_RANGE:
+ case EXIF_TAG_COLOR_SPACE:
+ CF (e,EXIF_FORMAT_SHORT, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_short = exif_get_short (e->data, o);
+
+ /* Search the tag */
+ for (i = 0; list2[i].tag && (list2[i].tag != e->tag); i++);
+ if (!list2[i].tag) {
+ snprintf (val, maxlen, _("Internal error (unknown "
+ "value %i)"), v_short);
+ break;
+ }
+
+ /* Find the value */
+ for (j = 0; list2[i].elem[j].values[0] &&
+ (list2[i].elem[j].index < v_short); j++);
+ if (list2[i].elem[j].index != v_short) {
+ snprintf (val, maxlen, _("Internal error (unknown "
+ "value %i)"), v_short);
+ break;
+ }
+
+ /* Find a short enough value */
+ memset (val, 0, maxlen);
+ for (k = 0; list2[i].elem[j].values[k]; k++) {
+ size_t l = strlen (_(list2[i].elem[j].values[k]));
+ if ((maxlen > l) && (strlen (val) < l))
+ strncpy (val, _(list2[i].elem[j].values[k]), maxlen);
+ }
+ if (!val[0]) snprintf (val, maxlen, "%i", v_short);
+
+ break;
+
+ case EXIF_TAG_PLANAR_CONFIGURATION:
+ case EXIF_TAG_SENSING_METHOD:
+ case EXIF_TAG_ORIENTATION:
+ case EXIF_TAG_YCBCR_POSITIONING:
+ case EXIF_TAG_PHOTOMETRIC_INTERPRETATION:
+ case EXIF_TAG_CUSTOM_RENDERED:
+ case EXIF_TAG_EXPOSURE_MODE:
+ case EXIF_TAG_WHITE_BALANCE:
+ case EXIF_TAG_SCENE_CAPTURE_TYPE:
+ case EXIF_TAG_GAIN_CONTROL:
+ case EXIF_TAG_SATURATION:
+ case EXIF_TAG_CONTRAST:
+ case EXIF_TAG_SHARPNESS:
+ CF (e, EXIF_FORMAT_SHORT, val, maxlen);
+ CC (e, 1, val, maxlen);
+ v_short = exif_get_short (e->data, o);
+
+ /* Search the tag */
+ for (i = 0; list[i].tag && (list[i].tag != e->tag); i++);
+ if (!list[i].tag) {
+ snprintf (val, maxlen, _("Internal error (unknown "
+ "value %i)"), v_short);
+ break;
+ }
+
+ /* Find the value */
+ for (j = 0; list[i].strings[j] && (j < v_short); j++);
+ if (!list[i].strings[j])
+ snprintf (val, maxlen, "%i", v_short);
+ else if (!*list[i].strings[j])
+ snprintf (val, maxlen, _("Unknown value %i"), v_short);
+ else
+ strncpy (val, _(list[i].strings[j]), maxlen);
+ break;
+
+ case EXIF_TAG_XP_TITLE:
+ case EXIF_TAG_XP_COMMENT:
+ case EXIF_TAG_XP_AUTHOR:
+ case EXIF_TAG_XP_KEYWORDS:
+ case EXIF_TAG_XP_SUBJECT:
+ {
+ /* Sanity check the size to prevent overflow */
+ if (e->size+sizeof(unsigned short) < e->size) break;
+
+ /* The tag may not be U+0000-terminated , so make a local
+ U+0000-terminated copy before converting it */
+ unsigned short *utf16 = exif_mem_alloc (e->priv->mem, e->size+sizeof(unsigned short));
+ if (!utf16) break;
+ memcpy(utf16, e->data, e->size);
+ utf16[e->size/sizeof(unsigned short)] = 0;
+
+ /* Warning! The texts are converted from UTF16 to UTF8 */
+ /* FIXME: use iconv to convert into the locale encoding */
+ exif_convert_utf16_to_utf8(val, utf16, maxlen);
+ exif_mem_free(e->priv->mem, utf16);
+ break;
+ }
+
+ default:
+ /* Use a generic value formatting */
+ exif_entry_format_value(e, val, maxlen);
+ }
+
+ return val;
+}
+
+
+/*!
+ * \bug Log and report failed exif_mem_malloc() calls.
+ */
+void
+exif_entry_initialize (ExifEntry *e, ExifTag tag)
+{
+ ExifRational r;
+ ExifByteOrder o;
+
+ /* We need the byte order */
+ if (!e || !e->parent || e->data || !e->parent->parent)
+ return;
+ o = exif_data_get_byte_order (e->parent->parent);
+
+ e->tag = tag;
+ switch (tag) {
+
+ /* LONG, 1 component, no default */
+ case EXIF_TAG_PIXEL_X_DIMENSION:
+ case EXIF_TAG_PIXEL_Y_DIMENSION:
+ case EXIF_TAG_EXIF_IFD_POINTER:
+ case EXIF_TAG_GPS_INFO_IFD_POINTER:
+ case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
+ case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
+ e->components = 1;
+ e->format = EXIF_FORMAT_LONG;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ break;
+
+ /* SHORT, 1 component, no default */
+ case EXIF_TAG_SUBJECT_LOCATION:
+ case EXIF_TAG_SENSING_METHOD:
+ case EXIF_TAG_PHOTOMETRIC_INTERPRETATION:
+ case EXIF_TAG_COMPRESSION:
+ case EXIF_TAG_EXPOSURE_MODE:
+ case EXIF_TAG_WHITE_BALANCE:
+ case EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM:
+ case EXIF_TAG_GAIN_CONTROL:
+ case EXIF_TAG_SUBJECT_DISTANCE_RANGE:
+ case EXIF_TAG_FLASH:
+ case EXIF_TAG_ISO_SPEED_RATINGS:
+
+ /* SHORT, 1 component, default 0 */
+ case EXIF_TAG_IMAGE_WIDTH:
+ case EXIF_TAG_IMAGE_LENGTH:
+ case EXIF_TAG_EXPOSURE_PROGRAM:
+ case EXIF_TAG_LIGHT_SOURCE:
+ case EXIF_TAG_METERING_MODE:
+ case EXIF_TAG_CUSTOM_RENDERED:
+ case EXIF_TAG_SCENE_CAPTURE_TYPE:
+ case EXIF_TAG_CONTRAST:
+ case EXIF_TAG_SATURATION:
+ case EXIF_TAG_SHARPNESS:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ exif_set_short (e->data, o, 0);
+ break;
+
+ /* SHORT, 1 component, default 1 */
+ case EXIF_TAG_ORIENTATION:
+ case EXIF_TAG_PLANAR_CONFIGURATION:
+ case EXIF_TAG_YCBCR_POSITIONING:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ exif_set_short (e->data, o, 1);
+ break;
+
+ /* SHORT, 1 component, default 2 */
+ case EXIF_TAG_RESOLUTION_UNIT:
+ case EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ exif_set_short (e->data, o, 2);
+ break;
+
+ /* SHORT, 1 component, default 3 */
+ case EXIF_TAG_SAMPLES_PER_PIXEL:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ exif_set_short (e->data, o, 3);
+ break;
+
+ /* SHORT, 1 component, default 0xffff */
+ case EXIF_TAG_COLOR_SPACE:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ exif_set_short (e->data, o, 0xffff);
+ break;
+
+ /* SHORT, 3 components, default 8 8 8 */
+ case EXIF_TAG_BITS_PER_SAMPLE:
+ e->components = 3;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ exif_set_short (e->data, o, 8);
+ exif_set_short (
+ e->data + exif_format_get_size (e->format),
+ o, 8);
+ exif_set_short (
+ e->data + 2 * exif_format_get_size (e->format),
+ o, 8);
+ break;
+
+ /* SHORT, 2 components, default 2 1 */
+ case EXIF_TAG_YCBCR_SUB_SAMPLING:
+ e->components = 2;
+ e->format = EXIF_FORMAT_SHORT;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ exif_set_short (e->data, o, 2);
+ exif_set_short (
+ e->data + exif_format_get_size (e->format),
+ o, 1);
+ break;
+
+ /* SRATIONAL, 1 component, no default */
+ case EXIF_TAG_EXPOSURE_BIAS_VALUE:
+ case EXIF_TAG_BRIGHTNESS_VALUE:
+ case EXIF_TAG_SHUTTER_SPEED_VALUE:
+ e->components = 1;
+ e->format = EXIF_FORMAT_SRATIONAL;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ break;
+
+ /* RATIONAL, 1 component, no default */
+ case EXIF_TAG_EXPOSURE_TIME:
+ case EXIF_TAG_FOCAL_PLANE_X_RESOLUTION:
+ case EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION:
+ case EXIF_TAG_EXPOSURE_INDEX:
+ case EXIF_TAG_FLASH_ENERGY:
+ case EXIF_TAG_FNUMBER:
+ case EXIF_TAG_FOCAL_LENGTH:
+ case EXIF_TAG_SUBJECT_DISTANCE:
+ case EXIF_TAG_MAX_APERTURE_VALUE:
+ case EXIF_TAG_APERTURE_VALUE:
+ case EXIF_TAG_COMPRESSED_BITS_PER_PIXEL:
+ case EXIF_TAG_PRIMARY_CHROMATICITIES:
+ case EXIF_TAG_DIGITAL_ZOOM_RATIO:
+ e->components = 1;
+ e->format = EXIF_FORMAT_RATIONAL;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ break;
+
+ /* RATIONAL, 1 component, default 72/1 */
+ case EXIF_TAG_X_RESOLUTION:
+ case EXIF_TAG_Y_RESOLUTION:
+ e->components = 1;
+ e->format = EXIF_FORMAT_RATIONAL;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ r.numerator = 72;
+ r.denominator = 1;
+ exif_set_rational (e->data, o, r);
+ break;
+
+ /* RATIONAL, 2 components, no default */
+ case EXIF_TAG_WHITE_POINT:
+ e->components = 2;
+ e->format = EXIF_FORMAT_RATIONAL;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ break;
+
+ /* RATIONAL, 6 components */
+ case EXIF_TAG_REFERENCE_BLACK_WHITE:
+ e->components = 6;
+ e->format = EXIF_FORMAT_RATIONAL;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ r.denominator = 1;
+ r.numerator = 0;
+ exif_set_rational (e->data, o, r);
+ r.numerator = 255;
+ exif_set_rational (
+ e->data + exif_format_get_size (e->format), o, r);
+ r.numerator = 0;
+ exif_set_rational (
+ e->data + 2 * exif_format_get_size (e->format), o, r);
+ r.numerator = 255;
+ exif_set_rational (
+ e->data + 3 * exif_format_get_size (e->format), o, r);
+ r.numerator = 0;
+ exif_set_rational (
+ e->data + 4 * exif_format_get_size (e->format), o, r);
+ r.numerator = 255;
+ exif_set_rational (
+ e->data + 5 * exif_format_get_size (e->format), o, r);
+ break;
+
+ /* ASCII, 20 components */
+ case EXIF_TAG_DATE_TIME:
+ case EXIF_TAG_DATE_TIME_ORIGINAL:
+ case EXIF_TAG_DATE_TIME_DIGITIZED:
+ {
+ time_t t;
+#ifdef HAVE_LOCALTIME_R
+ struct tm tms;
+#endif
+ struct tm *tm;
+
+ t = time (NULL);
+#ifdef HAVE_LOCALTIME_R
+ tm = localtime_r (&t, &tms);
+#else
+ tm = localtime (&t);
+#endif
+ e->components = 20;
+ e->format = EXIF_FORMAT_ASCII;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ snprintf ((char *) e->data, e->size,
+ "%04i:%02i:%02i %02i:%02i:%02i",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ break;
+ }
+
+ /* ASCII, no default */
+ case EXIF_TAG_SUB_SEC_TIME:
+ case EXIF_TAG_SUB_SEC_TIME_ORIGINAL:
+ case EXIF_TAG_SUB_SEC_TIME_DIGITIZED:
+ e->components = 0;
+ e->format = EXIF_FORMAT_ASCII;
+ e->size = 0;
+ e->data = NULL;
+ break;
+
+ /* ASCII, default "[None]" */
+ case EXIF_TAG_IMAGE_DESCRIPTION:
+ case EXIF_TAG_MAKE:
+ case EXIF_TAG_MODEL:
+ case EXIF_TAG_SOFTWARE:
+ case EXIF_TAG_ARTIST:
+ e->components = strlen (_("[None]")) + 1;
+ e->format = EXIF_FORMAT_ASCII;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ strncpy ((char *)e->data, _("[None]"), e->size);
+ break;
+ /* ASCII, default "[None]\0[None]\0" */
+ case EXIF_TAG_COPYRIGHT:
+ e->components = (strlen (_("[None]")) + 1) * 2;
+ e->format = EXIF_FORMAT_ASCII;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ strcpy (((char *)e->data) + 0, _("[None]"));
+ strcpy (((char *)e->data) + strlen (_("[None]")) + 1, _("[None]"));
+ break;
+
+ /* UNDEFINED, 1 component, default 1 */
+ case EXIF_TAG_SCENE_TYPE:
+ e->components = 1;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ e->data[0] = 0x01;
+ break;
+
+ /* UNDEFINED, 1 component, default 3 */
+ case EXIF_TAG_FILE_SOURCE:
+ e->components = 1;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ e->data[0] = 0x03;
+ break;
+
+ /* UNDEFINED, 4 components, default 48 49 48 48 */
+ case EXIF_TAG_FLASH_PIX_VERSION:
+ e->components = 4;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ memcpy (e->data, "0100", 4);
+ break;
+
+ /* UNDEFINED, 4 components, default 48 50 49 48 */
+ case EXIF_TAG_EXIF_VERSION:
+ e->components = 4;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ memcpy (e->data, "0210", 4);
+ break;
+
+ /* UNDEFINED, 4 components, default 1 2 3 0 */
+ case EXIF_TAG_COMPONENTS_CONFIGURATION:
+ e->components = 4;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = exif_format_get_size (e->format) * e->components;
+ e->data = exif_entry_alloc (e, e->size);
+ if (!e->data) break;
+ e->data[0] = 1;
+ e->data[1] = 2;
+ e->data[2] = 3;
+ e->data[3] = 0;
+ break;
+
+ /* UNDEFINED, no components, no default */
+ /* Use this if the tag is otherwise unsupported */
+ case EXIF_TAG_MAKER_NOTE:
+ case EXIF_TAG_USER_COMMENT:
+ default:
+ e->components = 0;
+ e->format = EXIF_FORMAT_UNDEFINED;
+ e->size = 0;
+ e->data = NULL;
+ break;
+ }
+}
diff --git a/libexif/exif-entry.h b/libexif/exif-entry.h
new file mode 100644
index 0000000..1dcdc73
--- /dev/null
+++ b/libexif/exif-entry.h
@@ -0,0 +1,185 @@
+/*! \file exif-entry.h
+ * \brief Handling EXIF entries
+ */
+/*
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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_ENTRY_H__
+#define __EXIF_ENTRY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*! Data found in one EXIF tag.
+ * The #exif_entry_get_value function can provide access to the
+ * formatted contents, or the struct members can be used directly to
+ * access the raw contents.
+ */
+typedef struct _ExifEntry ExifEntry;
+typedef struct _ExifEntryPrivate ExifEntryPrivate;
+
+#include <libexif/exif-content.h>
+#include <libexif/exif-format.h>
+#include <libexif/exif-mem.h>
+
+/*! Data found in one EXIF tag */
+struct _ExifEntry {
+ /*! EXIF tag for this entry */
+ ExifTag tag;
+
+ /*! Type of data in this entry */
+ ExifFormat format;
+
+ /*! Number of elements in the array, if this is an array entry.
+ * Contains 1 for non-array data types. */
+ unsigned long components;
+
+ /*! Pointer to the raw EXIF data for this entry. It is allocated
+ * by #exif_entry_initialize and is NULL beforehand. Data contained
+ * here may be manipulated using the functions in exif-utils.h */
+ unsigned char *data;
+
+ /*! Number of bytes in the buffer at \c data. This must be no less
+ * than exif_format_get_size(format)*components */
+ unsigned int size;
+
+ /*! #ExifContent containing this entry.
+ * \see exif_entry_get_ifd */
+ ExifContent *parent;
+
+ /*! Internal data to be used by libexif itself */
+ ExifEntryPrivate *priv;
+};
+
+/* Lifecycle */
+
+/*! Reserve memory for and initialize a new #ExifEntry.
+ * No memory is allocated for the \c data element of the returned #ExifEntry.
+ *
+ * \return new allocated #ExifEntry, or NULL on error
+ *
+ * \see exif_entry_new_mem, exif_entry_unref
+ */
+ExifEntry *exif_entry_new (void);
+
+/*! Reserve memory for and initialize new #ExifEntry using the specified
+ * memory allocator.
+ * No memory is allocated for the \c data element of the returned #ExifEntry.
+ *
+ * \return new allocated #ExifEntry, or NULL on error
+ *
+ * \see exif_entry_new, exif_entry_unref
+ */
+ExifEntry *exif_entry_new_mem (ExifMem *);
+
+/*! Increase reference counter for #ExifEntry.
+ *
+ * \param[in] entry #ExifEntry
+ *
+ * \see exif_entry_unref
+ */
+void exif_entry_ref (ExifEntry *entry);
+
+/*! Decrease reference counter for #ExifEntry.
+ * When the reference count drops to zero, free the entry.
+ *
+ * \param[in] entry #ExifEntry
+ */
+void exif_entry_unref (ExifEntry *entry);
+
+/*! Actually free the #ExifEntry.
+ *
+ * \deprecated Should not be called directly. Use #exif_entry_ref and
+ * #exif_entry_unref instead.
+ *
+ * \param[in] entry EXIF entry
+ */
+void exif_entry_free (ExifEntry *entry);
+
+/*! Initialize an empty #ExifEntry with default data in the correct format
+ * for the given tag. If the entry is already initialized, this function
+ * does nothing.
+ * This call allocates memory for the \c data element of the given #ExifEntry.
+ * That memory is freed at the same time as the #ExifEntry.
+ *
+ * \param[out] e entry to initialize
+ * \param[in] tag tag number to initialize as
+ */
+void exif_entry_initialize (ExifEntry *e, ExifTag tag);
+
+/*! Fix the type or format of the given EXIF entry to bring it into spec.
+ * If the data for this EXIF tag is in of the wrong type or is in an invalid
+ * format according to the EXIF specification, then it is converted to make it
+ * valid. This may involve, for example, converting an EXIF_FORMAT_LONG into a
+ * EXIF_FORMAT_SHORT. If the tag is unknown, its value is untouched.
+ *
+ * \note Unfortunately, some conversions are to a type with a more restricted
+ * range, which could have the side effect that the converted data becomes
+ * invalid. This is unlikely as the range of each tag in the standard is
+ * designed to encompass all likely data.
+ *
+ * \param[in,out] entry EXIF entry
+ */
+void exif_entry_fix (ExifEntry *entry);
+
+
+/* For your convenience */
+
+/*! Return a localized textual representation of the value of the EXIF entry.
+ * This is meant for display to the user. The format of each tag is subject
+ * to change between locales and in newer versions of libexif. Users who
+ * require the tag data in an unambiguous form should access the data members
+ * of the #ExifEntry structure directly.
+ *
+ * \warning The character set of the returned string may be in
+ * the encoding of the current locale or the native encoding
+ * of the camera.
+ * \bug The EXIF_TAG_XP_* tags are currently always returned in UTF-8,
+ * regardless of locale, and code points above U+FFFF are not
+ * supported.
+ *
+ * \param[in] entry EXIF entry
+ * \param[out] val buffer in which to store value
+ * \param[in] maxlen length of the buffer val
+ * \return val pointer
+ */
+const char *exif_entry_get_value (ExifEntry *entry, char *val,
+ unsigned int maxlen);
+
+/*! Dump text representation of #ExifEntry to stdout.
+ * This is intended for diagnostic purposes only.
+ *
+ * \param[in] entry EXIF tag data
+ * \param[in] indent how many levels deep to indent the data
+ */
+void exif_entry_dump (ExifEntry *entry, unsigned int indent);
+
+/*! Return the IFD number of the given #ExifEntry
+ *
+ * \param[in] e an #ExifEntry*
+ * \return #ExifIfd, or #EXIF_IFD_COUNT on error
+ */
+#define exif_entry_get_ifd(e) ((e)?exif_content_get_ifd((e)->parent):EXIF_IFD_COUNT)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_ENTRY_H__ */
diff --git a/libexif/exif-format.c b/libexif/exif-format.c
new file mode 100644
index 0000000..2c63c33
--- /dev/null
+++ b/libexif/exif-format.c
@@ -0,0 +1,81 @@
+/* exif-format.c
+ *
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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 <libexif/exif-format.h>
+#include <libexif/i18n.h>
+
+#include <stdlib.h>
+
+/*! Table of data format types, descriptions and sizes.
+ * This table should be sorted in decreasing order of popularity in order
+ * to decrease the total average lookup time.
+ */
+static const struct {
+ ExifFormat format;
+ const char *name;
+ unsigned char size;
+} ExifFormatTable[] = {
+ {EXIF_FORMAT_SHORT, N_("Short"), 2},
+ {EXIF_FORMAT_RATIONAL, N_("Rational"), 8},
+ {EXIF_FORMAT_SRATIONAL, N_("SRational"), 8},
+ {EXIF_FORMAT_UNDEFINED, N_("Undefined"), 1},
+ {EXIF_FORMAT_ASCII, N_("ASCII"), 1},
+ {EXIF_FORMAT_LONG, N_("Long"), 4},
+ {EXIF_FORMAT_BYTE, N_("Byte"), 1},
+ {EXIF_FORMAT_SBYTE, N_("SByte"), 1},
+ {EXIF_FORMAT_SSHORT, N_("SShort"), 2},
+ {EXIF_FORMAT_SLONG, N_("SLong"), 4},
+ {EXIF_FORMAT_FLOAT, N_("Float"), 4},
+ {EXIF_FORMAT_DOUBLE, N_("Double"), 8},
+ {0, NULL, 0}
+};
+
+const char *
+exif_format_get_name (ExifFormat format)
+{
+ unsigned int i;
+
+ /* FIXME: This belongs to somewhere else. */
+ /* libexif should use the default system locale.
+ * If an application specifically requires UTF-8, then we
+ * must give the application a way to tell libexif that.
+ *
+ * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ */
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+
+ for (i = 0; ExifFormatTable[i].name; i++)
+ if (ExifFormatTable[i].format == format)
+ return _(ExifFormatTable[i].name);
+ return NULL;
+}
+
+unsigned char
+exif_format_get_size (ExifFormat format)
+{
+ unsigned int i;
+
+ for (i = 0; ExifFormatTable[i].size; i++)
+ if (ExifFormatTable[i].format == format)
+ return ExifFormatTable[i].size;
+ return 0;
+}
diff --git a/libexif/exif-format.h b/libexif/exif-format.h
new file mode 100644
index 0000000..b7a79a4
--- /dev/null
+++ b/libexif/exif-format.h
@@ -0,0 +1,65 @@
+/*! \file exif-format.h
+ * \brief Handling native EXIF data types
+ */
+/*
+ *
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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_FORMAT_H__
+#define __EXIF_FORMAT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*! EXIF tag data formats */
+typedef enum {
+ EXIF_FORMAT_BYTE = 1,
+ EXIF_FORMAT_ASCII = 2,
+ EXIF_FORMAT_SHORT = 3,
+ EXIF_FORMAT_LONG = 4,
+ EXIF_FORMAT_RATIONAL = 5,
+ EXIF_FORMAT_SBYTE = 6,
+ EXIF_FORMAT_UNDEFINED = 7,
+ EXIF_FORMAT_SSHORT = 8,
+ EXIF_FORMAT_SLONG = 9,
+ EXIF_FORMAT_SRATIONAL = 10,
+ EXIF_FORMAT_FLOAT = 11,
+ EXIF_FORMAT_DOUBLE = 12
+} ExifFormat;
+
+/*! Return a textual representation of the given EXIF data type.
+ *
+ * \param[in] format EXIF data format
+ * \return localized textual name
+ */
+const char *exif_format_get_name (ExifFormat format);
+
+/*! Return the raw size of the given EXIF data type.
+ *
+ * \param[in] format EXIF data format
+ * \return size in bytes
+ */
+unsigned char exif_format_get_size (ExifFormat format);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_FORMAT_H__ */
diff --git a/libexif/exif-ifd.c b/libexif/exif-ifd.c
new file mode 100644
index 0000000..f0f8816
--- /dev/null
+++ b/libexif/exif-ifd.c
@@ -0,0 +1,49 @@
+/* exif-ifd.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.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-ifd.h>
+
+#include <stdlib.h>
+
+static const struct {
+ ExifIfd ifd;
+ const char *name;
+} ExifIfdTable[] = {
+ {EXIF_IFD_0, "0"},
+ {EXIF_IFD_1, "1"},
+ {EXIF_IFD_EXIF, "EXIF"},
+ {EXIF_IFD_GPS, "GPS"},
+ {EXIF_IFD_INTEROPERABILITY, "Interoperability"},
+ {0, NULL}
+};
+
+const char *
+exif_ifd_get_name (ExifIfd ifd)
+{
+ unsigned int i;
+
+ for (i = 0; ExifIfdTable[i].name; i++)
+ if (ExifIfdTable[i].ifd == ifd)
+ break;
+
+ return (ExifIfdTable[i].name);
+}
diff --git a/libexif/exif-ifd.h b/libexif/exif-ifd.h
new file mode 100644
index 0000000..26c4053
--- /dev/null
+++ b/libexif/exif-ifd.h
@@ -0,0 +1,43 @@
+/* exif-ifd.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.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __EXIF_IFD_H__
+#define __EXIF_IFD_H__
+
+/*! Possible EXIF Image File Directories */
+typedef enum {
+ EXIF_IFD_0 = 0, /*!< */
+ EXIF_IFD_1, /*!< */
+ EXIF_IFD_EXIF, /*!< */
+ EXIF_IFD_GPS, /*!< */
+ EXIF_IFD_INTEROPERABILITY, /*!< */
+ EXIF_IFD_COUNT /*!< Not a real value, just (max_value + 1). */
+} ExifIfd;
+
+/*! Return a textual name of the given IFD. The name is a short, unique,
+ * non-localized text string containing only US-ASCII alphanumeric
+ * characters.
+ *
+ * \param[in] ifd IFD
+ * \return textual name of the IFD
+ */
+const char *exif_ifd_get_name (ExifIfd ifd);
+
+#endif /* __EXIF_IFD_H__ */
diff --git a/libexif/exif-loader.c b/libexif/exif-loader.c
new file mode 100644
index 0000000..317b86b
--- /dev/null
+++ b/libexif/exif-loader.c
@@ -0,0 +1,434 @@
+/* exif-loader.c
+ *
+ * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-loader.h>
+#include <libexif/exif-utils.h>
+#include <libexif/i18n.h>
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#undef JPEG_MARKER_DHT
+#define JPEG_MARKER_DHT 0xc4
+#undef JPEG_MARKER_SOI
+#define JPEG_MARKER_SOI 0xd8
+#undef JPEG_MARKER_DQT
+#define JPEG_MARKER_DQT 0xdb
+#undef JPEG_MARKER_APP0
+#define JPEG_MARKER_APP0 0xe0
+#undef JPEG_MARKER_APP1
+#define JPEG_MARKER_APP1 0xe1
+#undef JPEG_MARKER_APP2
+#define JPEG_MARKER_APP2 0xe2
+#undef JPEG_MARKER_APP13
+#define JPEG_MARKER_APP13 0xed
+#undef JPEG_MARKER_COM
+#define JPEG_MARKER_COM 0xfe
+
+typedef enum {
+ EL_READ = 0,
+ EL_READ_SIZE_BYTE_24,
+ EL_READ_SIZE_BYTE_16,
+ EL_READ_SIZE_BYTE_08,
+ EL_READ_SIZE_BYTE_00,
+ EL_SKIP_BYTES,
+ EL_EXIF_FOUND,
+} ExifLoaderState;
+
+typedef enum {
+ EL_DATA_FORMAT_UNKNOWN,
+ EL_DATA_FORMAT_EXIF,
+ EL_DATA_FORMAT_JPEG,
+ EL_DATA_FORMAT_FUJI_RAW
+} ExifLoaderDataFormat;
+
+/*! \internal */
+struct _ExifLoader {
+ ExifLoaderState state;
+ ExifLoaderDataFormat data_format;
+
+ /*! Small buffer used for detection of format */
+ unsigned char b[12];
+
+ /*! Number of bytes in the small buffer \c b */
+ unsigned char b_len;
+
+ unsigned int size;
+ unsigned char *buf;
+ unsigned int bytes_read;
+
+ unsigned int ref_count;
+
+ ExifLog *log;
+ ExifMem *mem;
+};
+
+/*! Magic number for EXIF header */
+static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+
+static void *
+exif_loader_alloc (ExifLoader *l, unsigned int i)
+{
+ void *d;
+
+ if (!l || !i)
+ return NULL;
+
+ d = exif_mem_alloc (l->mem, i);
+ if (d)
+ return d;
+
+ EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i);
+ return NULL;
+}
+
+void
+exif_loader_write_file (ExifLoader *l, const char *path)
+{
+ FILE *f;
+ int size;
+ unsigned char data[1024];
+
+ if (!l)
+ return;
+
+ f = fopen (path, "rb");
+ if (!f) {
+ exif_log (l->log, EXIF_LOG_CODE_NONE, "ExifLoader",
+ _("The file '%s' could not be opened."), path);
+ return;
+ }
+ while (1) {
+ size = fread (data, 1, sizeof (data), f);
+ if (size <= 0)
+ break;
+ if (!exif_loader_write (l, data, size))
+ break;
+ }
+ fclose (f);
+}
+
+static unsigned int
+exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len)
+{
+ if (!eld || (len && !buf) || (eld->bytes_read >= eld->size))
+ return 0;
+
+ /* If needed, allocate the buffer. */
+ if (!eld->buf)
+ eld->buf = exif_loader_alloc (eld, eld->size);
+ if (!eld->buf)
+ return 0;
+
+ /* Copy memory */
+ len = MIN (len, eld->size - eld->bytes_read);
+ memcpy (eld->buf + eld->bytes_read, buf, len);
+ eld->bytes_read += len;
+
+ return (eld->bytes_read >= eld->size) ? 0 : 1;
+}
+
+unsigned char
+exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
+{
+ unsigned int i;
+
+ if (!eld || (len && !buf))
+ return 0;
+
+ switch (eld->state) {
+ case EL_EXIF_FOUND:
+ return exif_loader_copy (eld, buf, len);
+ case EL_SKIP_BYTES:
+ if (eld->size > len) {
+ eld->size -= len;
+ return 1;
+ }
+ len -= eld->size;
+ buf += eld->size;
+ eld->size = 0;
+ eld->b_len = 0;
+ switch (eld->data_format) {
+ case EL_DATA_FORMAT_FUJI_RAW:
+ eld->state = EL_READ_SIZE_BYTE_24;
+ break;
+ default:
+ eld->state = EL_READ;
+ break;
+ }
+ break;
+
+ case EL_READ:
+ default:
+ break;
+ }
+
+ if (!len)
+ return 1;
+ exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
+ "Scanning %i byte(s) of data...", len);
+
+ /*
+ * First fill the small buffer. Only continue if the buffer
+ * is filled. Note that EXIF data contains at least 12 bytes.
+ */
+ i = MIN (len, sizeof (eld->b) - eld->b_len);
+ if (i) {
+ memcpy (&eld->b[eld->b_len], buf, i);
+ eld->b_len += i;
+ if (eld->b_len < sizeof (eld->b))
+ return 1;
+ buf += i;
+ len -= i;
+ }
+
+ switch (eld->data_format) {
+ case EL_DATA_FORMAT_UNKNOWN:
+
+ /* Check the small buffer against known formats. */
+ if (!memcmp (eld->b, "FUJIFILM", 8)) {
+
+ /* Skip to byte 84. There is another offset there. */
+ eld->data_format = EL_DATA_FORMAT_FUJI_RAW;
+ eld->size = 84;
+ eld->state = EL_SKIP_BYTES;
+ eld->size = 84;
+
+ } else if (!memcmp (eld->b + 2, ExifHeader, sizeof (ExifHeader))) {
+
+ /* Read the size (2 bytes). */
+ eld->data_format = EL_DATA_FORMAT_EXIF;
+ eld->state = EL_READ_SIZE_BYTE_08;
+ }
+ default:
+ break;
+ }
+
+ for (i = 0; i < sizeof (eld->b); i++)
+ switch (eld->state) {
+ case EL_EXIF_FOUND:
+ if (!exif_loader_copy (eld, eld->b + i,
+ sizeof (eld->b) - i))
+ return 0;
+ return exif_loader_copy (eld, buf, len);
+ case EL_SKIP_BYTES:
+ eld->size--;
+ if (!eld->size)
+ eld->state = EL_READ;
+ break;
+
+ case EL_READ_SIZE_BYTE_24:
+ eld->size |= eld->b[i] << 24;
+ eld->state = EL_READ_SIZE_BYTE_16;
+ break;
+ case EL_READ_SIZE_BYTE_16:
+ eld->size |= eld->b[i] << 16;
+ eld->state = EL_READ_SIZE_BYTE_08;
+ break;
+ case EL_READ_SIZE_BYTE_08:
+ eld->size |= eld->b[i] << 8;
+ eld->state = EL_READ_SIZE_BYTE_00;
+ break;
+ case EL_READ_SIZE_BYTE_00:
+ eld->size |= eld->b[i] << 0;
+ switch (eld->data_format) {
+ case EL_DATA_FORMAT_JPEG:
+ eld->state = EL_SKIP_BYTES;
+ eld->size -= 2;
+ break;
+ case EL_DATA_FORMAT_FUJI_RAW:
+ eld->data_format = EL_DATA_FORMAT_EXIF;
+ eld->state = EL_SKIP_BYTES;
+ eld->size -= 86;
+ break;
+ case EL_DATA_FORMAT_EXIF:
+ eld->state = EL_EXIF_FOUND;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ switch (eld->b[i]) {
+ case JPEG_MARKER_APP1:
+ if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) {
+ eld->data_format = EL_DATA_FORMAT_EXIF;
+ } else {
+ eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/
+ }
+ eld->size = 0;
+ eld->state = EL_READ_SIZE_BYTE_08;
+ break;
+ case JPEG_MARKER_DHT:
+ case JPEG_MARKER_DQT:
+ case JPEG_MARKER_APP0:
+ case JPEG_MARKER_APP2:
+ case JPEG_MARKER_APP13:
+ case JPEG_MARKER_COM:
+ eld->data_format = EL_DATA_FORMAT_JPEG;
+ eld->size = 0;
+ eld->state = EL_READ_SIZE_BYTE_08;
+ break;
+ case 0xff:
+ case JPEG_MARKER_SOI:
+ break;
+ default:
+ exif_log (eld->log,
+ EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifLoader", _("The data supplied "
+ "does not seem to contain "
+ "EXIF data."));
+ exif_loader_reset (eld);
+ return 0;
+ }
+ }
+
+ /*
+ * If we reach this point, the buffer has not been big enough
+ * to read all data we need. Fill it with new data.
+ */
+ eld->b_len = 0;
+ return exif_loader_write (eld, buf, len);
+}
+
+ExifLoader *
+exif_loader_new (void)
+{
+ ExifMem *mem = exif_mem_new_default ();
+ ExifLoader *l = exif_loader_new_mem (mem);
+
+ exif_mem_unref (mem);
+
+ return l;
+}
+
+ExifLoader *
+exif_loader_new_mem (ExifMem *mem)
+{
+ ExifLoader *loader;
+
+ if (!mem)
+ return NULL;
+
+ loader = exif_mem_alloc (mem, sizeof (ExifLoader));
+ if (!loader)
+ return NULL;
+ loader->ref_count = 1;
+
+ loader->mem = mem;
+ exif_mem_ref (mem);
+
+ return loader;
+}
+
+void
+exif_loader_ref (ExifLoader *loader)
+{
+ if (loader)
+ loader->ref_count++;
+}
+
+static void
+exif_loader_free (ExifLoader *loader)
+{
+ ExifMem *mem;
+
+ if (!loader)
+ return;
+
+ mem = loader->mem;
+ exif_loader_reset (loader);
+ exif_log_unref (loader->log);
+ exif_mem_free (mem, loader);
+ exif_mem_unref (mem);
+}
+
+void
+exif_loader_unref (ExifLoader *loader)
+{
+ if (!loader)
+ return;
+ if (!--loader->ref_count)
+ exif_loader_free (loader);
+}
+
+void
+exif_loader_reset (ExifLoader *loader)
+{
+ if (!loader)
+ return;
+ exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;
+ loader->size = 0;
+ loader->bytes_read = 0;
+ loader->state = 0;
+ loader->b_len = 0;
+ loader->data_format = EL_DATA_FORMAT_UNKNOWN;
+}
+
+ExifData *
+exif_loader_get_data (ExifLoader *loader)
+{
+ ExifData *ed;
+
+ if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN) ||
+ !loader->bytes_read)
+ return NULL;
+
+ ed = exif_data_new_mem (loader->mem);
+ exif_data_log (ed, loader->log);
+ exif_data_load_data (ed, loader->buf, loader->bytes_read);
+
+ return ed;
+}
+
+void
+exif_loader_get_buf (ExifLoader *loader, const unsigned char **buf,
+ unsigned int *buf_size)
+{
+ const unsigned char* b = NULL;
+ unsigned int s = 0;
+
+ if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN)) {
+ exif_log (loader->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
+ "Loader format unknown");
+ } else {
+ b = loader->buf;
+ s = loader->bytes_read;
+ }
+ if (buf)
+ *buf = b;
+ if (buf_size)
+ *buf_size = s;
+}
+
+void
+exif_loader_log (ExifLoader *loader, ExifLog *log)
+{
+ if (!loader)
+ return;
+ exif_log_unref (loader->log);
+ loader->log = log;
+ exif_log_ref (log);
+}
diff --git a/libexif/exif-loader.h b/libexif/exif-loader.h
new file mode 100644
index 0000000..62ee87c
--- /dev/null
+++ b/libexif/exif-loader.h
@@ -0,0 +1,128 @@
+/*! \file exif-loader.h
+ * \brief Defines the ExifLoader type
+ */
+/*
+ * Copyright (c) 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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_LOADER_H__
+#define __EXIF_LOADER_H__
+
+#include <libexif/exif-data.h>
+#include <libexif/exif-log.h>
+#include <libexif/exif-mem.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*! Data used by the loader interface */
+typedef struct _ExifLoader ExifLoader;
+
+/*! Allocate a new #ExifLoader.
+ *
+ * \return allocated ExifLoader
+ */
+ExifLoader *exif_loader_new (void);
+
+/*! Allocate a new #ExifLoader using the specified memory allocator.
+ *
+ * \param[in] mem the ExifMem
+ * \return allocated ExifLoader
+ */
+ExifLoader *exif_loader_new_mem (ExifMem *mem);
+
+/*! Increase the refcount of the #ExifLoader.
+ *
+ * \param[in] loader the ExifLoader to increase the refcount of.
+ */
+void exif_loader_ref (ExifLoader *loader);
+
+/*! Decrease the refcount of the #ExifLoader.
+ * If the refcount reaches 0, the loader is freed.
+ *
+ * \param[in] loader ExifLoader for which to decrease the refcount
+ */
+void exif_loader_unref (ExifLoader *loader);
+
+/*! Load a file into the given #ExifLoader from the filesystem.
+ * The relevant data is copied in raw form into the #ExifLoader.
+ *
+ * \param[in] loader loader to write to
+ * \param[in] fname path to the file to read
+ */
+void exif_loader_write_file (ExifLoader *loader, const char *fname);
+
+/*! Load a buffer into the #ExifLoader from a memory buffer.
+ * The relevant data is copied in raw form into the #ExifLoader.
+ *
+ * \param[in] loader loader to write to
+ * \param[in] buf buffer to read from
+ * \param[in] sz size of the buffer
+ * \return 1 while EXIF data is read (or while there is still hope that
+ * there will be EXIF data later on), 0 otherwise.
+ */
+unsigned char exif_loader_write (ExifLoader *loader, unsigned char *buf, unsigned int sz);
+
+/*! Free any data previously loaded and reset the #ExifLoader to its
+ * newly-initialized state.
+ *
+ * \param[in] loader the loader
+ */
+void exif_loader_reset (ExifLoader *loader);
+
+/*! Create an #ExifData from the data in the loader. The loader must
+ * already contain data from a previous call to #exif_loader_write_file
+ * or #exif_loader_write.
+ *
+ * \note The #ExifData returned is created using its default options, which
+ * may take effect before the data is returned. If other options are desired,
+ * an #ExifData must be created explicitly and data extracted from the loader
+ * using #exif_loader_get_buf instead.
+ *
+ * \param[in] loader the loader
+ * \return allocated ExifData
+ *
+ * \see exif_loader_get_buf
+ */
+ExifData *exif_loader_get_data (ExifLoader *loader);
+
+/*! Return the raw data read by the loader. The returned pointer is only
+ * guaranteed to be valid until the next call to a function modifying
+ * this #ExifLoader. Either or both of buf and buf_size may be NULL on
+ * entry, in which case that value is not returned.
+ *
+ * \param[in] loader the loader
+ * \param[out] buf read-only pointer to the data read by the loader, or NULL
+ * in case of error
+ * \param[out] buf_size size of the data at buf, or 0 in case of error
+ */
+void exif_loader_get_buf (ExifLoader *loader, const unsigned char **buf,
+ unsigned int *buf_size);
+
+/*! Set the log message object used by this #ExifLoader.
+ * \param[in] loader the loader
+ * \param[in] log #ExifLog
+ */
+void exif_loader_log (ExifLoader *loader, ExifLog *log);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_LOADER_H__ */
diff --git a/libexif/exif-log.c b/libexif/exif-log.c
new file mode 100644
index 0000000..2db18e3
--- /dev/null
+++ b/libexif/exif-log.c
@@ -0,0 +1,152 @@
+/* exif-log.c
+ *
+ * Copyright (c) 2004 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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 <libexif/exif-log.h>
+#include <libexif/i18n.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+struct _ExifLog {
+ unsigned int ref_count;
+
+ ExifLogFunc func;
+ void *data;
+
+ ExifMem *mem;
+};
+
+static const struct {
+ ExifLogCode code;
+ const char *title;
+ const char *message;
+} codes[] = {
+ { EXIF_LOG_CODE_DEBUG, N_("Debugging information"),
+ N_("Debugging information is available.") },
+ { EXIF_LOG_CODE_NO_MEMORY, N_("Not enough memory"),
+ N_("The system cannot provide enough memory.") },
+ { EXIF_LOG_CODE_CORRUPT_DATA, N_("Corrupt data"),
+ N_("The data provided does not follow the specification.") },
+ { 0, NULL, NULL }
+};
+
+const char *
+exif_log_code_get_title (ExifLogCode code)
+{
+ unsigned int i;
+
+ for (i = 0; codes[i].title; i++) if (codes[i].code == code) break;
+ return _(codes[i].title);
+}
+
+const char *
+exif_log_code_get_message (ExifLogCode code)
+{
+ unsigned int i;
+
+ for (i = 0; codes[i].message; i++) if (codes[i].code == code) break;
+ return _(codes[i].message);
+}
+
+ExifLog *
+exif_log_new_mem (ExifMem *mem)
+{
+ ExifLog *log;
+
+ log = exif_mem_alloc (mem, sizeof (ExifLog));
+ if (!log) return NULL;
+ log->ref_count = 1;
+
+ log->mem = mem;
+ exif_mem_ref (mem);
+
+ return log;
+}
+
+ExifLog *
+exif_log_new (void)
+{
+ ExifMem *mem = exif_mem_new_default ();
+ ExifLog *log = exif_log_new_mem (mem);
+
+ exif_mem_unref (mem);
+
+ return log;
+}
+
+void
+exif_log_ref (ExifLog *log)
+{
+ if (!log) return;
+ log->ref_count++;
+}
+
+void
+exif_log_unref (ExifLog *log)
+{
+ if (!log) return;
+ if (log->ref_count > 0) log->ref_count--;
+ if (!log->ref_count) exif_log_free (log);
+}
+
+void
+exif_log_free (ExifLog *log)
+{
+ ExifMem *mem = log ? log->mem : NULL;
+
+ if (!log) return;
+
+ exif_mem_free (mem, log);
+ exif_mem_unref (mem);
+}
+
+void
+exif_log_set_func (ExifLog *log, ExifLogFunc func, void *data)
+{
+ if (!log) return;
+ log->func = func;
+ log->data = data;
+}
+
+#ifdef NO_VERBOSE_TAG_STRINGS
+/* exif_log forms part of the API and can't be commented away */
+#undef exif_log
+#endif
+void
+exif_log (ExifLog *log, ExifLogCode code, const char *domain,
+ const char *format, ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ exif_logv (log, code, domain, format, args);
+ va_end (args);
+}
+
+void
+exif_logv (ExifLog *log, ExifLogCode code, const char *domain,
+ const char *format, va_list args)
+{
+ if (!log) return;
+ if (!log->func) return;
+ log->func (log, code, domain, format, args, log->data);
+}
diff --git a/libexif/exif-log.h b/libexif/exif-log.h
new file mode 100644
index 0000000..9e71ad6
--- /dev/null
+++ b/libexif/exif-log.h
@@ -0,0 +1,116 @@
+/*! \file exif-log.h
+ * \brief Log message infrastructure
+ */
+/*
+ * Copyright (c) 2004 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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_LOG_H__
+#define __EXIF_LOG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-mem.h>
+#include <stdarg.h>
+
+/*! State maintained by the logging interface */
+typedef struct _ExifLog ExifLog;
+
+/*! Create a new logging instance.
+ * \see exif_log_free
+ *
+ * \return new instance of #ExifLog
+ */
+ExifLog *exif_log_new (void);
+ExifLog *exif_log_new_mem (ExifMem *);
+void exif_log_ref (ExifLog *log);
+void exif_log_unref (ExifLog *log);
+
+/*! Delete instance of #ExifLog.
+ * \see exif_log_new
+ *
+ * \param[in] log #ExifLog
+ * \return new instance of #ExifLog
+ */
+void exif_log_free (ExifLog *log);
+
+typedef enum {
+ EXIF_LOG_CODE_NONE,
+ EXIF_LOG_CODE_DEBUG,
+ EXIF_LOG_CODE_NO_MEMORY,
+ EXIF_LOG_CODE_CORRUPT_DATA
+} ExifLogCode;
+
+/*! Return a textual description of the given class of error log.
+ *
+ * \param[in] code logging message class
+ * \return textual description of the log class
+ */
+const char *exif_log_code_get_title (ExifLogCode code);
+
+/*! Return a verbose description of the given class of error log.
+ *
+ * \param[in] code logging message class
+ * \return verbose description of the log class
+ */
+const char *exif_log_code_get_message (ExifLogCode code);
+
+/*! Log callback function prototype.
+ */
+typedef void (* ExifLogFunc) (ExifLog *log, ExifLogCode, const char *domain,
+ const char *format, va_list args, void *data);
+
+/*! Register log callback function.
+ * Calls to the log callback function are purely for diagnostic purposes.
+ *
+ * \param[in] log logging state variable
+ * \param[in] func callback function to set
+ * \param[in] data data to pass into callback function
+ */
+void exif_log_set_func (ExifLog *log, ExifLogFunc func, void *data);
+
+#ifndef NO_VERBOSE_TAG_STRINGS
+void exif_log (ExifLog *log, ExifLogCode, const char *domain,
+ const char *format, ...)
+#ifdef __GNUC__
+ __attribute__((__format__(printf,4,5)))
+#endif
+;
+#else
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define exif_log(...) do { } while (0)
+#elif defined(__GNUC__)
+#define exif_log(x...) do { } while (0)
+#else
+#define exif_log (void)
+#endif
+#endif
+
+void exif_logv (ExifLog *log, ExifLogCode, const char *domain,
+ const char *format, va_list args);
+
+/* For your convenience */
+#define EXIF_LOG_NO_MEMORY(l,d,s) exif_log ((l), EXIF_LOG_CODE_NO_MEMORY, (d), "Could not allocate %lu byte(s).", (unsigned long)(s))
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_LOG_H__ */
diff --git a/libexif/exif-mem.c b/libexif/exif-mem.c
new file mode 100644
index 0000000..b4d7ece
--- /dev/null
+++ b/libexif/exif-mem.c
@@ -0,0 +1,99 @@
+#include <libexif/exif-mem.h>
+
+#include <stdlib.h>
+
+struct _ExifMem {
+ unsigned int ref_count;
+ ExifMemAllocFunc alloc_func;
+ ExifMemReallocFunc realloc_func;
+ ExifMemFreeFunc free_func;
+};
+
+/*! Default memory allocation function. */
+static void *
+exif_mem_alloc_func (ExifLong ds)
+{
+ return calloc ((size_t) ds, 1);
+}
+
+/*! Default memory reallocation function. */
+static void *
+exif_mem_realloc_func (void *d, ExifLong ds)
+{
+ return realloc (d, (size_t) ds);
+}
+
+/*! Default memory free function. */
+static void
+exif_mem_free_func (void *d)
+{
+ free (d);
+}
+
+ExifMem *
+exif_mem_new (ExifMemAllocFunc alloc_func, ExifMemReallocFunc realloc_func,
+ ExifMemFreeFunc free_func)
+{
+ ExifMem *mem;
+
+ if (!alloc_func && !realloc_func)
+ return NULL;
+ mem = alloc_func ? alloc_func (sizeof (ExifMem)) :
+ realloc_func (NULL, sizeof (ExifMem));
+ if (!mem) return NULL;
+ mem->ref_count = 1;
+
+ mem->alloc_func = alloc_func;
+ mem->realloc_func = realloc_func;
+ mem->free_func = free_func;
+
+ return mem;
+}
+
+void
+exif_mem_ref (ExifMem *mem)
+{
+ if (!mem) return;
+ mem->ref_count++;
+}
+
+void
+exif_mem_unref (ExifMem *mem)
+{
+ if (!mem) return;
+ if (!--mem->ref_count)
+ exif_mem_free (mem, mem);
+}
+
+void
+exif_mem_free (ExifMem *mem, void *d)
+{
+ if (!mem) return;
+ if (mem->free_func) {
+ mem->free_func (d);
+ return;
+ }
+}
+
+void *
+exif_mem_alloc (ExifMem *mem, ExifLong ds)
+{
+ if (!mem) return NULL;
+ if (mem->alloc_func || mem->realloc_func)
+ return mem->alloc_func ? mem->alloc_func (ds) :
+ mem->realloc_func (NULL, ds);
+ return NULL;
+}
+
+void *
+exif_mem_realloc (ExifMem *mem, void *d, ExifLong ds)
+{
+ return (mem && mem->realloc_func) ? mem->realloc_func (d, ds) : NULL;
+}
+
+ExifMem *
+exif_mem_new_default (void)
+{
+ return exif_mem_new (exif_mem_alloc_func, exif_mem_realloc_func,
+ exif_mem_free_func);
+}
diff --git a/libexif/exif-mem.h b/libexif/exif-mem.h
new file mode 100644
index 0000000..fd8f2fa
--- /dev/null
+++ b/libexif/exif-mem.h
@@ -0,0 +1,90 @@
+/*! \file exif-mem.h
+ * \brief Define the ExifMem data type and the associated functions.
+ * ExifMem defines the memory management functions used within libexif.
+ */
+/* exif-mem.h
+ *
+ * Copyright (c) 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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_MEM_H__
+#define __EXIF_MEM_H__
+
+#include <libexif/exif-utils.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*! Should work like calloc()
+ *
+ * \param[in] s the size of the block to allocate.
+ * \return the allocated memory and initialized.
+ */
+typedef void * (* ExifMemAllocFunc) (ExifLong s);
+
+/*! Should work like realloc()
+ *
+ * \param[in] p the pointer to reallocate
+ * \param[in] s the size of the reallocated block
+ * \return allocated memory
+ */
+typedef void * (* ExifMemReallocFunc) (void *p, ExifLong s);
+
+/*! Free method for ExifMem
+ *
+ * \param[in] p the pointer to free
+ * \return the freed pointer
+ */
+typedef void (* ExifMemFreeFunc) (void *p);
+
+/*! ExifMem define a memory allocator */
+typedef struct _ExifMem ExifMem;
+
+/*! Create a new ExifMem
+ *
+ * \param[in] a the allocator function
+ * \param[in] r the reallocator function
+ * \param[in] f the free function
+ */
+ExifMem *exif_mem_new (ExifMemAllocFunc a, ExifMemReallocFunc r,
+ ExifMemFreeFunc f);
+/*! Refcount an ExifMem
+ */
+void exif_mem_ref (ExifMem *);
+
+/*! Unrefcount an ExifMem.
+ * If the refcount reaches 0, the ExifMem is freed
+ */
+void exif_mem_unref (ExifMem *);
+
+void *exif_mem_alloc (ExifMem *m, ExifLong s);
+void *exif_mem_realloc (ExifMem *m, void *p, ExifLong s);
+void exif_mem_free (ExifMem *m, void *p);
+
+/*! Create a new ExifMem with default values for your convenience
+ *
+ * \return return a new default ExifMem
+ */
+ExifMem *exif_mem_new_default (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_MEM_H__ */
diff --git a/libexif/exif-mnote-data-priv.h b/libexif/exif-mnote-data-priv.h
new file mode 100644
index 0000000..7462c97
--- /dev/null
+++ b/libexif/exif-mnote-data-priv.h
@@ -0,0 +1,86 @@
+/* exif-mnote-data-priv.h
+ *
+ * Copyright (c) 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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_PRIV_H__
+#define __EXIF_MNOTE_DATA_PRIV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-mnote-data.h>
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-log.h>
+
+/*! \internal */
+typedef struct _ExifMnoteDataMethods ExifMnoteDataMethods;
+
+/*! \internal */
+struct _ExifMnoteDataMethods {
+
+ /* Life cycle */
+ void (* free) (ExifMnoteData *);
+
+ /* Modification */
+ void (* save) (ExifMnoteData *, unsigned char **, unsigned int *);
+ void (* load) (ExifMnoteData *, const unsigned char *, unsigned int);
+ void (* set_offset) (ExifMnoteData *, unsigned int);
+ void (* set_byte_order) (ExifMnoteData *, ExifByteOrder);
+
+ /* Query */
+ unsigned int (* count) (ExifMnoteData *);
+ unsigned int (* get_id) (ExifMnoteData *, unsigned int);
+ const char * (* get_name) (ExifMnoteData *, unsigned int);
+ const char * (* get_title) (ExifMnoteData *, unsigned int);
+ const char * (* get_description) (ExifMnoteData *, unsigned int);
+ char * (* get_value) (ExifMnoteData *, unsigned int, char *val, unsigned int maxlen);
+};
+
+/*! \internal */
+typedef struct _ExifMnoteDataPriv ExifMnoteDataPriv;
+
+/*! \internal */
+struct _ExifMnoteData
+{
+ ExifMnoteDataPriv *priv;
+
+ ExifMnoteDataMethods methods;
+
+ /* Logging */
+ ExifLog *log;
+
+ /* Memory management */
+ ExifMem *mem;
+};
+
+/*! \internal */
+void exif_mnote_data_construct (ExifMnoteData *, ExifMem *mem);
+
+/*! \internal */
+void exif_mnote_data_set_byte_order (ExifMnoteData *, ExifByteOrder);
+
+/*! \internal */
+void exif_mnote_data_set_offset (ExifMnoteData *, unsigned int);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_MNOTE_PRIV_H__ */
diff --git a/libexif/exif-mnote-data.c b/libexif/exif-mnote-data.c
new file mode 100644
index 0000000..248056e
--- /dev/null
+++ b/libexif/exif-mnote-data.c
@@ -0,0 +1,158 @@
+/* exif-mnote-data.c
+ *
+ * Copyright (C) 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <libexif/exif-mnote-data.h>
+#include <libexif/exif-mnote-data-priv.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+struct _ExifMnoteDataPriv
+{
+ unsigned int ref_count;
+};
+
+void
+exif_mnote_data_construct (ExifMnoteData *d, ExifMem *mem)
+{
+ if (!d || !mem) return;
+ if (d->priv) return;
+ d->priv = exif_mem_alloc (mem, sizeof (ExifMnoteDataPriv));
+ if (!d->priv) return;
+
+ d->priv->ref_count = 1;
+
+ d->mem = mem;
+ exif_mem_ref (mem);
+}
+
+void
+exif_mnote_data_ref (ExifMnoteData *d)
+{
+ if (d && d->priv) d->priv->ref_count++;
+}
+
+static void
+exif_mnote_data_free (ExifMnoteData *d)
+{
+ ExifMem *mem = d ? d->mem : NULL;
+
+ if (!d) return;
+ if (d->priv) {
+ if (d->methods.free) d->methods.free (d);
+ exif_mem_free (mem, d->priv);
+ d->priv = NULL;
+ }
+ exif_log_unref (d->log);
+ exif_mem_free (mem, d);
+ exif_mem_unref (mem);
+}
+
+void
+exif_mnote_data_unref (ExifMnoteData *d)
+{
+ if (!d || !d->priv) return;
+ if (d->priv->ref_count > 0) d->priv->ref_count--;
+ if (!d->priv->ref_count)
+ exif_mnote_data_free (d);
+}
+
+void
+exif_mnote_data_load (ExifMnoteData *d, const unsigned char *buf,
+ unsigned int buf_size)
+{
+ if (!d || !d->methods.load) return;
+ d->methods.load (d, buf, buf_size);
+}
+
+void
+exif_mnote_data_save (ExifMnoteData *d, unsigned char **buf,
+ unsigned int *buf_size)
+{
+ if (!d || !d->methods.save) return;
+ d->methods.save (d, buf, buf_size);
+}
+
+void
+exif_mnote_data_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
+{
+ if (!d || !d->methods.set_byte_order) return;
+ d->methods.set_byte_order (d, o);
+}
+
+void
+exif_mnote_data_set_offset (ExifMnoteData *d, unsigned int o)
+{
+ if (!d || !d->methods.set_offset) return;
+ d->methods.set_offset (d, o);
+}
+
+unsigned int
+exif_mnote_data_count (ExifMnoteData *d)
+{
+ if (!d || !d->methods.count) return 0;
+ return d->methods.count (d);
+}
+
+unsigned int
+exif_mnote_data_get_id (ExifMnoteData *d, unsigned int n)
+{
+ if (!d || !d->methods.get_id) return 0;
+ return d->methods.get_id (d, n);
+}
+
+const char *
+exif_mnote_data_get_name (ExifMnoteData *d, unsigned int n)
+{
+ if (!d || !d->methods.get_name) return NULL;
+ return d->methods.get_name (d, n);
+}
+
+const char *
+exif_mnote_data_get_title (ExifMnoteData *d, unsigned int n)
+{
+ if (!d || !d->methods.get_title) return NULL;
+ return d->methods.get_title (d, n);
+}
+
+const char *
+exif_mnote_data_get_description (ExifMnoteData *d, unsigned int n)
+{
+ if (!d || !d->methods.get_description) return NULL;
+ return d->methods.get_description (d, n);
+}
+
+char *
+exif_mnote_data_get_value (ExifMnoteData *d, unsigned int n, char *val, unsigned int maxlen)
+{
+ if (!d || !d->methods.get_value) return NULL;
+ return d->methods.get_value (d, n, val, maxlen);
+}
+
+void
+exif_mnote_data_log (ExifMnoteData *d, ExifLog *log)
+{
+ if (!d) return;
+ exif_log_unref (d->log);
+ d->log = log;
+ exif_log_ref (log);
+}
diff --git a/libexif/exif-mnote-data.h b/libexif/exif-mnote-data.h
new file mode 100644
index 0000000..19e1de5
--- /dev/null
+++ b/libexif/exif-mnote-data.h
@@ -0,0 +1,122 @@
+/*! \file exif-mnote-data.h
+ * \brief Handling EXIF MakerNote tags
+ */
+/*
+ * Copyright (c) 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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_H__
+#define __EXIF_MNOTE_DATA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-log.h>
+
+/*! Data found in the MakerNote tag */
+typedef struct _ExifMnoteData ExifMnoteData;
+
+void exif_mnote_data_ref (ExifMnoteData *);
+void exif_mnote_data_unref (ExifMnoteData *);
+
+/*! Load the MakerNote data from a memory buffer.
+ *
+ * \param[in] d MakerNote data
+ * \param[in] buf pointer to raw MakerNote tag data
+ * \param[in] buf_siz number of bytes of data at buf
+ */
+void exif_mnote_data_load (ExifMnoteData *d, const unsigned char *buf,
+ unsigned int buf_siz);
+
+/*!
+ * Save the raw MakerNote data into a memory buffer. The buffer is
+ * allocated by this function and must subsequently be freed by the
+ * caller.
+ *
+ * \param[in,out] d extract the data from this structure
+ * \param[out] buf pointer to buffer pointer containing MakerNote data on return
+ * \param[out] buf_siz pointer to the size of the buffer
+ */
+void exif_mnote_data_save (ExifMnoteData *d, unsigned char **buf,
+ unsigned int *buf_siz);
+
+/*! Return the number of tags in the MakerNote.
+ *
+ * \param[in] d MakerNote data
+ * \return number of tags, or 0 if no MakerNote or the type is not supported
+ */
+unsigned int exif_mnote_data_count (ExifMnoteData *d);
+
+/*! Return the MakerNote tag number for the tag at the specified index within
+ * the MakerNote.
+ *
+ * \param[in] d MakerNote data
+ * \param[in] n index of the entry within the MakerNote data
+ * \return MakerNote tag number
+ */
+unsigned int exif_mnote_data_get_id (ExifMnoteData *d, unsigned int n);
+
+/*! Returns textual name of the given MakerNote tag. The name is a short,
+ * unique (within this type of MakerNote), non-localized text string
+ * containing only US-ASCII alphanumeric characters.
+ *
+ * \param[in] d MakerNote data
+ * \param[in] n index of the entry within the MakerNote data
+ * \return textual name of the tag
+ */
+const char *exif_mnote_data_get_name (ExifMnoteData *d, unsigned int n);
+
+/*! Returns textual title of the given MakerNote tag.
+ * The title is a short, localized textual description of the tag.
+ *
+ * \param[in] d MakerNote data
+ * \param[in] n index of the entry within the MakerNote data
+ * \return textual name of the tag
+ */
+const char *exif_mnote_data_get_title (ExifMnoteData *d, unsigned int n);
+
+/*! Returns verbose textual description of the given MakerNote tag.
+ *
+ * \param[in] d MakerNote data
+ * \param[in] n index of the entry within the MakerNote data
+ * \return textual description of the tag
+ */
+const char *exif_mnote_data_get_description (ExifMnoteData *d, unsigned int n);
+
+/*! Return a textual representation of the value of the MakerNote entry.
+ *
+ * \warning The character set of the returned string may be in
+ * the encoding of the current locale or the native encoding
+ * of the camera.
+ *
+ * \param[in] d MakerNote data
+ * \param[in] n index of the entry within the MakerNote data
+ * \param[out] val buffer in which to store value
+ * \param[in] maxlen length of the buffer val
+ * \return val pointer, or NULL on error
+ */
+char *exif_mnote_data_get_value (ExifMnoteData *d, unsigned int n, char *val, unsigned int maxlen);
+
+void exif_mnote_data_log (ExifMnoteData *, ExifLog *);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_MNOTE_DATA_H__ */
diff --git a/libexif/exif-system.h b/libexif/exif-system.h
new file mode 100644
index 0000000..81fa703
--- /dev/null
+++ b/libexif/exif-system.h
@@ -0,0 +1,32 @@
+/*! \file exif-system.h
+ * \brief System specific definitions, not for installation!
+ */
+/*
+ * Copyright (c) 2007 Hans Ulrich Niedermann <gp@n-dimensional.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#ifndef EXIF_SYSTEM_H
+#define EXIF_SYSTEM_H
+
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+# define UNUSED(param) UNUSED_PARAM_##param __attribute__((unused))
+#else
+# define UNUSED(param) param
+#endif
+
+#endif /* !defined(EXIF_SYSTEM_H) */
diff --git a/libexif/exif-tag.c b/libexif/exif-tag.c
new file mode 100644
index 0000000..60f8331
--- /dev/null
+++ b/libexif/exif-tag.c
@@ -0,0 +1,1180 @@
+/* exif-tag.c
+ *
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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 <libexif/exif-tag.h>
+#include <libexif/i18n.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#define ESL_NNNN { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED }
+#define ESL_OOOO { EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL }
+#define ESL_MMMN { EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_NOT_RECORDED }
+#define ESL_MMMM { EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY }
+#define ESL_OMON { EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_NOT_RECORDED }
+#define ESL_NNOO { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_OPTIONAL, EXIF_SUPPORT_LEVEL_OPTIONAL }
+#define ESL_NNMN { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_NOT_RECORDED }
+#define ESL_NNMM { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_MANDATORY, EXIF_SUPPORT_LEVEL_MANDATORY }
+#define ESL_NNNM { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_MANDATORY }
+#define ESL_NNNO { EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_NOT_RECORDED, EXIF_SUPPORT_LEVEL_OPTIONAL }
+#define ESL_GPS { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN }
+
+/*!
+ * Table giving information about each EXIF tag.
+ * There may be more than one entry with the same tag value because some tags
+ * have different meanings depending on the IFD in which they appear.
+ * When there are such duplicate entries, there must be no overlap in their
+ * support levels.
+ * The entries MUST be sorted in tag order.
+ * The name and title are mandatory, but the description may be an empty
+ * string. None of the entries may be NULL except the final array terminator.
+ */
+static const struct TagEntry {
+ /*! Tag ID. There may be duplicate tags when the same number is used for
+ * different meanings in different IFDs. */
+ ExifTag tag;
+ const char *name;
+ const char *title;
+ const char *description;
+ /*! indexed by the types [ExifIfd][ExifDataType] */
+ ExifSupportLevel esl[EXIF_IFD_COUNT][EXIF_DATA_TYPE_COUNT];
+} ExifTagTable[] = {
+#ifndef NO_VERBOSE_TAG_STRINGS
+ {EXIF_TAG_GPS_VERSION_ID, "GPSVersionID", N_("GPS Tag Version"),
+ N_("Indicates the version of <GPSInfoIFD>. The version is given "
+ "as 2.0.0.0. This tag is mandatory when <GPSInfo> tag is "
+ "present. (Note: The <GPSVersionID> tag is given in bytes, "
+ "unlike the <ExifVersion> tag. When the version is "
+ "2.0.0.0, the tag value is 02000000.H)."), ESL_GPS},
+ {EXIF_TAG_INTEROPERABILITY_INDEX, "InteroperabilityIndex",
+ N_("Interoperability Index"),
+ N_("Indicates the identification of the Interoperability rule. "
+ "Use \"R98\" for stating ExifR98 Rules. Four bytes used "
+ "including the termination code (NULL). see the separate "
+ "volume of Recommended Exif Interoperability Rules (ExifR98) "
+ "for other tags used for ExifR98."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_OOOO } },
+ {EXIF_TAG_GPS_LATITUDE_REF, "GPSLatitudeRef", N_("North or South Latitude"),
+ N_("Indicates whether the latitude is north or south latitude. The "
+ "ASCII value 'N' indicates north latitude, and 'S' is south "
+ "latitude."), ESL_GPS},
+ {EXIF_TAG_INTEROPERABILITY_VERSION, "InteroperabilityVersion",
+ N_("Interoperability Version"), "",
+ { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_OOOO } },
+ {EXIF_TAG_GPS_LATITUDE, "GPSLatitude", N_("Latitude"),
+ N_("Indicates the latitude. The latitude is expressed as three "
+ "RATIONAL values giving the degrees, minutes, and seconds, "
+ "respectively. When degrees, minutes and seconds are expressed, "
+ "the format is dd/1,mm/1,ss/1. When degrees and minutes are used "
+ "and, for example, fractions of minutes are given up to two "
+ "decimal places, the format is dd/1,mmmm/100,0/1."),
+ ESL_GPS},
+ {EXIF_TAG_GPS_LONGITUDE_REF, "GPSLongitudeRef", N_("East or West Longitude"),
+ N_("Indicates whether the longitude is east or west longitude. "
+ "ASCII 'E' indicates east longitude, and 'W' is west "
+ "longitude."), ESL_GPS},
+ {EXIF_TAG_GPS_LONGITUDE, "GPSLongitude", N_("Longitude"),
+ N_("Indicates the longitude. The longitude is expressed as three "
+ "RATIONAL values giving the degrees, minutes, and seconds, "
+ "respectively. When degrees, minutes and seconds are expressed, "
+ "the format is ddd/1,mm/1,ss/1. When degrees and minutes are "
+ "used and, for example, fractions of minutes are given up to "
+ "two decimal places, the format is ddd/1,mmmm/100,0/1."),
+ ESL_GPS},
+ {EXIF_TAG_GPS_ALTITUDE_REF, "GPSAltitudeRef", N_("Altitude Reference"),
+ N_("Indicates the altitude used as the reference altitude. If the "
+ "reference is sea level and the altitude is above sea level, 0 "
+ "is given. If the altitude is below sea level, a value of 1 is given "
+ "and the altitude is indicated as an absolute value in the "
+ "GSPAltitude tag. The reference unit is meters. Note that this tag "
+ "is BYTE type, unlike other reference tags."), ESL_GPS},
+ {EXIF_TAG_GPS_ALTITUDE, "GPSAltitude", N_("Altitude"),
+ N_("Indicates the altitude based on the reference in GPSAltitudeRef. "
+ "Altitude is expressed as one RATIONAL value. The reference unit "
+ "is meters."), ESL_GPS},
+ {EXIF_TAG_GPS_TIME_STAMP, "GPSTimeStamp", N_("GPS Time (Atomic Clock)"),
+ N_("Indicates the time as UTC (Coordinated Universal Time). "
+ "TimeStamp is expressed as three RATIONAL values giving "
+ "the hour, minute, and second."), ESL_GPS},
+ {EXIF_TAG_GPS_SATELLITES, "GPSSatellites", N_("GPS Satellites"),
+ N_("Indicates the GPS satellites used for measurements. This "
+ "tag can be used to describe the number of satellites, their ID "
+ "number, angle of elevation, azimuth, SNR and other information "
+ "in ASCII notation. The format is not specified. If the GPS "
+ "receiver is incapable of taking measurements, value of the tag "
+ "shall be set to NULL."), ESL_GPS},
+ {EXIF_TAG_GPS_STATUS, "GPSStatus", N_("GPS Receiver Status"),
+ N_("Indicates the status of the GPS receiver when the image is "
+ "recorded. 'A' means measurement is in progress, and 'V' means "
+ "the measurement is Interoperability."), ESL_GPS},
+ {EXIF_TAG_GPS_MEASURE_MODE, "GPSMeasureMode", N_("GPS Measurement Mode"),
+ N_("Indicates the GPS measurement mode. '2' means "
+ "two-dimensional measurement and '3' means three-dimensional "
+ "measurement is in progress."), ESL_GPS},
+ {EXIF_TAG_GPS_DOP, "GPSDOP", N_("Measurement Precision"),
+ N_("Indicates the GPS DOP (data degree of precision). An HDOP "
+ "value is written during two-dimensional measurement, and PDOP "
+ "during three-dimensional measurement."), ESL_GPS},
+ {EXIF_TAG_GPS_SPEED_REF, "GPSSpeedRef", N_("Speed Unit"),
+ N_("Indicates the unit used to express the GPS receiver speed "
+ "of movement. 'K', 'M' and 'N' represent kilometers per hour, "
+ "miles per hour, and knots."), ESL_GPS},
+ {EXIF_TAG_GPS_SPEED, "GPSSpeed", N_("Speed of GPS Receiver"),
+ N_("Indicates the speed of GPS receiver movement."), ESL_GPS},
+ {EXIF_TAG_GPS_TRACK_REF, "GPSTrackRef", N_("Reference for direction of movement"),
+ N_("Indicates the reference for giving the direction of GPS "
+ "receiver movement. 'T' denotes true direction and 'M' is "
+ "magnetic direction."), ESL_GPS},
+ {EXIF_TAG_GPS_TRACK, "GPSTrack", N_("Direction of Movement"),
+ N_("Indicates the direction of GPS receiver movement. The range "
+ "of values is from 0.00 to 359.99."), ESL_GPS},
+ {EXIF_TAG_GPS_IMG_DIRECTION_REF, "GPSImgDirectionRef", N_("GPS Image Direction Reference"),
+ N_("Indicates the reference for giving the direction of the image when it is captured. "
+ "'T' denotes true direction and 'M' is magnetic direction."), ESL_GPS},
+ {EXIF_TAG_GPS_IMG_DIRECTION, "GPSImgDirection", N_("GPS Image Direction"),
+ N_("Indicates the direction of the image when it was captured. The range of values is "
+ "from 0.00 to 359.99."), ESL_GPS},
+ {EXIF_TAG_GPS_MAP_DATUM, "GPSMapDatum", N_("Geodetic Survey Data Used"),
+ N_("Indicates the geodetic survey data used by the GPS "
+ "receiver. If the survey data is restricted to Japan, the value "
+ "of this tag is 'TOKYO' or 'WGS-84'. If a GPS Info tag is "
+ "recorded, it is strongly recommended that this tag be recorded."), ESL_GPS},
+ {EXIF_TAG_GPS_DEST_LATITUDE_REF, "GPSDestLatitudeRef", N_("Reference For Latitude of Destination"),
+ N_("Indicates whether the latitude of the destination point is "
+ "north or south latitude. The ASCII value 'N' indicates north "
+ "latitude, and 'S' is south latitude."), ESL_GPS},
+ {EXIF_TAG_GPS_DEST_LATITUDE, "GPSDestLatitude", N_("Latitude of Destination"),
+ N_("Indicates the latitude of the destination point. The "
+ "latitude is expressed as three RATIONAL values giving the "
+ "degrees, minutes, and seconds, respectively. If latitude is "
+ "expressed as degrees, minutes and seconds, a typical format "
+ "would be dd/1,mm/1,ss/1. When degrees and minutes are used and, "
+ "for example, fractions of minutes are given up to two decimal "
+ "places, the format would be dd/1,mmmm/100,0/1."), ESL_GPS},
+ {EXIF_TAG_GPS_DEST_LONGITUDE_REF, "GPSDestLongitudeRef", N_("Reference for Longitude of Destination"),
+ N_("Indicates whether the longitude of the destination point is "
+ "east or west longitude. ASCII 'E' indicates east longitude, and "
+ "'W' is west longitude."), ESL_GPS},
+ {EXIF_TAG_GPS_DEST_LONGITUDE, "GPSDestLongitude", N_("Longitude of Destination"),
+ N_("Indicates the longitude of the destination point. The "
+ "longitude is expressed as three RATIONAL values giving the "
+ "degrees, minutes, and seconds, respectively. If longitude is "
+ "expressed as degrees, minutes and seconds, a typical format "
+ "would be ddd/1,mm/1,ss/1. When degrees and minutes are used "
+ "and, for example, fractions of minutes are given up to two "
+ "decimal places, the format would be ddd/1,mmmm/100,0/1."),
+ ESL_GPS},
+ {EXIF_TAG_GPS_DEST_BEARING_REF, "GPSDestBearingRef", N_("Reference for Bearing of Destination"),
+ N_("Indicates the reference used for giving the bearing to "
+ "the destination point. 'T' denotes true direction and 'M' is "
+ "magnetic direction."), ESL_GPS},
+ {EXIF_TAG_GPS_DEST_BEARING, "GPSDestBearing", N_("Bearing of Destination"),
+ N_("Indicates the bearing to the destination point. The range "
+ "of values is from 0.00 to 359.99."), ESL_GPS},
+ {EXIF_TAG_GPS_DEST_DISTANCE_REF, "GPSDestDistanceRef", N_("Reference for Distance to Destination"),
+ N_("Indicates the unit used to express the distance to the "
+ "destination point. 'K', 'M' and 'N' represent kilometers, miles "
+ "and nautical miles."), ESL_GPS},
+ {EXIF_TAG_GPS_DEST_DISTANCE, "GPSDestDistance", N_("Distance to Destination"),
+ N_("Indicates the distance to the destination point."), ESL_GPS},
+ {EXIF_TAG_GPS_PROCESSING_METHOD, "GPSProcessingMethod", N_("Name of GPS Processing Method"),
+ N_("A character string recording the name of the method used "
+ "for location finding. The first byte indicates the character "
+ "code used, and this is followed by the name "
+ "of the method. Since the Type is not ASCII, NULL termination is "
+ "not necessary."), ESL_GPS},
+ {EXIF_TAG_GPS_AREA_INFORMATION, "GPSAreaInformation", N_("Name of GPS Area"),
+ N_("A character string recording the name of the GPS area. The "
+ "first byte indicates the character code used, "
+ "and this is followed by the name of the GPS area. Since "
+ "the Type is not ASCII, NULL termination is not necessary."), ESL_GPS},
+ {EXIF_TAG_GPS_DATE_STAMP, "GPSDateStamp", N_("GPS Date"),
+ N_("A character string recording date and time information "
+ "relative to UTC (Coordinated Universal Time). The format is "
+ "\"YYYY:MM:DD\". The length of the string is 11 bytes including "
+ "NULL."), ESL_GPS},
+ {EXIF_TAG_GPS_DIFFERENTIAL, "GPSDifferential", N_("GPS Differential Correction"),
+ N_("Indicates whether differential correction is applied to the "
+ "GPS receiver."), ESL_GPS},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_NEW_SUBFILE_TYPE, "NewSubfileType",
+ N_("New Subfile Type"), N_("A general indication of the kind of data "
+ "contained in this subfile.")},
+ {EXIF_TAG_IMAGE_WIDTH, "ImageWidth", N_("Image Width"),
+ N_("The number of columns of image data, equal to the number of "
+ "pixels per row. In JPEG compressed data a JPEG marker is "
+ "used instead of this tag."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_IMAGE_LENGTH, "ImageLength", N_("Image Length"),
+ N_("The number of rows of image data. In JPEG compressed data a "
+ "JPEG marker is used instead of this tag."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_BITS_PER_SAMPLE, "BitsPerSample", N_("Bits per Sample"),
+ N_("The number of bits per image component. In this standard each "
+ "component of the image is 8 bits, so the value for this "
+ "tag is 8. See also <SamplesPerPixel>. In JPEG compressed data "
+ "a JPEG marker is used instead of this tag."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_COMPRESSION, "Compression", N_("Compression"),
+ N_("The compression scheme used for the image data. When a "
+ "primary image is JPEG compressed, this designation is "
+ "not necessary and is omitted. When thumbnails use JPEG "
+ "compression, this tag value is set to 6."),
+ { ESL_MMMN, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_PHOTOMETRIC_INTERPRETATION, "PhotometricInterpretation",
+ N_("Photometric Interpretation"),
+ N_("The pixel composition. In JPEG compressed data a JPEG "
+ "marker is used instead of this tag."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_FILL_ORDER, "FillOrder", N_("Fill Order"), ""},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_DOCUMENT_NAME, "DocumentName", N_("Document Name"), ""},
+ {EXIF_TAG_IMAGE_DESCRIPTION, "ImageDescription",
+ N_("Image Description"),
+ N_("A character string giving the title of the image. It may be "
+ "a comment such as \"1988 company picnic\" or "
+ "the like. Two-bytes character codes cannot be used. "
+ "When a 2-bytes code is necessary, the Exif Private tag "
+ "<UserComment> is to be used."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_MAKE, "Make", N_("Manufacturer"),
+ N_("The manufacturer of the recording "
+ "equipment. This is the manufacturer of the DSC, scanner, "
+ "video digitizer or other equipment that generated the "
+ "image. When the field is left blank, it is treated as "
+ "unknown."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_MODEL, "Model", N_("Model"),
+ N_("The model name or model number of the equipment. This is the "
+ "model name or number of the DSC, scanner, video digitizer "
+ "or other equipment that generated the image. When the field "
+ "is left blank, it is treated as unknown."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_STRIP_OFFSETS, "StripOffsets", N_("Strip Offsets"),
+ N_("For each strip, the byte offset of that strip. It is "
+ "recommended that this be selected so the number of strip "
+ "bytes does not exceed 64 Kbytes. With JPEG compressed "
+ "data this designation is not needed and is omitted. See also "
+ "<RowsPerStrip> and <StripByteCounts>."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_ORIENTATION, "Orientation", N_("Orientation"),
+ N_("The image orientation viewed in terms of rows and columns."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SAMPLES_PER_PIXEL, "SamplesPerPixel",
+ N_("Samples per Pixel"),
+ N_("The number of components per pixel. Since this standard applies "
+ "to RGB and YCbCr images, the value set for this tag is 3. "
+ "In JPEG compressed data a JPEG marker is used instead of this "
+ "tag."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_ROWS_PER_STRIP, "RowsPerStrip", N_("Rows per Strip"),
+ N_("The number of rows per strip. This is the number of rows "
+ "in the image of one strip when an image is divided into "
+ "strips. With JPEG compressed data this designation is not "
+ "needed and is omitted. See also <StripOffsets> and "
+ "<StripByteCounts>."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_STRIP_BYTE_COUNTS, "StripByteCounts", N_("Strip Byte Count"),
+ N_("The total number of bytes in each strip. With JPEG compressed "
+ "data this designation is not needed and is omitted."),
+ { ESL_MMMN, ESL_MMMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_X_RESOLUTION, "XResolution", N_("X-Resolution"),
+ N_("The number of pixels per <ResolutionUnit> in the <ImageWidth> "
+ "direction. When the image resolution is unknown, 72 [dpi] "
+ "is designated."),
+ { ESL_MMMM, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_Y_RESOLUTION, "YResolution", N_("Y-Resolution"),
+ N_("The number of pixels per <ResolutionUnit> in the <ImageLength> "
+ "direction. The same value as <XResolution> is designated."),
+ { ESL_MMMM, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_PLANAR_CONFIGURATION, "PlanarConfiguration",
+ N_("Planar Configuration"),
+ N_("Indicates whether pixel components are recorded in a chunky "
+ "or planar format. In JPEG compressed files a JPEG marker "
+ "is used instead of this tag. If this field does not exist, "
+ "the TIFF default of 1 (chunky) is assumed."),
+ { ESL_OMON, ESL_OMON, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_RESOLUTION_UNIT, "ResolutionUnit", N_("Resolution Unit"),
+ N_("The unit for measuring <XResolution> and <YResolution>. The same "
+ "unit is used for both <XResolution> and <YResolution>. If "
+ "the image resolution is unknown, 2 (inches) is designated."),
+ { ESL_MMMM, ESL_MMMM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_TRANSFER_FUNCTION, "TransferFunction",
+ N_("Transfer Function"),
+ N_("A transfer function for the image, described in tabular style. "
+ "Normally this tag is not necessary, since color space is "
+ "specified in the color space information tag (<ColorSpace>)."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SOFTWARE, "Software", N_("Software"),
+ N_("This tag records the name and version of the software or "
+ "firmware of the camera or image input device used to "
+ "generate the image. The detailed format is not specified, but "
+ "it is recommended that the example shown below be "
+ "followed. When the field is left blank, it is treated as "
+ "unknown."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_DATE_TIME, "DateTime", N_("Date and Time"),
+ N_("The date and time of image creation. In this standard "
+ "(EXIF-2.1) it is the date and time the file was changed."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_ARTIST, "Artist", N_("Artist"),
+ N_("This tag records the name of the camera owner, photographer or "
+ "image creator. The detailed format is not specified, but it is "
+ "recommended that the information be written as in the example "
+ "below for ease of Interoperability. When the field is "
+ "left blank, it is treated as unknown."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_WHITE_POINT, "WhitePoint", N_("White Point"),
+ N_("The chromaticity of the white point of the image. Normally "
+ "this tag is not necessary, since color space is specified "
+ "in the color space information tag (<ColorSpace>)."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_PRIMARY_CHROMATICITIES, "PrimaryChromaticities",
+ N_("Primary Chromaticities"),
+ N_("The chromaticity of the three primary colors of the image. "
+ "Normally this tag is not necessary, since color space is "
+ "specified in the color space information tag (<ColorSpace>)."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_SUB_IFDS, "SubIFDs", "SubIFD Offsets", N_("Defined by Adobe Corporation "
+ "to enable TIFF Trees within a TIFF file.")},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_TRANSFER_RANGE, "TransferRange", N_("Transfer Range"), ""},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_JPEG_PROC, "JPEGProc", "JPEGProc", ""},
+ {EXIF_TAG_JPEG_INTERCHANGE_FORMAT, "JPEGInterchangeFormat",
+ N_("JPEG Interchange Format"),
+ N_("The offset to the start byte (SOI) of JPEG compressed "
+ "thumbnail data. This is not used for primary image "
+ "JPEG data."),
+ { ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
+ "JPEGInterchangeFormatLength", N_("JPEG Interchange Format Length"),
+ N_("The number of bytes of JPEG compressed thumbnail data. This "
+ "is not used for primary image JPEG data. JPEG thumbnails "
+ "are not divided but are recorded as a continuous JPEG "
+ "bitstream from SOI to EOI. Appn and COM markers should "
+ "not be recorded. Compressed thumbnails must be recorded in no "
+ "more than 64 Kbytes, including all other data to be "
+ "recorded in APP1."),
+ { ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_YCBCR_COEFFICIENTS, "YCbCrCoefficients",
+ N_("YCbCr Coefficients"),
+ N_("The matrix coefficients for transformation from RGB to YCbCr "
+ "image data. No default is given in TIFF; but here the "
+ "value given in \"Color Space Guidelines\", is used "
+ "as the default. The color space is declared in a "
+ "color space information tag, with the default being the value "
+ "that gives the optimal image characteristics "
+ "Interoperability this condition."),
+ { ESL_NNOO, ESL_NNOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_YCBCR_SUB_SAMPLING, "YCbCrSubSampling",
+ N_("YCbCr Sub-Sampling"),
+ N_("The sampling ratio of chrominance components in relation to the "
+ "luminance component. In JPEG compressed data a JPEG marker "
+ "is used instead of this tag."),
+ { ESL_NNMN, ESL_NNMN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_YCBCR_POSITIONING, "YCbCrPositioning",
+ N_("YCbCr Positioning"),
+ N_("The position of chrominance components in relation to the "
+ "luminance component. This field is designated only for "
+ "JPEG compressed data or uncompressed YCbCr data. The TIFF "
+ "default is 1 (centered); but when Y:Cb:Cr = 4:2:2 it is "
+ "recommended in this standard that 2 (co-sited) be used to "
+ "record data, in order to improve the image quality when viewed "
+ "on TV systems. When this field does not exist, the reader shall "
+ "assume the TIFF default. In the case of Y:Cb:Cr = 4:2:0, the "
+ "TIFF default (centered) is recommended. If the reader "
+ "does not have the capability of supporting both kinds of "
+ "<YCbCrPositioning>, it shall follow the TIFF default regardless "
+ "of the value in this field. It is preferable that readers "
+ "be able to support both centered and co-sited positioning."),
+ { ESL_NNMM, ESL_NNOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_REFERENCE_BLACK_WHITE, "ReferenceBlackWhite",
+ N_("Reference Black/White"),
+ N_("The reference black point value and reference white point "
+ "value. No defaults are given in TIFF, but the values "
+ "below are given as defaults here. The color space is declared "
+ "in a color space information tag, with the default "
+ "being the value that gives the optimal image characteristics "
+ "Interoperability these conditions."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_XML_PACKET, "XMLPacket", N_("XML Packet"), N_("XMP Metadata")},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_RELATED_IMAGE_FILE_FORMAT, "RelatedImageFileFormat",
+ "RelatedImageFileFormat", ""},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_RELATED_IMAGE_WIDTH, "RelatedImageWidth",
+ "RelatedImageWidth", ""},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_RELATED_IMAGE_LENGTH, "RelatedImageLength",
+ "RelatedImageLength", ""},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_CFA_REPEAT_PATTERN_DIM, "CFARepeatPatternDim",
+ "CFARepeatPatternDim", ""},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_CFA_PATTERN, "CFAPattern",
+ N_("CFA Pattern"),
+ N_("Indicates the color filter array (CFA) geometric pattern of the "
+ "image sensor when a one-chip color area sensor is used. "
+ "It does not apply to all sensing methods.")},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_BATTERY_LEVEL, "BatteryLevel", N_("Battery Level"), ""},
+ {EXIF_TAG_COPYRIGHT, "Copyright", N_("Copyright"),
+ N_("Copyright information. In this standard the tag is used to "
+ "indicate both the photographer and editor copyrights. It is "
+ "the copyright notice of the person or organization claiming "
+ "rights to the image. The Interoperability copyright "
+ "statement including date and rights should be written in this "
+ "field; e.g., \"Copyright, John Smith, 19xx. All rights "
+ "reserved.\". In this standard the field records both the "
+ "photographer and editor copyrights, with each recorded in a "
+ "separate part of the statement. When there is a clear "
+ "distinction between the photographer and editor copyrights, "
+ "these are to be written in the order of photographer followed "
+ "by editor copyright, separated by NULL (in this case, "
+ "since the statement also ends with a NULL, there are two NULL "
+ "codes) (see example 1). When only the photographer is given, "
+ "it is terminated by one NULL code (see example 2). When only "
+ "the editor copyright is given, "
+ "the photographer copyright part consists of one space followed "
+ "by a terminating NULL code, then the editor copyright is given "
+ "(see example 3). When the field is left blank, it is treated "
+ "as unknown."),
+ { ESL_OOOO, ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_EXPOSURE_TIME, "ExposureTime", N_("Exposure Time"),
+ N_("Exposure time, given in seconds (sec)."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_FNUMBER, "FNumber", N_("F-Number"),
+ N_("The F number."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_IPTC_NAA, "IPTC/NAA", "IPTC/NAA", ""},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_IMAGE_RESOURCES, "ImageResources", N_("Image Resources Block"), ""},
+ {EXIF_TAG_EXIF_IFD_POINTER, "ExifIfdPointer", "ExifIFDPointer",
+ N_("A pointer to the Exif IFD. Interoperability, Exif IFD has the "
+ "same structure as that of the IFD specified in TIFF. "
+ "ordinarily, however, it does not contain image data as in "
+ "the case of TIFF."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_INTER_COLOR_PROFILE, "InterColorProfile",
+ "InterColorProfile", ""},
+ {EXIF_TAG_EXPOSURE_PROGRAM, "ExposureProgram", N_("Exposure Program"),
+ N_("The class of the program used by the camera to set exposure "
+ "when the picture is taken."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SPECTRAL_SENSITIVITY, "SpectralSensitivity",
+ N_("Spectral Sensitivity"),
+ N_("Indicates the spectral sensitivity of each channel of the "
+ "camera used. The tag value is an ASCII string compatible "
+ "with the standard developed by the ASTM Technical Committee."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_GPS_INFO_IFD_POINTER, "GPSInfoIFDPointer",
+ N_("GPS Info IFD Pointer"),
+ N_("A pointer to the GPS Info IFD. The "
+ "Interoperability structure of the GPS Info IFD, like that of "
+ "Exif IFD, has no image data."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+
+ {EXIF_TAG_ISO_SPEED_RATINGS, "ISOSpeedRatings",
+ N_("ISO Speed Ratings"),
+ N_("Indicates the ISO Speed and ISO Latitude of the camera or "
+ "input device as specified in ISO 12232."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_OECF, "OECF", N_("Opto-Electronic Conversion Function"),
+ N_("Indicates the Opto-Electronic Conversion Function (OECF) "
+ "specified in ISO 14524. <OECF> is the relationship between "
+ "the camera optical input and the image values."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_TIME_ZONE_OFFSET, "TimeZoneOffset", N_("Time Zone Offset"),
+ N_("Encodes time zone of camera clock relative to GMT.")},
+ {EXIF_TAG_EXIF_VERSION, "ExifVersion", N_("Exif Version"),
+ N_("The version of this standard supported. Nonexistence of this "
+ "field is taken to mean nonconformance to the standard."),
+ { ESL_NNNN, ESL_NNNN, ESL_MMMM, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_DATE_TIME_ORIGINAL, "DateTimeOriginal",
+ N_("Date and Time (Original)"),
+ N_("The date and time when the original image data was generated. "
+ "For a digital still camera "
+ "the date and time the picture was taken are recorded."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_DATE_TIME_DIGITIZED, "DateTimeDigitized",
+ N_("Date and Time (Digitized)"),
+ N_("The date and time when the image was stored as digital data."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_COMPONENTS_CONFIGURATION, "ComponentsConfiguration",
+ N_("Components Configuration"),
+ N_("Information specific to compressed data. The channels of "
+ "each component are arranged in order from the 1st "
+ "component to the 4th. For uncompressed data the data "
+ "arrangement is given in the <PhotometricInterpretation> tag. "
+ "However, since <PhotometricInterpretation> can only "
+ "express the order of Y, Cb and Cr, this tag is provided "
+ "for cases when compressed data uses components other than "
+ "Y, Cb, and Cr and to enable support of other sequences."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_COMPRESSED_BITS_PER_PIXEL, "CompressedBitsPerPixel",
+ N_("Compressed Bits per Pixel"),
+ N_("Information specific to compressed data. The compression mode "
+ "used for a compressed image is indicated in unit bits "
+ "per pixel."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SHUTTER_SPEED_VALUE, "ShutterSpeedValue", N_("Shutter Speed"),
+ N_("Shutter speed. The unit is the APEX (Additive System of "
+ "Photographic Exposure) setting."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_APERTURE_VALUE, "ApertureValue", N_("Aperture"),
+ N_("The lens aperture. The unit is the APEX value."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_BRIGHTNESS_VALUE, "BrightnessValue", N_("Brightness"),
+ N_("The value of brightness. The unit is the APEX value. "
+ "Ordinarily it is given in the range of -99.99 to 99.99."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_EXPOSURE_BIAS_VALUE, "ExposureBiasValue",
+ N_("Exposure Bias"),
+ N_("The exposure bias. The units is the APEX value. Ordinarily "
+ "it is given in the range of -99.99 to 99.99."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_MAX_APERTURE_VALUE, "MaxApertureValue", N_("Maximum Aperture Value"),
+ N_("The smallest F number of the lens. The unit is the APEX value. "
+ "Ordinarily it is given in the range of 00.00 to 99.99, "
+ "but it is not limited to this range."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SUBJECT_DISTANCE, "SubjectDistance",
+ N_("Subject Distance"),
+ N_("The distance to the subject, given in meters."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_METERING_MODE, "MeteringMode", N_("Metering Mode"),
+ N_("The metering mode."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_LIGHT_SOURCE, "LightSource", N_("Light Source"),
+ N_("The kind of light source."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_FLASH, "Flash", N_("Flash"),
+ N_("This tag is recorded when an image is taken using a strobe "
+ "light (flash)."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_FOCAL_LENGTH, "FocalLength", N_("Focal Length"),
+ N_("The actual focal length of the lens, in mm. Conversion is not "
+ "made to the focal length of a 35 mm film camera."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SUBJECT_AREA, "SubjectArea", N_("Subject Area"),
+ N_("This tag indicates the location and area of the main subject "
+ "in the overall scene."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_TIFF_EP_STANDARD_ID, "TIFF/EPStandardID", N_("TIFF/EP Standard ID"), ""},
+ {EXIF_TAG_MAKER_NOTE, "MakerNote", N_("Maker Note"),
+ N_("A tag for manufacturers of Exif writers to record any desired "
+ "information. The contents are up to the manufacturer."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_USER_COMMENT, "UserComment", N_("User Comment"),
+ N_("A tag for Exif users to write keywords or comments on the image "
+ "besides those in <ImageDescription>, and without the "
+ "character code limitations of the <ImageDescription> tag. The "
+ "character code used in the <UserComment> tag is identified "
+ "based on an ID code in a fixed 8-byte area at the start of "
+ "the tag data area. The unused portion of the area is padded "
+ "with NULL (\"00.h\"). ID codes are assigned by means of "
+ "registration. The designation method and references for each "
+ "character code are defined in the specification. The value of "
+ "CountN is determined based on the 8 bytes in the character code "
+ "area and the number of bytes in the user comment part. Since "
+ "the TYPE is not ASCII, NULL termination is not necessary. "
+ "The ID code for the <UserComment> area may be a Defined code "
+ "such as JIS or ASCII, or may be Undefined. The Undefined name "
+ "is UndefinedText, and the ID code is filled with 8 bytes of all "
+ "\"NULL\" (\"00.H\"). An Exif reader that reads the "
+ "<UserComment> tag must have a function for determining the "
+ "ID code. This function is not required in Exif readers that "
+ "do not use the <UserComment> tag. "
+ "When a <UserComment> area is set aside, it is recommended that "
+ "the ID code be ASCII and that the following user comment "
+ "part be filled with blank characters [20.H]."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SUB_SEC_TIME, "SubsecTime", N_("Sub-second Time"),
+ N_("A tag used to record fractions of seconds for the "
+ "<DateTime> tag."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SUB_SEC_TIME_ORIGINAL, "SubSecTimeOriginal",
+ N_("Sub-second Time (Original)"),
+ N_("A tag used to record fractions of seconds for the "
+ "<DateTimeOriginal> tag."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SUB_SEC_TIME_DIGITIZED, "SubSecTimeDigitized",
+ N_("Sub-second Time (Digitized)"),
+ N_("A tag used to record fractions of seconds for the "
+ "<DateTimeDigitized> tag."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 (Microsoft extension) */
+ {EXIF_TAG_XP_TITLE, "XPTitle", N_("XP Title"),
+ N_("A character string giving the title of the image, encoded in "
+ "UTF-16LE."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 (Microsoft extension) */
+ {EXIF_TAG_XP_COMMENT, "XPComment", N_("XP Comment"),
+ N_("A character string containing a comment about the image, encoded "
+ "in UTF-16LE."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 (Microsoft extension) */
+ {EXIF_TAG_XP_AUTHOR, "XPAuthor", N_("XP Author"),
+ N_("A character string containing the name of the image creator, "
+ "encoded in UTF-16LE."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 (Microsoft extension) */
+ {EXIF_TAG_XP_KEYWORDS, "XPKeywords", N_("XP Keywords"),
+ N_("A character string containing key words describing the image, "
+ "encoded in UTF-16LE."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 (Microsoft extension) */
+ {EXIF_TAG_XP_SUBJECT, "XPSubject", N_("XP Subject"),
+ N_("A character string giving the image subject, encoded in "
+ "UTF-16LE."),
+ { ESL_OOOO, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_FLASH_PIX_VERSION, "FlashPixVersion", "FlashPixVersion",
+ N_("The FlashPix format version supported by a FPXR file."),
+ { ESL_NNNN, ESL_NNNN, ESL_MMMM, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_COLOR_SPACE, "ColorSpace", N_("Color Space"),
+ N_("The color space information tag is always "
+ "recorded as the color space specifier. Normally sRGB (=1) "
+ "is used to define the color space based on the PC monitor "
+ "conditions and environment. If a color space other than "
+ "sRGB is used, Uncalibrated (=FFFF.H) is set. Image data "
+ "recorded as Uncalibrated can be treated as sRGB when it is "
+ "converted to FlashPix."),
+ { ESL_NNNN, ESL_NNNN, ESL_MMMM, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_PIXEL_X_DIMENSION, "PixelXDimension", N_("Pixel X Dimension"),
+ N_("Information specific to compressed data. When a "
+ "compressed file is recorded, the valid width of the "
+ "meaningful image must be recorded in this tag, whether or "
+ "not there is padding data or a restart marker. This tag "
+ "should not exist in an uncompressed file."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_PIXEL_Y_DIMENSION, "PixelYDimension", N_("Pixel Y Dimension"),
+ N_("Information specific to compressed data. When a compressed "
+ "file is recorded, the valid height of the meaningful image "
+ "must be recorded in this tag, whether or not there is padding "
+ "data or a restart marker. This tag should not exist in an "
+ "uncompressed file. "
+ "Since data padding is unnecessary in the vertical direction, "
+ "the number of lines recorded in this valid image height tag "
+ "will in fact be the same as that recorded in the SOF."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNM, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_RELATED_SOUND_FILE, "RelatedSoundFile",
+ N_("Related Sound File"),
+ N_("This tag is used to record the name of an audio file related "
+ "to the image data. The only relational information "
+ "recorded here is the Exif audio file name and extension (an "
+ "ASCII string consisting of 8 characters + '.' + 3 "
+ "characters). The path is not recorded. Stipulations on audio "
+ "and file naming conventions are defined in the specification. "
+ "When using this tag, audio files must be recorded in "
+ "conformance to the Exif audio format. Writers are also allowed "
+ "to store the data such as Audio within APP2 as FlashPix "
+ "extension stream data. "
+ "The mapping of Exif image files and audio files is done "
+ "in any of three ways, [1], [2] and [3]. If multiple files "
+ "are mapped to one file as in [2] or [3], the above "
+ "format is used to record just one audio file name. If "
+ "there are multiple audio files, the first recorded file is "
+ "given. In the case of [3], for example, for the "
+ "Exif image file \"DSC00001.JPG\" only \"SND00001.WAV\" is "
+ "given as the related Exif audio file. When there are three "
+ "Exif audio files \"SND00001.WAV\", \"SND00002.WAV\" and "
+ "\"SND00003.WAV\", the Exif image file name for each of them, "
+ "\"DSC00001.JPG\", is indicated. By combining multiple "
+ "relational information, a variety of playback possibilities "
+ "can be supported. The method of using relational information "
+ "is left to the implementation on the playback side. Since this "
+ "information is an ASCII character string, it is terminated by "
+ "NULL. When this tag is used to map audio files, the relation "
+ "of the audio file to image data must also be indicated on the "
+ "audio file end."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_INTEROPERABILITY_IFD_POINTER, "InteroperabilityIFDPointer",
+ N_("Interoperability IFD Pointer"),
+ N_("Interoperability IFD is composed of tags which stores the "
+ "information to ensure the Interoperability and pointed "
+ "by the following tag located in Exif IFD. "
+ "The Interoperability structure of Interoperability IFD is "
+ "the same as TIFF defined IFD structure "
+ "but does not contain the "
+ "image data characteristically compared with normal TIFF "
+ "IFD."),
+ { ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_FLASH_ENERGY, "FlashEnergy", N_("Flash Energy"),
+ N_("Indicates the strobe energy at the time the image is "
+ "captured, as measured in Beam Candle Power Seconds (BCPS)."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE, "SpatialFrequencyResponse",
+ N_("Spatial Frequency Response"),
+ N_("This tag records the camera or input device spatial frequency "
+ "table and SFR values in the direction of image width, "
+ "image height, and diagonal direction, as specified in ISO "
+ "12233."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_FOCAL_PLANE_X_RESOLUTION, "FocalPlaneXResolution",
+ N_("Focal Plane X-Resolution"),
+ N_("Indicates the number of pixels in the image width (X) direction "
+ "per <FocalPlaneResolutionUnit> on the camera focal plane."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION, "FocalPlaneYResolution",
+ N_("Focal Plane Y-Resolution"),
+ N_("Indicates the number of pixels in the image height (V) direction "
+ "per <FocalPlaneResolutionUnit> on the camera focal plane."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT, "FocalPlaneResolutionUnit",
+ N_("Focal Plane Resolution Unit"),
+ N_("Indicates the unit for measuring <FocalPlaneXResolution> and "
+ "<FocalPlaneYResolution>. This value is the same as the "
+ "<ResolutionUnit>."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SUBJECT_LOCATION, "SubjectLocation",
+ N_("Subject Location"),
+ N_("Indicates the location of the main subject in the scene. The "
+ "value of this tag represents the pixel at the center of the "
+ "main subject relative to the left edge, prior to rotation "
+ "processing as per the <Rotation> tag. The first value "
+ "indicates the X column number and the second indicates "
+ "the Y row number."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_EXPOSURE_INDEX, "ExposureIndex", N_("Exposure Index"),
+ N_("Indicates the exposure index selected on the camera or "
+ "input device at the time the image is captured."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SENSING_METHOD, "SensingMethod", N_("Sensing Method"),
+ N_("Indicates the image sensor type on the camera or input "
+ "device."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_FILE_SOURCE, "FileSource", N_("File Source"),
+ N_("Indicates the image source. If a DSC recorded the image, "
+ "the tag value of this tag always be set to 3, indicating "
+ "that the image was recorded on a DSC."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SCENE_TYPE, "SceneType", N_("Scene Type"),
+ N_("Indicates the type of scene. If a DSC recorded the image, "
+ "this tag value must always be set to 1, indicating that the "
+ "image was directly photographed."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_NEW_CFA_PATTERN, "CFAPattern",
+ N_("CFA Pattern"),
+ N_("Indicates the color filter array (CFA) geometric pattern of the "
+ "image sensor when a one-chip color area sensor is used. "
+ "It does not apply to all sensing methods."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_CUSTOM_RENDERED, "CustomRendered", N_("Custom Rendered"),
+ N_("This tag indicates the use of special processing on image "
+ "data, such as rendering geared to output. When special "
+ "processing is performed, the reader is expected to disable "
+ "or minimize any further processing."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_EXPOSURE_MODE, "ExposureMode", N_("Exposure Mode"),
+ N_("This tag indicates the exposure mode set when the image was "
+ "shot. In auto-bracketing mode, the camera shoots a series of "
+ "frames of the same scene at different exposure settings."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance"),
+ N_("This tag indicates the white balance mode set when the image "
+ "was shot."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_DIGITAL_ZOOM_RATIO, "DigitalZoomRatio",
+ N_("Digital Zoom Ratio"),
+ N_("This tag indicates the digital zoom ratio when the image was "
+ "shot. If the numerator of the recorded value is 0, this "
+ "indicates that digital zoom was not used."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM, "FocalLengthIn35mmFilm",
+ N_("Focal Length in 35mm Film"),
+ N_("This tag indicates the equivalent focal length assuming a "
+ "35mm film camera, in mm. A value of 0 means the focal "
+ "length is unknown. Note that this tag differs from the "
+ "FocalLength tag."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SCENE_CAPTURE_TYPE, "SceneCaptureType",
+ N_("Scene Capture Type"),
+ N_("This tag indicates the type of scene that was shot. It can "
+ "also be used to record the mode in which the image was "
+ "shot. Note that this differs from the scene type "
+ "<SceneType> tag."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_GAIN_CONTROL, "GainControl", N_("Gain Control"),
+ N_("This tag indicates the degree of overall image gain "
+ "adjustment."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_CONTRAST, "Contrast", N_("Contrast"),
+ N_("This tag indicates the direction of contrast processing "
+ "applied by the camera when the image was shot."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SATURATION, "Saturation", N_("Saturation"),
+ N_("This tag indicates the direction of saturation processing "
+ "applied by the camera when the image was shot."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SHARPNESS, "Sharpness", N_("Sharpness"),
+ N_("This tag indicates the direction of sharpness processing "
+ "applied by the camera when the image was shot."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_DEVICE_SETTING_DESCRIPTION, "DeviceSettingDescription",
+ N_("Device Setting Description"),
+ N_("This tag indicates information on the picture-taking "
+ "conditions of a particular camera model. The tag is used "
+ "only to indicate the picture-taking conditions in the "
+ "reader."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_SUBJECT_DISTANCE_RANGE, "SubjectDistanceRange",
+ N_("Subject Distance Range"),
+ N_("This tag indicates the distance to the subject."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ {EXIF_TAG_IMAGE_UNIQUE_ID, "ImageUniqueID", N_("Image Unique ID"),
+ N_("This tag indicates an identifier assigned uniquely to "
+ "each image. It is recorded as an ASCII string equivalent "
+ "to hexadecimal notation and 128-bit fixed length."),
+ { ESL_NNNN, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_GAMMA, "Gamma", N_("Gamma"),
+ N_("Indicates the value of coefficient gamma.")},
+ /* Not in EXIF 2.2 */
+ {EXIF_TAG_PRINT_IMAGE_MATCHING, "PrintImageMatching", N_("PRINT Image Matching"),
+ N_("Related to Epson's PRINT Image Matching technology")},
+ /* Not in EXIF 2.2 (from the Microsoft HD Photo specification) */
+ {EXIF_TAG_PADDING, "Padding", N_("Padding"),
+ N_("This tag reserves space that can be reclaimed later when "
+ "additional metadata are added. New metadata can be written "
+ "in place by replacing this tag with a smaller data element "
+ "and using the reclaimed space to store the new or expanded "
+ "metadata tags."),
+ { ESL_OOOO, ESL_NNNN, ESL_OOOO, ESL_NNNN, ESL_NNNN } },
+#endif
+ {0, NULL, NULL, NULL}
+};
+
+/* For now, do not use these functions. */
+
+/*!
+ * Return the number of entries in the EXIF tag table, including the
+ * terminating NULL entry.
+ */
+inline unsigned int
+exif_tag_table_count (void)
+{
+ return sizeof (ExifTagTable) / sizeof (ExifTagTable[0]);
+}
+
+
+ExifTag
+exif_tag_table_get_tag (unsigned int n)
+{
+ return (n < exif_tag_table_count ()) ? ExifTagTable[n].tag : 0;
+}
+
+const char *
+exif_tag_table_get_name (unsigned int n)
+{
+ return (n < exif_tag_table_count ()) ? ExifTagTable[n].name : NULL;
+}
+
+/*!
+ * Compares the tag with that in entry.
+ * \param[in] tag pointer to integer tag value
+ * \param[in] entry pointer to a struct TagEntry
+ * \return 0 if tags are equal, <0 if tag < entry, >0 if tag > entry
+ */
+static int
+match_tag(const void *tag, const void *entry)
+{
+ return *(int*)tag - ((struct TagEntry *)entry)->tag;
+}
+
+
+/*!
+ * Finds the first entry in the EXIF tag table with the given tag number
+ * using a binary search.
+ * \param[in] tag to find
+ * \return index into table, or -1 if not found
+ */
+static int
+exif_tag_table_first(ExifTag tag)
+{
+ int i;
+ struct TagEntry *entry = bsearch(&tag, ExifTagTable,
+ exif_tag_table_count()-1, sizeof(struct TagEntry), match_tag);
+ if (!entry)
+ return -1; /* Not found */
+
+ /* Calculate index of found entry */
+ i = entry - ExifTagTable;
+
+ /* There may be other entries with the same tag number, so search
+ * backwards to find the first
+ */
+ while ((i > 0) && (ExifTagTable[i-1].tag == tag)) {
+ --i;
+ }
+ return i;
+}
+
+#define RECORDED \
+((ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_CHUNKY] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \
+ (ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_PLANAR] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \
+ (ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_YCC] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \
+ (ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_COMPRESSED] != EXIF_SUPPORT_LEVEL_NOT_RECORDED))
+
+const char *
+exif_tag_get_name_in_ifd (ExifTag tag, ExifIfd ifd)
+{
+ unsigned int i;
+ int first;
+
+ if (ifd >= EXIF_IFD_COUNT)
+ return NULL;
+ first = exif_tag_table_first(tag);
+ if (first < 0)
+ return NULL;
+
+ for (i = first; ExifTagTable[i].name; i++) {
+ if (ExifTagTable[i].tag == tag) {
+ if (RECORDED)
+ break;
+ } else
+ return NULL; /* Recorded tag not found in the table */
+ }
+ return ExifTagTable[i].name;
+}
+
+const char *
+exif_tag_get_title_in_ifd (ExifTag tag, ExifIfd ifd)
+{
+ unsigned int i;
+ int first;
+
+ if (ifd >= EXIF_IFD_COUNT)
+ return NULL;
+ first = exif_tag_table_first(tag);
+ if (first < 0)
+ return NULL;
+
+ for (i = first; ExifTagTable[i].name; i++) {
+ if (ExifTagTable[i].tag == tag) {
+ if (RECORDED)
+ break;
+ } else
+ return NULL; /* Recorded tag not found in the table */
+ }
+ /* FIXME: This belongs to somewhere else. */
+ /* libexif should use the default system locale.
+ * If an application specifically requires UTF-8, then we
+ * must give the application a way to tell libexif that.
+ *
+ * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ */
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ return _(ExifTagTable[i].title);
+}
+
+const char *
+exif_tag_get_description_in_ifd (ExifTag tag, ExifIfd ifd)
+{
+ unsigned int i;
+ int first;
+
+ if (ifd >= EXIF_IFD_COUNT)
+ return NULL;
+ first = exif_tag_table_first(tag);
+ if (first < 0)
+ return NULL;
+
+ for (i = first; ExifTagTable[i].name; i++) {
+ if (ExifTagTable[i].tag == tag) {
+ if (RECORDED)
+ break;
+ } else
+ return NULL; /* Recorded tag not found in the table */
+ }
+
+ /* GNU gettext acts strangely when given an empty string */
+ if (!ExifTagTable[i].description || !*ExifTagTable[i].description)
+ return "";
+
+ /* libexif should use the default system locale.
+ * If an application specifically requires UTF-8, then we
+ * must give the application a way to tell libexif that.
+ *
+ * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ */
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ return _(ExifTagTable[i].description);
+}
+
+
+/**********************************************************************
+ * convenience functions
+ **********************************************************************/
+
+/* generic part: iterate through IFD list and return first result */
+typedef const char * (*get_stuff_func) (ExifTag tag, ExifIfd ifd);
+
+static const char *
+exif_tag_get_stuff (ExifTag tag, get_stuff_func func)
+{
+ /* Search IFDs in this order, in decreasing order of number of valid tags */
+ static const ExifIfd ifds[EXIF_IFD_COUNT] = {
+ EXIF_IFD_EXIF,
+ EXIF_IFD_0,
+ EXIF_IFD_1,
+ EXIF_IFD_INTEROPERABILITY,
+ EXIF_IFD_GPS
+ };
+ int i;
+ for (i=0; i<EXIF_IFD_COUNT; i++) {
+ const char *result = func(tag, ifds[i]);
+ if (result != NULL) {
+ return result;
+ }
+ }
+ return (const char *) NULL;
+}
+
+/* explicit functions */
+const char *
+exif_tag_get_name (ExifTag tag)
+{
+ return exif_tag_get_stuff(tag, exif_tag_get_name_in_ifd);
+}
+
+const char *
+exif_tag_get_title (ExifTag tag)
+{
+ return exif_tag_get_stuff(tag, exif_tag_get_title_in_ifd);
+}
+
+const char *
+exif_tag_get_description (ExifTag tag)
+{
+ return exif_tag_get_stuff(tag, exif_tag_get_description_in_ifd);
+}
+
+
+
+ExifTag
+exif_tag_from_name (const char *name)
+{
+ unsigned int i;
+ unsigned int result=0;
+
+ if (!name) return 0;
+
+ for (i = 0; ExifTagTable[i].name; i++)
+ if (!strcmp (ExifTagTable[i].name, name)) {
+ result = ExifTagTable[i].tag;
+ break;
+ }
+ return result;
+}
+
+/*! Return the support level of a tag in the given IFD with the given data
+ * type. If the tag is not specified in the EXIF standard, this function
+ * returns EXIF_SUPPORT_LEVEL_NOT_RECORDED.
+ *
+ * \param[in] tag EXIF tag
+ * \param[in] ifd a valid IFD (not EXIF_IFD_COUNT)
+ * \param[in] t a valid data type (not EXIF_DATA_TYPE_UNKNOWN)
+ * \return the level of support for this tag
+ */
+static inline ExifSupportLevel
+get_support_level_in_ifd (ExifTag tag, ExifIfd ifd, ExifDataType t)
+{
+ unsigned int i;
+ int first = exif_tag_table_first(tag);
+ if (first < 0)
+ return EXIF_SUPPORT_LEVEL_NOT_RECORDED;
+
+ for (i = first; ExifTagTable[i].name; i++) {
+ if (ExifTagTable[i].tag == tag) {
+ const ExifSupportLevel supp = ExifTagTable[i].esl[ifd][t];
+ if (supp != EXIF_SUPPORT_LEVEL_NOT_RECORDED)
+ return supp;
+ /* Try looking for another entry */
+ } else {
+ break; /* We've reached the end of the matching tags */
+ }
+ }
+ return EXIF_SUPPORT_LEVEL_NOT_RECORDED;
+}
+
+/*! Return the support level of a tag in the given IFD, regardless of the
+ * data type. If the support level varies depending on the data type, this
+ * function returns EXIF_SUPPORT_LEVEL_UNKNOWN. If the tag is not specified
+ * in the EXIF standard, this function returns EXIF_SUPPORT_LEVEL_UNKNOWN.
+ *
+ * \param[in] tag EXIF tag
+ * \param[in] ifd a valid IFD (not EXIF_IFD_COUNT)
+ * \return the level of support for this tag
+ */
+static inline ExifSupportLevel
+get_support_level_any_type (ExifTag tag, ExifIfd ifd)
+{
+ unsigned int i;
+ int first = exif_tag_table_first(tag);
+ if (first < 0)
+ return EXIF_SUPPORT_LEVEL_UNKNOWN;
+
+ for (i = first; ExifTagTable[i].name; i++) {
+ if (ExifTagTable[i].tag == tag) {
+ /*
+ * Check whether the support level is the same for all possible
+ * data types and isn't marked not recorded.
+ */
+ const ExifSupportLevel supp = ExifTagTable[i].esl[ifd][0];
+ /* If level is not recorded, keep searching for another */
+ if (supp != EXIF_SUPPORT_LEVEL_NOT_RECORDED) {
+ unsigned int dt;
+ for (dt = 0; dt < EXIF_DATA_TYPE_COUNT; ++dt) {
+ if (ExifTagTable[i].esl[ifd][dt] != supp)
+ break;
+ }
+ if (dt == EXIF_DATA_TYPE_COUNT)
+ /* Support level is always the same, so return it */
+ return supp;
+ }
+ /* Keep searching the table for another tag for our IFD */
+ } else {
+ break; /* We've reached the end of the matching tags */
+ }
+ }
+ return EXIF_SUPPORT_LEVEL_UNKNOWN;
+}
+
+ExifSupportLevel
+exif_tag_get_support_level_in_ifd (ExifTag tag, ExifIfd ifd, ExifDataType t)
+{
+ if (ifd >= EXIF_IFD_COUNT)
+ return EXIF_SUPPORT_LEVEL_UNKNOWN;
+
+ if (t >= EXIF_DATA_TYPE_COUNT)
+ return get_support_level_any_type (tag, ifd);
+
+ return get_support_level_in_ifd (tag, ifd, t);
+}
diff --git a/libexif/exif-tag.h b/libexif/exif-tag.h
new file mode 100644
index 0000000..d8b8657
--- /dev/null
+++ b/libexif/exif-tag.h
@@ -0,0 +1,287 @@
+/*! \file exif-tag.h
+ * \brief Handling EXIF tags
+ */
+/*
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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_TAG_H__
+#define __EXIF_TAG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-ifd.h>
+#include <libexif/exif-data-type.h>
+
+/*! EXIF tags */
+typedef enum {
+ EXIF_TAG_INTEROPERABILITY_INDEX = 0x0001,
+ EXIF_TAG_INTEROPERABILITY_VERSION = 0x0002,
+ EXIF_TAG_NEW_SUBFILE_TYPE = 0x00fe,
+ EXIF_TAG_IMAGE_WIDTH = 0x0100,
+ EXIF_TAG_IMAGE_LENGTH = 0x0101,
+ EXIF_TAG_BITS_PER_SAMPLE = 0x0102,
+ EXIF_TAG_COMPRESSION = 0x0103,
+ EXIF_TAG_PHOTOMETRIC_INTERPRETATION = 0x0106,
+ EXIF_TAG_FILL_ORDER = 0x010a,
+ EXIF_TAG_DOCUMENT_NAME = 0x010d,
+ EXIF_TAG_IMAGE_DESCRIPTION = 0x010e,
+ EXIF_TAG_MAKE = 0x010f,
+ EXIF_TAG_MODEL = 0x0110,
+ EXIF_TAG_STRIP_OFFSETS = 0x0111,
+ EXIF_TAG_ORIENTATION = 0x0112,
+ EXIF_TAG_SAMPLES_PER_PIXEL = 0x0115,
+ EXIF_TAG_ROWS_PER_STRIP = 0x0116,
+ EXIF_TAG_STRIP_BYTE_COUNTS = 0x0117,
+ EXIF_TAG_X_RESOLUTION = 0x011a,
+ EXIF_TAG_Y_RESOLUTION = 0x011b,
+ EXIF_TAG_PLANAR_CONFIGURATION = 0x011c,
+ EXIF_TAG_RESOLUTION_UNIT = 0x0128,
+ EXIF_TAG_TRANSFER_FUNCTION = 0x012d,
+ EXIF_TAG_SOFTWARE = 0x0131,
+ EXIF_TAG_DATE_TIME = 0x0132,
+ EXIF_TAG_ARTIST = 0x013b,
+ EXIF_TAG_WHITE_POINT = 0x013e,
+ EXIF_TAG_PRIMARY_CHROMATICITIES = 0x013f,
+ EXIF_TAG_SUB_IFDS = 0x014a,
+ EXIF_TAG_TRANSFER_RANGE = 0x0156,
+ EXIF_TAG_JPEG_PROC = 0x0200,
+ EXIF_TAG_JPEG_INTERCHANGE_FORMAT = 0x0201,
+ EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 0x0202,
+ EXIF_TAG_YCBCR_COEFFICIENTS = 0x0211,
+ EXIF_TAG_YCBCR_SUB_SAMPLING = 0x0212,
+ EXIF_TAG_YCBCR_POSITIONING = 0x0213,
+ EXIF_TAG_REFERENCE_BLACK_WHITE = 0x0214,
+ EXIF_TAG_XML_PACKET = 0x02bc,
+ EXIF_TAG_RELATED_IMAGE_FILE_FORMAT = 0x1000,
+ EXIF_TAG_RELATED_IMAGE_WIDTH = 0x1001,
+ EXIF_TAG_RELATED_IMAGE_LENGTH = 0x1002,
+ EXIF_TAG_CFA_REPEAT_PATTERN_DIM = 0x828d,
+ EXIF_TAG_CFA_PATTERN = 0x828e,
+ EXIF_TAG_BATTERY_LEVEL = 0x828f,
+ EXIF_TAG_COPYRIGHT = 0x8298,
+ EXIF_TAG_EXPOSURE_TIME = 0x829a,
+ EXIF_TAG_FNUMBER = 0x829d,
+ EXIF_TAG_IPTC_NAA = 0x83bb,
+ EXIF_TAG_IMAGE_RESOURCES = 0x8649,
+ EXIF_TAG_EXIF_IFD_POINTER = 0x8769,
+ EXIF_TAG_INTER_COLOR_PROFILE = 0x8773,
+ EXIF_TAG_EXPOSURE_PROGRAM = 0x8822,
+ EXIF_TAG_SPECTRAL_SENSITIVITY = 0x8824,
+ EXIF_TAG_GPS_INFO_IFD_POINTER = 0x8825,
+ EXIF_TAG_ISO_SPEED_RATINGS = 0x8827,
+ EXIF_TAG_OECF = 0x8828,
+ EXIF_TAG_TIME_ZONE_OFFSET = 0x882a,
+ EXIF_TAG_EXIF_VERSION = 0x9000,
+ EXIF_TAG_DATE_TIME_ORIGINAL = 0x9003,
+ EXIF_TAG_DATE_TIME_DIGITIZED = 0x9004,
+ EXIF_TAG_COMPONENTS_CONFIGURATION = 0x9101,
+ EXIF_TAG_COMPRESSED_BITS_PER_PIXEL = 0x9102,
+ EXIF_TAG_SHUTTER_SPEED_VALUE = 0x9201,
+ EXIF_TAG_APERTURE_VALUE = 0x9202,
+ EXIF_TAG_BRIGHTNESS_VALUE = 0x9203,
+ EXIF_TAG_EXPOSURE_BIAS_VALUE = 0x9204,
+ EXIF_TAG_MAX_APERTURE_VALUE = 0x9205,
+ EXIF_TAG_SUBJECT_DISTANCE = 0x9206,
+ EXIF_TAG_METERING_MODE = 0x9207,
+ EXIF_TAG_LIGHT_SOURCE = 0x9208,
+ EXIF_TAG_FLASH = 0x9209,
+ EXIF_TAG_FOCAL_LENGTH = 0x920a,
+ EXIF_TAG_SUBJECT_AREA = 0x9214,
+ EXIF_TAG_TIFF_EP_STANDARD_ID = 0x9216,
+ EXIF_TAG_MAKER_NOTE = 0x927c,
+ EXIF_TAG_USER_COMMENT = 0x9286,
+ EXIF_TAG_SUB_SEC_TIME = 0x9290,
+ EXIF_TAG_SUB_SEC_TIME_ORIGINAL = 0x9291,
+ EXIF_TAG_SUB_SEC_TIME_DIGITIZED = 0x9292,
+ EXIF_TAG_XP_TITLE = 0x9c9b,
+ EXIF_TAG_XP_COMMENT = 0x9c9c,
+ EXIF_TAG_XP_AUTHOR = 0x9c9d,
+ EXIF_TAG_XP_KEYWORDS = 0x9c9e,
+ EXIF_TAG_XP_SUBJECT = 0x9c9f,
+ EXIF_TAG_FLASH_PIX_VERSION = 0xa000,
+ EXIF_TAG_COLOR_SPACE = 0xa001,
+ EXIF_TAG_PIXEL_X_DIMENSION = 0xa002,
+ EXIF_TAG_PIXEL_Y_DIMENSION = 0xa003,
+ EXIF_TAG_RELATED_SOUND_FILE = 0xa004,
+ EXIF_TAG_INTEROPERABILITY_IFD_POINTER = 0xa005,
+ EXIF_TAG_FLASH_ENERGY = 0xa20b,
+ EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE = 0xa20c,
+ EXIF_TAG_FOCAL_PLANE_X_RESOLUTION = 0xa20e,
+ EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION = 0xa20f,
+ EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT = 0xa210,
+ EXIF_TAG_SUBJECT_LOCATION = 0xa214,
+ EXIF_TAG_EXPOSURE_INDEX = 0xa215,
+ EXIF_TAG_SENSING_METHOD = 0xa217,
+ EXIF_TAG_FILE_SOURCE = 0xa300,
+ EXIF_TAG_SCENE_TYPE = 0xa301,
+ EXIF_TAG_NEW_CFA_PATTERN = 0xa302,
+ EXIF_TAG_CUSTOM_RENDERED = 0xa401,
+ EXIF_TAG_EXPOSURE_MODE = 0xa402,
+ EXIF_TAG_WHITE_BALANCE = 0xa403,
+ EXIF_TAG_DIGITAL_ZOOM_RATIO = 0xa404,
+ EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM = 0xa405,
+ EXIF_TAG_SCENE_CAPTURE_TYPE = 0xa406,
+ EXIF_TAG_GAIN_CONTROL = 0xa407,
+ EXIF_TAG_CONTRAST = 0xa408,
+ EXIF_TAG_SATURATION = 0xa409,
+ EXIF_TAG_SHARPNESS = 0xa40a,
+ EXIF_TAG_DEVICE_SETTING_DESCRIPTION = 0xa40b,
+ EXIF_TAG_SUBJECT_DISTANCE_RANGE = 0xa40c,
+ EXIF_TAG_IMAGE_UNIQUE_ID = 0xa420,
+ EXIF_TAG_GAMMA = 0xa500,
+ EXIF_TAG_PRINT_IMAGE_MATCHING = 0xc4a5,
+ EXIF_TAG_PADDING = 0xea1c
+} ExifTag;
+
+/* GPS tags overlap with above ones. */
+#define EXIF_TAG_GPS_VERSION_ID 0x0000
+#define EXIF_TAG_GPS_LATITUDE_REF 0x0001 /* INTEROPERABILITY_INDEX */
+#define EXIF_TAG_GPS_LATITUDE 0x0002 /* INTEROPERABILITY_VERSION */
+#define EXIF_TAG_GPS_LONGITUDE_REF 0x0003
+#define EXIF_TAG_GPS_LONGITUDE 0x0004
+#define EXIF_TAG_GPS_ALTITUDE_REF 0x0005
+#define EXIF_TAG_GPS_ALTITUDE 0x0006
+#define EXIF_TAG_GPS_TIME_STAMP 0x0007
+#define EXIF_TAG_GPS_SATELLITES 0x0008
+#define EXIF_TAG_GPS_STATUS 0x0009
+#define EXIF_TAG_GPS_MEASURE_MODE 0x000a
+#define EXIF_TAG_GPS_DOP 0x000b
+#define EXIF_TAG_GPS_SPEED_REF 0x000c
+#define EXIF_TAG_GPS_SPEED 0x000d
+#define EXIF_TAG_GPS_TRACK_REF 0x000e
+#define EXIF_TAG_GPS_TRACK 0x000f
+#define EXIF_TAG_GPS_IMG_DIRECTION_REF 0x0010
+#define EXIF_TAG_GPS_IMG_DIRECTION 0x0011
+#define EXIF_TAG_GPS_MAP_DATUM 0x0012
+#define EXIF_TAG_GPS_DEST_LATITUDE_REF 0x0013
+#define EXIF_TAG_GPS_DEST_LATITUDE 0x0014
+#define EXIF_TAG_GPS_DEST_LONGITUDE_REF 0x0015
+#define EXIF_TAG_GPS_DEST_LONGITUDE 0x0016
+#define EXIF_TAG_GPS_DEST_BEARING_REF 0x0017
+#define EXIF_TAG_GPS_DEST_BEARING 0x0018
+#define EXIF_TAG_GPS_DEST_DISTANCE_REF 0x0019
+#define EXIF_TAG_GPS_DEST_DISTANCE 0x001a
+#define EXIF_TAG_GPS_PROCESSING_METHOD 0x001b
+#define EXIF_TAG_GPS_AREA_INFORMATION 0x001c
+#define EXIF_TAG_GPS_DATE_STAMP 0x001d
+#define EXIF_TAG_GPS_DIFFERENTIAL 0x001e
+
+/*! What level of support a tag enjoys in the EXIF standard */
+typedef enum {
+ /*! The meaning of this tag is unknown */
+ EXIF_SUPPORT_LEVEL_UNKNOWN = 0,
+
+ /*! This tag is not allowed in the given IFD */
+ EXIF_SUPPORT_LEVEL_NOT_RECORDED,
+
+ /*! This tag is mandatory in the given IFD */
+ EXIF_SUPPORT_LEVEL_MANDATORY,
+
+ /*! This tag is optional in the given IFD */
+ EXIF_SUPPORT_LEVEL_OPTIONAL
+} ExifSupportLevel;
+
+/*! Return the tag ID given its unique textual name.
+ *
+ * \param[in] name tag name
+ * \return tag ID, or 0 if tag not found
+ * \note The tag not found value cannot be distinguished from a legitimate
+ * tag number 0.
+ */
+ExifTag exif_tag_from_name (const char *name);
+
+/*! Return a textual name of the given tag when found in the given IFD. The
+ * name is a short, unique, non-localized text string containing only
+ * US-ASCII alphanumeric characters.
+ *
+ * \param[in] tag EXIF tag
+ * \param[in] ifd IFD
+ * \return textual name of the tag, or NULL if the tag is unknown
+ */
+const char *exif_tag_get_name_in_ifd (ExifTag tag, ExifIfd ifd);
+
+/*! Return a textual title of the given tag when found in the given IFD.
+ * The title is a short, localized description of the tag.
+ *
+ * \param[in] tag EXIF tag
+ * \param[in] ifd IFD
+ * \return textual title of the tag, or NULL if the tag is unknown
+ */
+const char *exif_tag_get_title_in_ifd (ExifTag tag, ExifIfd ifd);
+
+/*! Return a verbose textual description of the given tag when found in the
+ * given IFD. The description is a verbose, localized description of the tag.
+ *
+ * \param[in] tag EXIF tag
+ * \param[in] ifd IFD
+ * \return textual description of the tag, or NULL if the tag is unknown
+ */
+const char *exif_tag_get_description_in_ifd (ExifTag tag, ExifIfd ifd);
+
+/*! Return whether the given tag is mandatory or not in the given IFD and
+ * data type according to the EXIF specification. If the IFD given is
+ * EXIF_IFD_COUNT, the result is EXIF_SUPPORT_LEVEL_UNKNOWN. If the data
+ * type is EXIF_DATA_TYPE_UNKNOWN, the result is
+ * EXIF_SUPPORT_LEVEL_UNKNOWN unless the support level is the same for
+ * all data types.
+ *
+ * \param[in] tag EXIF tag
+ * \param[in] ifd IFD or EXIF_IFD_COUNT
+ * \param[in] t data type or EXIF_DATA_TYPE_UNKNOWN
+ * \return the level of support for this tag
+ */
+ExifSupportLevel exif_tag_get_support_level_in_ifd (ExifTag tag, ExifIfd ifd,
+ ExifDataType t);
+
+/* Don't use these functions. They are here for compatibility only. */
+
+/*! \deprecated Use #exif_tag_get_name_in_ifd instead */
+const char *exif_tag_get_name (ExifTag tag);
+
+/*! \deprecated Use #exif_tag_get_title_in_ifd instead */
+const char *exif_tag_get_title (ExifTag tag);
+
+/*! \deprecated Use #exif_tag_get_description_in_ifd instead */
+const char *exif_tag_get_description (ExifTag tag);
+
+
+/* For now, do not use these functions. */
+
+/*! \internal */
+ExifTag exif_tag_table_get_tag (unsigned int n);
+
+/*! \internal */
+const char *exif_tag_table_get_name (unsigned int n);
+
+/*! \internal */
+unsigned int exif_tag_table_count (void);
+
+
+/* Don't use these definitions. They are here for compatibility only. */
+
+/*! \deprecated Use EXIF_TAG_PRINT_IMAGE_MATCHING instead. */
+#define EXIF_TAG_UNKNOWN_C4A5 EXIF_TAG_PRINT_IMAGE_MATCHING
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_TAG_H__ */
diff --git a/libexif/exif-utils.c b/libexif/exif-utils.c
new file mode 100644
index 0000000..f375de1
--- /dev/null
+++ b/libexif/exif-utils.c
@@ -0,0 +1,253 @@
+/* exif-utils.c
+ *
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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 <libexif/exif-utils.h>
+
+void
+exif_array_set_byte_order (ExifFormat f, unsigned char *b, unsigned int n,
+ ExifByteOrder o_orig, ExifByteOrder o_new)
+{
+ unsigned int j;
+ unsigned int fs = exif_format_get_size (f);
+ ExifShort s;
+ ExifSShort ss;
+ ExifLong l;
+ ExifSLong sl;
+ ExifRational r;
+ ExifSRational sr;
+
+ if (!b || !n || !fs) return;
+
+ switch (f) {
+ case EXIF_FORMAT_SHORT:
+ for (j = 0; j < n; j++) {
+ s = exif_get_short (b + j * fs, o_orig);
+ exif_set_short (b + j * fs, o_new, s);
+ }
+ break;
+ case EXIF_FORMAT_SSHORT:
+ for (j = 0; j < n; j++) {
+ ss = exif_get_sshort (b + j * fs, o_orig);
+ exif_set_sshort (b + j * fs, o_new, ss);
+ }
+ break;
+ case EXIF_FORMAT_LONG:
+ for (j = 0; j < n; j++) {
+ l = exif_get_long (b + j * fs, o_orig);
+ exif_set_long (b + j * fs, o_new, l);
+ }
+ break;
+ case EXIF_FORMAT_RATIONAL:
+ for (j = 0; j < n; j++) {
+ r = exif_get_rational (b + j * fs, o_orig);
+ exif_set_rational (b + j * fs, o_new, r);
+ }
+ break;
+ case EXIF_FORMAT_SLONG:
+ for (j = 0; j < n; j++) {
+ sl = exif_get_slong (b + j * fs, o_orig);
+ exif_set_slong (b + j * fs, o_new, sl);
+ }
+ break;
+ case EXIF_FORMAT_SRATIONAL:
+ for (j = 0; j < n; j++) {
+ sr = exif_get_srational (b + j * fs, o_orig);
+ exif_set_srational (b + j * fs, o_new, sr);
+ }
+ break;
+ case EXIF_FORMAT_UNDEFINED:
+ case EXIF_FORMAT_BYTE:
+ case EXIF_FORMAT_ASCII:
+ default:
+ /* Nothing here. */
+ break;
+ }
+}
+
+ExifSShort
+exif_get_sshort (const unsigned char *buf, ExifByteOrder order)
+{
+ if (!buf) return 0;
+ switch (order) {
+ case EXIF_BYTE_ORDER_MOTOROLA:
+ return ((buf[0] << 8) | buf[1]);
+ case EXIF_BYTE_ORDER_INTEL:
+ return ((buf[1] << 8) | buf[0]);
+ }
+
+ /* Won't be reached */
+ return (0);
+}
+
+ExifShort
+exif_get_short (const unsigned char *buf, ExifByteOrder order)
+{
+ return (exif_get_sshort (buf, order) & 0xffff);
+}
+
+void
+exif_set_sshort (unsigned char *b, ExifByteOrder order, ExifSShort value)
+{
+ if (!b) return;
+ switch (order) {
+ case EXIF_BYTE_ORDER_MOTOROLA:
+ b[0] = (unsigned char) (value >> 8);
+ b[1] = (unsigned char) value;
+ break;
+ case EXIF_BYTE_ORDER_INTEL:
+ b[0] = (unsigned char) value;
+ b[1] = (unsigned char) (value >> 8);
+ break;
+ }
+}
+
+void
+exif_set_short (unsigned char *b, ExifByteOrder order, ExifShort value)
+{
+ exif_set_sshort (b, order, value);
+}
+
+ExifSLong
+exif_get_slong (const unsigned char *b, ExifByteOrder order)
+{
+ if (!b) return 0;
+ switch (order) {
+ case EXIF_BYTE_ORDER_MOTOROLA:
+ return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]);
+ case EXIF_BYTE_ORDER_INTEL:
+ return ((b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]);
+ }
+
+ /* Won't be reached */
+ return (0);
+}
+
+void
+exif_set_slong (unsigned char *b, ExifByteOrder order, ExifSLong value)
+{
+ if (!b) return;
+ switch (order) {
+ case EXIF_BYTE_ORDER_MOTOROLA:
+ b[0] = (unsigned char) (value >> 24);
+ b[1] = (unsigned char) (value >> 16);
+ b[2] = (unsigned char) (value >> 8);
+ b[3] = (unsigned char) value;
+ break;
+ case EXIF_BYTE_ORDER_INTEL:
+ b[3] = (unsigned char) (value >> 24);
+ b[2] = (unsigned char) (value >> 16);
+ b[1] = (unsigned char) (value >> 8);
+ b[0] = (unsigned char) value;
+ break;
+ }
+}
+
+ExifLong
+exif_get_long (const unsigned char *buf, ExifByteOrder order)
+{
+ return (exif_get_slong (buf, order) & 0xffffffff);
+}
+
+void
+exif_set_long (unsigned char *b, ExifByteOrder order, ExifLong value)
+{
+ exif_set_slong (b, order, value);
+}
+
+ExifSRational
+exif_get_srational (const unsigned char *buf, ExifByteOrder order)
+{
+ ExifSRational r;
+
+ r.numerator = buf ? exif_get_slong (buf, order) : 0;
+ r.denominator = buf ? exif_get_slong (buf + 4, order) : 0;
+
+ return (r);
+}
+
+ExifRational
+exif_get_rational (const unsigned char *buf, ExifByteOrder order)
+{
+ ExifRational r;
+
+ r.numerator = buf ? exif_get_long (buf, order) : 0;
+ r.denominator = buf ? exif_get_long (buf + 4, order) : 0;
+
+ return (r);
+}
+
+void
+exif_set_rational (unsigned char *buf, ExifByteOrder order,
+ ExifRational value)
+{
+ if (!buf) return;
+ exif_set_long (buf, order, value.numerator);
+ exif_set_long (buf + 4, order, value.denominator);
+}
+
+void
+exif_set_srational (unsigned char *buf, ExifByteOrder order,
+ ExifSRational value)
+{
+ if (!buf) return;
+ exif_set_slong (buf, order, value.numerator);
+ exif_set_slong (buf + 4, order, value.denominator);
+}
+
+/*! This function converts rather UCS-2LE than UTF-16 to UTF-8.
+ * It should really be replaced by iconv().
+ */
+void
+exif_convert_utf16_to_utf8 (char *out, const unsigned short *in, int maxlen)
+{
+ if (maxlen <= 0) {
+ return;
+ }
+ while (*in) {
+ if (*in < 0x80) {
+ if (maxlen > 1) {
+ *out++ = (char)*in++;
+ maxlen--;
+ } else {
+ break;
+ }
+ } else if (*in < 0x800) {
+ if (maxlen > 2) {
+ *out++ = ((*in >> 6) & 0x1F) | 0xC0;
+ *out++ = (*in++ & 0x3F) | 0x80;
+ maxlen -= 2;
+ } else {
+ break;
+ }
+ } else {
+ if (maxlen > 3) {
+ *out++ = ((*in >> 12) & 0x0F) | 0xE0;
+ *out++ = ((*in >> 6) & 0x3F) | 0x80;
+ *out++ = (*in++ & 0x3F) | 0x80;
+ maxlen -= 3;
+ } else {
+ break;
+ }
+ }
+ }
+ *out = 0;
+}
diff --git a/libexif/exif-utils.h b/libexif/exif-utils.h
new file mode 100644
index 0000000..7861564
--- /dev/null
+++ b/libexif/exif-utils.h
@@ -0,0 +1,194 @@
+/*! \file exif-utils.h
+ * \brief EXIF data manipulation functions and types
+ */
+/*
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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_UTILS_H__
+#define __EXIF_UTILS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libexif/exif-byte-order.h>
+#include <libexif/exif-format.h>
+#include <libexif/_stdint.h>
+
+
+/* If these definitions don't work for you, please let us fix the
+ * macro generating _stdint.h */
+
+/*! EXIF Unsigned Byte data type */
+typedef unsigned char ExifByte; /* 1 byte */
+
+/*! EXIF Signed Byte data type */
+typedef signed char ExifSByte; /* 1 byte */
+
+/*! EXIF Text String data type */
+typedef char * ExifAscii;
+
+/*! EXIF Unsigned Short data type */
+typedef uint16_t ExifShort; /* 2 bytes */
+
+/*! EXIF Signed Short data type */
+typedef int16_t ExifSShort; /* 2 bytes */
+
+/*! EXIF Unsigned Long data type */
+typedef uint32_t ExifLong; /* 4 bytes */
+
+/*! EXIF Signed Long data type */
+typedef int32_t ExifSLong; /* 4 bytes */
+
+/*! EXIF Unsigned Rational data type */
+typedef struct {ExifLong numerator; ExifLong denominator;} ExifRational;
+
+typedef char ExifUndefined; /* 1 byte */
+
+/*! EXIF Signed Rational data type */
+typedef struct {ExifSLong numerator; ExifSLong denominator;} ExifSRational;
+
+
+/*! Retrieve an #ExifShort value from memory.
+ *
+ * \param[in] b pointer to raw EXIF value in memory
+ * \param[in] order byte order of raw value
+ * \return value
+ */
+ExifShort exif_get_short (const unsigned char *b, ExifByteOrder order);
+
+/*! Retrieve an #ExifSShort value from memory.
+ *
+ * \param[in] b pointer to raw EXIF value in memory
+ * \param[in] order byte order of raw value
+ * \return value
+ */
+ExifSShort exif_get_sshort (const unsigned char *b, ExifByteOrder order);
+
+/*! Retrieve an #ExifLong value from memory.
+ *
+ * \param[in] b pointer to raw EXIF value in memory
+ * \param[in] order byte order of raw value
+ * \return value
+ */
+ExifLong exif_get_long (const unsigned char *b, ExifByteOrder order);
+
+/*! Retrieve an #ExifSLong value from memory.
+ *
+ * \param[in] b pointer to raw EXIF value in memory
+ * \param[in] order byte order of raw value
+ * \return value
+ */
+ExifSLong exif_get_slong (const unsigned char *b, ExifByteOrder order);
+
+/*! Retrieve an #ExifRational value from memory.
+ *
+ * \param[in] b pointer to raw EXIF value in memory
+ * \param[in] order byte order of raw value
+ * \return value
+ */
+ExifRational exif_get_rational (const unsigned char *b, ExifByteOrder order);
+
+/*! Retrieve an #ExifSRational value from memory.
+ *
+ * \param[in] b pointer to raw EXIF value in memory
+ * \param[in] order byte order of raw value
+ * \return value
+ */
+ExifSRational exif_get_srational (const unsigned char *b, ExifByteOrder order);
+
+/*! Store an ExifShort value into memory in EXIF format.
+ *
+ * \param[out] b buffer in which to write raw value
+ * \param[in] order byte order to use
+ * \param[in] value data value to store
+ */
+void exif_set_short (unsigned char *b, ExifByteOrder order,
+ ExifShort value);
+
+/*! Store an ExifSShort value into memory in EXIF format.
+ *
+ * \param[out] b buffer in which to write raw value
+ * \param[in] order byte order to use
+ * \param[in] value data value to store
+ */
+void exif_set_sshort (unsigned char *b, ExifByteOrder order,
+ ExifSShort value);
+
+/*! Store an ExifLong value into memory in EXIF format.
+ *
+ * \param[out] b buffer in which to write raw value
+ * \param[in] order byte order to use
+ * \param[in] value data value to store
+ */
+void exif_set_long (unsigned char *b, ExifByteOrder order,
+ ExifLong value);
+
+/*! Store an ExifSLong value into memory in EXIF format.
+ *
+ * \param[out] b buffer in which to write raw value
+ * \param[in] order byte order to use
+ * \param[in] value data value to store
+ */
+void exif_set_slong (unsigned char *b, ExifByteOrder order,
+ ExifSLong value);
+
+/*! Store an ExifRational value into memory in EXIF format.
+ *
+ * \param[out] b buffer in which to write raw value
+ * \param[in] order byte order to use
+ * \param[in] value data value to store
+ */
+void exif_set_rational (unsigned char *b, ExifByteOrder order,
+ ExifRational value);
+
+/*! Store an ExifSRational value into memory in EXIF format.
+ *
+ * \param[out] b buffer in which to write raw value
+ * \param[in] order byte order to use
+ * \param[in] value data value to store
+ */
+void exif_set_srational (unsigned char *b, ExifByteOrder order,
+ ExifSRational value);
+
+/*! \internal */
+void exif_convert_utf16_to_utf8 (char *out, const unsigned short *in, int maxlen);
+
+/* Please do not use this function outside of the library. */
+
+/*! \internal */
+void exif_array_set_byte_order (ExifFormat, unsigned char *, unsigned int,
+ ExifByteOrder o_orig, ExifByteOrder o_new);
+
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+#undef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+/* For compatibility with older versions */
+
+/*! \deprecated Use EXIF_TAG_SUB_SEC_TIME instead. */
+#define EXIF_TAG_SUBSEC_TIME EXIF_TAG_SUB_SEC_TIME
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXIF_UTILS_H__ */
diff --git a/libexif/exif.h b/libexif/exif.h
new file mode 100644
index 0000000..1c8e0f6
--- /dev/null
+++ b/libexif/exif.h
@@ -0,0 +1,87 @@
+/*! \file exif.h exif/exif.h
+ * \brief Dummy header file for documentation purposes
+ * \date 2007
+ * \author Hans Ulrich Niedermann, et. al.
+ *
+ * \mainpage The libexif library
+ *
+ * \section general_notes General Notes
+ *
+ * This documentation is work in progress, as is the code itself.
+ *
+ * \section using_libexif Using libexif
+ *
+ * \#include <libexif/exif-data.h>
+ *
+ * libexif provides a libexif.pc file for use with pkgconfig on the
+ * libexif installation. If you are using libtool to build your
+ * package, you can also make use of libexif-uninstalled.pc.
+ *
+ * An application using libexif would typically first create an #ExifLoader to
+ * load EXIF data into memory. From there, it would extract that data as
+ * an #ExifData to start manipulating it. Each IFD is represented by its own
+ * #ExifContent within that #ExifData, which contains all the tag data in
+ * #ExifEntry form. If the MakerNote data is required, an #ExifMnoteData
+ * can be extracted from the #ExifData and manipulated with the MakerNote
+ * functions.
+ *
+ * libexif is written in C using an object-based style that defines
+ * sets of functions that operate on each data structure.
+ *
+ * \section data_structures Primary Data Structures
+ *
+ * #ExifLoader
+ * State maintained by the loader interface while importing EXIF data
+ * from an external file or memory
+ *
+ * #ExifData
+ * The entirety of EXIF data found in an image
+ *
+ * #ExifContent
+ * All EXIF tags in a single IFD
+ *
+ * #ExifEntry
+ * Data found in a single EXIF tag
+ *
+ * #ExifMnoteData
+ * All data found in the MakerNote tag
+ *
+ * #ExifLog
+ * State maintained by the logging interface
+ *
+ * \section string_conventions String Conventions
+ *
+ * Strings are 8 bit characters ("char*"). When libexif is compiled with
+ * NLS, character set and encoding are as set in the current locale,
+ * except for strings that come directly from the data in EXIF
+ * tags which are generally returned in raw form. Most EXIF strings are
+ * defined to be plain 7-bit ASCII so this raw form should be acceptable in
+ * any UNIX locale, but some software ignores the specification and
+ * writes 8-bit characters. It is up to the application to detect this
+ * and deal with it intelligently.
+ *
+ * \section memory_management Memory Management Patterns
+ *
+ * For pointers to data objects, libexif uses reference counting. The
+ * pattern is to use the foo_new() function to create a data object,
+ * foo_ref() to increase the reference counter, and foo_unref() to
+ * decrease the reference counter and possibly free(3)ing the memory.
+ *
+ * Libexif by default relies on the calloc(3), realloc(3), and free(3)
+ * functions, but the libexif user can tell libexif to use their
+ * special memory management functions at runtime.
+ *
+ * \section thread_safety Thread Safety
+ *
+ * libexif is thread safe when the underlying C library is also thread safe.
+ * Some C libraries may require defining a special macro (like _REENTRANT)
+ * to ensure this, or may require linking to a special thread-safe version of
+ * the library.
+ *
+ * The programmer must ensure that each object allocated by libexif is only
+ * used in a single thread at once. For example, an ExifData* allocated
+ * in one thread can't be used in a second thread if there is any chance
+ * that the first thread could use it at the same time. Multiple threads
+ * can use libexif without issues if they never share handles.
+ *
+ */
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..9514654
--- /dev/null
+++ b/libexif/fuji/exif-mnote-data-fuji.c
@@ -0,0 +1,349 @@
+/* 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"
+
+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 ((datao + 12 < datao) || (datao + 12 < 12) || (datao + 12 > buf_size)) {
+ 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 ((datao + 2 < datao) || (datao + 2 < 2) ||
+ (datao + 2 > buf_size)) {
+ 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;
+ if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
+ 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));
+
+ /*
+ * 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 ((dataofs + s < dataofs) || (dataofs + s < s) ||
+ (dataofs + s >= buf_size)) {
+ exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteDataFuji", "Tag data past end of "
+ "buffer (%u >= %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;
+
+ 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/i18n.h b/libexif/i18n.h
new file mode 100644
index 0000000..dbfe258
--- /dev/null
+++ b/libexif/i18n.h
@@ -0,0 +1,52 @@
+/* i18n.h
+ *
+ * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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 __I18N_H__
+#define __I18N_H__
+
+#include "config.h"
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# undef _
+# define _(String) dgettext (GETTEXT_PACKAGE, String)
+# ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+# else
+# define N_(String) (String)
+# endif
+#else
+# define textdomain(String) (String)
+# define gettext(String) (String)
+# define ngettext(String1,String2,Count) (Count==1?String1:String2)
+# define dgettext(Domain,Message) (Message)
+# define dcgettext(Domain,Message,Type) (Message)
+#ifdef __WATCOMC__
+# define bind_textdomain_codeset(Domain,Codeset)
+# define bindtextdomain(Domain,Directory)
+#else
+# define bind_textdomain_codeset(Domain,Codeset) (Codeset)
+# define bindtextdomain(Domain,Directory) (Domain)
+#endif
+# define _(String) (String)
+# define N_(String) (String)
+#endif
+
+#endif /* __I18N_H__ */
diff --git a/libexif/libexif.sym b/libexif/libexif.sym
new file mode 100644
index 0000000..f1d77cf
--- /dev/null
+++ b/libexif/libexif.sym
@@ -0,0 +1,129 @@
+exif_array_set_byte_order
+exif_byte_order_get_name
+exif_content_add_entry
+exif_content_dump
+exif_content_fix
+exif_content_foreach_entry
+exif_content_free
+exif_content_get_entry
+exif_content_get_ifd
+exif_content_log
+exif_content_new
+exif_content_new_mem
+exif_content_ref
+exif_content_remove_entry
+exif_content_unref
+exif_data_dump
+exif_data_fix
+exif_data_foreach_content
+exif_data_free
+exif_data_get_byte_order
+exif_data_get_data_type
+exif_data_get_log
+exif_data_get_mnote_data
+exif_data_load_data
+exif_data_log
+exif_data_new
+exif_data_new_from_data
+exif_data_new_from_file
+exif_data_new_mem
+exif_data_option_get_description
+exif_data_option_get_name
+exif_data_ref
+exif_data_save_data
+exif_data_set_byte_order
+exif_data_set_data_type
+exif_data_set_option
+exif_data_unref
+exif_data_unset_option
+exif_entry_dump
+exif_entry_fix
+exif_entry_free
+exif_entry_get_value
+exif_entry_initialize
+exif_entry_new
+exif_entry_new_mem
+exif_entry_ref
+exif_entry_unref
+exif_format_get_name
+exif_format_get_size
+exif_get_long
+exif_get_rational
+exif_get_short
+exif_get_slong
+exif_get_srational
+exif_get_sshort
+exif_ifd_get_name
+exif_loader_get_data
+exif_loader_log
+exif_loader_new
+exif_loader_new_mem
+exif_loader_ref
+exif_loader_reset
+exif_loader_unref
+exif_loader_write
+exif_loader_write_file
+exif_log
+exif_log_code_get_message
+exif_log_code_get_title
+exif_log_free
+exif_log_new
+exif_log_new_mem
+exif_log_ref
+exif_log_set_func
+exif_log_unref
+exif_logv
+exif_mem_alloc
+exif_mem_free
+exif_mem_new
+exif_mem_new_default
+exif_mem_realloc
+exif_mem_ref
+exif_mem_unref
+exif_mnote_data_canon_new
+exif_mnote_data_construct
+exif_mnote_data_count
+exif_mnote_data_get_description
+exif_mnote_data_get_id
+exif_mnote_data_get_name
+exif_mnote_data_get_title
+exif_mnote_data_get_value
+exif_mnote_data_load
+exif_mnote_data_log
+exif_mnote_data_olympus_new
+exif_mnote_data_pentax_new
+exif_mnote_data_ref
+exif_mnote_data_save
+exif_mnote_data_set_byte_order
+exif_mnote_data_set_offset
+exif_mnote_data_unref
+exif_set_long
+exif_set_rational
+exif_set_short
+exif_set_slong
+exif_set_srational
+exif_set_sshort
+exif_tag_from_name
+exif_tag_get_description
+exif_tag_get_description_in_ifd
+exif_tag_get_name
+exif_tag_get_name_in_ifd
+exif_tag_get_support_level_in_ifd
+exif_tag_get_title
+exif_tag_get_title_in_ifd
+exif_tag_table_count
+exif_tag_table_get_name
+exif_tag_table_get_tag
+mnote_canon_entry_get_value
+mnote_canon_tag_get_description
+mnote_canon_tag_get_name
+mnote_canon_tag_get_title
+mnote_olympus_entry_get_value
+mnote_olympus_tag_get_description
+mnote_olympus_tag_get_name
+mnote_olympus_tag_get_title
+mnote_pentax_entry_get_value
+mnote_pentax_tag_get_description
+mnote_pentax_tag_get_name
+mnote_pentax_tag_get_title
+exif_loader_get_buf
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..099671d
--- /dev/null
+++ b/libexif/olympus/exif-mnote-data-olympus.c
@@ -0,0 +1,659 @@
+/* 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 */
+
+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 ((o2 + 10 < o2) || (o2 + 10 < 10) || (o2 + 10 > buf_size)) {
+ 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;
+ 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;
+ 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 ((o2 + 2 < o2) || (o2 + 2 < 2) || (o2 + 2 > buf_size)) {
+ 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;
+ if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
+ 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)); */
+
+ /*
+ * 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 + s > buf_size && 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 ((dataofs + s < dataofs) || (dataofs + s < s) ||
+ (dataofs + s > buf_size)) {
+ exif_log (en->log, EXIF_LOG_CODE_DEBUG,
+ "ExifMnoteOlympus",
+ "Tag data past end of buffer (%u > %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;
+
+ 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..757bb72
--- /dev/null
+++ b/libexif/pentax/exif-mnote-data-pentax.c
@@ -0,0 +1,449 @@
+/* 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>
+
+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 ((datao + 8 < datao) || (datao + 8 < 8) || (datao + 8 > buf_size)) {
+ 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;
+ if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
+ 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));
+
+ /*
+ * 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 ((dataofs + s < dataofs) || (dataofs + s < s) ||
+ (dataofs + s > buf_size)) {
+ exif_log (en->log, EXIF_LOG_CODE_DEBUG,
+ "ExifMnoteDataPentax", "Tag data past end "
+ "of buffer (%u > %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;
+
+ 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..7e97c2c
--- /dev/null
+++ b/libexif/pentax/mnote-pentax-entry.c
@@ -0,0 +1,459 @@
+/* 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);
+ for(k=0; k<entry->components; k++) {
+ vs = exif_get_short (data, entry->order);
+ snprintf (val+len, maxlen-len, "%i ", vs);
+ len = strlen(val);
+ data += 2;
+ }
+ }
+ break;
+ case EXIF_FORMAT_LONG:
+ {
+ const unsigned char *data = entry->data;
+ size_t k, len = strlen(val);
+ for(k=0; k<entry->components; k++) {
+ vl = exif_get_long (data, entry->order);
+ snprintf (val+len, maxlen-len, "%li", (long int) vl);
+ len = strlen(val);
+ data += 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__ */