2001-12-11 Lutz Müller <urc8@rz.uni-karlsruhe.de>
authorLutz Mueller <lutz.s.mueller@gmail.com>
Tue, 11 Dec 2001 20:28:30 +0000 (21:28 +0100)
committerLutz Mueller <lutz.s.mueller@gmail.com>
Tue, 11 Dec 2001 20:28:30 +0000 (21:28 +0100)
        Initial automake setup.

17 files changed:
.gitignore
AUTHORS [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Makefile
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.in [new file with mode: 0644]
libexif.pc.in [new file with mode: 0644]
libexif/.gitignore [new file with mode: 0644]
libexif/Makefile.am [new file with mode: 0644]
libexif/exif.c [new file with mode: 0644]
libexif/exif.h [new file with mode: 0644]
test/.gitignore [new file with mode: 0644]
test/Makefile.am [new file with mode: 0644]
test/test-exif.c [new file with mode: 0644]

index 40caffa..98aae83 100644 (file)
@@ -26,3 +26,22 @@ _$*
 *.ln
 core
 # CVS default ignores end
+Makefile
+Makefile.in
+aclocal.m4
+config.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+install-sh
+libexif.pc
+libtool
+ltmain.sh
+missing
+mkinstalldirs
+stamp-h
+stamp-h.in
diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..ccf01e3
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,3 @@
+2001-12-11  Lutz Müller <urc8@rz.uni-karlsruhe.de>
+
+       Initial automake setup.
index cbe6a60..4d38074 100644 (file)
--- a/Makefile
+++ b/Makefile
-CC=gcc
+# Generated automatically from Makefile.in by configure.
+# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
 
-CFLAGS=-g -D_REENTRANT
-LD=ld
-AR=ar
+# Copyright (C) 1994, 1995-8, 1999 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.
 
-OBJS=exif.o
+# 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.
 
-all: libexif.a exif
 
-libexif.a: $(OBJS)
-       $(AR) r $@ $^
+SHELL = /bin/sh
 
-exif: main.o libexif.a
-       $(CC) -o $@ main.o -L. -lexif -lm
+srcdir = .
+top_srcdir = .
+prefix = /usr/local
+exec_prefix = ${prefix}
 
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libexecdir = ${exec_prefix}/libexec
+datadir = ${prefix}/share
+sysconfdir = ${prefix}/etc
+sharedstatedir = ${prefix}/com
+localstatedir = ${prefix}/var
+libdir = ${exec_prefix}/lib
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
 
+DESTDIR =
 
+pkgdatadir = $(datadir)/libexif
+pkglibdir = $(libdir)/libexif
+pkgincludedir = $(includedir)/libexif
+
+top_builddir = .
+
+ACLOCAL = aclocal
+AUTOCONF = autoconf
+AUTOMAKE = automake
+AUTOHEADER = autoheader
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL_PROGRAM}
+transform = s,x,x,
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = i686-pc-linux-gnu
+host_triplet = i686-pc-linux-gnu
+AS = @AS@
+CC = gcc
+CFLAGS = -g -O2 -g -Wall -Wmissing-declarations -Wmissing-prototypes
+DLLTOOL = @DLLTOOL@
+ECHO = echo
+EXEEXT = 
+LDFLAGS =  -g -Wall
+LIBEXIF_VERSION_INFO = 0:1:0
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LN_S = ln -s
+MAINT = #
+MAKEINFO = makeinfo
+OBJDUMP = @OBJDUMP@
+OBJEXT = o
+PACKAGE = libexif
+RANLIB = ranlib
+STRIP = strip
+VERSION = 0.1
+
+SUBDIRS = libexif test
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libexif.pc
+EXTRA_DIST = libexif.pc.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =  libexif.pc
+DATA =  $(pkgconfig_DATA)
+
+DIST_COMMON =  README ./stamp-h.in AUTHORS COPYING ChangeLog INSTALL \
+Makefile.am Makefile.in NEWS aclocal.m4 config.guess config.h.in \
+config.sub configure configure.in install-sh libexif.pc.in ltmain.sh \
+missing mkinstalldirs
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+$(srcdir)/Makefile.in: # Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4): # configure.in 
+       cd $(srcdir) && $(ACLOCAL)
+
+config.status: $(srcdir)/configure.in $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+$(srcdir)/configure: #$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+       cd $(srcdir) && $(AUTOCONF)
+
+config.h: stamp-h
+       @if test ! -f $@; then \
+               rm -f stamp-h; \
+               $(MAKE) stamp-h; \
+       else :; fi
+stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES= CONFIG_HEADERS=config.h \
+            $(SHELL) ./config.status
+       @echo timestamp > stamp-h 2> /dev/null
+$(srcdir)/config.h.in: #$(srcdir)/stamp-h.in
+       @if test ! -f $@; then \
+               rm -f $(srcdir)/stamp-h.in; \
+               $(MAKE) $(srcdir)/stamp-h.in; \
+       else :; fi
+$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOHEADER)
+       @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+       -rm -f config.h
+
+maintainer-clean-hdr:
+libexif.pc: $(top_builddir)/config.status libexif.pc.in
+       cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+install-pkgconfigDATA: $(pkgconfig_DATA)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(pkgconfigdir)
+       @list='$(pkgconfig_DATA)'; for p in $$list; do \
+         if test -f $(srcdir)/$$p; then \
+           echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkgconfigdir)/$$p"; \
+           $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkgconfigdir)/$$p; \
+         else if test -f $$p; then \
+           echo " $(INSTALL_DATA) $$p $(DESTDIR)$(pkgconfigdir)/$$p"; \
+           $(INSTALL_DATA) $$p $(DESTDIR)$(pkgconfigdir)/$$p; \
+         fi; fi; \
+       done
+
+uninstall-pkgconfigDATA:
+       @$(NORMAL_UNINSTALL)
+       list='$(pkgconfig_DATA)'; for p in $$list; do \
+         rm -f $(DESTDIR)$(pkgconfigdir)/$$p; \
+       done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive  \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+         rev="$$subdir $$rev"; \
+         test "$$subdir" = "." && dot_seen=yes; \
+       done; \
+       test "$$dot_seen" = "no" && rev=". $$rev"; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+   if test "$$subdir" = .; then :; else \
+           test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+   fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       -rm -rf $(distdir)
+       GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
+       mkdir $(distdir)/=build
+       mkdir $(distdir)/=inst
+       dc_install_base=`cd $(distdir)/=inst && pwd`; \
+       cd $(distdir)/=build \
+         && ../configure --srcdir=.. --prefix=$$dc_install_base \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) dist
+       -rm -rf $(distdir)
+       @banner="$(distdir).tar.gz is ready for distribution"; \
+       dashes=`echo "$$banner" | sed s/./=/g`; \
+       echo "$$dashes"; \
+       echo "$$banner"; \
+       echo "$$dashes"
+dist: distdir
+       -chmod -R a+r $(distdir)
+       GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+       -rm -rf $(distdir)
+dist-all: distdir
+       -chmod -R a+r $(distdir)
+       GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+       -rm -rf $(distdir)
+distdir: $(DISTFILES)
+       -rm -rf $(distdir)
+       mkdir $(distdir)
+       -chmod 777 $(distdir)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+       for subdir in $(SUBDIRS); do \
+         if test "$$subdir" = .; then :; else \
+           test -d $(distdir)/$$subdir \
+           || mkdir $(distdir)/$$subdir \
+           || exit 1; \
+           chmod 777 $(distdir)/$$subdir; \
+           (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
+             || exit 1; \
+         fi; \
+       done
+info-am:
+info: info-recursive
+dvi-am:
+dvi: dvi-recursive
+check-am: all-am
+check: check-recursive
+installcheck-am:
+installcheck: installcheck-recursive
+all-recursive-am: config.h
+       $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+install-exec-am:
+install-exec: install-exec-recursive
+
+install-data-am: install-pkgconfigDATA
+install-data: install-data-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-recursive
+uninstall-am: uninstall-pkgconfigDATA
+uninstall: uninstall-recursive
+all-am: Makefile $(DATA) config.h
+all-redirect: all-recursive-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs: installdirs-recursive
+installdirs-am:
+       $(mkinstalldirs)  $(DESTDIR)$(pkgconfigdir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-hdr mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-recursive
+
+clean-am:  clean-hdr clean-tags clean-generic mostlyclean-am
+
+clean: clean-recursive
+
+distclean-am:  distclean-hdr distclean-tags distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-recursive
+       -rm -f config.status
+
+maintainer-clean-am:  maintainer-clean-hdr maintainer-clean-tags \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f config.status
+
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+uninstall-pkgconfigDATA install-pkgconfigDATA install-data-recursive \
+uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive installcheck-recursive info-recursive \
+dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \
+install-exec-am install-exec install-data-am install-data install-am \
+install uninstall-am uninstall all-redirect all-am all installdirs-am \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# 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/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..4389fa5
--- /dev/null
@@ -0,0 +1,5 @@
+SUBDIRS = libexif test
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libexif.pc
+EXTRA_DIST = libexif.pc.in
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..2958b69
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+# This was lifted from the Gimp, and adapted slightly by
+# Raph Levien .
+
+DIE=0
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+test "$srcdir" = "." && srcdir=`pwd`
+
+PROJECT=libexif
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+    echo
+    echo "You must have autoconf installed to compile $PROJECT."
+    echo "Download the appropriate package for your distribution,"
+    echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+    DIE=1
+}
+
+(libtool --version) < /dev/null > /dev/null 2>&1 || {
+    echo
+    echo "You must have libtool installed to compile $PROJECT."
+    echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2.tar.gz"
+    echo "(or a newer version if it is available)"
+    DIE=1
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+    echo
+    echo "You must have automake installed to compile $PROJECT."
+    echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
+    echo "(or a newer version if it is available)"
+    DIE=1
+}
+
+if test "$DIE" -eq 1; then
+    exit 1
+fi
+
+test -f libexif/exif.h || {
+        echo "You must run this script in the top-level gphoto2 directory"
+        exit 1
+}
+
+if test -z "$*"; then
+    echo "I am going to run ./configure with no arguments - if you wish "
+    echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+
+case "$CC" in
+*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;;
+esac
+
+echo "Running aclocal $ACLOCAL_FLAGS"
+aclocal $ACLOCAL_FLAGS
+echo "Running autoheader"
+autoheader
+echo "Running automake --add-missing --gnu $am_opt"
+automake --add-missing --gnu $am_opt
+echo "Running autoconf"
+autoconf
+echo "Running ./configure"
+./configure "$@"
+
+echo 
+echo "Now type 'make' to compile $PROJECT."
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..6b9c7d3
--- /dev/null
@@ -0,0 +1,38 @@
+AC_INIT(libexif/exif.h)
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(libexif, 0.1)
+AM_MAINTAINER_MODE
+
+LIBEXIF_VERSION_INFO=0:1:0
+AC_SUBST(LIBEXIF_VERSION_INFO)
+
+AC_PROG_LIBTOOL
+
+dnl ---------------------------------------------------------------------------
+dnl i18n support
+dnl ---------------------------------------------------------------------------
+dnl ALL_LINGUAS=""
+dnl AM_GNU_GETTEXT
+
+dnl ---------------------------------------------------------------------------
+dnl Warnings
+dnl ---------------------------------------------------------------------------
+CFLAGS="$CFLAGS -g -Wall -Wmissing-declarations -Wmissing-prototypes"
+LDFLAGS="$LDFLAGS -g -Wall"
+AC_SUBST(CFLAGS)
+AC_SUBST(LDFLAGS)
+
+AC_OUTPUT([
+Makefile
+libexif/Makefile
+test/Makefile
+libexif.pc
+])
+
+echo "
+
+Configuration:
+
+       Source code location:      ${srcdir}
+       Compiler:                  ${CC}
+"
diff --git a/libexif.pc.in b/libexif.pc.in
new file mode 100644 (file)
index 0000000..bc9847e
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libexif
+Description: Library for easy access to EXIF data
+Requires:
+Version: @VERSION@
+Libs: -L${libdir} -lexif -lm
+Cflags: -I${includedir}/libexif -I${includedir}
diff --git a/libexif/.gitignore b/libexif/.gitignore
new file mode 100644 (file)
index 0000000..0f19e06
--- /dev/null
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+.libs
+.deps
+libexif.la
+*.o
+*.lo
diff --git a/libexif/Makefile.am b/libexif/Makefile.am
new file mode 100644 (file)
index 0000000..0dbe154
--- /dev/null
@@ -0,0 +1,12 @@
+INCLUDES =              \
+        -I$(top_srcdir)
+
+lib_LTLIBRARIES = libexif.la
+
+libexif_la_LDFLAGS = -version-info @LIBEXIF_VERSION_INFO@
+libexif_la_SOURCES = exif.c
+libexif_la_LIBADD = -lm
+
+libexifincludedir = $(includedir)/libexif
+libexifinclude_HEADERS = exif.h
+
diff --git a/libexif/exif.c b/libexif/exif.c
new file mode 100644 (file)
index 0000000..198ff7d
--- /dev/null
@@ -0,0 +1,1276 @@
+/*
+
+Copyright (c) 2000 Matthias Wandel, The PHP Group, Curtis Galloway
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+$Id: exif.c,v 1.1.1.1 2000/10/09 19:19:47 curtisg Exp $
+
+*/
+
+#include <sys/time.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <math.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+#include <fcntl.h>
+
+#include "exif.h"
+
+typedef unsigned char uchar;
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+/* 
+   This structure stores global state for an EXIF image file.
+*/
+typedef struct {
+       exif_data_t *d;
+       int MotorolaOrder;
+       const char *filename;
+
+       char *Thumbnail;
+       int ThumbnailSize;
+} ImageInfoType;
+
+void *(*exif_malloc_fn)(int);
+void *(*exif_realloc_fn)(void *, int);
+void (*exif_free_fn)(void *);
+
+static char *
+exif_strndup(char *str, int len)
+{
+       char *rval = (*exif_malloc_fn)(len+1);
+       strncpy(rval, str, len);
+       rval[len] = '\0';
+       return rval;
+}
+
+struct exif_data *
+exif_alloc(void)
+{
+       exif_data_t *d;
+
+       d = (*exif_malloc_fn)(sizeof(exif_data_t));
+       bzero(d, sizeof(*d));
+       return d;
+}
+
+static void
+exif_error(char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       va_end(ap);
+}
+
+
+/* This structure is used to store a section of a Jpeg file. */
+typedef struct {
+    uchar *Data;
+    int      Type;
+    unsigned Size;
+} Section_t;
+
+#define EXIT_FAILURE  1
+#define EXIT_SUCCESS  0
+
+
+/* 
+   JPEG markers consist of one or more 0xFF bytes, followed by a marker
+   code byte (which is not an FF).  Here are the marker codes of interest
+   in this program.  (See jdmarker.c for a more complete list.)
+*/
+
+#define M_SOF0  0xC0            /* Start Of Frame N                        */
+#define M_SOF1  0xC1            /* N indicates which compression process   */
+#define M_SOF2  0xC2            /* Only SOF0-SOF2 are now in common use    */
+#define M_SOF3  0xC3
+#define M_SOF5  0xC5            /* NB: codes C4 and CC are NOT SOF markers */
+#define M_SOF6  0xC6
+#define M_SOF7  0xC7
+#define M_SOF9  0xC9
+#define M_SOF10 0xCA
+#define M_SOF11 0xCB
+#define M_SOF13 0xCD
+#define M_SOF14 0xCE
+#define M_SOF15 0xCF
+#define M_SOI   0xD8            /* Start Of Image (beginning of datastream) */
+#define M_EOI   0xD9            /* End Of Image (end of datastream)         */
+#define M_SOS   0xDA            /* Start Of Scan (begins compressed data)   */
+#define M_EXIF  0xE1            
+#define M_COM   0xFE            /* COMment                                  */
+
+
+#define PSEUDO_IMAGE_MARKER 0x123; /* Extra value. */
+
+#define EXIF_ALLOC_SIZE 16
+
+/*
+ * The name gets copied, so you can pass a static string;
+ * the data is not copied, so if it is a string,
+ * you must allocate it yourself.
+ */
+static int
+exif_append_data(exif_data_t **d_p,
+                                char *name,
+                                char rec_type,
+                                int exif_format,
+                                exif_rec_data_t *data)
+{
+       exif_data_t *d = *d_p;
+
+       if (rec_type == '\0')
+               return EXIT_FAILURE;
+
+       if (d->n_alloc <= d->n_recs) {
+               d->n_alloc += EXIF_ALLOC_SIZE;
+               d = (*exif_realloc_fn)(d, sizeof(exif_data_t) +
+                                                          sizeof(exif_record_t) * d->n_alloc);
+               *d_p = d;
+       }
+       d->recs[d->n_recs].rec_type = rec_type;
+       bcopy(data, &d->recs[d->n_recs].rec_data, sizeof(exif_rec_data_t));
+       d->recs[d->n_recs].rec_name = strdup(name);
+       d->n_recs++;
+       return EXIT_SUCCESS;
+}
+
+/*
+   Get 16 bits motorola order (always) for jpeg header stuff.
+*/
+static int
+Get16m(void *Short)
+{
+    return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1];
+}
+
+
+/*
+   Process a COM marker.
+   We want to print out the marker contents as legible text;
+   we must guard against random junk and varying newline representations.
+*/
+static void
+process_COM (ImageInfoType *ImageInfo, uchar *Data, int length)
+{
+    int ch;
+    char *Comment;
+    int nch;
+    int a;
+    exif_rec_data_t rd;
+
+    nch = 0;
+    Comment = (*exif_malloc_fn)(length+1);
+
+    for (a=2;a<length;a++) {
+        ch = Data[a];
+
+        if (ch == '\r' && Data[a+1] == '\n') continue; /* Remove cr followed by lf. */
+
+        if (isprint(ch) || ch == '\n' || ch == '\t') {
+            Comment[nch++] = (char)ch;
+        } else {
+            Comment[nch++] = '?';
+        }
+    }
+
+    Comment[nch] = '\0'; /* Null terminate */
+
+    rd.s = Comment;
+    exif_append_data(&ImageInfo->d, "Comment", 's', EXIF_FMT_COMPUTED, &rd);
+}
+/* Process a SOFn marker.  This is useful for the image dimensions. */
+static void
+process_SOFn (ImageInfoType *ImageInfo, uchar *Data, int marker)
+{
+    int data_precision, num_components;
+    const char *process;
+    exif_rec_data_t rd;
+
+    data_precision = Data[2];
+    rd.l = Get16m(Data+3);
+    exif_append_data(&ImageInfo->d,
+                                        "Height",
+                                        'l',
+                                        EXIF_FMT_COMPUTED,
+                                        &rd);
+    rd.l = Get16m(Data+5);
+    exif_append_data(&ImageInfo->d,
+                                        "Width",
+                                        'l',
+                                        EXIF_FMT_COMPUTED,
+                                        &rd);
+    num_components = Data[7];
+
+    if (num_components == 3) {
+               rd.l = 1;
+    } else {
+               rd.l = 0;
+    }
+    exif_append_data(&ImageInfo->d, "IsColor", 'l', EXIF_FMT_COMPUTED, &rd);
+
+    switch (marker) {
+       case M_SOF0:  process = "Baseline";  break;
+       case M_SOF1:  process = "Extended sequential";  break;
+       case M_SOF2:  process = "Progressive";  break;
+       case M_SOF3:  process = "Lossless";  break;
+       case M_SOF5:  process = "Differential sequential";  break;
+       case M_SOF6:  process = "Differential progressive";  break;
+       case M_SOF7:  process = "Differential lossless";  break;
+       case M_SOF9:  process = "Extended sequential, arithmetic coding";  break;
+       case M_SOF10: process = "Progressive, arithmetic coding";  break;
+       case M_SOF11: process = "Lossless, arithmetic coding";  break;
+       case M_SOF13: process = "Differential sequential, arithmetic coding";  break;
+       case M_SOF14: process = "Differential progressive, arithmetic coding"; break;
+       case M_SOF15: process = "Differential lossless, arithmetic coding";  break;
+       default:      process = "Unknown";  break;
+    }
+}
+
+/*
+   Describes format descriptor
+*/
+static int ExifBytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
+#define NUM_FORMATS EXIF_FMT_DOUBLE
+
+/*
+   Describes tag values
+*/
+
+#define TAG_EXIF_OFFSET       0x8769
+#define TAG_INTEROP_OFFSET    0xa005
+
+#define TAG_COMPRESSION       0x0103
+
+#define TAG_MAKE              0x010F
+#define TAG_MODEL             0x0110
+#define TAG_ORIENTATION       0x0112
+
+#define TAG_SOFTWARE          0x0131
+
+/* Olympus specific tags */
+#define TAG_SPECIALMODE       0x0200
+#define TAG_JPEGQUAL          0x0201
+#define TAG_MACRO             0x0202
+#define TAG_DIGIZOOM          0x0204
+#define TAG_SOFTWARERELEASE   0x0207
+#define TAG_PICTINFO          0x0208
+#define TAG_CAMERAID          0x0209
+/* end Olympus specific tags */
+
+#define TAG_COPYRIGHT         0x8298
+
+#define TAG_EXPOSURETIME      0x829A
+#define TAG_FNUMBER           0x829D
+
+#define TAG_GPSINFO           0x8825
+#define TAG_ISOSPEED          0x8827
+#define TAG_EXIFVERSION       0x9000
+
+#define TAG_SHUTTERSPEED      0x9201
+#define TAG_APERTURE          0x9202
+#define TAG_MAXAPERTURE       0x9205
+#define TAG_FOCALLENGTH       0x920A
+
+#define TAG_DATETIME_ORIGINAL 0x9003
+#define TAG_USERCOMMENT       0x9286
+
+#define TAG_SUBJECT_DISTANCE  0x9206
+#define TAG_LIGHT_SOURCE      0x9208
+#define TAG_FLASH             0x9209
+
+#define TAG_FOCALPLANEXRES    0xa20E
+#define TAG_FOCALPLANEUNITS   0xa210
+#define TAG_IMAGEWIDTH        0xA002
+
+struct ExifTag {
+    unsigned short Tag;
+    char *Desc;
+       void (*Func)();
+};
+
+
+
+/* Convert a 16 bit unsigned value from file's native byte order */
+static int
+Get16u(void *Short, int MotorolaOrder)
+{
+    if (MotorolaOrder) {
+        return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1];
+    } else {
+        return (((uchar *)Short)[1] << 8) | ((uchar *)Short)[0];
+    }
+}
+
+/* Convert a 32 bit signed value from file's native byte order */
+static int
+Get32s(void *Long, int MotorolaOrder)
+{
+    if (MotorolaOrder) {
+        return  ((( char *)Long)[0] << 24) | (((uchar *)Long)[1] << 16)
+                       | (((uchar *)Long)[2] << 8 ) | (((uchar *)Long)[3] << 0 );
+    } else {
+        return  ((( char *)Long)[3] << 24) | (((uchar *)Long)[2] << 16)
+                       | (((uchar *)Long)[1] << 8 ) | (((uchar *)Long)[0] << 0 );
+    }
+}
+
+/* Convert a 32 bit unsigned value from file's native byte order */
+static unsigned
+Get32u(void *Long, int MotorolaOrder)
+{
+    return (unsigned)Get32s(Long, MotorolaOrder) & 0xffffffff;
+}
+
+
+/* Evaluate number, be it int, rational, or float from directory. */
+static double
+ConvertAnyFormat(void *ValuePtr, int Format, int MotorolaOrder)
+{
+    double Value;
+    Value = 0;
+
+    switch(Format) {
+       case EXIF_FMT_SBYTE:     Value = *(signed char *)ValuePtr;  break;
+       case EXIF_FMT_BYTE:      Value = *(uchar *)ValuePtr;        break;
+
+       case EXIF_FMT_USHORT:    Value = Get16u(ValuePtr,MotorolaOrder);          break;
+       case EXIF_FMT_ULONG:     Value = Get32u(ValuePtr,MotorolaOrder);          break;
+
+       case EXIF_FMT_URATIONAL:
+       case EXIF_FMT_SRATIONAL: 
+               {
+                       int Num,Den;
+                       Num = Get32s(ValuePtr,MotorolaOrder);
+                       Den = Get32s(4+(char *)ValuePtr,MotorolaOrder);
+                       if (Den == 0) {
+                               Value = 0;
+                       } else {
+                               Value = (double)Num/Den;
+                       }
+                       break;
+               }
+
+       case EXIF_FMT_SSHORT:    Value = (signed short)Get16u(ValuePtr,MotorolaOrder);  break;
+       case EXIF_FMT_SLONG:     Value = Get32s(ValuePtr,MotorolaOrder);                break;
+
+        /* Not sure if this is correct (never seen float used in Exif format) */
+       case EXIF_FMT_SINGLE:    Value = (double)*(float *)ValuePtr;      break;
+       case EXIF_FMT_DOUBLE:    Value = *(double *)ValuePtr;             break;
+    }
+    return Value;
+}
+
+/* Evaluate number, be it int, rational, or float from directory. */
+static char
+ConvertAnyFormat2(void *ValuePtr, int ByteCount, int Format, int MotorolaOrder, exif_rec_data_t *data_p)
+{
+       char *str, *p;
+       char r_type;
+       unsigned char c;
+       static char hexdigits[] = "0123456789ABCDEF";
+
+    switch(Format) {
+       case EXIF_FMT_STRING:
+               data_p->s = exif_strndup(ValuePtr, ByteCount);
+               r_type = 's';
+               break;
+
+       case EXIF_FMT_SBYTE:
+               data_p->l = (long)*(signed char *)ValuePtr;
+               r_type = 'l';
+               break;
+
+       case EXIF_FMT_BYTE:
+               data_p->l = (long)*(uchar *)ValuePtr;
+               r_type = 'l';
+        break;
+
+       case EXIF_FMT_USHORT:
+               data_p->l = (long)Get16u(ValuePtr,MotorolaOrder);
+               r_type = 'l';
+               break;
+       case EXIF_FMT_ULONG:
+               data_p->l = (long)Get32u(ValuePtr,MotorolaOrder);
+               r_type = 'l';
+               break;
+
+       case EXIF_FMT_URATIONAL:
+       case EXIF_FMT_SRATIONAL: 
+               {
+                       int Num,Den;
+                       data_p->r.num = Get32s(ValuePtr,MotorolaOrder);
+                       data_p->r.denom = Get32s(4+(char *)ValuePtr,MotorolaOrder);
+                       r_type = 'r';
+                       break;
+               }
+
+       case EXIF_FMT_SSHORT:
+               data_p->l = (signed short)Get16u(ValuePtr,MotorolaOrder);
+               r_type = 'l';
+               break;
+       case EXIF_FMT_SLONG:
+               data_p->l = (long)Get32s(ValuePtr,MotorolaOrder);
+               r_type = 'l';
+               break;
+
+        /* Not sure if this is correct (never seen float used in Exif format) */
+       case EXIF_FMT_SINGLE:
+               data_p->f = *(float *)ValuePtr;
+               r_type = 'f';
+               break;
+
+       case EXIF_FMT_DOUBLE:
+               data_p->g = *(double *)ValuePtr;
+               r_type = 'f';
+               break;
+
+       default:
+               /* unknown type */
+               p = str = (*exif_malloc_fn)(ByteCount*2 + 1);
+               while (ByteCount--) {
+                       c = *(unsigned char *)ValuePtr++;
+                       *p++ = hexdigits[c / 16];
+                       *p++ = hexdigits[c % 16];
+               }
+               *p++ = '\0';
+               data_p->s = str;
+               r_type = 's';
+               break;
+    }
+    return r_type;
+}
+
+
+static void
+ProcessFocalPlaneUnits(ImageInfoType *ImageInfo,
+                                          void *ValuePtr,
+                                          int ByteCount,
+                                          int Format,
+                                          struct ExifTag *tag_p)
+{
+    exif_rec_data_t rd;
+       float FocalPlaneUnits;
+
+       switch((int)ConvertAnyFormat(ValuePtr, Format, ImageInfo->MotorolaOrder)) {
+       case 1:
+               FocalPlaneUnits = 25.4;
+               break; /* inch */
+       case 2: 
+               /* According to the information I was using, 2 means meters.
+                  But looking at the Canon PowerShot's files, inches is the only
+                  sensible value. */
+               FocalPlaneUnits = 25.4;
+               break;
+
+       case 3:
+               FocalPlaneUnits = 10;
+               break;  /* centimeter */
+       case 4:
+               FocalPlaneUnits = 1;
+               break;  /* milimeter  */
+       case 5:
+               FocalPlaneUnits = .001;
+               break;  /* micrometer */
+       }
+
+       rd.f = FocalPlaneUnits;
+       exif_append_data(&ImageInfo->d,
+                                        "FocalPlaneUnits",
+                                        'f',
+                                        Format,
+                                        &rd);
+}
+
+static void
+ProcessVersion(ImageInfoType *ImageInfo,
+                                  void *ValuePtr,
+                                  int ByteCount,
+                                  int Format,
+                                  struct ExifTag *tag_p)
+{
+    exif_rec_data_t rd;
+       rd.s = exif_strndup(ValuePtr, ByteCount);
+       exif_append_data(&ImageInfo->d,
+                                        tag_p->Desc,
+                                        's',
+                                        Format,
+                                        &rd);
+}
+
+static void
+ProcessUserComment(ImageInfoType *ImageInfo,
+                                  void *_ValuePtr,
+                                  int ByteCount,
+                                  int Format,
+                                  struct ExifTag *tag_p)
+{
+       char *ValuePtr = (char *)_ValuePtr;
+    exif_rec_data_t rd;
+       int a;
+
+       /* Olympus has this padded with trailing spaces.  Remove these first. */
+       for (a=ByteCount;;) {
+               a--;
+               if ((ValuePtr)[a] == ' ') {
+                       (ValuePtr)[a] = '\0';
+               } else {
+                       break;
+               }
+               if (a == 0) break;
+       }
+
+       /* Copy the comment */
+       if (memcmp(ValuePtr, "ASCII",5) == 0) {
+               for (a=5;a<10;a++) {
+                       int c;
+                       c = (ValuePtr)[a];
+                       if (c != '\0' && c != ' ') {
+                               rd.s = exif_strndup(a+ValuePtr, ByteCount - a);
+                               exif_append_data(&ImageInfo->d,
+                                                                "UserComment",
+                                                                's',
+                                                                Format,
+                                                                &rd);
+                               break;
+                       }
+               }
+                    
+       } else {
+               rd.s = exif_strndup(ValuePtr, ByteCount);
+               exif_append_data(&ImageInfo->d,
+                                                "UserComment",
+                                                's',
+                                                Format,
+                                                &rd);
+       }
+}
+
+static void
+ProcessShutterSpeed(ImageInfoType *ImageInfo,
+                                       void *ValuePtr,
+                                       int ByteCount,
+                                       int Format,
+                                       struct ExifTag *tag_p)
+{
+    exif_rec_data_t rd;
+       char rec_type;
+
+       rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format,
+                                                                ImageInfo->MotorolaOrder,
+                                                                &rd);
+       exif_append_data(&ImageInfo->d,
+                                        tag_p->Desc,
+                                        rec_type,
+                                        Format,
+                                        &rd);
+
+       /* Convert shutter speed value to shutter speed;
+        * shutter speed is 1/(2**ShutterSpeedValue)
+     */
+       rd.r.denom = (int)pow(2.0, ((double)rd.r.num)/((double)rd.r.denom));
+       rd.r.num = 1;
+       exif_append_data(&ImageInfo->d,
+                                        "ShutterSpeed",
+                                        'r',
+                                        EXIF_FMT_COMPUTED,
+                                        &rd);
+       
+}
+
+static void
+ProcessAperture(ImageInfoType *ImageInfo,
+                               void *ValuePtr,
+                               int ByteCount,
+                               int Format,
+                               struct ExifTag *tag_p)
+{
+    exif_rec_data_t rd;
+       char rec_type;
+       double fstop;
+       char label[32];
+
+       rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format,
+                                                                ImageInfo->MotorolaOrder,
+                                                                &rd);
+       exif_append_data(&ImageInfo->d,
+                                        tag_p->Desc,
+                                        rec_type,
+                                        Format,
+                                        &rd);
+
+       if (exif_find_record(ImageInfo->d, "FNumber") == NULL) {
+               /* Convert aperture to F-stop. */
+               fstop = pow(sqrt(2), ((double)rd.r.num)/((double)rd.r.denom));
+               sprintf(label, "f%.1g", fstop);
+               rd.s = strdup(label);
+               exif_append_data(&ImageInfo->d,
+                                                "FNumber",
+                                                's',
+                                                EXIF_FMT_COMPUTED,
+                                                &rd);
+       }
+}
+
+static void
+ProcessCanonMakerNote(ImageInfoType *ImageInfo,
+                                void *ValuePtr,
+                                int ByteCount,
+                                int Format,
+                                struct ExifTag *tag_p,
+                                char *OffsetBase)
+{
+       
+       /* This is for the Canon MakerNote. */
+       /* XXX - go by value of Maker tag. */
+    exif_rec_data_t rd;
+       char rec_type;
+       unsigned long n_dir, tag, format, components, offset;
+       char label[32];
+       void *OffsetPtr;
+
+       n_dir = Get16u(ValuePtr, ImageInfo->MotorolaOrder);
+       ValuePtr += 2;
+       while (n_dir--) {
+               tag = Get16u(ValuePtr, ImageInfo->MotorolaOrder);
+               ValuePtr += 2;
+               format = Get16u(ValuePtr, ImageInfo->MotorolaOrder);
+               ValuePtr += 2;
+               components = Get32u(ValuePtr, ImageInfo->MotorolaOrder);
+               ValuePtr += 4;
+               offset = Get32u(ValuePtr, ImageInfo->MotorolaOrder);
+        ByteCount = components * ExifBytesPerFormat[format];
+               if (ByteCount > 4) {
+                       OffsetPtr = OffsetBase + offset;
+               } else {
+                       OffsetPtr = ValuePtr;
+               }
+               ValuePtr += 4;
+               rec_type = ConvertAnyFormat2(OffsetPtr, ByteCount, format,
+                                                                        ImageInfo->MotorolaOrder,
+                                                                        &rd);
+               sprintf(label, "MakerNote%04x", tag);
+               exif_append_data(&ImageInfo->d,
+                                                label,
+                                                rec_type,
+                                                format,
+                                                &rd);
+               
+       }
+}
+
+
+struct MakerNote {
+       char *Make;
+       void (*Func)();
+};
+
+static struct MakerNote
+MakerProcessors[] = {
+       {"Canon", ProcessCanonMakerNote},
+    {NULL, NULL}
+};
+
+static void
+ProcessMakerNote(ImageInfoType *ImageInfo,
+                                void *ValuePtr,
+                                int ByteCount,
+                                int Format,
+                                struct ExifTag *tag_p,
+                                char *OffsetBase)
+{
+       struct MakerNote *mn_p;
+       exif_record_t *rec_p;
+
+       rec_p = exif_find_record(ImageInfo->d, "Make");
+       if (rec_p == NULL) {
+               return;
+       }
+
+       for(mn_p = &MakerProcessors[0]; mn_p->Make != NULL; mn_p++) {
+               if (strcmp(mn_p->Make, rec_p->rec_data.s) == 0) {
+                       (*mn_p->Func)(ImageInfo, ValuePtr, ByteCount, Format, tag_p, OffsetBase);
+                       break;
+               }
+       }
+}
+
+static struct ExifTag
+TagTable[] = {
+       {   0x0001, "InteroperabilityIndex"},
+       {   0x0002, "InteroperabilityVersion", ProcessVersion},
+       {       0x0100, "ImageWidth"},
+       {       0x0101, "ImageLength"},
+       {       0x0102, "BitsPerSample"},
+       {       0x0103, "Compression"},
+       {       0x0106, "PhotometricInterpretation"},
+       {       0x010A, "FillOrder"},
+       {       0x010D, "DocumentName"},
+       {       0x010E, "ImageDescription"},
+       {       0x010F, "Make"},
+       {       0x0110, "Model"},
+       {       0x0111, "StripOffsets"},
+       {       0x0112, "Orientation"},
+       {       0x0115, "SamplesPerPixel"},
+       {       0x0116, "RowsPerStrip"},
+       {       0x0117, "StripByteCounts"},
+       {       0x011A, "XResolution"},
+       {       0x011B, "YResolution"},
+       {       0x011C, "PlanarConfiguration"},
+       {       0x0128, "ResolutionUnit"},
+       {       0x012D, "TransferFunction"},
+       {       0x0131, "Software"},
+       {       0x0132, "DateTime"},
+       {       0x013B, "Artist"},
+       {       0x013E, "WhitePoint"},
+       {       0x013F, "PrimaryChromaticities"},
+       {       0x0156, "TransferRange"},
+       {       0x0200, "JPEGProc"},
+       {       0x0201, "JPEGInterchangeFormat"},
+       {       0x0202, "JPEGInterchangeFormatLength"},
+       {       0x0211, "YCbCrCoefficients"},
+       {       0x0212, "YCbCrSubSampling"},
+       {       0x0213, "YCbCrPositioning"},
+       {       0x0214, "ReferenceBlackWhite"},
+       {   0x1000, "RelatedImageFileFormat"},
+       {   0x1001, "RelatedImageWidth"},
+       {   0x1002, "RelatedImageLength"},
+       {       0x828D, "CFARepeatPatternDim"},
+       {       0x828E, "CFAPattern"},
+       {       0x828F, "BatteryLevel"},
+       {       0x8298, "Copyright"},
+       {       0x829A, "ExposureTime"},
+       {       0x829D, "FNumber"},
+       {       0x83BB, "IPTC/NAA"},
+       {       0x8769, "ExifOffset"},
+       {       0x8773, "InterColorProfile"},
+       {       0x8822, "ExposureProgram"},
+       {       0x8824, "SpectralSensitivity"},
+       {       0x8825, "GPSInfo"},
+       {       0x8827, "ISOSpeedRatings"},
+       {       0x8828, "OECF"},
+       {       0x9000, "ExifVersion", ProcessVersion},
+       {       0x9003, "DateTimeOriginal"},
+       {       0x9004, "DateTimeDigitized"},
+       {       0x9101, "ComponentsConfiguration"},
+       {       0x9102, "CompressedBitsPerPixel"},
+       {       0x9201, "ShutterSpeedValue", ProcessShutterSpeed},
+       {       0x9202, "ApertureValue", ProcessAperture},
+       {       0x9203, "BrightnessValue"},
+       {       0x9204, "ExposureBiasValue"},
+       {       0x9205, "MaxApertureValue", ProcessAperture},
+       {       0x9206, "SubjectDistance"},
+       {       0x9207, "MeteringMode"},
+       {       0x9208, "LightSource"},
+       {       0x9209, "Flash"},
+       {       0x920A, "FocalLength"},
+       {       0x927C, "MakerNote", ProcessMakerNote},
+       {       0x9286, "UserComment", ProcessUserComment},
+       {       0x9290, "SubSecTime"},
+       {       0x9291, "SubSecTimeOriginal"},
+       {       0x9292, "SubSecTimeDigitized"},
+       {       0xA000, "FlashPixVersion", ProcessVersion},
+       {       0xA001, "ColorSpace"},
+       {       0xA002, "ExifImageWidth"},
+       {       0xA003, "ExifImageLength"},
+       {       0xA005, "InteroperabilityOffset"},
+       {       0xA20B, "FlashEnergy"},                         /* 0x920B in TIFF/EP */
+       {       0xA20C, "SpatialFrequencyResponse"},    /* 0x920C    -  -    */
+       {       0xA20E, "FocalPlaneXResolution"},       /* 0x920E    -  -    */
+       {       0xA20F, "FocalPlaneYResolution"},           /* 0x920F    -  -    */
+       {       0xA210, "FocalPlaneResolutionUnit", ProcessFocalPlaneUnits},
+                                                   /* 0x9210    -  -    */
+       {       0xA214, "SubjectLocation"},                     /* 0x9214    -  -    */
+       {       0xA215, "ExposureIndex"},                       /* 0x9215    -  -    */
+       {       0xA217, "SensingMethod"},                       /* 0x9217    -  -    */
+       {       0xA300, "FileSource"},
+       {       0xA301, "SceneType"},
+       {        0, NULL}
+} ;
+
+
+
+/* Process one of the nested EXIF directories. */
+static int
+ProcessExifDir(ImageInfoType *ImageInfo, char *DirStart, char *OffsetBase, unsigned ExifLength, char *LastExifRefd)
+{
+    int de;
+    int a;
+    int NumDirEntries;
+    exif_rec_data_t rd;
+       char rec_type;
+       char label[32];
+
+    NumDirEntries = Get16u(DirStart, ImageInfo->MotorolaOrder);
+
+    if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength)) {
+               exif_error("Illegally sized directory");
+               return FALSE;
+    }
+
+
+    for (de=0;de<NumDirEntries;de++) {
+        int Tag, Format, Components;
+        char *ValuePtr;
+        int ByteCount;
+        char *DirEntry;
+               struct ExifTag *tag_p;
+
+        DirEntry = DirStart+2+12*de;
+
+        Tag = Get16u(DirEntry, ImageInfo->MotorolaOrder);
+        Format = Get16u(DirEntry+2, ImageInfo->MotorolaOrder);
+        Components = Get32u(DirEntry+4, ImageInfo->MotorolaOrder);
+
+        if ((Format-1) >= NUM_FORMATS) {
+            /* (-1) catches illegal zero case as unsigned underflows to positive large. */
+                       exif_error("Illegal format code in EXIF dir");
+                       return FALSE;
+        }
+
+        ByteCount = Components * ExifBytesPerFormat[Format];
+
+        if (ByteCount > 4) {
+            unsigned OffsetVal;
+            OffsetVal = Get32u(DirEntry+8, ImageInfo->MotorolaOrder);
+            /* If its bigger than 4 bytes, the dir entry contains an offset. */
+            if (OffsetVal+ByteCount > ExifLength) {
+                /* Bogus pointer offset and / or bytecount value */
+                               /*                printf("Offset %d bytes %d ExifLen %d\n",OffsetVal, ByteCount, ExifLength); */
+
+                               exif_error("Illegal pointer offset value in EXIF");
+                               return FALSE;
+            }
+            ValuePtr = OffsetBase+OffsetVal;
+        } else {
+            /* 4 bytes or less and value is in the dir entry itself */
+            ValuePtr = DirEntry+8;
+        }
+
+        if (LastExifRefd < ValuePtr+ByteCount) {
+            /* 
+                          Keep track of last byte in the exif header that was actually referenced.
+               That way, we know where the discardable thumbnail data begins.
+                       */
+            LastExifRefd = ValuePtr+ByteCount;
+        }
+
+        if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET) {
+            char *SubdirStart;
+            SubdirStart = OffsetBase + Get32u(ValuePtr, ImageInfo->MotorolaOrder);
+            if (SubdirStart < OffsetBase || SubdirStart > OffsetBase+ExifLength) {
+                               exif_error("Illegal subdirectory link");
+                               return FALSE;
+            }
+            ProcessExifDir(ImageInfo, SubdirStart, OffsetBase, ExifLength, LastExifRefd);
+            continue;
+        }
+
+               /* Search through tag table */
+               for (tag_p = &TagTable[0]; tag_p->Desc != NULL; tag_p++) {
+                       if (tag_p->Tag == Tag) {
+                               if (tag_p->Func != NULL) {
+                                       (*tag_p->Func)(ImageInfo, ValuePtr, ByteCount, Format, tag_p, OffsetBase);
+                               } else {
+                                       rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format,
+                                                                                                ImageInfo->MotorolaOrder,
+                                                                                                &rd);
+                                       exif_append_data(&ImageInfo->d,
+                                                                        tag_p->Desc,
+                                                                        rec_type,
+                                                                        Format,
+                                                                        &rd);
+                               }
+                               break;
+                       }
+               }
+               if (tag_p->Desc == NULL) {
+                       rec_type = ConvertAnyFormat2(ValuePtr, ByteCount, Format,
+                                                                                ImageInfo->MotorolaOrder,
+                                                                                &rd);
+                       sprintf(label, "0x%04x", Tag);
+                       exif_append_data(&ImageInfo->d,
+                                                        label,
+                                                        rec_type,
+                                                        Format,
+                                                        &rd);
+               }
+       }
+    return TRUE;
+}
+
+/* 
+   Process an EXIF marker
+   Describes all the drivel that most digital cameras include...
+*/
+static int
+process_EXIF (ImageInfoType *ImageInfo, char *CharBuf, unsigned int length, char *LastExifRefd)
+{
+       int cc;
+       exif_rec_data_t rd;
+       LastExifRefd = CharBuf;
+
+       {   /* Check the EXIF header component */
+               static const uchar ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+               if (memcmp(CharBuf+2, ExifHeader,6)) {
+                       exif_error("Incorrect Exif header");
+                       return FALSE;
+               }
+       }
+
+       if (memcmp(CharBuf+8,"II",2) == 0) {
+               ImageInfo->MotorolaOrder = 0;
+       } else {
+               if (memcmp(CharBuf+8,"MM",2) == 0) {
+                       ImageInfo->MotorolaOrder = 1;
+               } else {
+                       exif_error("Invalid Exif alignment marker.");
+                       return FALSE;
+               }
+       }
+
+       /* Check the next two values for correctness. */
+       if (Get16u(CharBuf+10,ImageInfo->MotorolaOrder) != 0x2a
+               || Get32u(CharBuf+12,ImageInfo->MotorolaOrder) != 0x08) {
+               exif_error("Invalid Exif start (1, NULL)");
+               return FALSE;
+       }
+
+       /* First directory starts 16 bytes in.  Offsets start at 8 bytes in. */
+       cc = ProcessExifDir(ImageInfo, CharBuf+16, CharBuf+8, length-6, LastExifRefd);
+       if (cc != TRUE) {
+               return cc;
+       }
+       return TRUE;
+}
+/* Parse the marker stream until SOS or EOI is seen; */
+static int 
+scan_JPEG_header (ImageInfoType *ImageInfo, FILE *infile, Section_t *Sections, int *SectionsRead, int ReadAll, char *LastExifRefd)
+{
+    int a;
+    int HaveCom = FALSE;
+
+    a = fgetc(infile);
+    if (a != 0xff || fgetc(infile) != M_SOI) {
+        return FALSE;
+    }
+
+    for(*SectionsRead=0;*SectionsRead < 19;) {
+        int itemlen;
+        int marker = 0;
+        int ll,lh, got;
+        uchar *Data;
+
+        for (a=0;a<7;a++) {
+            marker = fgetc(infile);
+            if (marker != 0xff) break;
+        }
+        if (marker == 0xff) {
+            /* 0xff is legal padding, but if we get that many, something's wrong. */
+                       exif_error("too many padding bytes!");
+                       return FALSE;
+        }
+
+        Sections[*SectionsRead].Type = marker;
+  
+        /* Read the length of the section. */
+        lh = fgetc(infile);
+        ll = fgetc(infile);
+
+        itemlen = (lh << 8) | ll;
+
+        if (itemlen < 2) {
+                       exif_error("invalid marker");
+                       return FALSE;
+        }
+
+        Sections[*SectionsRead].Size = itemlen;
+
+        Data = (uchar *)(*exif_malloc_fn)(itemlen+1); /* Add 1 to allow sticking a 0 at the end. */
+        Sections[*SectionsRead].Data = Data;
+
+        /* Store first two pre-read bytes. */
+        Data[0] = (uchar)lh;
+        Data[1] = (uchar)ll;
+
+        got = fread(Data+2, 1, itemlen-2, infile); /* Read the whole section. */
+        if (got != itemlen-2) {
+                       exif_error("reading from file");
+                       return FALSE;
+        }
+        *SectionsRead += 1;
+
+        switch(marker) {
+               case M_SOS:   /* stop before hitting compressed data  */
+                       /* If reading entire image is requested, read the rest of the data. */
+                       if (ReadAll) {
+                               int cp, ep, size;
+                               /* Determine how much file is left. */
+                               cp = ftell(infile);
+                               fseek(infile, 0, SEEK_END);
+                               ep = ftell(infile);
+                               fseek(infile, cp, SEEK_SET);
+
+                               size = ep-cp;
+                               Data = (uchar *)(*exif_malloc_fn)(size);
+                               if (Data == NULL) {
+                                       exif_error("could not allocate data for entire image");
+                                       return FALSE;
+                               }
+
+                               got = fread(Data, 1, size, infile);
+                               if (got != size) {
+                                       exif_error("could not read the rest of the image");
+                                       return FALSE;
+                               }
+
+                               Sections[*SectionsRead].Data = Data;
+                               Sections[*SectionsRead].Size = size;
+                               Sections[*SectionsRead].Type = PSEUDO_IMAGE_MARKER;
+                               (*SectionsRead)++;
+                               /*
+                                *HaveAll = 1;
+                                */
+                       }
+                       return TRUE;
+
+               case M_EOI:   /* in case it's a tables-only JPEG stream */
+                       exif_error("No image in jpeg!");
+                       return FALSE;
+
+               case M_COM: /* Comment section */
+                       if (HaveCom) {
+                               (*SectionsRead) -= 1;
+                               (*exif_free_fn)(Sections[*SectionsRead].Data);
+                       } else {
+                               process_COM(ImageInfo, Data, itemlen);
+                               HaveCom = TRUE;
+                       }
+                       break;
+
+               case M_EXIF:
+                       if (*SectionsRead <= 2) {
+                               /* Seen files from some 'U-lead' software with Vivitar scanner
+                                  that uses marker 31 later in the file (no clue what for!) */
+                               process_EXIF(ImageInfo, (char *)Data, itemlen, LastExifRefd);
+                       }
+                       break;
+
+               case M_SOF0: 
+               case M_SOF1: 
+               case M_SOF2: 
+               case M_SOF3: 
+               case M_SOF5: 
+               case M_SOF6: 
+               case M_SOF7: 
+               case M_SOF9: 
+               case M_SOF10:
+               case M_SOF11:
+               case M_SOF13:
+               case M_SOF14:
+               case M_SOF15:
+                       process_SOFn(ImageInfo, Data, marker);
+                       break;
+               default:
+                       /* skip any other marker silently. */
+                       break;
+        }
+    }
+    return TRUE;
+}
+
+/* 
+   Discard read data.
+*/
+static void
+DiscardData(Section_t *Sections, int *SectionsRead)
+{
+    int a;
+    for (a=0;a<*SectionsRead-1;a++) {
+        (*exif_free_fn)(Sections[a].Data);
+    }
+    *SectionsRead = 0;
+}
+
+/* 
+   Read image data.
+*/
+static int
+ReadJpegFile(ImageInfoType *ImageInfo, Section_t *Sections, 
+                        int *SectionsRead, int fd, 
+                        int ReadAll, char *LastExifRefd)
+{
+    FILE *infile;
+    int ret;
+       char *tmp;
+       char **p_argv;
+       int p_argc;
+
+    infile = fdopen(fd, "rb"); /* Unix ignores 'b', windows needs it. */
+
+    if (infile == NULL) {
+               exif_error("Unable to open '%s'", ImageInfo->filename);
+               return FALSE;
+    }
+
+    /* Start with an empty image information structure. */
+    memset(ImageInfo, 0, sizeof(*ImageInfo));
+    memset(Sections, 0, sizeof(*Sections));
+
+    ImageInfo->d = exif_alloc();
+
+    /* Scan the JPEG headers. */
+    ret = scan_JPEG_header(ImageInfo, infile, Sections, SectionsRead, ReadAll, LastExifRefd);
+    if (!ret) {
+               exif_error("Invalid Jpeg file: '%s'",ImageInfo->filename);
+               return FALSE;
+    }
+
+    fclose(infile);
+
+    return ret;
+}
+
+static int
+read_jpeg_exif(ImageInfoType *ImageInfo, int fd, int ReadAll)
+{
+       Section_t Sections[20];
+       int SectionsRead;
+       char *LastExifRefd=NULL;
+       int ret;
+       int thumbsize=0;
+
+       ret = ReadJpegFile(ImageInfo, Sections, &SectionsRead, fd, ReadAll, LastExifRefd); 
+#if 0
+       /*
+        * Thought this might pick out the embedded thumbnail, but it doesn't work.   -RL
+     */
+       for (i=0;i<SectionsRead-1;i++) {
+               if (Sections[i].Type == M_EXIF) {
+                       thumbsize = Sections[i].Size;
+                       if(thumbsize>0) {
+                               ImageInfo->Thumbnail = (*exif_malloc_fn)(thumbsize+5);
+                               ImageInfo->ThumbnailSize = thumbsize;
+                               ImageInfo->Thumbnail[0] = 0xff;
+                               ImageInfo->Thumbnail[1] = 0xd8;
+                               ImageInfo->Thumbnail[2] = 0xff;
+                               memcpy(ImageInfo->Thumbnail+4, Sections[i].Data, thumbsize+4);
+                       }
+               }
+       }
+#endif
+    if (ret != FALSE) {
+        DiscardData(Sections, &SectionsRead);
+    }
+       return(ret);
+}
+
+exif_data_t *
+exif_parse_fd(int fd)
+{
+       ImageInfoType ImageInfo;
+
+       ImageInfo.filename = "<file stream>";
+       if (read_jpeg_exif(&ImageInfo, fd, 1) != TRUE) {
+               return NULL;
+       }
+       return ImageInfo.d;
+}
+
+exif_data_t *
+exif_parse_file(const char *filename)
+{
+       ImageInfoType ImageInfo;
+       int fd;
+       
+       ImageInfo.filename = filename;
+       fd = open(filename, O_RDONLY);
+       if (fd < 0) {
+               return NULL;
+       }
+
+       if (read_jpeg_exif(&ImageInfo, fd, 1) != TRUE) {
+               return NULL;
+       }
+       return ImageInfo.d;
+}
+
+void
+exif_free_data(struct exif_data *d)
+{
+       int i;
+       for (i=0; i<d->n_recs; i++) {
+               (*exif_free_fn)(d->recs[i].rec_name);
+               if (d->recs[i].rec_type == 's') {
+                       (*exif_free_fn)(d->recs[i].rec_data.s);
+               }
+       }
+       (*exif_free_fn)(d);
+}
+
+void
+exif_init(void *(*malloc_fn)(int),
+                 void (*free_fn)(void *),
+                 void *(*realloc_fn)(void *, int))
+{
+       if (malloc_fn == NULL) {
+               malloc_fn = (void *(*)(int))malloc;
+       }
+       exif_malloc_fn = malloc_fn;
+       if (free_fn == NULL) {
+               free_fn = (void (*)(void *))free;
+       }
+       exif_free_fn = free_fn;
+       if (realloc_fn == NULL) {
+               realloc_fn = (void *(*)(void *, int))realloc;
+       }
+       exif_realloc_fn = realloc_fn;
+}
+
+extern exif_record_t *
+exif_find_record(exif_data_t *d, const char *rec_name)
+{
+       int i;
+       for (i=0; i<d->n_recs; i++) {
+               if (strcmp(d->recs[i].rec_name, rec_name) == 0) {
+                       return &d->recs[i];
+               }
+       }
+       return NULL;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+
+
diff --git a/libexif/exif.h b/libexif/exif.h
new file mode 100644 (file)
index 0000000..3a78161
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+
+Copyright (c) 2000 Curtis Galloway
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+$Id: exif.h,v 1.1 2000/10/09 19:23:56 curtisg Exp $
+
+*/
+
+typedef struct exif_rational {
+  int      num;
+  unsigned denom;
+} exif_rational_t;
+
+typedef union {
+  long            l;
+  float           f;
+  double          g;
+  char *          s;
+  exif_rational_t r;
+} exif_rec_data_t;
+
+typedef struct exif_record {
+  char *           rec_name;
+  char             rec_type;
+  int              exif_format;
+  exif_rec_data_t  rec_data;
+} exif_record_t;
+
+typedef struct exif_data {
+  int           n_recs;
+  int           n_alloc;
+  exif_record_t recs[0];
+} exif_data_t;
+
+
+/* EXIF data formats */
+
+#define EXIF_FMT_COMPUTED  -1 /* Not in raw data */
+#define EXIF_FMT_BYTE       1 
+#define EXIF_FMT_STRING     2
+#define EXIF_FMT_USHORT     3
+#define EXIF_FMT_ULONG      4
+#define EXIF_FMT_URATIONAL  5
+#define EXIF_FMT_SBYTE      6
+#define EXIF_FMT_UNDEFINED  7
+#define EXIF_FMT_SSHORT     8
+#define EXIF_FMT_SLONG      9
+#define EXIF_FMT_SRATIONAL 10
+#define EXIF_FMT_SINGLE    11
+#define EXIF_FMT_DOUBLE    12
+
+extern void
+exif_init(void *(*malloc_fn)(int),
+         void (*free_fn)(void *),
+         void *(*realloc_fn)(void *, int));
+
+extern exif_data_t *
+exif_parse_fd(int fd);
+
+extern exif_data_t *
+exif_parse_file(const char *filename);
+
+extern void
+exif_free_data(exif_data_t *d);
+
+extern exif_record_t *
+exif_find_record(exif_data_t *d, const char *rec_name);
+
+
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644 (file)
index 0000000..c14133f
--- /dev/null
@@ -0,0 +1,4 @@
+Makefile.in
+Makefile
+test-exif
+*.o
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644 (file)
index 0000000..82f8ce8
--- /dev/null
@@ -0,0 +1,9 @@
+INCLUDES =                     \
+       -I$(top_srcdir)         \
+       -I$(top_srcdir)/libexif
+
+noinst_PROGRAMS =      \
+       test-exif
+
+test_exif_SOURCES = test-exif.c
+test_exif_LDADD = ../libexif/libexif.la
diff --git a/test/test-exif.c b/test/test-exif.c
new file mode 100644 (file)
index 0000000..4e39cef
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+
+Copyright (c) 2000 Curtis Galloway
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+$Id: main.c,v 1.1.1.1 2000/10/09 19:19:47 curtisg Exp $
+
+*/
+
+#include <stdio.h>
+#include "exif.h"
+
+static void
+usage(void)
+{
+  fprintf(stderr, "Usage: exif <file> [<tag> ...]\n");
+}
+
+static void
+print_record(exif_record_t *rec)
+{
+  printf("%s: ", rec->rec_name);
+  switch (rec->rec_type) {
+  case 's':
+    printf("\"%s\"", rec->rec_data.s);
+    break;
+  case 'f':
+    printf("%f", rec->rec_data.f);
+    break;
+  case 'g':
+    printf("%g", rec->rec_data.f);
+    break;
+  case 'l':
+    printf("%ld", rec->rec_data.l);
+    break;
+  case 'r':
+    printf("%ld/%ld", rec->rec_data.r.num,
+          rec->rec_data.r.denom);
+    break;
+  }
+  printf("\n");
+}
+
+
+main(int argc, char **argv)
+{
+  int ret;
+  exif_data_t *d;
+  exif_record_t *rec;
+  int i;
+
+  exif_init(NULL, NULL, NULL);
+  if (argc < 1) {
+    usage();
+    exit(1);
+  }
+  d = exif_parse_file(argv[1]);
+  if (d == NULL) {
+    printf("Null returned.\n");
+    exit(1);
+  }
+  if (argc > 2) {
+    for (i=2; i<argc; i++) {
+      rec = exif_find_record(d, argv[i]);
+      if (rec) {
+       print_record(rec);
+      }
+    }
+  } else {
+    for (i=0; i<d->n_recs; i++) {
+      print_record(&d->recs[i]);
+    }
+  }
+  exif_free_data(d);
+  return 0;
+}