summaryrefslogtreecommitdiff
path: root/tiff/contrib/pds
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2014-09-01 13:56:46 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2014-09-01 13:56:46 +0200
commit22f703cab05b7cd368f4de9e03991b7664dc5022 (patch)
tree6f4d50beaa42328e24b1c6b56b6ec059e4ef21a5 /tiff/contrib/pds
Initial import of argyll version 1.5.1-8debian/1.5.1-8
Diffstat (limited to 'tiff/contrib/pds')
-rw-r--r--tiff/contrib/pds/Makefile.am28
-rw-r--r--tiff/contrib/pds/Makefile.in421
-rw-r--r--tiff/contrib/pds/README90
-rw-r--r--tiff/contrib/pds/tif_imageiter.c525
-rw-r--r--tiff/contrib/pds/tif_imageiter.h64
-rw-r--r--tiff/contrib/pds/tif_pdsdirread.c1131
-rw-r--r--tiff/contrib/pds/tif_pdsdirwrite.c971
7 files changed, 3230 insertions, 0 deletions
diff --git a/tiff/contrib/pds/Makefile.am b/tiff/contrib/pds/Makefile.am
new file mode 100644
index 0000000..2ead6a7
--- /dev/null
+++ b/tiff/contrib/pds/Makefile.am
@@ -0,0 +1,28 @@
+# Tag Image File Format (TIFF) Software
+#
+# Copyright (C) 2004, Andrey Kiselev <dron@ak4719.spb.edu>
+#
+# Permission to use, copy, modify, distribute, and sell this software and
+# its documentation for any purpose is hereby granted without fee, provided
+# that (i) the above copyright notices and this permission notice appear in
+# all copies of the software and related documentation, and (ii) the names of
+# Sam Leffler and Silicon Graphics may not be used in any advertising or
+# publicity relating to the software without the specific, prior written
+# permission of Sam Leffler and Silicon Graphics.
+#
+# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+#
+# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+
+# Process this file with automake to produce Makefile.in.
+
+EXTRA_DIST = README tif_imageiter.c tif_imageiter.h tif_pdsdirread.c tif_pdsdirwrite.c
+
+INCLUDES = -I../../libtiff -I$(top_srcdir)/libtiff
diff --git a/tiff/contrib/pds/Makefile.in b/tiff/contrib/pds/Makefile.in
new file mode 100644
index 0000000..bc5134b
--- /dev/null
+++ b/tiff/contrib/pds/Makefile.in
@@ -0,0 +1,421 @@
+# Makefile.in generated by automake 1.11 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@
+
+# Tag Image File Format (TIFF) Software
+#
+# Copyright (C) 2004, Andrey Kiselev <dron@ak4719.spb.edu>
+#
+# Permission to use, copy, modify, distribute, and sell this software and
+# its documentation for any purpose is hereby granted without fee, provided
+# that (i) the above copyright notices and this permission notice appear in
+# all copies of the software and related documentation, and (ii) the names of
+# Sam Leffler and Silicon Graphics may not be used in any advertising or
+# publicity relating to the software without the specific, prior written
+# permission of Sam Leffler and Silicon Graphics.
+#
+# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+#
+# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+
+# Process this file with automake to produce Makefile.in.
+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@
+target_triplet = @target@
+subdir = contrib/pds
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/libtiff/tif_config.h \
+ $(top_builddir)/libtiff/tiffconf.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLUT_CFLAGS = @GLUT_CFLAGS@
+GLUT_LIBS = @GLUT_LIBS@
+GLU_CFLAGS = @GLU_CFLAGS@
+GLU_LIBS = @GLU_LIBS@
+GL_CFLAGS = @GL_CFLAGS@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDIR = @LIBDIR@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTIFF_ALPHA_VERSION = @LIBTIFF_ALPHA_VERSION@
+LIBTIFF_DOCDIR = @LIBTIFF_DOCDIR@
+LIBTIFF_MAJOR_VERSION = @LIBTIFF_MAJOR_VERSION@
+LIBTIFF_MICRO_VERSION = @LIBTIFF_MICRO_VERSION@
+LIBTIFF_MINOR_VERSION = @LIBTIFF_MINOR_VERSION@
+LIBTIFF_RELEASE_DATE = @LIBTIFF_RELEASE_DATE@
+LIBTIFF_VERSION = @LIBTIFF_VERSION@
+LIBTIFF_VERSION_INFO = @LIBTIFF_VERSION_INFO@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+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@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+acx_pthread_config = @acx_pthread_config@
+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 = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = README tif_imageiter.c tif_imageiter.h tif_pdsdirread.c tif_pdsdirwrite.c
+INCLUDES = -I../../libtiff -I$(top_srcdir)/libtiff
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(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) --foreign contrib/pds/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign contrib/pds/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):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+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
+installdirs:
+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)
+
+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-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+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 -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool 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-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+# 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/tiff/contrib/pds/README b/tiff/contrib/pds/README
new file mode 100644
index 0000000..b9abc6b
--- /dev/null
+++ b/tiff/contrib/pds/README
@@ -0,0 +1,90 @@
+Date: Fri, 01 Aug 1997 20:14:52 MDT
+To: Sam Leffler <sam@cthulhu.engr.sgi.com>
+
+From: "Conrad J. Poelman (WSAT)" <poelmanc@plk.af.mil>
+Subject: Potential TIFF library additions
+
+Delivery-Date: Fri, 01 Aug 1997 19:21:06 -0700
+
+Sam,
+
+You probably don't remember me, but I sent in a couple of bug fixes
+regarding the TIFF library about a 16 months ago or so...
+
+I just wanted to send you two other additions that I have made to our
+local version of the TIFF library in hopes that you will want to
+incorporate them into your next major release of the TIFF library.
+(These additions are based on TIFF version 3.4beta31, but they sit on
+top of the library so they shouldn't be much trouble to incorporate them
+into any more recent version.) They are internally documented to a
+reasonable extent and we've been successfully using them in our code
+here for over a year. If you think they would make good additions to the
+TIFF library, I'd be happy to clean them up more, document them more,
+and/or integrate them with the latest version of the TIFF library, but I
+figured I'd see if you were interested in using them before I went to
+all that trouble.
+
+TIFF Image Iterator
+-------------------
+Your ReadRGBA() routine works well for reading many different formats
+(TILED, STIP, compressed or not, etc.) of the most basic types of data
+(RGB, 8-bit greyscale, 8-bit colormapped) into an SGI-style data array,
+and serves as a good template for users with other needs. I used it as
+an exmaple of how to make an iterator which, rather than fill a data
+array, calls an arbitrary user-supplied callback function for each
+"chunk" of data - that "chunk" might be a strip or a tile, and might
+have one sample-per-pixel or two, and might be 8-bit data or 16-bit or
+24-bit. The callback function can do whatever it wants with the data -
+store it in a big array, convert it to RGBA, or draw it directly to the
+screen. I was able to use this iterator to read 16-bit greyscale and 32-
+and 64-bit floating point data, which wasn't possible with ReadRGBA().
+
+I have tested this routine with 8- and 16-bit greyscale data as well as
+with 32- and 64-bit floating point data. I believe nearly all of our
+data is organized in strips, so actually I'd appreciate it if you had
+some tiled images that I could test it with.
+
+It should certainly be possible and would be cleanest to reimplement
+ReadRGBA() in terms of the image iterator, but I haven't done that.
+
+
+Private Sub-Directory Read/Write
+--------------------------------
+TIFF-PL is a Phillips Laboratory extension to the TIFF tags that allows
+us to store satellite imaging-specific information in a TIFF format,
+such as the satellite's trajectory, the imaging time, etc. In order to
+give us the flexibility to modify the tag definitions without getting
+approval from the TIFF committee every time, we were given only three
+TIFF tags - a PL signature, a PL version number, and PL directory
+offset, which lists the position in the file at which to find a private
+sub-directory of tags-value pairs. So I wrote two routines:
+TIFFWritePrivateDataSubDirectory(), which takes a list of tags and a
+"get" function and writes the tag values into the TIFF file, returning
+the offset within the file at which it wrote the directory; and
+TIFFReadPrivateDataSubDirectory(), which takes an offset, a list of
+tags, and a "set" function and reads all the data from the private
+directory. The functions themselves are pretty simple. (The files are
+huge because I had to basically copy all of the tif_dirread.c and
+tif_dirwrite.c files in order to access the various fetching routines
+which were all declared static and therefore inaccessible in the TIFF
+library.)
+
+
+I'm including the four source files (tif_imgiter.h, tif_imgiter.c,
+tif_pdsdirread.c, tif_pdsdirwrite.c) in case you want to take a look at
+them. I can also send you some sample code that uses them if you like.
+If you're interested in having them incorporated into the standard TIFF
+library, I'd be happy to do that integration and clean up and document
+the routines. (For example, I've already realized that instead of
+limiting the SEP callback function to three bands (R,G,B) it should take
+an array to enable the handling of n-banded multi-spectral data...) If
+not, I'll just leave them as they are, since they work fine for us now.
+
+Holler if you have any questions.
+
+-- Conrad
+__________________________________________________________________
+ Capt Conrad J. Poelman PL/WSAT (Phillips Laboratory)
+ 505-846-4347 3550 Aberdeen Ave SE
+ (FAX) 505-846-4374 Kirtland AFB, NM 87117-5776
+
diff --git a/tiff/contrib/pds/tif_imageiter.c b/tiff/contrib/pds/tif_imageiter.c
new file mode 100644
index 0000000..6140f96
--- /dev/null
+++ b/tiff/contrib/pds/tif_imageiter.c
@@ -0,0 +1,525 @@
+/* $Header: /cvs/maptools/cvsroot/libtiff/contrib/pds/tif_imageiter.c,v 1.3.2.1 2010-06-08 18:50:41 bfriesen Exp $ */
+
+/*
+ * Copyright (c) 1991-1996 Sam Leffler
+ * Copyright (c) 1991-1996 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library
+ *
+ * Written by Conrad J. Poelman, PL/WSAT, Kirtland AFB, NM on 26 Mar 96.
+ *
+ * This file contains code to allow a calling program to "iterate" over each
+ * pixels in an image as it is read from the file. The iterator takes care of
+ * reading strips versus (possibly clipped) tiles, decoding the information
+ * according to the decoding method, and so on, so that calling program can
+ * ignore those details. The calling program does, however, need to be
+ * conscious of the type of the pixel data that it is receiving.
+ *
+ * For reasons of efficiency, the callback function actually gets called for
+ * "blocks" of pixels rather than for individual pixels. The format of the
+ * callback arguments is given below.
+ *
+ * This code was taken from TIFFReadRGBAImage() in tif_getimage.c of the original
+ * TIFF distribution, and simplified and generalized to provide this general
+ * iteration capability. Those routines could certainly be re-implemented in terms
+ * of a TIFFImageIter if desired.
+ *
+ */
+#include "tiffiop.h"
+#include "tif_imageiter.h"
+#include <assert.h>
+#include <stdio.h>
+
+static int gtTileContig(TIFFImageIter*, void *udata, uint32, uint32);
+static int gtTileSeparate(TIFFImageIter*, void *udata, uint32, uint32);
+static int gtStripContig(TIFFImageIter*, void *udata, uint32, uint32);
+static int gtStripSeparate(TIFFImageIter*, void *udata, uint32, uint32);
+
+static const char photoTag[] = "PhotometricInterpretation";
+
+static int
+isCCITTCompression(TIFF* tif)
+{
+ uint16 compress;
+ TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
+ return (compress == COMPRESSION_CCITTFAX3 ||
+ compress == COMPRESSION_CCITTFAX4 ||
+ compress == COMPRESSION_CCITTRLE ||
+ compress == COMPRESSION_CCITTRLEW);
+}
+
+int
+TIFFImageIterBegin(TIFFImageIter* img, TIFF* tif, int stop, char emsg[1024])
+{
+ uint16* sampleinfo;
+ uint16 extrasamples;
+ uint16 planarconfig;
+ int colorchannels;
+
+ img->tif = tif;
+ img->stoponerr = stop;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
+ img->alpha = 0;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
+ TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
+ &extrasamples, &sampleinfo);
+ if (extrasamples == 1)
+ switch (sampleinfo[0]) {
+ case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */
+ case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */
+ img->alpha = sampleinfo[0];
+ break;
+ }
+ colorchannels = img->samplesperpixel - extrasamples;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
+ if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) {
+ switch (colorchannels) {
+ case 1:
+ if (isCCITTCompression(tif))
+ img->photometric = PHOTOMETRIC_MINISWHITE;
+ else
+ img->photometric = PHOTOMETRIC_MINISBLACK;
+ break;
+ case 3:
+ img->photometric = PHOTOMETRIC_RGB;
+ break;
+ default:
+ sprintf(emsg, "Missing needed %s tag", photoTag);
+ return (0);
+ }
+ }
+ switch (img->photometric) {
+ case PHOTOMETRIC_PALETTE:
+ if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
+ &img->redcmap, &img->greencmap, &img->bluecmap)) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Missing required \"Colormap\" tag");
+ return (0);
+ }
+ /* fall thru... */
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+/* This should work now so skip the check - BSR
+ if (planarconfig == PLANARCONFIG_CONTIG && img->samplesperpixel != 1) {
+ sprintf(emsg,
+ "Sorry, can not handle contiguous data with %s=%d, and %s=%d",
+ photoTag, img->photometric,
+ "Samples/pixel", img->samplesperpixel);
+ return (0);
+ }
+ */
+ break;
+ case PHOTOMETRIC_YCBCR:
+ if (planarconfig != PLANARCONFIG_CONTIG) {
+ sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d",
+ "Planarconfiguration", planarconfig);
+ return (0);
+ }
+ /* It would probably be nice to have a reality check here. */
+ { uint16 compress;
+ TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
+ if (compress == COMPRESSION_JPEG && planarconfig == PLANARCONFIG_CONTIG) {
+ /* can rely on libjpeg to convert to RGB */
+ /* XXX should restore current state on exit */
+ TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
+ img->photometric = PHOTOMETRIC_RGB;
+ }
+ }
+ break;
+ case PHOTOMETRIC_RGB:
+ if (colorchannels < 3) {
+ sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
+ "Color channels", colorchannels);
+ return (0);
+ }
+ break;
+ case PHOTOMETRIC_SEPARATED: {
+ uint16 inkset;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
+ if (inkset != INKSET_CMYK) {
+ sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
+ "InkSet", inkset);
+ return (0);
+ }
+ if (img->samplesperpixel != 4) {
+ sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
+ "Samples/pixel", img->samplesperpixel);
+ return (0);
+ }
+ break;
+ }
+ default:
+ sprintf(emsg, "Sorry, can not handle image with %s=%d",
+ photoTag, img->photometric);
+ return (0);
+ }
+ TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
+ TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
+
+ TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
+ switch (img->orientation) {
+ case ORIENTATION_BOTRIGHT:
+ case ORIENTATION_RIGHTBOT: /* XXX */
+ case ORIENTATION_LEFTBOT: /* XXX */
+ TIFFWarning(TIFFFileName(tif), "using bottom-left orientation");
+ img->orientation = ORIENTATION_BOTLEFT;
+ /* fall thru... */
+ case ORIENTATION_BOTLEFT:
+ break;
+ case ORIENTATION_TOPRIGHT:
+ case ORIENTATION_RIGHTTOP: /* XXX */
+ case ORIENTATION_LEFTTOP: /* XXX */
+ default:
+ TIFFWarning(TIFFFileName(tif), "using top-left orientation");
+ img->orientation = ORIENTATION_TOPLEFT;
+ /* fall thru... */
+ case ORIENTATION_TOPLEFT:
+ break;
+ }
+
+ img->isContig =
+ !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1);
+ if (img->isContig) {
+ img->get = TIFFIsTiled(tif) ? gtTileContig : gtStripContig;
+ } else {
+ img->get = TIFFIsTiled(tif) ? gtTileSeparate : gtStripSeparate;
+ }
+ return (1);
+}
+
+int
+TIFFImageIterGet(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
+{
+ if (img->get == NULL) {
+ TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No \"get\" routine setup");
+ return (0);
+ }
+ if (img->callback.any == NULL) {
+ TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif),
+ "No \"put\" routine setupl; probably can not handle image format");
+ return (0);
+ }
+ return (*img->get)(img, udata, w, h);
+}
+
+TIFFImageIterEnd(TIFFImageIter* img)
+{
+ /* Nothing to free... ? */
+}
+
+/*
+ * Read the specified image into an ABGR-format raster.
+ */
+int
+TIFFReadImageIter(TIFF* tif,
+ uint32 rwidth, uint32 rheight, uint8* raster, int stop)
+{
+ char emsg[1024];
+ TIFFImageIter img;
+ int ok;
+
+ if (TIFFImageIterBegin(&img, tif, stop, emsg)) {
+ /* XXX verify rwidth and rheight against width and height */
+ ok = TIFFImageIterGet(&img, raster, rwidth, img.height);
+ TIFFImageIterEnd(&img);
+ } else {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), emsg);
+ ok = 0;
+ }
+ return (ok);
+}
+
+
+/*
+ * Get an tile-organized image that has
+ * PlanarConfiguration contiguous if SamplesPerPixel > 1
+ * or
+ * SamplesPerPixel == 1
+ */
+static int
+gtTileContig(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
+{
+ TIFF* tif = img->tif;
+ ImageIterTileContigRoutine callback = img->callback.contig;
+ uint16 orientation;
+ uint32 col, row;
+ uint32 tw, th;
+ u_char* buf;
+ int32 fromskew;
+ uint32 nrow;
+
+ buf = (u_char*) _TIFFmalloc(TIFFTileSize(tif));
+ if (buf == 0) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
+ return (0);
+ }
+ TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
+ TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
+ orientation = img->orientation;
+ for (row = 0; row < h; row += th) {
+ nrow = (row + th > h ? h - row : th);
+ for (col = 0; col < w; col += tw) {
+ if (TIFFReadTile(tif, buf, col, row, 0, 0) < 0 && img->stoponerr)
+ break;
+ if (col + tw > w) {
+ /*
+ * Tile is clipped horizontally. Calculate
+ * visible portion and skewing factors.
+ */
+ uint32 npix = w - col;
+ fromskew = tw - npix;
+ (*callback)(img, udata, col, row, npix, nrow, fromskew, buf);
+ } else {
+ (*callback)(img, udata, col, row, tw, nrow, 0, buf);
+ }
+ }
+ }
+ _TIFFfree(buf);
+ return (1);
+}
+
+/*
+ * Get an tile-organized image that has
+ * SamplesPerPixel > 1
+ * PlanarConfiguration separated
+ * We assume that all such images are RGB.
+ */
+static int
+gtTileSeparate(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
+{
+ TIFF* tif = img->tif;
+ ImageIterTileSeparateRoutine callback = img->callback.separate;
+ uint16 orientation;
+ uint32 col, row;
+ uint32 tw, th;
+ u_char* buf;
+ u_char* r;
+ u_char* g;
+ u_char* b;
+ u_char* a;
+ tsize_t tilesize;
+ int32 fromskew;
+ int alpha = img->alpha;
+ uint32 nrow;
+
+ tilesize = TIFFTileSize(tif);
+ buf = (u_char*) _TIFFmalloc(4*tilesize);
+ if (buf == 0) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
+ return (0);
+ }
+ r = buf;
+ g = r + tilesize;
+ b = g + tilesize;
+ a = b + tilesize;
+ if (!alpha)
+ memset(a, 0xff, tilesize);
+ TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
+ TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
+ orientation = img->orientation;
+ for (row = 0; row < h; row += th) {
+ nrow = (row + th > h ? h - row : th);
+ for (col = 0; col < w; col += tw) {
+ if (TIFFReadTile(tif, r, col, row,0,0) < 0 && img->stoponerr)
+ break;
+ if (TIFFReadTile(tif, g, col, row,0,1) < 0 && img->stoponerr)
+ break;
+ if (TIFFReadTile(tif, b, col, row,0,2) < 0 && img->stoponerr)
+ break;
+ if (alpha && TIFFReadTile(tif,a,col,row,0,3) < 0 && img->stoponerr)
+ break;
+ if (col + tw > w) {
+ /*
+ * Tile is clipped horizontally. Calculate
+ * visible portion and skewing factors.
+ */
+ uint32 npix = w - col;
+ fromskew = tw - npix;
+ (*callback)(img, udata, col, row, npix, nrow, fromskew, r, g, b, a);
+ } else {
+ (*callback)(img, udata, col, row, tw, nrow, 0, r, g, b, a);
+ }
+ }
+ }
+ _TIFFfree(buf);
+ return (1);
+}
+
+/*
+ * Get a strip-organized image that has
+ * PlanarConfiguration contiguous if SamplesPerPixel > 1
+ * or
+ * SamplesPerPixel == 1
+ */
+static int
+gtStripContig(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
+{
+ TIFF* tif = img->tif;
+ ImageIterTileContigRoutine callback = img->callback.contig;
+ uint16 orientation;
+ uint32 row, nrow;
+ u_char* buf;
+ uint32 rowsperstrip;
+ uint32 imagewidth = img->width;
+ tsize_t scanline;
+ int32 fromskew;
+
+ buf = (u_char*) _TIFFmalloc(TIFFStripSize(tif));
+ if (buf == 0) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer");
+ return (0);
+ }
+ orientation = img->orientation;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+ scanline = TIFFScanlineSize(tif);
+ fromskew = (w < imagewidth ? imagewidth - w : 0);
+ for (row = 0; row < h; row += rowsperstrip) {
+ nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
+ buf, nrow*scanline) < 0 && img->stoponerr)
+ break;
+ (*callback)(img, udata, 0, row, w, nrow, fromskew, buf);
+ }
+ _TIFFfree(buf);
+ return (1);
+}
+
+/*
+ * Get a strip-organized image with
+ * SamplesPerPixel > 1
+ * PlanarConfiguration separated
+ * We assume that all such images are RGB.
+ */
+static int
+gtStripSeparate(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
+{
+ TIFF* tif = img->tif;
+ ImageIterTileSeparateRoutine callback = img->callback.separate;
+ uint16 orientation;
+ u_char *buf;
+ u_char *r, *g, *b, *a;
+ uint32 row, nrow;
+ tsize_t scanline;
+ uint32 rowsperstrip;
+ uint32 imagewidth = img->width;
+ tsize_t stripsize;
+ int32 fromskew;
+ int alpha = img->alpha;
+
+ stripsize = TIFFStripSize(tif);
+ r = buf = (u_char *)_TIFFmalloc(4*stripsize);
+ if (buf == 0) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
+ return (0);
+ }
+ g = r + stripsize;
+ b = g + stripsize;
+ a = b + stripsize;
+ if (!alpha)
+ memset(a, 0xff, stripsize);
+ orientation = img->orientation;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+ scanline = TIFFScanlineSize(tif);
+ fromskew = (w < imagewidth ? imagewidth - w : 0);
+ for (row = 0; row < h; row += rowsperstrip) {
+ nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
+ r, nrow*scanline) < 0 && img->stoponerr)
+ break;
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 1),
+ g, nrow*scanline) < 0 && img->stoponerr)
+ break;
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 2),
+ b, nrow*scanline) < 0 && img->stoponerr)
+ break;
+ if (alpha &&
+ (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 3),
+ a, nrow*scanline) < 0 && img->stoponerr))
+ break;
+ (*callback)(img, udata, 0, row, w, nrow, fromskew, r, g, b, a);
+ }
+ _TIFFfree(buf);
+ return (1);
+}
+
+DECLAREContigCallbackFunc(TestContigCallback)
+{
+ printf("Contig Callback called with x = %d, y = %d, w = %d, h = %d, fromskew = %d\n",
+ x, y, w, h, fromskew);
+}
+
+
+DECLARESepCallbackFunc(TestSepCallback)
+{
+ printf("Sep Callback called with x = %d, y = %d, w = %d, h = %d, fromskew = %d\n",
+ x, y, w, h, fromskew);
+}
+
+
+#ifdef MAIN
+main(int argc, char **argv)
+{
+ char emsg[1024];
+ TIFFImageIter img;
+ int ok;
+ int stop = 1;
+
+ TIFF *tif;
+ unsigned long nx, ny;
+ unsigned short BitsPerSample, SamplesPerPixel;
+ int isColorMapped, isPliFile;
+ unsigned char *ColorMap;
+ unsigned char *data;
+
+ if (argc < 2) {
+ fprintf(stderr,"usage: %s tiff_file\n",argv[0]);
+ exit(1);
+ }
+ tif = (TIFF *)PLIGetImage(argv[1], (void *) &data, &ColorMap,
+ &nx, &ny, &BitsPerSample, &SamplesPerPixel,
+ &isColorMapped, &isPliFile);
+ if (tif != NULL) {
+
+ if (TIFFImageIterBegin(&img, tif, stop, emsg)) {
+ /* Here need to set data and callback function! */
+ if (img.isContig) {
+ img.callback = TestContigCallback;
+ } else {
+ img.callback = TestSepCallback;
+ }
+ ok = TIFFImageIterGet(&img, NULL, img.width, img.height);
+ TIFFImageIterEnd(&img);
+ } else {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), emsg);
+ }
+ }
+
+}
+#endif
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 8
+ * fill-column: 78
+ * End:
+ */
diff --git a/tiff/contrib/pds/tif_imageiter.h b/tiff/contrib/pds/tif_imageiter.h
new file mode 100644
index 0000000..e7dbe46
--- /dev/null
+++ b/tiff/contrib/pds/tif_imageiter.h
@@ -0,0 +1,64 @@
+typedef struct _TIFFImageIter TIFFImageIter;
+
+/* The callback function is called for each "block" of image pixel data after
+ it has been read from the file and decoded. This image pixel data is in the
+ buffer pp, and this data represents the image pixels from (x,y) to
+ (x+w,y+h). It is stored in pixel format, so each pixel contains
+ img->samplesperpixel consecutive samples each containing img->bitspersample
+ bits of data. The array pp is ordered in h consecutive rows of w+fromskew
+ pixels each. */
+typedef void (*ImageIterTileContigRoutine)
+ (TIFFImageIter*, void *, uint32, uint32, uint32, uint32, int32,
+ unsigned char*);
+#define DECLAREContigCallbackFunc(name) \
+static void name(\
+ TIFFImageIter* img, \
+ void* user_data, \
+ uint32 x, uint32 y, \
+ uint32 w, uint32 h, \
+ int32 fromskew, \
+ u_char* pp \
+)
+
+typedef void (*ImageIterTileSeparateRoutine)
+ (TIFFImageIter*, void *, uint32, uint32, uint32, uint32, int32,
+ unsigned char*, unsigned char*, unsigned char*, unsigned char*);
+#define DECLARESepCallbackFunc(name) \
+static void name(\
+ TIFFImageIter* img, \
+ void* user_data, \
+ uint32 x, uint32 y, \
+ uint32 w, uint32 h,\
+ int32 fromskew, \
+ u_char* r, u_char* g, u_char* b, u_char* a\
+)
+
+struct _TIFFImageIter {
+ TIFF* tif; /* image handle */
+ int stoponerr; /* stop on read error */
+ int isContig; /* data is packed/separate */
+ int alpha; /* type of alpha data present */
+ uint32 width; /* image width */
+ uint32 height; /* image height */
+ uint16 bitspersample; /* image bits/sample */
+ uint16 samplesperpixel; /* image samples/pixel */
+ uint16 orientation; /* image orientation */
+ uint16 photometric; /* image photometric interp */
+ uint16* redcmap; /* colormap pallete */
+ uint16* greencmap;
+ uint16* bluecmap;
+ /* get image data routine */
+ int (*get)(TIFFImageIter*, void *udata, uint32, uint32);
+ union {
+ void (*any)(TIFFImageIter*);
+ ImageIterTileContigRoutine contig;
+ ImageIterTileSeparateRoutine separate;
+ } callback; /* fn to exec for each block */
+};
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 8
+ * fill-column: 78
+ * End:
+ */
diff --git a/tiff/contrib/pds/tif_pdsdirread.c b/tiff/contrib/pds/tif_pdsdirread.c
new file mode 100644
index 0000000..3d01311
--- /dev/null
+++ b/tiff/contrib/pds/tif_pdsdirread.c
@@ -0,0 +1,1131 @@
+/* $Header: /cvs/maptools/cvsroot/libtiff/contrib/pds/tif_pdsdirread.c,v 1.3.2.1 2010-06-08 18:50:41 bfriesen Exp $ */
+
+/*
+ * Copyright (c) 1988-1996 Sam Leffler
+ * Copyright (c) 1991-1996 Silicon Graphics, Inc.
+ * Copyright (c( 1996 USAF Phillips Laboratory
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * These routines written by Conrad J. Poelman on a single late-night of
+ * March 20-21, 1996.
+ *
+ * The entire purpose of this file is to provide a single external function,
+ * TIFFReadPrivateDataSubDirectory(). This function is intended for use in reading a
+ * private subdirectory from a TIFF file into a private structure. The
+ * actual writing of data into the structure is handled by the setFieldFn(),
+ * which is passed to TIFFReadPrivateDataSubDirectory() as a parameter. The idea is to
+ * enable any application wishing to store private subdirectories to do so
+ * easily using this function, without modifying the TIFF library.
+ *
+ * The astute observer will notice that only two functions are at all different
+ * from the original tif_dirread.c file: TIFFReadPrivateDataSubDirectory() and
+ * TIFFFetchNormalSubTag(). All the other stuff that makes this file so huge
+ * is only necessary because all of those functions are declared static in
+ * tif_dirread.c, so we have to totally duplicate them in order to use them.
+ *
+ * Oh, also note the bug fix in TIFFFetchFloat().
+ *
+ */
+
+#include "tiffiop.h"
+
+#define IGNORE 0 /* tag placeholder used below */
+
+#if HAVE_IEEEFP
+#define TIFFCvtIEEEFloatToNative(tif, n, fp)
+#define TIFFCvtIEEEDoubleToNative(tif, n, dp)
+#else
+extern void TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*);
+extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*);
+#endif
+
+static void EstimateStripByteCounts(TIFF*, TIFFDirEntry*, uint16);
+static void MissingRequired(TIFF*, const char*);
+static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32);
+static tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*);
+static tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*);
+static float TIFFFetchRational(TIFF*, TIFFDirEntry*);
+static int TIFFFetchNormalSubTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*,
+ int (*getFieldFn)(TIFF *tif,ttag_t tag,...));
+static int TIFFFetchPerSampleShorts(TIFF*, TIFFDirEntry*, int*);
+static int TIFFFetchPerSampleAnys(TIFF*, TIFFDirEntry*, double*);
+static int TIFFFetchShortArray(TIFF*, TIFFDirEntry*, uint16*);
+static int TIFFFetchStripThing(TIFF*, TIFFDirEntry*, long, uint32**);
+static int TIFFFetchExtraSamples(TIFF*, TIFFDirEntry*);
+static int TIFFFetchRefBlackWhite(TIFF*, TIFFDirEntry*);
+static float TIFFFetchFloat(TIFF*, TIFFDirEntry*);
+static int TIFFFetchFloatArray(TIFF*, TIFFDirEntry*, float*);
+static int TIFFFetchDoubleArray(TIFF*, TIFFDirEntry*, double*);
+static int TIFFFetchAnyArray(TIFF*, TIFFDirEntry*, double*);
+static int TIFFFetchShortPair(TIFF*, TIFFDirEntry*);
+#if STRIPCHOP_SUPPORT
+static void ChopUpSingleUncompressedStrip(TIFF*);
+#endif
+
+static char *
+CheckMalloc(TIFF* tif, tsize_t n, const char* what)
+{
+ char *cp = (char*)_TIFFmalloc(n);
+ if (cp == NULL)
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "No space %s", what);
+ return (cp);
+}
+
+/* Just as was done with TIFFWritePrivateDataSubDirectory(), here we implement
+ TIFFReadPrivateDataSubDirectory() which takes an offset into the TIFF file,
+ a TIFFFieldInfo structure specifying the types of the various tags,
+ and a function to use to set individual tags when they are encountered.
+ The data is read from the file, translated using the TIFF library's
+ built-in machine-independent conversion functions, and filled into
+ private subdirectory structure.
+
+ This code was written by copying the original TIFFReadDirectory() function
+ from tif_dirread.c and paring it down to what is needed for this.
+
+ It is the caller's responsibility to allocate and initialize the internal
+ structure that setFieldFn() will be writing into. If this function is being
+ called more than once before closing the file, the caller also must be
+ careful to free data in the structure before re-initializing.
+
+ It is also the caller's responsibility to verify the presence of
+ any required fields after reading the directory in.
+*/
+
+
+int
+TIFFReadPrivateDataSubDirectory(TIFF* tif, toff_t pdir_offset,
+ TIFFFieldInfo *field_info,
+ int (*setFieldFn)(TIFF *tif, ttag_t tag, ...))
+{
+ register TIFFDirEntry* dp;
+ register int n;
+ register TIFFDirectory* td;
+ TIFFDirEntry* dir;
+ int iv;
+ long v;
+ double dv;
+ const TIFFFieldInfo* fip;
+ int fix;
+ uint16 dircount;
+ uint32 nextdiroff;
+ char* cp;
+ int diroutoforderwarning = 0;
+
+ /* Skipped part about checking for directories or compression data. */
+
+ if (!isMapped(tif)) {
+ if (!SeekOK(tif, pdir_offset)) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Seek error accessing TIFF private subdirectory");
+ return (0);
+ }
+ if (!ReadOK(tif, &dircount, sizeof (uint16))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Can not read TIFF private subdirectory count");
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ dir = (TIFFDirEntry *)CheckMalloc(tif,
+ dircount * sizeof (TIFFDirEntry), "to read TIFF private subdirectory");
+ if (dir == NULL)
+ return (0);
+ if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Can not read TIFF private subdirectory");
+ goto bad;
+ }
+ /*
+ * Read offset to next directory for sequential scans.
+ */
+ (void) ReadOK(tif, &nextdiroff, sizeof (uint32));
+ } else {
+ toff_t off = pdir_offset;
+
+ if (off + sizeof (short) > tif->tif_size) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Can not read TIFF private subdirectory count");
+ return (0);
+ } else
+ _TIFFmemcpy(&dircount, tif->tif_base + off, sizeof (uint16));
+ off += sizeof (uint16);
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ dir = (TIFFDirEntry *)CheckMalloc(tif,
+ dircount * sizeof (TIFFDirEntry), "to read TIFF private subdirectory");
+ if (dir == NULL)
+ return (0);
+ if (off + dircount*sizeof (TIFFDirEntry) > tif->tif_size) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Can not read TIFF private subdirectory");
+ goto bad;
+ } else
+ _TIFFmemcpy(dir, tif->tif_base + off,
+ dircount*sizeof (TIFFDirEntry));
+ off += dircount* sizeof (TIFFDirEntry);
+ if (off + sizeof (uint32) < tif->tif_size)
+ _TIFFmemcpy(&nextdiroff, tif->tif_base+off, sizeof (uint32));
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&nextdiroff);
+
+ /*
+ * Setup default value and then make a pass over
+ * the fields to check type and tag information,
+ * and to extract info required to size data
+ * structures. A second pass is made afterwards
+ * to read in everthing not taken in the first pass.
+ */
+ td = &tif->tif_dir;
+
+ for (fip = field_info, dp = dir, n = dircount;
+ n > 0; n--, dp++) {
+ if (tif->tif_flags & TIFF_SWAB) {
+ TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
+ TIFFSwabArrayOfLong(&dp->tdir_count, 2);
+ }
+ /*
+ * Find the field information entry for this tag.
+ */
+ /*
+ * Silicon Beach (at least) writes unordered
+ * directory tags (violating the spec). Handle
+ * it here, but be obnoxious (maybe they'll fix it?).
+ */
+ if (dp->tdir_tag < fip->field_tag) {
+ if (!diroutoforderwarning) {
+ TIFFWarning(tif->tif_name,
+ "invalid TIFF private subdirectory; tags are not sorted in ascending order");
+ diroutoforderwarning = 1;
+ }
+ fip = field_info; /* O(n^2) */
+ }
+
+ while (fip->field_tag && fip->field_tag < dp->tdir_tag)
+ fip++;
+ if (!fip->field_tag || fip->field_tag != dp->tdir_tag) {
+ TIFFWarning(tif->tif_name,
+ "unknown field with tag %d (0x%x) in private subdirectory ignored",
+ dp->tdir_tag, dp->tdir_tag);
+ dp->tdir_tag = IGNORE;
+ fip = field_info;/* restart search */
+ continue;
+ }
+ /*
+ * Null out old tags that we ignore.
+ */
+
+ /* Not implemented yet, since FIELD_IGNORE is specific to
+ the main directories. Could pass this in too... */
+ if (0 /* && fip->field_bit == FIELD_IGNORE */) {
+ ignore:
+ dp->tdir_tag = IGNORE;
+ continue;
+ }
+
+ /*
+ * Check data type.
+ */
+
+ while (dp->tdir_type != (u_short)fip->field_type) {
+ if (fip->field_type == TIFF_ANY) /* wildcard */
+ break;
+ fip++;
+ if (!fip->field_tag || fip->field_tag != dp->tdir_tag) {
+ TIFFWarning(tif->tif_name,
+ "wrong data type %d for \"%s\"; tag ignored",
+ dp->tdir_type, fip[-1].field_name);
+ goto ignore;
+ }
+ }
+ /*
+ * Check count if known in advance.
+ */
+ if (fip->field_readcount != TIFF_VARIABLE) {
+ uint32 expected = (fip->field_readcount == TIFF_SPP) ?
+ (uint32) td->td_samplesperpixel :
+ (uint32) fip->field_readcount;
+ if (!CheckDirCount(tif, dp, expected))
+ goto ignore;
+ }
+
+ /* Now read in and process data from field. */
+ if (!TIFFFetchNormalSubTag(tif, dp, fip, setFieldFn))
+ goto bad;
+
+ }
+
+ if (dir)
+ _TIFFfree(dir);
+ return (1);
+bad:
+ if (dir)
+ _TIFFfree(dir);
+ return (0);
+}
+
+static void
+EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
+{
+ register TIFFDirEntry *dp;
+ register TIFFDirectory *td = &tif->tif_dir;
+ uint16 i;
+
+ if (td->td_stripbytecount)
+ _TIFFfree(td->td_stripbytecount);
+ td->td_stripbytecount = (uint32*)
+ CheckMalloc(tif, td->td_nstrips * sizeof (uint32),
+ "for \"StripByteCounts\" array");
+ if (td->td_compression != COMPRESSION_NONE) {
+ uint32 space = (uint32)(sizeof (TIFFHeader)
+ + sizeof (uint16)
+ + (dircount * sizeof (TIFFDirEntry))
+ + sizeof (uint32));
+ toff_t filesize = TIFFGetFileSize(tif);
+ uint16 n;
+
+ /* calculate amount of space used by indirect values */
+ for (dp = dir, n = dircount; n > 0; n--, dp++) {
+ uint32 cc = dp->tdir_count*TIFFDataWidth(dp->tdir_type);
+ if (cc > sizeof (uint32))
+ space += cc;
+ }
+ space = (filesize - space) / td->td_samplesperpixel;
+ for (i = 0; i < td->td_nstrips; i++)
+ td->td_stripbytecount[i] = space;
+ /*
+ * This gross hack handles the case were the offset to
+ * the last strip is past the place where we think the strip
+ * should begin. Since a strip of data must be contiguous,
+ * it's safe to assume that we've overestimated the amount
+ * of data in the strip and trim this number back accordingly.
+ */
+ i--;
+ if (td->td_stripoffset[i] + td->td_stripbytecount[i] > filesize)
+ td->td_stripbytecount[i] =
+ filesize - td->td_stripoffset[i];
+ } else {
+ uint32 rowbytes = TIFFScanlineSize(tif);
+ uint32 rowsperstrip = td->td_imagelength / td->td_nstrips;
+ for (i = 0; i < td->td_nstrips; i++)
+ td->td_stripbytecount[i] = rowbytes*rowsperstrip;
+ }
+ TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
+ if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
+ td->td_rowsperstrip = td->td_imagelength;
+}
+
+static void
+MissingRequired(TIFF* tif, const char* tagname)
+{
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "TIFF directory is missing required \"%s\" field", tagname);
+}
+
+/*
+ * Check the count field of a directory
+ * entry against a known value. The caller
+ * is expected to skip/ignore the tag if
+ * there is a mismatch.
+ */
+static int
+CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count)
+{
+ if (count != dir->tdir_count) {
+ TIFFWarning(tif->tif_name,
+ "incorrect count for field \"%s\" (%lu, expecting %lu); tag ignored",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,
+ dir->tdir_count, count);
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Fetch a contiguous directory item.
+ */
+static tsize_t
+TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+ int w = TIFFDataWidth(dir->tdir_type);
+ tsize_t cc = dir->tdir_count * w;
+
+ if (!isMapped(tif)) {
+ if (!SeekOK(tif, dir->tdir_offset))
+ goto bad;
+ if (!ReadOK(tif, cp, cc))
+ goto bad;
+ } else {
+ if (dir->tdir_offset + cc > tif->tif_size)
+ goto bad;
+ _TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc);
+ }
+ if (tif->tif_flags & TIFF_SWAB) {
+ switch (dir->tdir_type) {
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
+ break;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ case TIFF_FLOAT:
+ TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
+ break;
+ case TIFF_DOUBLE:
+ TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
+ break;
+ }
+ }
+ return (cc);
+bad:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error fetching data for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ return ((tsize_t) 0);
+}
+
+/*
+ * Fetch an ASCII item from the file.
+ */
+static tsize_t
+TIFFFetchString(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+ if (dir->tdir_count <= 4) {
+ uint32 l = dir->tdir_offset;
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&l);
+ _TIFFmemcpy(cp, &l, dir->tdir_count);
+ return (1);
+ }
+ return (TIFFFetchData(tif, dir, cp));
+}
+
+/*
+ * Convert numerator+denominator to float.
+ */
+static int
+cvtRational(TIFF* tif, TIFFDirEntry* dir, uint32 num, uint32 denom, float* rv)
+{
+ if (denom == 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%s: Rational with zero denominator (num = %lu)",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, num);
+ return (0);
+ } else {
+ if (dir->tdir_type == TIFF_RATIONAL)
+ *rv = ((float)num / (float)denom);
+ else
+ *rv = ((float)(int32)num / (float)(int32)denom);
+ return (1);
+ }
+}
+
+/*
+ * Fetch a rational item from the file
+ * at offset off and return the value
+ * as a floating point number.
+ */
+static float
+TIFFFetchRational(TIFF* tif, TIFFDirEntry* dir)
+{
+ uint32 l[2];
+ float v;
+
+ return (!TIFFFetchData(tif, dir, (char *)l) ||
+ !cvtRational(tif, dir, l[0], l[1], &v) ? 1.0f : v);
+}
+
+/*
+ * Fetch a single floating point value
+ * from the offset field and return it
+ * as a native float.
+ */
+static float
+TIFFFetchFloat(TIFF* tif, TIFFDirEntry* dir)
+{
+ /* This appears to be a flagrant bug in the TIFF library, yet I
+ actually don't understand how it could have ever worked the old
+ way. Look at the comments in my new code and you'll understand. */
+#if (0)
+ float v = (float)
+ TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset);
+ TIFFCvtIEEEFloatToNative(tif, 1, &v);
+#else
+ float v;
+ /* This is a little bit tricky - if we just cast the uint32 to a float,
+ C will perform a numerical conversion, which is not what we want.
+ We want to take the actual bit pattern in the uint32 and interpret
+ it as a float. Thus we cast a uint32 * into a float * and then
+ dereference to get v. */
+ uint32 l = (uint32)
+ TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset);
+ v = * (float *) &l;
+ TIFFCvtIEEEFloatToNative(tif, 1, &v);
+#endif
+ return (v);
+
+}
+
+/*
+ * Fetch an array of BYTE or SBYTE values.
+ */
+static int
+TIFFFetchByteArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
+{
+ if (dir->tdir_count <= 4) {
+ /*
+ * Extract data from offset field.
+ */
+ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+ switch (dir->tdir_count) {
+ case 4: v[3] = dir->tdir_offset & 0xff;
+ case 3: v[2] = (dir->tdir_offset >> 8) & 0xff;
+ case 2: v[1] = (dir->tdir_offset >> 16) & 0xff;
+ case 1: v[0] = dir->tdir_offset >> 24;
+ }
+ } else {
+ switch (dir->tdir_count) {
+ case 4: v[3] = dir->tdir_offset >> 24;
+ case 3: v[2] = (dir->tdir_offset >> 16) & 0xff;
+ case 2: v[1] = (dir->tdir_offset >> 8) & 0xff;
+ case 1: v[0] = dir->tdir_offset & 0xff;
+ }
+ }
+ return (1);
+ } else
+ return (TIFFFetchData(tif, dir, (char*) v) != 0); /* XXX */
+}
+
+/*
+ * Fetch an array of SHORT or SSHORT values.
+ */
+static int
+TIFFFetchShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
+{
+ if (dir->tdir_count <= 2) {
+ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+ switch (dir->tdir_count) {
+ case 2: v[1] = dir->tdir_offset & 0xffff;
+ case 1: v[0] = dir->tdir_offset >> 16;
+ }
+ } else {
+ switch (dir->tdir_count) {
+ case 2: v[1] = dir->tdir_offset >> 16;
+ case 1: v[0] = dir->tdir_offset & 0xffff;
+ }
+ }
+ return (1);
+ } else
+ return (TIFFFetchData(tif, dir, (char *)v) != 0);
+}
+
+/*
+ * Fetch a pair of SHORT or BYTE values.
+ */
+static int
+TIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir)
+{
+ uint16 v[2];
+ int ok = 0;
+
+ switch (dir->tdir_type) {
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ ok = TIFFFetchShortArray(tif, dir, v);
+ break;
+ case TIFF_BYTE:
+ case TIFF_SBYTE:
+ ok = TIFFFetchByteArray(tif, dir, v);
+ break;
+ }
+ if (ok)
+ TIFFSetField(tif, dir->tdir_tag, v[0], v[1]);
+ return (ok);
+}
+
+/*
+ * Fetch an array of LONG or SLONG values.
+ */
+static int
+TIFFFetchLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v)
+{
+ if (dir->tdir_count == 1) {
+ v[0] = dir->tdir_offset;
+ return (1);
+ } else
+ return (TIFFFetchData(tif, dir, (char*) v) != 0);
+}
+
+/*
+ * Fetch an array of RATIONAL or SRATIONAL values.
+ */
+static int
+TIFFFetchRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v)
+{
+ int ok = 0;
+ uint32* l;
+
+ l = (uint32*)CheckMalloc(tif,
+ dir->tdir_count*TIFFDataWidth(dir->tdir_type),
+ "to fetch array of rationals");
+ if (l) {
+ if (TIFFFetchData(tif, dir, (char *)l)) {
+ uint32 i;
+ for (i = 0; i < dir->tdir_count; i++) {
+ ok = cvtRational(tif, dir,
+ l[2*i+0], l[2*i+1], &v[i]);
+ if (!ok)
+ break;
+ }
+ }
+ _TIFFfree((char *)l);
+ }
+ return (ok);
+}
+
+/*
+ * Fetch an array of FLOAT values.
+ */
+static int
+TIFFFetchFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v)
+{
+
+ if (dir->tdir_count == 1) {
+ v[0] = *(float*) &dir->tdir_offset;
+ TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v);
+ return (1);
+ } else if (TIFFFetchData(tif, dir, (char*) v)) {
+ TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v);
+ return (1);
+ } else
+ return (0);
+}
+
+/*
+ * Fetch an array of DOUBLE values.
+ */
+static int
+TIFFFetchDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v)
+{
+ if (TIFFFetchData(tif, dir, (char*) v)) {
+ TIFFCvtIEEEDoubleToNative(tif, dir->tdir_count, v);
+ return (1);
+ } else
+ return (0);
+}
+
+/*
+ * Fetch an array of ANY values. The actual values are
+ * returned as doubles which should be able hold all the
+ * types. Yes, there really should be an tany_t to avoid
+ * this potential non-portability ... Note in particular
+ * that we assume that the double return value vector is
+ * large enough to read in any fundamental type. We use
+ * that vector as a buffer to read in the base type vector
+ * and then convert it in place to double (from end
+ * to front of course).
+ */
+static int
+TIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v)
+{
+ int i;
+
+ switch (dir->tdir_type) {
+ case TIFF_BYTE:
+ case TIFF_SBYTE:
+ if (!TIFFFetchByteArray(tif, dir, (uint16*) v))
+ return (0);
+ if (dir->tdir_type == TIFF_BYTE) {
+ uint16* vp = (uint16*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ } else {
+ int16* vp = (int16*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ }
+ break;
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ if (!TIFFFetchShortArray(tif, dir, (uint16*) v))
+ return (0);
+ if (dir->tdir_type == TIFF_SHORT) {
+ uint16* vp = (uint16*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ } else {
+ int16* vp = (int16*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ }
+ break;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ if (!TIFFFetchLongArray(tif, dir, (uint32*) v))
+ return (0);
+ if (dir->tdir_type == TIFF_LONG) {
+ uint32* vp = (uint32*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ } else {
+ int32* vp = (int32*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ }
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ if (!TIFFFetchRationalArray(tif, dir, (float*) v))
+ return (0);
+ { float* vp = (float*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ }
+ break;
+ case TIFF_FLOAT:
+ if (!TIFFFetchFloatArray(tif, dir, (float*) v))
+ return (0);
+ { float* vp = (float*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ }
+ break;
+ case TIFF_DOUBLE:
+ return (TIFFFetchDoubleArray(tif, dir, (double*) v));
+ default:
+ /* TIFF_NOTYPE */
+ /* TIFF_ASCII */
+ /* TIFF_UNDEFINED */
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Cannot read TIFF_ANY type %d for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ return (0);
+ }
+ return (1);
+}
+
+
+/*
+ * Fetch a tag that is not handled by special case code.
+ */
+/* The standard function TIFFFetchNormalTag() could definitely be replaced
+ with a simple call to this function, just adding TIFFSetField() as the
+ last argument. */
+static int
+TIFFFetchNormalSubTag(TIFF* tif, TIFFDirEntry* dp, const TIFFFieldInfo* fip,
+ int (*setFieldFn)(TIFF *tif, ttag_t tag, ...))
+{
+ static char mesg[] = "to fetch tag value";
+ int ok = 0;
+
+ if (dp->tdir_count > 1) { /* array of values */
+ char* cp = NULL;
+
+ switch (dp->tdir_type) {
+ case TIFF_BYTE:
+ case TIFF_SBYTE:
+ /* NB: always expand BYTE values to shorts */
+ cp = CheckMalloc(tif,
+ dp->tdir_count * sizeof (uint16), mesg);
+ ok = cp && TIFFFetchByteArray(tif, dp, (uint16*) cp);
+ break;
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ cp = CheckMalloc(tif,
+ dp->tdir_count * sizeof (uint16), mesg);
+ ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp);
+ break;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ cp = CheckMalloc(tif,
+ dp->tdir_count * sizeof (uint32), mesg);
+ ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp);
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ cp = CheckMalloc(tif,
+ dp->tdir_count * sizeof (float), mesg);
+ ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp);
+ break;
+ case TIFF_FLOAT:
+ cp = CheckMalloc(tif,
+ dp->tdir_count * sizeof (float), mesg);
+ ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp);
+ break;
+ case TIFF_DOUBLE:
+ cp = CheckMalloc(tif,
+ dp->tdir_count * sizeof (double), mesg);
+ ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp);
+ break;
+ case TIFF_ASCII:
+ case TIFF_UNDEFINED: /* bit of a cheat... */
+ /*
+ * Some vendors write strings w/o the trailing
+ * NULL byte, so always append one just in case.
+ */
+ cp = CheckMalloc(tif, dp->tdir_count+1, mesg);
+ if (ok = (cp && TIFFFetchString(tif, dp, cp)))
+ cp[dp->tdir_count] = '\0'; /* XXX */
+ break;
+ }
+ if (ok) {
+ ok = (fip->field_passcount ?
+ (*setFieldFn)(tif, dp->tdir_tag, dp->tdir_count, cp)
+ : (*setFieldFn)(tif, dp->tdir_tag, cp));
+ }
+ if (cp != NULL)
+ _TIFFfree(cp);
+ } else if (CheckDirCount(tif, dp, 1)) { /* singleton value */
+ switch (dp->tdir_type) {
+ case TIFF_BYTE:
+ case TIFF_SBYTE:
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ /*
+ * If the tag is also acceptable as a LONG or SLONG
+ * then (*setFieldFn) will expect an uint32 parameter
+ * passed to it (through varargs). Thus, for machines
+ * where sizeof (int) != sizeof (uint32) we must do
+ * a careful check here. It's hard to say if this
+ * is worth optimizing.
+ *
+ * NB: We use TIFFFieldWithTag here knowing that
+ * it returns us the first entry in the table
+ * for the tag and that that entry is for the
+ * widest potential data type the tag may have.
+ */
+ { TIFFDataType type = fip->field_type;
+ if (type != TIFF_LONG && type != TIFF_SLONG) {
+ uint16 v = (uint16)
+ TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset);
+ ok = (fip->field_passcount ?
+ (*setFieldFn)(tif, dp->tdir_tag, 1, &v)
+ : (*setFieldFn)(tif, dp->tdir_tag, v));
+ break;
+ }
+ }
+ /* fall thru... */
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ { uint32 v32 =
+ TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset);
+ ok = (fip->field_passcount ?
+ (*setFieldFn)(tif, dp->tdir_tag, 1, &v32)
+ : (*setFieldFn)(tif, dp->tdir_tag, v32));
+ }
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ case TIFF_FLOAT:
+ { float v = (dp->tdir_type == TIFF_FLOAT ?
+ TIFFFetchFloat(tif, dp)
+ : TIFFFetchRational(tif, dp));
+ ok = (fip->field_passcount ?
+ (*setFieldFn)(tif, dp->tdir_tag, 1, &v)
+ : (*setFieldFn)(tif, dp->tdir_tag, v));
+ }
+ break;
+ case TIFF_DOUBLE:
+ { double v;
+ ok = (TIFFFetchDoubleArray(tif, dp, &v) &&
+ (fip->field_passcount ?
+ (*setFieldFn)(tif, dp->tdir_tag, 1, &v)
+ : (*setFieldFn)(tif, dp->tdir_tag, v))
+ );
+ }
+ break;
+ case TIFF_ASCII:
+ case TIFF_UNDEFINED: /* bit of a cheat... */
+ { char c[2];
+ if (ok = (TIFFFetchString(tif, dp, c) != 0)) {
+ c[1] = '\0'; /* XXX paranoid */
+ ok = (*setFieldFn)(tif, dp->tdir_tag, c);
+ }
+ }
+ break;
+ }
+ }
+ return (ok);
+}
+
+/* Everything after this is exactly duplicated from the standard tif_dirread.c
+ file, necessitated by the fact that they are declared static there so
+ we can't call them!
+*/
+#define NITEMS(x) (sizeof (x) / sizeof (x[0]))
+/*
+ * Fetch samples/pixel short values for
+ * the specified tag and verify that
+ * all values are the same.
+ */
+static int
+TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, int* pl)
+{
+ int samples = tif->tif_dir.td_samplesperpixel;
+ int status = 0;
+
+ if (CheckDirCount(tif, dir, (uint32) samples)) {
+ uint16 buf[10];
+ uint16* v = buf;
+
+ if (samples > NITEMS(buf))
+ v = (uint16*) _TIFFmalloc(samples * sizeof (uint16));
+ if (TIFFFetchShortArray(tif, dir, v)) {
+ int i;
+ for (i = 1; i < samples; i++)
+ if (v[i] != v[0]) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Cannot handle different per-sample values for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ goto bad;
+ }
+ *pl = v[0];
+ status = 1;
+ }
+ bad:
+ if (v != buf)
+ _TIFFfree((char*) v);
+ }
+ return (status);
+}
+
+/*
+ * Fetch samples/pixel ANY values for
+ * the specified tag and verify that
+ * all values are the same.
+ */
+static int
+TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl)
+{
+ int samples = (int) tif->tif_dir.td_samplesperpixel;
+ int status = 0;
+
+ if (CheckDirCount(tif, dir, (uint32) samples)) {
+ double buf[10];
+ double* v = buf;
+
+ if (samples > NITEMS(buf))
+ v = (double*) _TIFFmalloc(samples * sizeof (double));
+ if (TIFFFetchAnyArray(tif, dir, v)) {
+ int i;
+ for (i = 1; i < samples; i++)
+ if (v[i] != v[0]) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Cannot handle different per-sample values for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ goto bad;
+ }
+ *pl = v[0];
+ status = 1;
+ }
+ bad:
+ if (v != buf)
+ _TIFFfree(v);
+ }
+ return (status);
+}
+#undef NITEMS
+
+/*
+ * Fetch a set of offsets or lengths.
+ * While this routine says "strips",
+ * in fact it's also used for tiles.
+ */
+static int
+TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, long nstrips, uint32** lpp)
+{
+ register uint32* lp;
+ int status;
+
+ if (!CheckDirCount(tif, dir, (uint32) nstrips))
+ return (0);
+ /*
+ * Allocate space for strip information.
+ */
+ if (*lpp == NULL &&
+ (*lpp = (uint32 *)CheckMalloc(tif,
+ nstrips * sizeof (uint32), "for strip array")) == NULL)
+ return (0);
+ lp = *lpp;
+ if (dir->tdir_type == (int)TIFF_SHORT) {
+ /*
+ * Handle uint16->uint32 expansion.
+ */
+ uint16* dp = (uint16*) CheckMalloc(tif,
+ dir->tdir_count* sizeof (uint16), "to fetch strip tag");
+ if (dp == NULL)
+ return (0);
+ if (status = TIFFFetchShortArray(tif, dir, dp)) {
+ register uint16* wp = dp;
+ while (nstrips-- > 0)
+ *lp++ = *wp++;
+ }
+ _TIFFfree((char*) dp);
+ } else
+ status = TIFFFetchLongArray(tif, dir, lp);
+ return (status);
+}
+
+#define NITEMS(x) (sizeof (x) / sizeof (x[0]))
+/*
+ * Fetch and set the ExtraSamples tag.
+ */
+static int
+TIFFFetchExtraSamples(TIFF* tif, TIFFDirEntry* dir)
+{
+ uint16 buf[10];
+ uint16* v = buf;
+ int status;
+
+ if (dir->tdir_count > NITEMS(buf))
+ v = (uint16*) _TIFFmalloc(dir->tdir_count * sizeof (uint16));
+ if (dir->tdir_type == TIFF_BYTE)
+ status = TIFFFetchByteArray(tif, dir, v);
+ else
+ status = TIFFFetchShortArray(tif, dir, v);
+ if (status)
+ status = TIFFSetField(tif, dir->tdir_tag, dir->tdir_count, v);
+ if (v != buf)
+ _TIFFfree((char*) v);
+ return (status);
+}
+#undef NITEMS
+
+#ifdef COLORIMETRY_SUPPORT
+/*
+ * Fetch and set the RefBlackWhite tag.
+ */
+static int
+TIFFFetchRefBlackWhite(TIFF* tif, TIFFDirEntry* dir)
+{
+ static char mesg[] = "for \"ReferenceBlackWhite\" array";
+ char* cp;
+ int ok;
+
+ if (dir->tdir_type == TIFF_RATIONAL)
+ return (1/*TIFFFetchNormalTag(tif, dir) just so linker won't complain - this part of the code is never used anyway */);
+ /*
+ * Handle LONG's for backward compatibility.
+ */
+ cp = CheckMalloc(tif, dir->tdir_count * sizeof (uint32), mesg);
+ if (ok = (cp && TIFFFetchLongArray(tif, dir, (uint32*) cp))) {
+ float* fp = (float*)
+ CheckMalloc(tif, dir->tdir_count * sizeof (float), mesg);
+ if (ok = (fp != NULL)) {
+ uint32 i;
+ for (i = 0; i < dir->tdir_count; i++)
+ fp[i] = (float)((uint32*) cp)[i];
+ ok = TIFFSetField(tif, dir->tdir_tag, fp);
+ _TIFFfree((char*) fp);
+ }
+ }
+ if (cp)
+ _TIFFfree(cp);
+ return (ok);
+}
+#endif
+
+#if STRIPCHOP_SUPPORT
+/*
+ * Replace a single strip (tile) of uncompressed data by
+ * multiple strips (tiles), each approximately 8Kbytes.
+ * This is useful for dealing with large images or
+ * for dealing with machines with a limited amount
+ * memory.
+ */
+static void
+ChopUpSingleUncompressedStrip(TIFF* tif)
+{
+ register TIFFDirectory *td = &tif->tif_dir;
+ uint32 bytecount = td->td_stripbytecount[0];
+ uint32 offset = td->td_stripoffset[0];
+ tsize_t rowbytes = TIFFVTileSize(tif, 1), stripbytes;
+ tstrip_t strip, nstrips, rowsperstrip;
+ uint32* newcounts;
+ uint32* newoffsets;
+
+ /*
+ * Make the rows hold at least one
+ * scanline, but fill 8k if possible.
+ */
+ if (rowbytes > 8192) {
+ stripbytes = rowbytes;
+ rowsperstrip = 1;
+ } else {
+ rowsperstrip = 8192 / rowbytes;
+ stripbytes = rowbytes * rowsperstrip;
+ }
+ /* never increase the number of strips in an image */
+ if (rowsperstrip >= td->td_rowsperstrip)
+ return;
+ nstrips = (tstrip_t) TIFFhowmany(bytecount, stripbytes);
+ newcounts = (uint32*) CheckMalloc(tif, nstrips * sizeof (uint32),
+ "for chopped \"StripByteCounts\" array");
+ newoffsets = (uint32*) CheckMalloc(tif, nstrips * sizeof (uint32),
+ "for chopped \"StripOffsets\" array");
+ if (newcounts == NULL || newoffsets == NULL) {
+ /*
+ * Unable to allocate new strip information, give
+ * up and use the original one strip information.
+ */
+ if (newcounts != NULL)
+ _TIFFfree(newcounts);
+ if (newoffsets != NULL)
+ _TIFFfree(newoffsets);
+ return;
+ }
+ /*
+ * Fill the strip information arrays with
+ * new bytecounts and offsets that reflect
+ * the broken-up format.
+ */
+ for (strip = 0; strip < nstrips; strip++) {
+ if (stripbytes > bytecount)
+ stripbytes = bytecount;
+ newcounts[strip] = stripbytes;
+ newoffsets[strip] = offset;
+ offset += stripbytes;
+ bytecount -= stripbytes;
+ }
+ /*
+ * Replace old single strip info with multi-strip info.
+ */
+ td->td_stripsperimage = td->td_nstrips = nstrips;
+ TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
+
+ _TIFFfree(td->td_stripbytecount);
+ _TIFFfree(td->td_stripoffset);
+ td->td_stripbytecount = newcounts;
+ td->td_stripoffset = newoffsets;
+}
+#endif /* STRIPCHOP_SUPPORT */
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 8
+ * fill-column: 78
+ * End:
+ */
diff --git a/tiff/contrib/pds/tif_pdsdirwrite.c b/tiff/contrib/pds/tif_pdsdirwrite.c
new file mode 100644
index 0000000..eb71d42
--- /dev/null
+++ b/tiff/contrib/pds/tif_pdsdirwrite.c
@@ -0,0 +1,971 @@
+/* $Header: /cvs/maptools/cvsroot/libtiff/contrib/pds/tif_pdsdirwrite.c,v 1.3.2.1 2010-06-08 18:50:41 bfriesen Exp $ */
+
+/* When writing data to TIFF files, it is often useful to store application-
+ specific data in a private TIFF directory so that the tags don't need to
+ be registered and won't conflict with other people's user-defined tags.
+ One needs to have a registered public tag which contains some amount of
+ raw data. That raw data, however, is interpreted at an independent,
+ separate, private tiff directory. This file provides some routines which
+ will be useful for converting that data from its raw binary form into
+ the proper form for your application.
+*/
+
+/*
+ * Copyright (c) 1988-1996 Sam Leffler
+ * Copyright (c) 1991-1996 Silicon Graphics, Inc.
+ * Copyright (c( 1996 USAF Phillips Laboratory
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * These routines written by Conrad J. Poelman on a single late-night of
+ * March 20-21, 1996.
+ *
+ * The entire purpose of this file is to provide a single external function,
+ * TIFFWritePrivateDataSubDirectory(). This function is intended for use
+ * in writing a private subdirectory structure into a TIFF file. The
+ * actual reading of data from the structure is handled by the getFieldFn(),
+ * which is passed to TIFFWritePrivateDataSubDirectory() as a parameter. The
+ * idea is to enable any application wishing to read private subdirectories to
+ * do so easily using this function, without modifying the TIFF library.
+ *
+ * The astute observer will notice that only two functions are at all different
+ * from the original tif_dirwrite.c file: TIFFWritePrivateDataSubDirectory()and
+ * TIFFWriteNormalSubTag(). All the other stuff that makes this file so huge
+ * is only necessary because all of those functions are declared static in
+ * tif_dirwrite.c, so we have to totally duplicate them in order to use them.
+ *
+ * Oh, also please note the bug-fix in the routine TIFFWriteNormalSubTag(),
+ * which equally should be applied to TIFFWriteNormalTag().
+ *
+ */
+#include "tiffiop.h"
+
+#if HAVE_IEEEFP
+#define TIFFCvtNativeToIEEEFloat(tif, n, fp)
+#define TIFFCvtNativeToIEEEDouble(tif, n, dp)
+#else
+extern void TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*);
+extern void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*);
+#endif
+
+static int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*);
+static int TIFFWriteNormalSubTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*,
+ int (*getFieldFn)(TIFF *tif,ttag_t tag,...));
+static void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32);
+static int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*);
+static int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*);
+static int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*);
+static int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**);
+static int TIFFWriteShortArray(TIFF*,
+ TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint16*);
+static int TIFFWriteLongArray(TIFF *,
+ TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint32*);
+static int TIFFWriteRationalArray(TIFF *,
+ TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*);
+static int TIFFWriteFloatArray(TIFF *,
+ TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*);
+static int TIFFWriteDoubleArray(TIFF *,
+ TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);
+static int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*);
+static int TIFFWriteAnyArray(TIFF*,
+ TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);
+#ifdef COLORIMETRY_SUPPORT
+static int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*);
+#endif
+static int TIFFWriteData(TIFF*, TIFFDirEntry*, char*);
+static int TIFFLinkDirectory(TIFF*);
+
+#define WriteRationalPair(type, tag1, v1, tag2, v2) { \
+ if (!TIFFWriteRational(tif, type, tag1, dir, v1)) \
+ goto bad; \
+ if (!TIFFWriteRational(tif, type, tag2, dir+1, v2)) \
+ goto bad; \
+ dir++; \
+}
+#define TIFFWriteRational(tif, type, tag, dir, v) \
+ TIFFWriteRationalArray((tif), (type), (tag), (dir), 1, &(v))
+#ifndef TIFFWriteRational
+static int TIFFWriteRational(TIFF*,
+ TIFFDataType, ttag_t, TIFFDirEntry*, float);
+#endif
+
+/* This function will write an entire directory to the disk, and return the
+ offset value indicating where in the file it wrote the beginning of the
+ directory structure. This is NOT the same as the offset value before
+ calling this function, because some of the fields may have caused various
+ data items to be written out BEFORE writing the directory structure.
+
+ This code was basically written by ripping of the TIFFWriteDirectory()
+ code and generalizing it, using RPS's TIFFWritePliIfd() code for
+ inspiration. My original goal was to make this code general enough that
+ the original TIFFWriteDirectory() could be rewritten to just call this
+ function with the appropriate field and field-accessing arguments.
+
+ However, now I realize that there's a lot of code that gets executed for
+ the main, standard TIFF directories that does not apply to special
+ private subdirectories, so such a reimplementation for the sake of
+ eliminating redundant or duplicate code is probably not possible,
+ unless we also pass in a Main flag to indiciate which type of handling
+ to do, which would be kind of a hack. I've marked those places where I
+ changed or ripped out code which would have to be re-inserted to
+ generalize this function. If it can be done in a clean and graceful way,
+ it would be a great way to generalize the TIFF library. Otherwise, I'll
+ just leave this code here where it duplicates but remains on top of and
+ hopefully mostly independent of the main TIFF library.
+
+ The caller will probably want to free the sub directory structure after
+ returning from this call, since otherwise once written out, the user
+ is likely to forget about it and leave data lying around.
+*/
+toff_t
+TIFFWritePrivateDataSubDirectory(TIFF* tif,
+ uint32 pdir_fieldsset[], int pdir_fields_last,
+ TIFFFieldInfo *field_info,
+ int (*getFieldFn)(TIFF *tif, ttag_t tag, ...))
+{
+ uint16 dircount;
+ uint32 diroff, nextdiroff;
+ ttag_t tag;
+ uint32 nfields;
+ tsize_t dirsize;
+ char* data;
+ TIFFDirEntry* dir;
+ u_long b, *fields, fields_size;
+ toff_t directory_offset;
+ TIFFFieldInfo* fip;
+
+ /*
+ * Deleted out all of the encoder flushing and such code from here -
+ * not necessary for subdirectories.
+ */
+
+ /* Finish writing out any image data. */
+ TIFFFlushData(tif);
+
+ /*
+ * Size the directory so that we can calculate
+ * offsets for the data items that aren't kept
+ * in-place in each field.
+ */
+ nfields = 0;
+ for (b = 0; b <= pdir_fields_last; b++)
+ if (FieldSet(pdir_fieldsset, b))
+ /* Deleted code to make size of first 4 tags 2
+ instead of 1. */
+ nfields += 1;
+ dirsize = nfields * sizeof (TIFFDirEntry);
+ data = (char*) _TIFFmalloc(dirsize);
+ if (data == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Cannot write private subdirectory, out of space");
+ return (0);
+ }
+ /*
+ * Place directory in data section of the file. If there isn't one
+ * yet, place it at the end of the file. The directory is treated as
+ * data, so we don't link it into the directory structure at all.
+ */
+ if (tif->tif_dataoff == 0)
+ tif->tif_dataoff =(TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
+ diroff = tif->tif_dataoff;
+ tif->tif_dataoff = (toff_t)(
+ diroff + sizeof (uint16) + dirsize + sizeof (toff_t));
+ if (tif->tif_dataoff & 1)
+ tif->tif_dataoff++;
+ (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
+ /*tif->tif_curdir++;*/
+ dir = (TIFFDirEntry*) data;
+ /*
+ * Setup external form of directory
+ * entries and write data items.
+ */
+ /*
+ * We make a local copy of the fieldsset here so that we don't mess
+ * up the original one when we call ResetFieldBit(). But I'm not sure
+ * why the original code calls ResetFieldBit(), since we're already
+ * going through the fields in order...
+ *
+ * fields_size is the number of uint32's we will need to hold the
+ * bit-mask for all of the fields. If our highest field number is
+ * 100, then we'll need 100 / (8*4)+1 == 4 uint32's to hold the
+ * fieldset.
+ *
+ * Unlike the original code, we allocate fields dynamically based
+ * on the requested pdir_fields_last value, allowing private
+ * data subdirectories to contain more than the built-in code's limit
+ * of 95 tags in a directory.
+ */
+ fields_size = pdir_fields_last / (8*sizeof(uint32)) + 1;
+ fields = _TIFFmalloc(fields_size*sizeof(uint32));
+ _TIFFmemcpy(fields, pdir_fieldsset, fields_size * sizeof(uint32));
+
+ /* Deleted "write out extra samples tag" code here. */
+
+ /* Deleted code for checking a billion little special cases for the
+ * standard TIFF tags. Should add a general mechanism for overloading
+ * write function for each field, just like Brian kept telling me!!!
+ */
+ for (fip = field_info; fip->field_tag; fip++) {
+ /* Deleted code to check for FIELD_IGNORE!! */
+ if (/* fip->field_bit == FIELD_IGNORE || */
+ !FieldSet(fields, fip->field_bit))
+ continue;
+ if (!TIFFWriteNormalSubTag(tif, dir, fip, getFieldFn))
+ goto bad;
+ dir++;
+ ResetFieldBit(fields, fip->field_bit);
+ }
+
+ /* Now we've written all of the referenced data, and are about to
+ write the main directory structure, so grab the tif_dataoff value
+ now so we can remember where we wrote the directory. */
+ directory_offset = tif->tif_dataoff;
+
+ /*
+ * Write directory.
+ */
+ dircount = (uint16) nfields;
+ /* Deleted code to link to the next directory - we set it to zero! */
+ nextdiroff = 0;
+ if (tif->tif_flags & TIFF_SWAB) {
+ /*
+ * The file's byte order is opposite to the
+ * native machine architecture. We overwrite
+ * the directory information with impunity
+ * because it'll be released below after we
+ * write it to the file. Note that all the
+ * other tag construction routines assume that
+ * we do this byte-swapping; i.e. they only
+ * byte-swap indirect data.
+ */
+ for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) {
+ TIFFSwabArrayOfShort(&dir->tdir_tag, 2);
+ TIFFSwabArrayOfLong(&dir->tdir_count, 2);
+ }
+ dircount = (uint16) nfields;
+ TIFFSwabShort(&dircount);
+ TIFFSwabLong(&nextdiroff);
+ }
+
+ (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
+ if (!WriteOK(tif, &dircount, sizeof (dircount))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing private subdirectory count");
+ goto bad;
+ }
+ if (!WriteOK(tif, data, dirsize)) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing private subdirectory contents");
+ goto bad;
+ }
+ if (!WriteOK(tif, &nextdiroff, sizeof (nextdiroff))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing private subdirectory link");
+ goto bad;
+ }
+ tif->tif_dataoff += sizeof(dircount) + dirsize + sizeof(nextdiroff);
+
+ _TIFFfree(data);
+ _TIFFfree(fields);
+ tif->tif_flags &= ~TIFF_DIRTYDIRECT;
+
+#if (0)
+ /* This stuff commented out because I don't think we want it for
+ subdirectories, but I could be wrong. */
+ (*tif->tif_cleanup)(tif);
+
+ /*
+ * Reset directory-related state for subsequent
+ * directories.
+ */
+ TIFFDefaultDirectory(tif);
+ tif->tif_curoff = 0;
+ tif->tif_row = (uint32) -1;
+ tif->tif_curstrip = (tstrip_t) -1;
+#endif
+
+ return (directory_offset);
+bad:
+ _TIFFfree(data);
+ _TIFFfree(fields);
+ return (0);
+}
+#undef WriteRationalPair
+
+/*
+ * Process tags that are not special cased.
+ */
+/* The standard function TIFFWriteNormalTag() could definitely be replaced
+ with a simple call to this function, just adding TIFFGetField() as the
+ last argument. */
+static int
+TIFFWriteNormalSubTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip,
+ int (*getFieldFn)(TIFF *tif, ttag_t tag, ...))
+{
+ u_short wc = (u_short) fip->field_writecount;
+
+ dir->tdir_tag = fip->field_tag;
+ dir->tdir_type = (u_short) fip->field_type;
+ dir->tdir_count = wc;
+#define WRITEF(x,y) x(tif, fip->field_type, fip->field_tag, dir, wc, y)
+ switch (fip->field_type) {
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ if (wc > 1) {
+ uint16* wp;
+ if (wc == (u_short) TIFF_VARIABLE) {
+ (*getFieldFn)(tif, fip->field_tag, &wc, &wp);
+ dir->tdir_count = wc;
+ } else
+ (*getFieldFn)(tif, fip->field_tag, &wp);
+ if (!WRITEF(TIFFWriteShortArray, wp))
+ return (0);
+ } else {
+ uint16 sv;
+ (*getFieldFn)(tif, fip->field_tag, &sv);
+ dir->tdir_offset =
+ TIFFInsertData(tif, dir->tdir_type, sv);
+ }
+ break;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ if (wc > 1) {
+ uint32* lp;
+ if (wc == (u_short) TIFF_VARIABLE) {
+ (*getFieldFn)(tif, fip->field_tag, &wc, &lp);
+ dir->tdir_count = wc;
+ } else
+ (*getFieldFn)(tif, fip->field_tag, &lp);
+ if (!WRITEF(TIFFWriteLongArray, lp))
+ return (0);
+ } else {
+ /* XXX handle LONG->SHORT conversion */
+ (*getFieldFn)(tif, fip->field_tag, &dir->tdir_offset);
+ }
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ if (wc > 1) {
+ float* fp;
+ if (wc == (u_short) TIFF_VARIABLE) {
+ (*getFieldFn)(tif, fip->field_tag, &wc, &fp);
+ dir->tdir_count = wc;
+ } else
+ (*getFieldFn)(tif, fip->field_tag, &fp);
+ if (!WRITEF(TIFFWriteRationalArray, fp))
+ return (0);
+ } else {
+ float fv;
+ (*getFieldFn)(tif, fip->field_tag, &fv);
+ if (!WRITEF(TIFFWriteRationalArray, &fv))
+ return (0);
+ }
+ break;
+ case TIFF_FLOAT:
+ if (wc > 1) {
+ float* fp;
+ if (wc == (u_short) TIFF_VARIABLE) {
+ (*getFieldFn)(tif, fip->field_tag, &wc, &fp);
+ dir->tdir_count = wc;
+ } else
+ (*getFieldFn)(tif, fip->field_tag, &fp);
+ if (!WRITEF(TIFFWriteFloatArray, fp))
+ return (0);
+ } else {
+ float fv;
+ (*getFieldFn)(tif, fip->field_tag, &fv);
+ if (!WRITEF(TIFFWriteFloatArray, &fv))
+ return (0);
+ }
+ break;
+ case TIFF_DOUBLE:
+ /* Hey - I think this is a bug, or at least a "gross
+ inconsistency", in the TIFF library. Look at the original
+ TIFF library code below within the "#if (0) ... #else".
+ Just from the type of *dp, you can see that this code
+ expects TIFFGetField() to be handed a double ** for
+ any TIFF_DOUBLE tag, even for the constant wc==1 case.
+ This is totally inconsistent with other fields (like
+ TIFF_FLOAT, above) and is also inconsistent with the
+ TIFFSetField() function for TIFF_DOUBLEs, which expects
+ to be passed a single double by value for the wc==1 case.
+ (See the handling of TIFFFetchNormalTag() in tif_dirread.c
+ for an example.) Maybe this function was written before
+ TIFFWriteDoubleArray() was written, not that that's an
+ excuse. Anyway, the new code below is a trivial modification
+ of the TIFF_FLOAT code above. The fact that even single
+ doubles get written out in the data segment and get an
+ offset value stored is irrelevant here - that is all
+ handled by TIFFWriteDoubleArray(). */
+#if (0)
+ { double* dp;
+ if (wc == (u_short) TIFF_VARIABLE) {
+ (*getFieldFn)(tif, fip->field_tag, &wc, &dp);
+ dir->tdir_count = wc;
+ } else
+ (*getFieldFn)(tif, fip->field_tag, &dp);
+ TIFFCvtNativeToIEEEDouble(tif, wc, dp);
+ if (!TIFFWriteData(tif, dir, (char*) dp))
+ return (0);
+ }
+#else
+ if (wc > 1) {
+ double* dp;
+ if (wc == (u_short) TIFF_VARIABLE) {
+ (*getFieldFn)(tif, fip->field_tag, &wc, &dp);
+ dir->tdir_count = wc;
+ } else
+ (*getFieldFn)(tif, fip->field_tag, &dp);
+ if (!WRITEF(TIFFWriteDoubleArray, dp))
+ return (0);
+ } else {
+ double dv;
+ (*getFieldFn)(tif, fip->field_tag, &dv);
+ if (!WRITEF(TIFFWriteDoubleArray, &dv))
+ return (0);
+ }
+#endif
+ break;
+ case TIFF_ASCII:
+ { char* cp;
+ (*getFieldFn)(tif, fip->field_tag, &cp);
+ dir->tdir_count = (uint32) (strlen(cp) + 1);
+ if (!TIFFWriteByteArray(tif, dir, cp))
+ return (0);
+ }
+ break;
+ case TIFF_UNDEFINED:
+ { char* cp;
+ if (wc == (u_short) TIFF_VARIABLE) {
+ (*getFieldFn)(tif, fip->field_tag, &wc, &cp);
+ dir->tdir_count = wc;
+ } else
+ (*getFieldFn)(tif, fip->field_tag, &cp);
+ if (!TIFFWriteByteArray(tif, dir, cp))
+ return (0);
+ }
+ break;
+ }
+ return (1);
+}
+#undef WRITEF
+
+/* Everything after this is exactly duplicated from the standard tif_dirwrite.c
+ file, necessitated by the fact that they are declared static there so
+ we can't call them!
+*/
+/*
+ * Setup a directory entry with either a SHORT
+ * or LONG type according to the value.
+ */
+static void
+TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v)
+{
+ dir->tdir_tag = tag;
+ dir->tdir_count = 1;
+ if (v > 0xffffL) {
+ dir->tdir_type = (short) TIFF_LONG;
+ dir->tdir_offset = v;
+ } else {
+ dir->tdir_type = (short) TIFF_SHORT;
+ dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v);
+ }
+}
+#undef MakeShortDirent
+
+#ifndef TIFFWriteRational
+/*
+ * Setup a RATIONAL directory entry and
+ * write the associated indirect value.
+ */
+static int
+TIFFWriteRational(TIFF* tif,
+ TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, float v)
+{
+ return (TIFFWriteRationalArray(tif, type, tag, dir, 1, &v));
+}
+#endif
+
+#define NITEMS(x) (sizeof (x) / sizeof (x[0]))
+/*
+ * Setup a directory entry that references a
+ * samples/pixel array of SHORT values and
+ * (potentially) write the associated indirect
+ * values.
+ */
+static int
+TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
+{
+ uint16 buf[10], v;
+ uint16* w = buf;
+ int i, status, samples = tif->tif_dir.td_samplesperpixel;
+
+ if (samples > NITEMS(buf))
+ w = (uint16*) _TIFFmalloc(samples * sizeof (uint16));
+ TIFFGetField(tif, tag, &v);
+ for (i = 0; i < samples; i++)
+ w[i] = v;
+ status = TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, samples, w);
+ if (w != buf)
+ _TIFFfree((char*) w);
+ return (status);
+}
+
+/*
+ * Setup a directory entry that references a samples/pixel array of ``type''
+ * values and (potentially) write the associated indirect values. The source
+ * data from TIFFGetField() for the specified tag must be returned as double.
+ */
+static int
+TIFFWritePerSampleAnys(TIFF* tif,
+ TIFFDataType type, ttag_t tag, TIFFDirEntry* dir)
+{
+ double buf[10], v;
+ double* w = buf;
+ int i, status;
+ int samples = (int) tif->tif_dir.td_samplesperpixel;
+
+ if (samples > NITEMS(buf))
+ w = (double*) _TIFFmalloc(samples * sizeof (double));
+ TIFFGetField(tif, tag, &v);
+ for (i = 0; i < samples; i++)
+ w[i] = v;
+ status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w);
+ if (w != buf)
+ _TIFFfree(w);
+ return (status);
+}
+#undef NITEMS
+
+/*
+ * Setup a pair of shorts that are returned by
+ * value, rather than as a reference to an array.
+ */
+static int
+TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
+{
+ uint16 v[2];
+
+ TIFFGetField(tif, tag, &v[0], &v[1]);
+ return (TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, 2, v));
+}
+
+/*
+ * Setup a directory entry for an NxM table of shorts,
+ * where M is known to be 2**bitspersample, and write
+ * the associated indirect data.
+ */
+static int
+TIFFWriteShortTable(TIFF* tif,
+ ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table)
+{
+ uint32 i, off;
+
+ dir->tdir_tag = tag;
+ dir->tdir_type = (short) TIFF_SHORT;
+ /* XXX -- yech, fool TIFFWriteData */
+ dir->tdir_count = (uint32) (1L<<tif->tif_dir.td_bitspersample);
+ off = tif->tif_dataoff;
+ for (i = 0; i < n; i++)
+ if (!TIFFWriteData(tif, dir, (char *)table[i]))
+ return (0);
+ dir->tdir_count *= n;
+ dir->tdir_offset = off;
+ return (1);
+}
+
+/*
+ * Write/copy data associated with an ASCII or opaque tag value.
+ */
+static int
+TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+ if (dir->tdir_count > 4) {
+ if (!TIFFWriteData(tif, dir, cp))
+ return (0);
+ } else
+ _TIFFmemcpy(&dir->tdir_offset, cp, dir->tdir_count);
+ return (1);
+}
+
+/*
+ * Setup a directory entry of an array of SHORT
+ * or SSHORT and write the associated indirect values.
+ */
+static int
+TIFFWriteShortArray(TIFF* tif,
+ TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16* v)
+{
+ dir->tdir_tag = tag;
+ dir->tdir_type = (short) type;
+ dir->tdir_count = n;
+ if (n <= 2) {
+ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+ dir->tdir_offset = (uint32) ((long) v[0] << 16);
+ if (n == 2)
+ dir->tdir_offset |= v[1] & 0xffff;
+ } else {
+ dir->tdir_offset = v[0] & 0xffff;
+ if (n == 2)
+ dir->tdir_offset |= (long) v[1] << 16;
+ }
+ return (1);
+ } else
+ return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+/*
+ * Setup a directory entry of an array of LONG
+ * or SLONG and write the associated indirect values.
+ */
+static int
+TIFFWriteLongArray(TIFF* tif,
+ TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint32* v)
+{
+ dir->tdir_tag = tag;
+ dir->tdir_type = (short) type;
+ dir->tdir_count = n;
+ if (n == 1) {
+ dir->tdir_offset = v[0];
+ return (1);
+ } else
+ return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+/*
+ * Setup a directory entry of an array of RATIONAL
+ * or SRATIONAL and write the associated indirect values.
+ */
+static int
+TIFFWriteRationalArray(TIFF* tif,
+ TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v)
+{
+ uint32 i;
+ uint32* t;
+ int status;
+
+ dir->tdir_tag = tag;
+ dir->tdir_type = (short) type;
+ dir->tdir_count = n;
+ t = (uint32*) _TIFFmalloc(2*n * sizeof (uint32));
+ for (i = 0; i < n; i++) {
+ float fv = v[i];
+ int sign = 1;
+ uint32 den;
+
+ if (fv < 0) {
+ if (type == TIFF_RATIONAL) {
+ TIFFWarning(tif->tif_name,
+ "\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL",
+ _TIFFFieldWithTag(tif,tag)->field_name, v);
+ fv = 0;
+ } else
+ fv = -fv, sign = -1;
+ }
+ den = 1L;
+ if (fv > 0) {
+ while (fv < 1L<<(31-3) && den < 1L<<(31-3))
+ fv *= 1<<3, den *= 1L<<3;
+ }
+ t[2*i+0] = sign * (fv + 0.5);
+ t[2*i+1] = den;
+ }
+ status = TIFFWriteData(tif, dir, (char *)t);
+ _TIFFfree((char*) t);
+ return (status);
+}
+
+static int
+TIFFWriteFloatArray(TIFF* tif,
+ TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v)
+{
+ dir->tdir_tag = tag;
+ dir->tdir_type = (short) type;
+ dir->tdir_count = n;
+ TIFFCvtNativeToIEEEFloat(tif, n, v);
+ if (n == 1) {
+ dir->tdir_offset = *(uint32*) &v[0];
+ return (1);
+ } else
+ return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+static int
+TIFFWriteDoubleArray(TIFF* tif,
+ TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v)
+{
+ dir->tdir_tag = tag;
+ dir->tdir_type = (short) type;
+ dir->tdir_count = n;
+ TIFFCvtNativeToIEEEDouble(tif, n, v);
+ return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+/*
+ * Write an array of ``type'' values for a specified tag (i.e. this is a tag
+ * which is allowed to have different types, e.g. SMaxSampleType).
+ * Internally the data values are represented as double since a double can
+ * hold any of the TIFF tag types (yes, this should really be an abstract
+ * type tany_t for portability). The data is converted into the specified
+ * type in a temporary buffer and then handed off to the appropriate array
+ * writer.
+ */
+static int
+TIFFWriteAnyArray(TIFF* tif,
+ TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v)
+{
+ char buf[10 * sizeof(double)];
+ char* w = buf;
+ int i, status = 0;
+
+ if (n * TIFFDataWidth(type) > sizeof buf)
+ w = (char*) _TIFFmalloc(n * TIFFDataWidth(type));
+ switch (type) {
+ case TIFF_BYTE:
+ { unsigned char* bp = (unsigned char*) w;
+ for (i = 0; i < n; i++)
+ bp[i] = (unsigned char) v[i];
+ dir->tdir_tag = tag;
+ dir->tdir_type = (short) type;
+ dir->tdir_count = n;
+ if (!TIFFWriteByteArray(tif, dir, (char*) bp))
+ goto out;
+ }
+ break;
+ case TIFF_SBYTE:
+ { signed char* bp = (signed char*) w;
+ for (i = 0; i < n; i++)
+ bp[i] = (signed char) v[i];
+ dir->tdir_tag = tag;
+ dir->tdir_type = (short) type;
+ dir->tdir_count = n;
+ if (!TIFFWriteByteArray(tif, dir, (char*) bp))
+ goto out;
+ }
+ break;
+ case TIFF_SHORT:
+ { uint16* bp = (uint16*) w;
+ for (i = 0; i < n; i++)
+ bp[i] = (uint16) v[i];
+ if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp))
+ goto out;
+ }
+ break;
+ case TIFF_SSHORT:
+ { int16* bp = (int16*) w;
+ for (i = 0; i < n; i++)
+ bp[i] = (int16) v[i];
+ if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp))
+ goto out;
+ }
+ break;
+ case TIFF_LONG:
+ { uint32* bp = (uint32*) w;
+ for (i = 0; i < n; i++)
+ bp[i] = (uint32) v[i];
+ if (!TIFFWriteLongArray(tif, type, tag, dir, n, bp))
+ goto out;
+ }
+ break;
+ case TIFF_SLONG:
+ { int32* bp = (int32*) w;
+ for (i = 0; i < n; i++)
+ bp[i] = (int32) v[i];
+ if (!TIFFWriteLongArray(tif, type, tag, dir, n, (uint32*) bp))
+ goto out;
+ }
+ break;
+ case TIFF_FLOAT:
+ { float* bp = (float*) w;
+ for (i = 0; i < n; i++)
+ bp[i] = (float) v[i];
+ if (!TIFFWriteFloatArray(tif, type, tag, dir, n, bp))
+ goto out;
+ }
+ break;
+ case TIFF_DOUBLE:
+ return (TIFFWriteDoubleArray(tif, type, tag, dir, n, v));
+ default:
+ /* TIFF_NOTYPE */
+ /* TIFF_ASCII */
+ /* TIFF_UNDEFINED */
+ /* TIFF_RATIONAL */
+ /* TIFF_SRATIONAL */
+ goto out;
+ }
+ status = 1;
+ out:
+ if (w != buf)
+ _TIFFfree(w);
+ return (status);
+}
+
+#ifdef COLORIMETRY_SUPPORT
+static int
+TIFFWriteTransferFunction(TIFF* tif, TIFFDirEntry* dir)
+{
+ TIFFDirectory* td = &tif->tif_dir;
+ tsize_t n = (1L<<td->td_bitspersample) * sizeof (uint16);
+ uint16** tf = td->td_transferfunction;
+ int ncols;
+
+ /*
+ * Check if the table can be written as a single column,
+ * or if it must be written as 3 columns. Note that we
+ * write a 3-column tag if there are 2 samples/pixel and
+ * a single column of data won't suffice--hmm.
+ */
+ switch (td->td_samplesperpixel - td->td_extrasamples) {
+ default: if (_TIFFmemcmp(tf[0], tf[2], n)) { ncols = 3; break; }
+ case 2: if (_TIFFmemcmp(tf[0], tf[1], n)) { ncols = 3; break; }
+ case 1: case 0: ncols = 1;
+ }
+ return (TIFFWriteShortTable(tif,
+ TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf));
+}
+#endif
+
+/*
+ * Write a contiguous directory item.
+ */
+static int
+TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+ tsize_t cc;
+
+ if (tif->tif_flags & TIFF_SWAB) {
+ switch (dir->tdir_type) {
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
+ break;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ case TIFF_FLOAT:
+ TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
+ break;
+ case TIFF_DOUBLE:
+ TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
+ break;
+ }
+ }
+ dir->tdir_offset = tif->tif_dataoff;
+ cc = dir->tdir_count * TIFFDataWidth(dir->tdir_type);
+ if (SeekOK(tif, dir->tdir_offset) &&
+ WriteOK(tif, cp, cc)) {
+ tif->tif_dataoff += (cc + 1) & ~1;
+ return (1);
+ }
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing data for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ return (0);
+}
+
+/*
+ * Link the current directory into the
+ * directory chain for the file.
+ */
+static int
+TIFFLinkDirectory(TIFF* tif)
+{
+ static const char module[] = "TIFFLinkDirectory";
+ uint32 nextdir;
+ uint32 diroff;
+
+ tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
+ diroff = (uint32) tif->tif_diroff;
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&diroff);
+#if SUBIFD_SUPPORT
+ if (tif->tif_flags & TIFF_INSUBIFD) {
+ (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
+ if (!WriteOK(tif, &diroff, sizeof (diroff))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Error writing SubIFD directory link",
+ tif->tif_name);
+ return (0);
+ }
+ /*
+ * Advance to the next SubIFD or, if this is
+ * the last one configured, revert back to the
+ * normal directory linkage.
+ */
+ if (--tif->tif_nsubifd)
+ tif->tif_subifdoff += sizeof (diroff);
+ else
+ tif->tif_flags &= ~TIFF_INSUBIFD;
+ return (1);
+ }
+#endif
+ if (tif->tif_header.tiff_diroff == 0) {
+ /*
+ * First directory, overwrite offset in header.
+ */
+ tif->tif_header.tiff_diroff = (uint32) tif->tif_diroff;
+#define HDROFF(f) ((toff_t) &(((TIFFHeader*) 0)->f))
+ (void) TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET);
+ if (!WriteOK(tif, &diroff, sizeof (diroff))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing TIFF header");
+ return (0);
+ }
+ return (1);
+ }
+ /*
+ * Not the first directory, search to the last and append.
+ */
+ nextdir = tif->tif_header.tiff_diroff;
+ do {
+ uint16 dircount;
+
+ if (!SeekOK(tif, nextdir) ||
+ !ReadOK(tif, &dircount, sizeof (dircount))) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count");
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ (void) TIFFSeekFile(tif,
+ dircount * sizeof (TIFFDirEntry), SEEK_CUR);
+ if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory link");
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&nextdir);
+ } while (nextdir != 0);
+ (void) TIFFSeekFile(tif, -(toff_t) sizeof (nextdir), SEEK_CUR);
+ if (!WriteOK(tif, &diroff, sizeof (diroff))) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link");
+ return (0);
+ }
+ return (1);
+}
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 8
+ * fill-column: 78
+ * End:
+ */