From news@decwrl.dec.com  Sun May 13 22:55:55 1990
Received: by jove.pa.dec.com; id AA01688; Sun, 13 May 90 22:55:55 -0700
Received: by decwrl.dec.com; id AA12550; Sun, 13 May 90 22:55:27 -0700
Path: decwrl!ucbvax!ucsd!usc!samsung!munnari.oz.au!metro!sunaus.oz!newstop!sun!decpa.pa.dec.com
From: dbs@decpa.dec.com (dan sears)
Newsgroups: comp.sources.x
Subject: v07i036: Xtiff -- TIFF previewer, Part01/01
Message-Id: <135599@sun.Eng.Sun.COM>
Date: 12 May 90 08:03:02 GMT
Sender: news@sun.Eng.Sun.COM
Lines: 1400
Approved: argv@sun.com
Apparently-To: vixie

Submitted-by: dbs@decpa.pa.dec.com (dan sears)
Posting-number: Volume 7, Issue 36
Archive-name: xtiff/part01

I've finished my TIFF viewer for X11.  It displays all forms of TIFF
images on 24, 8 and 1-bit X displays.  You need Sam Leffler's libtiff
library (ucbvax.berkeley.edu:/pub/tiff/*).  Here's a shar file of the
sources and the man page.  xtiff is very thorough at reading different
kinds of TIFF files but it only displays them.  It doesn't rotate, scale
or perform any manipulation other than gamma correction on 24-bit images.

Sam will be including xtiff with his libtiff release and I also plan on
putting it on expo.lcs.mit.edu.

--Dan Sears
#!/bin/sh
# This is a shell archive (shar 3.21)
# made 05/08/1990 20:32 UTC by dbs@dungeon
# Source directory /catacomb/cc1/home/dbs/xtiff/src
#
# existing files WILL be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#    700 -rw-r--r-- Imakefile
#   9282 -rw-r--r-- Makefile
#  28249 -rw-r--r-- xtiff.c
#   4005 -rw-rw-rw- xtiff.man
#    890 -rw-r--r-- xtifficon.h
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= Imakefile ==============
echo "x - extracting Imakefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Imakefile &&
X#
X# Imakefile -- to generate a Makefile for xtiff use:
X#       /dc0/X11/R4/mit/config/imake \
X#           -I/dc0/X11/R4/mit/config \
X#           -DTOPDIR=/dc0/X11/R4/mit \
X#           -DCURDIR=/dc0/X11/R4/mit \
X#           -DDESTDIR=/dc0/X11/R4/mit
X#
X        PROGRAMS = xtiff
X LOCAL_LIBRARIES = ../libtiff/libtiff/libtiff.a -lX11 -lm
X  EXTRA_INCLUDES = -I../libtiff/libtiff
X            SRCS = xtiff.c
X            OBJS = xtiff.o
X     CDEBUGFLAGS = -g
X       CCOPTIONS =
X
XAllTarget(xtiff)
XNormalProgramTarget(xtiff, $(OBJS), /* */, $(LOCAL_LIBRARIES), /* */)
XDependTarget()
X
Xproto::
X	cproto $(TIFF_INCLUDES) xtiff.c > xtiff.proto
X
Xlint::
X	lint $(TIFF_INCLUDES) xtiff.c -lX11 -lm
X
Xtags::
X	ctags xtiff.c
SHAR_EOF
$TOUCH -am 0508133190 Imakefile &&
chmod 0644 Imakefile ||
echo "restore of Imakefile failed"
set `wc -c Imakefile`;Wc_c=$1
if test "$Wc_c" != "700"; then
	echo original size 700, current size $Wc_c
fi
# ============= Makefile ==============
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X# Makefile generated by imake - do not edit!
X# $XConsortium: imake.c,v 1.51 89/12/12 12:37:30 jim Exp $
X
X###########################################################################
X# Makefile generated from "Imake.tmpl" and </tmp/IIf.a03165>
X# $XConsortium: Imake.tmpl,v 1.77 89/12/18 17:01:37 jim Exp $
X#
X# Platform-specific parameters may be set in the appropriate .cf
X# configuration files.  Site-wide parameters may be set in the file
X# site.def.  Full rebuilds are recommended if any parameters are changed.
X#
X# If your C preprocessor doesn't define any unique symbols, you'll need
X# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
X# "make Makefile", "make Makefiles", or "make World").
X#
X# If you absolutely can't get imake to work, you'll need to set the
X# variables at the top of each Makefile as well as the dependencies at the
X# bottom (makedepend will do this automatically).
X#
X
X###########################################################################
X# platform-specific configuration parameters - edit ultrix.cf to change
X
X# platform:  $XConsortium: ultrix.cf,v 1.20 89/12/22 15:56:14 rws Exp $
X# operating system:             Ultrix-32 4.0
X
X###########################################################################
X# site-specific configuration parameters - edit site.def to change
X
X# site:  $XConsortium: site.def,v 1.21 89/12/06 11:46:50 jim Exp $
X
X            SHELL = 	/bin/sh
X
X              TOP = /dc0/X11/R4/mit
X      CURRENT_DIR = /dc0/X11/R4/mit
X
X               AR = ar cq
X  BOOTSTRAPCFLAGS =
X               CC = cc
X
X         COMPRESS = compress
X              CPP = /lib/cpp $(STD_CPP_DEFINES)
X    PREPROCESSCMD = cc -E $(STD_CPP_DEFINES)
X          INSTALL = install
X               LD = ld
X             LINT = lint
X      LINTLIBFLAG = -C
X         LINTOPTS = -axz
X               LN = ln -s
X             MAKE = make
X               MV = mv
X               CP = cp
X           RANLIB = ranlib
X  RANLIBINSTFLAGS =
X               RM = rm -f
X     STD_INCLUDES =
X  STD_CPP_DEFINES =
X      STD_DEFINES =
X EXTRA_LOAD_FLAGS =
X  EXTRA_LIBRARIES =
X             TAGS = ctags
X
X    PROTO_DEFINES =
X
X     INSTPGMFLAGS =
X
X     INSTBINFLAGS = -m 0755
X     INSTUIDFLAGS = -m 4755
X     INSTLIBFLAGS = -m 0664
X     INSTINCFLAGS = -m 0444
X     INSTMANFLAGS = -m 0444
X     INSTDATFLAGS = -m 0444
X    INSTKMEMFLAGS = -m 4755
X
X          /dc0/X11/R4/mit = /dc0/X11/R4
X
X     TOP_INCLUDES = -I$(TOP)
X
X      CDEBUGFLAGS = -O
X        CCOPTIONS = -Wf,-XNh2000 -Olimit 2000
X      COMPATFLAGS =
X
X      ALLINCLUDES = $(STD_INCLUDES) $(TOP_INCLUDES) $(INCLUDES) $(EXTRA_INCLUDES)
X       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(DEFINES) $(COMPATFLAGS)
X           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
X        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
X           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
X        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS)
X   LDCOMBINEFLAGS = -X -r
X
X        MACROFILE = ultrix.cf
X           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
X
X    IMAKE_DEFINES =
X
X         IRULESRC = $(CONFIGSRC)
X        IMAKE_CMD = $(NEWTOP)$(IMAKE) -I$(NEWTOP)$(IRULESRC) $(IMAKE_DEFINES)
X
X     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
X			$(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
X			$(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
X
X###########################################################################
X# X Window System Build Parameters
X# $XConsortium: Project.tmpl,v 1.63 89/12/18 16:46:44 jim Exp $
X
X###########################################################################
X# X Window System make variables; this need to be coordinated with rules
X# $XConsortium: Project.tmpl,v 1.63 89/12/18 16:46:44 jim Exp $
X
X          PATHSEP = /
X        USRLIBDIR = $(/dc0/X11/R4/mit)/usr/lib
X           BINDIR = $(/dc0/X11/R4/mit)/usr/bin/X11
X          INCROOT = $(/dc0/X11/R4/mit)/usr/include
X     BUILDINCROOT = $(TOP)
X      BUILDINCDIR = $(BUILDINCROOT)/X11
X      BUILDINCTOP = ..
X           INCDIR = $(INCROOT)/X11
X           ADMDIR = $(/dc0/X11/R4/mit)/usr/adm
X           LIBDIR = $(USRLIBDIR)/X11
X        CONFIGDIR = $(LIBDIR)/config
X       LINTLIBDIR = $(USRLIBDIR)/lint
X
X          FONTDIR = $(LIBDIR)/fonts
X         XINITDIR = $(LIBDIR)/xinit
X           XDMDIR = $(LIBDIR)/xdm
X           AWMDIR = $(LIBDIR)/awm
X           TWMDIR = $(LIBDIR)/twm
X           GWMDIR = $(LIBDIR)/gwm
X          MANPATH = $(/dc0/X11/R4/mit)/usr/man
X    MANSOURCEPATH = $(MANPATH)/man
X           MANDIR = $(MANSOURCEPATH)n
X        LIBMANDIR = $(MANSOURCEPATH)3
X      XAPPLOADDIR = $(LIBDIR)/app-defaults
X
X       FONTCFLAGS = -t
X
X     INSTAPPFLAGS = $(INSTDATFLAGS)
X
X            IMAKE = $(IMAKESRC)/imake
X           DEPEND = $(DEPENDSRC)/makedepend
X              RGB = $(RGBSRC)/rgb
X            FONTC = $(BDFTOSNFSRC)/bdftosnf
X        MKFONTDIR = $(MKFONTDIRSRC)/mkfontdir
X        MKDIRHIER = 	/bin/sh $(SCRIPTSRC)/mkdirhier.sh
X
X        CONFIGSRC = $(TOP)/config
X        CLIENTSRC = $(TOP)/clients
X          DEMOSRC = $(TOP)/demos
X           LIBSRC = $(TOP)/lib
X          FONTSRC = $(TOP)/fonts
X       INCLUDESRC = $(TOP)/X11
X        SERVERSRC = $(TOP)/server
X          UTILSRC = $(TOP)/util
X        SCRIPTSRC = $(UTILSRC)/scripts
X       EXAMPLESRC = $(TOP)/examples
X       CONTRIBSRC = $(TOP)/../contrib
X           DOCSRC = $(TOP)/doc
X           RGBSRC = $(TOP)/rgb
X        DEPENDSRC = $(UTILSRC)/makedepend
X         IMAKESRC = $(CONFIGSRC)
X         XAUTHSRC = $(LIBSRC)/Xau
X          XLIBSRC = $(LIBSRC)/X
X           XMUSRC = $(LIBSRC)/Xmu
X       TOOLKITSRC = $(LIBSRC)/Xt
X       AWIDGETSRC = $(LIBSRC)/Xaw
X       OLDXLIBSRC = $(LIBSRC)/oldX
X      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
X      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
X     MKFONTDIRSRC = $(FONTSRC)/mkfontdir
X     EXTENSIONSRC = $(TOP)/extensions
X
X  DEPEXTENSIONLIB =  $(EXTENSIONSRC)/lib/libXext.a
X     EXTENSIONLIB = 			   $(DEPEXTENSIONLIB)
X
X          DEPXLIB = $(DEPEXTENSIONLIB)  $(XLIBSRC)/libX11.a
X             XLIB = $(EXTENSIONLIB) 			  $(XLIBSRC)/libX11.a
X
X      DEPXAUTHLIB =  $(XAUTHSRC)/libXau.a
X         XAUTHLIB = 			  $(DEPXAUTHLIB)
X
X        DEPXMULIB =  $(XMUSRC)/libXmu.a
X           XMULIB = 			  $(DEPXMULIB)
X
X       DEPOLDXLIB =  $(OLDXLIBSRC)/liboldX.a
X          OLDXLIB = 			  $(DEPOLDXLIB)
X
X      DEPXTOOLLIB =  $(TOOLKITSRC)/libXt.a
X         XTOOLLIB = 			  $(DEPXTOOLLIB)
X
X        DEPXAWLIB =  $(AWIDGETSRC)/libXaw.a
X           XAWLIB = 			  $(DEPXAWLIB)
X
X LINTEXTENSIONLIB =  $(EXTENSIONSRC)/lib/llib-lXext.ln
X         LINTXLIB =  $(XLIBSRC)/llib-lX11.ln
X          LINTXMU =  $(XMUSRC)/llib-lXmu.ln
X        LINTXTOOL =  $(TOOLKITSRC)/llib-lXt.ln
X          LINTXAW =  $(AWIDGETSRC)/llib-lXaw.ln
X
X          DEPLIBS = $(LOCAL_LIBRARIES)
X
X         DEPLIBS1 = $(DEPLIBS)
X         DEPLIBS2 = $(DEPLIBS)
X         DEPLIBS3 = $(DEPLIBS)
X
X###########################################################################
X# Imake rules for building libraries, programs, scripts, and data files
X# rules:  $XConsortium: Imake.rules,v 1.67 89/12/18 17:14:15 jim Exp $
X
X###########################################################################
X# start of Imakefile
X
X#
X# Imakefile -- to generate a Makefile for xtiff use:
X#       /dc0/X11/R4/mit/config/imake \
X#           -I/dc0/X11/R4/mit/config \
X#           -DTOPDIR=/dc0/X11/R4/mit \
X#           -DCURDIR=/dc0/X11/R4/mit \
X#           -DDESTDIR=/dc0/X11/R4/mit
X#
X        PROGRAMS = xtiff
X LOCAL_LIBRARIES = ../libtiff/libtiff/libtiff.a -lX11 -lm
X  EXTRA_INCLUDES = -I../libtiff/libtiff
X            SRCS = xtiff.c
X            OBJS = xtiff.o
X     CDEBUGFLAGS = -g
X       CCOPTIONS =
X
Xall:: xtiff
X
Xxtiff:  $(OBJS)
X	 $(RM) $@
X	$(CC) -o $@  $(OBJS) $(LDOPTIONS)  $(LOCAL_LIBRARIES) $(LDLIBS)   $(EXTRA_LOAD_FLAGS)
X
Xclean::
X	$(RM) xtiff
X
Xdepend:: $(DEPEND)
X
X$(DEPEND):
X	@echo "checking $@ over in $(DEPENDSRC) first..."; \
X	cd $(DEPENDSRC); $(MAKE); \
X	echo "okay, continuing in $(CURRENT_DIR)"
X
Xdepend::
X	$(DEPEND) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
X
Xproto::
X	cproto $(TIFF_INCLUDES) xtiff.c > xtiff.proto
X
Xlint::
X	lint $(TIFF_INCLUDES) xtiff.c -lX11 -lm
X
Xtags::
X	ctags xtiff.c
X
X###########################################################################
X# common rules for all Makefiles - do not edit
X
Xemptyrule::
X
Xclean::
X	$(RM_CMD) \#*
X
XMakefile:: $(IMAKE)
X
X$(IMAKE):
X	@(cd $(IMAKESRC); if [ -f Makefile ]; then \
X	echo "checking $@ in $(IMAKESRC) first..."; $(MAKE) all; else \
X	echo "bootstrapping $@ from Makefile.ini in $(IMAKESRC) first..."; \
X	$(MAKE) -f Makefile.ini BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS); fi; \
X	echo "okay, continuing in $(CURRENT_DIR)")
X
XMakefile::
X	-@if [ -f Makefile ]; then \
X		echo "	$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
X		$(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
X	else exit 0; fi
X	$(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
X
Xtags::
X	$(TAGS) -w *.[ch]
X	$(TAGS) -xw *.[ch] > TAGS
X
X###########################################################################
X# empty rules for directories that do not have SUBDIRS - do not edit
X
Xinstall::
X	@echo "install in $(CURRENT_DIR) done"
X
Xinstall.man::
X	@echo "install.man in $(CURRENT_DIR) done"
X
XMakefiles::
X
Xincludes::
X
X###########################################################################
X# dependencies generated by makedepend
X
SHAR_EOF
$TOUCH -am 0508133190 Makefile &&
chmod 0644 Makefile ||
echo "restore of Makefile failed"
set `wc -c Makefile`;Wc_c=$1
if test "$Wc_c" != "9282"; then
	echo original size 9282, current size $Wc_c
fi
# ============= xtiff.c ==============
echo "x - extracting xtiff.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > xtiff.c &&
X/*
X * xtiff - view a TIFF file in an X window
X *
X * Dan Sears - May 7, 1990
X * Chris Sears
X *
X * Copyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
X *
X *                        All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital not be
X * used in advertising or publicity pertaining to distribution of the
X * software without specific, written prior permission.
X *
X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X *
X * Notes:
X *
X * According to the TIFF 5.0 Specification, it is possible to have
X * both a TIFFTAG_COLORMAP and a TIFFTAG_COLORRESPONSECURVE.  This
X * doesn't make sense since a TIFFTAG_COLORMAP is 16 bits wide and
X * a TIFFTAG_COLORRESPONSECURVE is tfBitsPerSample bits wide for each
X * channel.  This is probably a bug in the specification.
X * In this case, TIFFTAG_COLORRESPONSECURVE is ignored.
X * This might make sense if TIFFTAG_COLORMAP was 8 bits wide.
X *
X * TIFFTAG_COLORMAP is often incorrectly written as ranging from
X * 0 to 255 rather than from 0 to 65535.  CheckAndCorrectColormap()
X * takes care of this.
X *
X * Only ORIENTATION_TOPLEFT is supported correctly.  This is the
X * default TIFF and X orientation.  Other orientations will be
X * displayed incorrectly.
X *
X * Only TIFFTAG_BITSPERSAMPLE values that are powers of 2 (1, 2, 4 or 8)
X * are supported.
X */
X
X#include <math.h>
X#include <stdio.h>
X#include <tiffio.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xproto.h>
X#include "xtifficon.h"
X
X#define TIFF_GAMMA  2.2
X#define ROUND(x)    (u_short) ((x) + 0.5)
X#define SCALE(x, s) (((x) * 65535L) / (s))
X#define MCHECK(m)   if (!m) { fprintf(stderr, "malloc failed\n"); exit(0); }
X
Xvoid                GetTIFFHeader();
Xvoid                CheckAndCorrectColormap();
Xvoid                SimpleGammaCorrection();
Xvoid                InitializeX();
Xvoid                GetTIFFImage();
Xvoid                CreateXImage();
Xint                 SearchVisualList();
Xvoid                EventLoop();
Xint                 XTiffErrorHandler();
X
X/*
X * X data structures
X */
XColormap            xColormap;
XDisplay *           xDisplay;
XWindow              xWindow;
XPixmap              xImagePixmap, xTiffIconPixmap;
XVisual *            xVisual;
XXImage *            xImage;
XGC                  xWinGc, xBitmapGc;
XXGCValues           xGcValues;
Xint                 xScreen, xSyncFlag = False, xImageDepth, xNVisuals,
X                    xPixmapFlag = True;
Xchar *              xGeometry = NULL, *xDisplayName = NULL;
XXVisualInfo *       xVisualList;
X
X/*
X * TIFF data structures
X */
XTIFF *              tfFile;
Xu_short             tfBitsPerSample, tfSamplesPerPixel, tfPlanarConfiguration,
X                    tfPhotometricInterpretation, tfGrayResponseUnit,
X                    tfImageDepth, tfImageWidth, tfImageHeight, tfBytesPerRow,
X                    tfFillOrder;
Xint                 tfDirectory = 0;
Xdouble              tfUnitMap, tfGrayResponseUnitMap[] = {
X                        -1, -10, -100, -1000, -10000, -100000
X                    };
X
X/*
X * display data structures
X */
Xdouble              dGamma = TIFF_GAMMA, *dRed, *dGreen, *dBlue;
X
X/*
X * shared data structures
X */
Xu_short *           redMap = NULL, *greenMap = NULL, *blueMap = NULL,
X                    *grayMap = NULL, colormapSize;
Xu_char *            imageMemory;
Xchar *              fileName, *programName;
X
Xvoid
Xmain(argc, argv)
X    int argc;
X    char ** argv;
X{
X    int i;
X
X    programName = argv[0];
X
X    if (argc == 1) {
X        fprintf(stderr, "Usage: %s file\n", programName);
X        fprintf(stderr, "options:\n");
X        fprintf(stderr, "    [-directory directory]\n");
X        fprintf(stderr, "    [-display display]\n");
X        fprintf(stderr, "    [-gamma gamma]\n");
X        fprintf(stderr, "    [-geometry geometry]\n");
X        fprintf(stderr, "    [-nopixmap]\n");
X        fprintf(stderr, "    [-sync]\n");
X        exit(0);
X    }
X
X    for (i = 1; i < argc; i++) {
X        if (strcmp(argv[i], "-display") == 0)
X            xDisplayName = argv[++i];
X        else if (strcmp(argv[i], "-gamma") == 0)
X            dGamma = atof(argv[++i]);
X        else if (strcmp(argv[i], "-geometry") == 0)
X            xGeometry = argv[++i];
X        else if (strcmp(argv[i], "-nopixmap") == 0)
X            xPixmapFlag = False;
X        else if (strcmp(argv[i], "-sync") == 0)
X            xSyncFlag = True;
X        else if (strcmp(argv[i], "-directory") == 0)
X            tfDirectory = atoi(argv[++i]);
X        else
X            fileName = argv[i];
X    }
X
X    GetTIFFHeader();
X    SimpleGammaCorrection();
X    InitializeX(argc, argv);
X    GetTIFFImage();
X    CreateXImage();
X    XMapWindow(xDisplay, xWindow);
X    EventLoop();
X}
X
Xvoid
XGetTIFFHeader()
X{
X    register int i;
X
X    if ((tfFile = TIFFOpen(fileName, "r")) == NULL) {
X        fprintf(stderr, "%s: can't open %s as a TIFF file\n",
X            programName, fileName);
X        exit(0);
X    }
X
X    if (!TIFFSetDirectory(tfFile, tfDirectory)) {
X        fprintf(stderr, "%s: can't seek to directory %d in %s\n",
X            programName, tfDirectory, fileName);
X        exit(0);
X    }
X
X    TIFFGetField(tfFile, TIFFTAG_IMAGEWIDTH, &tfImageWidth);
X    TIFFGetField(tfFile, TIFFTAG_IMAGELENGTH, &tfImageHeight);
X
X    /*
X     * If the following tags aren't present then use the TIFF defaults.
X     */
X    if (!TIFFGetField(tfFile, TIFFTAG_FILLORDER, &tfFillOrder))
X        tfFillOrder = FILLORDER_MSB2LSB;
X    if (!TIFFGetField(tfFile, TIFFTAG_BITSPERSAMPLE, &tfBitsPerSample))
X        tfBitsPerSample = 1;
X    if (!TIFFGetField(tfFile, TIFFTAG_SAMPLESPERPIXEL, &tfSamplesPerPixel))
X        tfSamplesPerPixel = 1;
X    if (!TIFFGetField(tfFile, TIFFTAG_PLANARCONFIG, &tfPlanarConfiguration))
X        tfPlanarConfiguration = PLANARCONFIG_CONTIG;
X    if (!TIFFGetField(tfFile, TIFFTAG_GRAYRESPONSEUNIT, &tfGrayResponseUnit))
X        tfGrayResponseUnit = 2;
X
X    tfUnitMap = tfGrayResponseUnitMap[tfGrayResponseUnit];
X    colormapSize = 1 << tfBitsPerSample;
X    tfImageDepth = tfBitsPerSample * tfSamplesPerPixel;
X
X    dRed = (double *) malloc(colormapSize * sizeof(double));
X    dGreen = (double *) malloc(colormapSize * sizeof(double));
X    dBlue = (double *) malloc(colormapSize * sizeof(double));
X
X    /*
X     * If TIFFTAG_PHOTOMETRIC is not present then assign a reasonable default.
X     * The TIFF 5.0 specification doesn't give a default.
X     */
X    if (!TIFFGetField(tfFile, TIFFTAG_PHOTOMETRIC,
X            &tfPhotometricInterpretation)) {
X        if (tfSamplesPerPixel != 1)
X            tfPhotometricInterpretation = PHOTOMETRIC_RGB;
X        else if (tfBitsPerSample == 1)
X            tfPhotometricInterpretation = PHOTOMETRIC_MINISBLACK;
X        else if (TIFFGetField(tfFile, TIFFTAG_COLORMAP,
X                &redMap, &greenMap, &blueMap)) {
X            tfPhotometricInterpretation = PHOTOMETRIC_PALETTE;
X            free(redMap); free(greenMap); free(blueMap);
X            redMap = greenMap = blueMap = NULL;
X        } else
X            tfPhotometricInterpretation = PHOTOMETRIC_MINISBLACK;
X    }
X
X    /*
X     * Given TIFFTAG_PHOTOMETRIC extract or create the response curves.
X     */
X    switch (tfPhotometricInterpretation) {
X    case PHOTOMETRIC_RGB:
X        if (!TIFFGetField(tfFile, TIFFTAG_COLORRESPONSECURVE,
X                &redMap, &greenMap, &blueMap)) {
X            redMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X            greenMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X            blueMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X            MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
X            for (i = 0; i < colormapSize; i++)
X                dRed[i] = dGreen[i] = dBlue[i]
X                    = (double) SCALE(i, colormapSize - 1);
X        } else {
X            CheckAndCorrectColormap();
X            for (i = 0; i < colormapSize; i++) {
X                dRed[i] = (double) redMap[i];
X                dGreen[i] = (double) greenMap[i];
X                dBlue[i] = (double) blueMap[i];
X            }
X        }
X        break;
X    case PHOTOMETRIC_PALETTE:
X        if (!TIFFGetField(tfFile, TIFFTAG_COLORMAP,
X                &redMap, &greenMap, &blueMap)) {
X            redMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X            greenMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X            blueMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X            MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
X            for (i = 0; i < colormapSize; i++)
X                dRed[i] = dGreen[i] = dBlue[i]
X                    = (double) SCALE(i, colormapSize - 1);
X        } else {
X            CheckAndCorrectColormap();
X            for (i = 0; i < colormapSize; i++) {
X                dRed[i] = (double) redMap[i];
X                dGreen[i] = (double) greenMap[i];
X                dBlue[i] = (double) blueMap[i];
X            }
X        }
X        break;
X    case PHOTOMETRIC_MINISWHITE:
X        redMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X        greenMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X        blueMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X        MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
X        if (!TIFFGetField(tfFile, TIFFTAG_GRAYRESPONSECURVE, &grayMap))
X            for (i = 0; i < colormapSize; i++)
X                dRed[i] = dGreen[i] = dBlue[i]
X                    = (double) SCALE(colormapSize - 1 - i, colormapSize - 1);
X        else {
X            dRed[colormapSize - 1] = dGreen[colormapSize - 1]
X                = dBlue[colormapSize - 1] = 0;
X            for (i = 0; i < colormapSize - 1; i++)
X                dRed[i] = dGreen[i] = dBlue[i] = 65535.0 -
X                    (65535.0 * pow(10.0, (double) grayMap[i] / tfUnitMap));
X        }
X        break;
X    case PHOTOMETRIC_MINISBLACK:
X        redMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X        greenMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X        blueMap = (u_short *) malloc(colormapSize * sizeof(u_short));
X        MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
X        if (!TIFFGetField(tfFile, TIFFTAG_GRAYRESPONSECURVE, &grayMap))
X            for (i = 0; i < colormapSize; i++)
X                dRed[i] = dGreen[i] = dBlue[i]
X                    = (double) SCALE(i, colormapSize - 1);
X        else {
X            dRed[0] = dGreen[0] = dBlue[0] = 0;
X            for (i = 1; i < colormapSize; i++)
X                dRed[i] = dGreen[i] = dBlue[i] =
X                    (65535.0 * pow(10.0, (double) grayMap[i] / tfUnitMap));
X        }
X        break;
X    default:
X        fprintf(stderr,
X            "%s: can't display photometric interpretation type %d\n",
X            programName, tfPhotometricInterpretation);
X        exit(0);
X    }
X
X    return;
X}
X
X/*
X * Many programs get TIFF colormaps wrong.  They use 8-bit colormaps instead
X * of 16-bit colormaps.  This function is a heuristic to detect and correct
X * that problem.
X */
Xvoid
XCheckAndCorrectColormap()
X{
X    register int i;
X
X    for (i = 0; i < colormapSize; i++)
X        if ((redMap[i] > 255) || (greenMap[i] > 255) || (blueMap[i] > 255))
X            return;
X
X    for (i = 0; i < colormapSize; i++) {
X       redMap[i] = SCALE(redMap[i], 255);
X       greenMap[i] = SCALE(greenMap[i], 255);
X       blueMap[i] = SCALE(blueMap[i], 255);
X    }
X
X    return;
X}
X
Xvoid
XSimpleGammaCorrection()
X{
X    register int i;
X
X    for (i = 0; i < colormapSize; i++) {
X        if ((tfPhotometricInterpretation == PHOTOMETRIC_MINISWHITE)
X            && (i == colormapSize - 1))
X            redMap[i] = greenMap[i] = blueMap[i] = 0;
X        else if (i == 0)
X            redMap[i] = greenMap[i] = blueMap[i] = 0;
X
X        redMap[i] = ROUND((pow(dRed[i] / 65535.0, 1.0 / dGamma) * 65535.0));
X        greenMap[i] = ROUND((pow(dGreen[i] / 65535.0, 1.0 / dGamma) * 65535.0));
X        blueMap[i] = ROUND((pow(dBlue[i] / 65535.0, 1.0 / dGamma) * 65535.0));
X    }
X
X    free(dRed); free(dGreen); free(dBlue);
X    return;
X}
X
Xvoid
XInitializeX(xargc, xargv)
X    int xargc;
X    char **xargv;
X{
X    register int i;
X    int win_x = 0, win_y = 0, win_width, win_height;
X    u_int border_width = 3;
X    XSizeHints size_hints;
X    XSetWindowAttributes window_attributes;
X    XVisualInfo template_visual;
X    register XColor *colors = NULL;
X
X    if ((xDisplay = XOpenDisplay(xDisplayName)) == NULL) {
X        fprintf(stderr, "%s: cannot connect to X server %s\n",
X            programName, XDisplayName(xDisplayName));
X        exit(0);
X    }
X
X    xScreen = DefaultScreen(xDisplay);
X    XSetErrorHandler(XTiffErrorHandler);
X    XSynchronize(xDisplay, xSyncFlag);
X
X    if (tfImageDepth != 1) {
X        template_visual.screen = xScreen;
X        xVisualList = XGetVisualInfo(xDisplay, VisualScreenMask,
X            &template_visual, &xNVisuals);
X
X        if (xNVisuals == 0) {
X            fprintf(stderr, "%s: visual list not available\n", programName);
X            exit(0);
X        }
X    }
X
X    switch (tfImageDepth) {
X    /*
X     * X really wants a 32-bit image with the fourth channel unused,
X     * but the visual structure thinks it's 24-bit.
X     */
X    case 32:
X    case 24:
X        if (!SearchVisualList(24, DirectColor, &xVisual)) {
X            fprintf(stderr, "%s: 24-bit DirectColor visual not available\n",
X                programName);
X            exit(0);
X        }
X
X        colors = (XColor *) malloc(3 * colormapSize * sizeof(XColor));
X
X        for (i = 0; i < colormapSize; i++) {
X            colors[i].pixel = (u_long) (i << 16) + (i << 8) + i;
X            colors[i].red = redMap[i];
X            colors[i].green = greenMap[i];
X            colors[i].blue = blueMap[i];
X            colors[i].flags = DoRed | DoGreen | DoBlue;
X        }
X
X        xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen),
X            xVisual, AllocAll);
X        XStoreColors(xDisplay, xColormap, colors, colormapSize);
X        break;
X    case 8:
X    case 4:
X    case 2:
X        /*
X         * We assume that systems with 24-bit visuals also have 8-bit visuals.
X         * We don't promote from 8-bit PseudoColor to 24/32 bit DirectColor.
X         */
X        switch (tfPhotometricInterpretation) {
X        case PHOTOMETRIC_MINISWHITE:
X        case PHOTOMETRIC_MINISBLACK:
X            /*
X             * The VAX Firefox is broken here so PseudoColor is searched first.
X             * The GrayScale visual doesn't seem to work.
X             */
X            if (SearchVisualList((int) tfImageDepth, PseudoColor, &xVisual))
X                break;
X            if (SearchVisualList((int) tfImageDepth, GrayScale, &xVisual))
X                break;
X        case PHOTOMETRIC_PALETTE:
X            if (SearchVisualList((int) tfImageDepth, PseudoColor, &xVisual))
X                break;
X        default:
X            fprintf(stderr, "%s: Unsupported TIFF/X configuration\n",
X                programName);
X            exit(0);
X        }
X
X        colors = (XColor *) malloc(colormapSize * sizeof(XColor));
X
X        for (i = 0; i < colormapSize; i++) {
X            colors[i].pixel = (u_long) i;
X            colors[i].red = redMap[i];
X            colors[i].green = greenMap[i];
X            colors[i].blue = blueMap[i];
X            colors[i].flags = DoRed | DoGreen | DoBlue;
X        }
X
X        /*
X         * xtiff's colormap allocation is private.  It does not attempt
X         * to detect whether any existing colormap entries are suitable
X         * for its use.
X         */
X        xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen),
X            xVisual, AllocAll);
X        XStoreColors(xDisplay, xColormap, colors, colormapSize);
X        break;
X    case 1:
X        xImageDepth = 1;
X        xVisual = DefaultVisual(xDisplay, xScreen);
X        xColormap = DefaultColormap(xDisplay, xScreen);
X        break;
X    default:
X        fprintf(stderr, "%s: unsupported image depth %d\n",
X            programName, tfImageDepth);
X        exit(0);
X    }
X
X    window_attributes.colormap = xColormap;
X    window_attributes.background_pixel = XWhitePixel(xDisplay, xScreen);
X    window_attributes.border_pixel = XBlackPixel(xDisplay, xScreen);
X    window_attributes.event_mask = ExposureMask | ButtonPressMask;
X
X    /*
X     * win_width and win_height are not currently used.
X     */
X    XParseGeometry(xGeometry, &win_x, &win_y, &win_width, &win_height);
X
X    xWindow = XCreateWindow(xDisplay, RootWindow(xDisplay, xScreen),
X        win_x, win_y, tfImageWidth, tfImageHeight, border_width,
X        xImageDepth == 1 ? CopyFromParent : xImageDepth, InputOutput,
X        xVisual, CWColormap | CWBackPixel | CWBorderPixel | CWEventMask,
X        &window_attributes);
X
X    xGcValues.function = GXcopy;
X    xGcValues.plane_mask = AllPlanes;
X    xGcValues.foreground = XWhitePixel(xDisplay, xScreen);
X    xGcValues.background = XBlackPixel(xDisplay, xScreen);
X
X    xWinGc = XCreateGC(xDisplay, xWindow, GCFunction | GCPlaneMask
X        | GCForeground | GCBackground, &xGcValues);
X
X    xTiffIconPixmap = XCreateBitmapFromData(xDisplay, xWindow,
X        xtifficon_bits, xtifficon_width, xtifficon_height);
X
X    size_hints.flags = PPosition | PSize | PMinSize | PMaxSize;
X    size_hints.x = win_x;
X    size_hints.y = win_y;
X    size_hints.width = tfImageWidth;
X    size_hints.height = tfImageHeight;
X    size_hints.min_width = tfImageWidth;
X    size_hints.min_height = tfImageHeight;
X    size_hints.max_width = tfImageWidth;
X    size_hints.max_height = tfImageHeight;
X
X    XSetStandardProperties(xDisplay, xWindow, programName, programName,
X        xTiffIconPixmap, xargv, xargc, &size_hints);
X
X    if (colors != NULL)
X        free(colors);
X
X    return;
X}
X
Xint
XSearchVisualList(image_depth, visual_class, visual)
X    register int image_depth, visual_class;
X    Visual **visual;
X{
X    register XVisualInfo *vis;
X    register int i;
X
X    for (vis = xVisualList, i = 0; i < xNVisuals; vis++, i++) {
X        if ((vis->class == visual_class) && (vis->depth >= image_depth)) {
X            xImageDepth = vis->depth;
X            xVisual = vis->visual;
X            return True;
X        }
X    }
X
X    return False;
X}
X
Xvoid
XGetTIFFImage()
X{
X    register int i, j, s;
X    register u_char *scan_line, *output_p, *input_p, p;
X
X    tfBytesPerRow = TIFFScanlineSize(tfFile);
X    scan_line = (u_char *) malloc(tfBytesPerRow);
X    MCHECK(scan_line);
X
X    if ((tfImageDepth == 32) || (tfImageDepth == 24)) {
X        output_p = imageMemory =
X            (u_char *) malloc(tfImageWidth * tfImageHeight * 4);
X        MCHECK(imageMemory);
X
X        if (tfPlanarConfiguration == PLANARCONFIG_CONTIG) {
X            for (i = 0; i < tfImageHeight; i++) {
X                if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
X                    break;
X                for (input_p = scan_line, j = 0; j < tfImageWidth; j++) {
X                    *output_p++ = *input_p++;
X                    *output_p++ = *input_p++;
X                    *output_p++ = *input_p++;
X                    output_p++;
X                    if (tfSamplesPerPixel == 4) /* skip the fourth channel */
X                        input_p++;
X                }
X            }
X        } else {
X            for (s = 0; s < tfSamplesPerPixel; s++) {
X                if (s == 3)                     /* skip the fourth channel */
X                    continue;
X                for (i = 0; i < tfImageHeight; i++) {
X                    if (TIFFReadScanline(tfFile, scan_line, i, s) < 0)
X                        break;
X                    input_p = scan_line;
X                    output_p = imageMemory + (i * tfImageWidth * 4) + s;
X                    for (j = 0; j < tfImageWidth; j++, output_p += 4)
X                        *output_p = *input_p++;
X                }
X            }
X        }
X    } else {
X        /*
X         * If the image is 1-bit and PHOTOMETRIC_MINISWHITE then invert
X         * the image because we use the default colormap and can't change it.
X         */
X        if ((tfPhotometricInterpretation == PHOTOMETRIC_MINISWHITE)
X            && (tfImageDepth == 1)) {
X            output_p = imageMemory =
X                (u_char *) malloc(tfBytesPerRow * tfImageHeight);
X            MCHECK(imageMemory);
X
X            for (i = 0; i < tfImageHeight; i++, output_p += tfBytesPerRow) {
X                if (TIFFReadScanline(tfFile, output_p, i, 0) < 0)
X                    break;
X                input_p = output_p;
X                for (j = 0; j < tfBytesPerRow; j++, input_p++)
X                    *input_p = ~ *input_p;
X            }
X        } else if (xImageDepth == tfImageDepth) {
X            output_p = imageMemory =
X                (u_char *) malloc(tfBytesPerRow * tfImageHeight);
X            MCHECK(imageMemory);
X
X            for (i = 0; i < tfImageHeight; i++, output_p += tfBytesPerRow)
X                if (TIFFReadScanline(tfFile, output_p, i, 0) < 0)
X                    break;
X        } else if ((xImageDepth == 8) && (tfImageDepth == 4)) {
X            output_p = imageMemory =
X                (u_char *) malloc(tfBytesPerRow * 2 * tfImageHeight + 2);
X            MCHECK(imageMemory);
X
X            /*
X             * If a scanline is of odd size the inner loop below will overshoot.
X             * This is handled very simply by recalculating the start point at
X             * each scanline and padding imageMemory a little at the end.
X             */
X            for (i = 0; i < tfImageHeight; i++) {
X                if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
X                    break;
X                output_p = &imageMemory[i * tfImageWidth];
X                input_p = scan_line;
X                for (j = 0; j < tfImageWidth; j += 2, input_p++) {
X                    *output_p++ = (*input_p) >> 4;
X                    *output_p++ = (*input_p) & 0xf;
X                }
X            }
X        } else if ((xImageDepth == 8) && (tfImageDepth == 2)) {
X            output_p = imageMemory =
X                (u_char *) malloc(tfBytesPerRow * 4 * tfImageHeight + 4);
X            MCHECK(imageMemory);
X
X            for (i = 0; i < tfImageHeight; i++) {
X                if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
X                    break;
X                output_p = &imageMemory[i * tfImageWidth];
X                input_p = scan_line;
X                for (j = 0; j < tfImageWidth; j += 4, input_p++) {
X                    *output_p++ = *input_p >> 6;
X                    *output_p++ = (*input_p >> 4) & 3;
X                    *output_p++ = (*input_p >> 2) & 3;
X                    *output_p++ = *input_p & 3;
X                }
X            }
X        } else if ((xImageDepth == 4) && (tfImageDepth == 2)) {
X            output_p = imageMemory =
X                (u_char *) malloc(tfBytesPerRow * 2 * tfImageHeight + 2);
X            MCHECK(imageMemory);
X
X            for (i = 0; i < tfImageHeight; i++) {
X                if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
X                    break;
X                output_p = &imageMemory[i * tfImageWidth];
X                input_p = scan_line;
X                for (j = 0; j < tfImageWidth; j += 4, input_p++) {
X                    *output_p++ = ((*input_p >> 6) << 4) | (*input_p >> 4) & 3;
X                    *output_p++ = (((*input_p >> 2) & 3) << 4) | *input_p & 3;
X                }
X            }
X        } else {
X            fprintf(stderr,
X                "%s: can't handle %d-bit TIFF file on an %d-bit display\n",
X                programName, tfImageDepth, xImageDepth);
X            exit(0);
X        }
X    }
X
X    TIFFClose(tfFile);
X    free(scan_line);
X
X    return;
X}
X
Xvoid
XCreateXImage()
X{
X    xImage = XCreateImage(xDisplay, xVisual, xImageDepth,
X        xImageDepth == 1 ? XYBitmap : ZPixmap, /* offset */ 0,
X        (char *) imageMemory, tfImageWidth, tfImageHeight,
X        /* bitmap_pad */ 8, /* bytes_per_line */ 0);
X
X    /*
X     * libtiff converts LSB data into MSB but doesn't change the FillOrder tag.
X     */
X    xImage->bitmap_bit_order = MSBFirst;
X
X    if (xImageDepth <= 8)
X        xImage->byte_order = MSBFirst;
X    else
X        xImage->byte_order = xVisual->red_mask > xVisual->blue_mask
X            ? LSBFirst : MSBFirst;
X
X    /*
X     * According to the O'Reilly X Protocol Reference Manual, page 53,
X     * "A pixmap depth of one is always supported and listed, but windows
X     * of depth one might not be supported."  Therefore we create a pixmap
X     * of depth one and use XCopyPlane().
X     */
X    if (xPixmapFlag == True) {
X        xImagePixmap = XCreatePixmap(xDisplay, RootWindow(xDisplay, xScreen),
X            xImage->width, xImage->height, xImageDepth);
X
X        if (xImageDepth == 1) {
X            xBitmapGc = XCreateGC(xDisplay, xImagePixmap,
X                GCFunction | GCPlaneMask | GCForeground | GCBackground,
X                &xGcValues);
X            XPutImage(xDisplay, xImagePixmap, xBitmapGc, xImage,
X                0, 0, 0, 0, xImage->width, xImage->height);
X        } else
X            XPutImage(xDisplay, xImagePixmap, xWinGc, xImage,
X                0, 0, 0, 0, xImage->width, xImage->height);
X        XDestroyImage(xImage);
X    }
X
X    if (xPixmapFlag == True)
X        free(imageMemory);
X
X    if (grayMap != NULL)
X        free(grayMap);
X    if (redMap != NULL)
X        free(redMap);
X    if (greenMap != NULL)
X        free(greenMap);
X    if (blueMap != NULL)
X        free(blueMap);
X
X    return;
X}
X
Xvoid
XEventLoop()
X{
X    XEvent event;
X
X    for (;;) {
X        XNextEvent(xDisplay, &event);
X
X        switch (event.type) {
X        case Expose:
X            if (xPixmapFlag == True) {
X                if (xImageDepth == 1)
X                    XCopyPlane(xDisplay, xImagePixmap, xWindow, xWinGc,
X                        event.xexpose.x, event.xexpose.y,
X                        event.xexpose.width, event.xexpose.height,
X                        event.xexpose.x, event.xexpose.y, 1);
X                else
X                    XCopyArea(xDisplay, xImagePixmap, xWindow, xWinGc,
X                        event.xexpose.x, event.xexpose.y,
X                        event.xexpose.width, event.xexpose.height,
X                        event.xexpose.x, event.xexpose.y);
X            } else
X                XPutImage(xDisplay, xWindow, xWinGc, xImage,
X                    event.xexpose.x, event.xexpose.y,
X                    event.xexpose.x, event.xexpose.y,
X                    event.xexpose.width, event.xexpose.height);
X            break;
X        case ButtonPress:
X            if (xPixmapFlag == False)
X                free(imageMemory);
X            XFree(xVisualList);
X            XFreeGC(xDisplay, xWinGc);
X            if (xPixmapFlag == True) {
X                if (xImageDepth == 1)
X                    XFreeGC(xDisplay, xBitmapGc);
X                else
X                    XFreeColormap(xDisplay, xColormap);
X                XFreePixmap(xDisplay, xImagePixmap);
X            } else {
X                if (xImageDepth != 1)
X                    XFreeColormap(xDisplay, xColormap);
X                XDestroyImage(xImage);
X            }
X            XFreePixmap(xDisplay, xTiffIconPixmap);
X            XDestroyWindow(xDisplay, xWindow);
X            XCloseDisplay(xDisplay);
X            exit(0);
X        default:
X            break;
X        }
X    }
X}
X
Xint
XXTiffErrorHandler(display, error_event)
X    Display *display;
X    XErrorEvent *error_event;
X{
X    char message[80];
X
X    /*
X     * Some X implementations have limitations on the size of pixmaps.
X     */
X    if ((error_event->error_code == BadAlloc)
X            && (error_event->request_code == X_CreatePixmap))
X        fprintf(stderr, "%s: requested pixmap too big for display\n",
X            programName);
X    else {
X        XGetErrorText(display, error_event->error_code, message, 80);
X        fprintf(stderr, "%s: error code %s\n", programName, message);
X    }
X
X    exit(0);
X}
SHAR_EOF
$TOUCH -am 0508132190 xtiff.c &&
chmod 0644 xtiff.c ||
echo "restore of xtiff.c failed"
set `wc -c xtiff.c`;Wc_c=$1
if test "$Wc_c" != "28249"; then
	echo original size 28249, current size $Wc_c
fi
# ============= xtiff.man ==============
echo "x - extracting xtiff.man (Text)"
sed 's/^X//' << 'SHAR_EOF' > xtiff.man &&
X.TH XTIFF 1 "May 7, 1990" "X Version 11"
X.SH NAME
Xxtiff \- view a TIFF file in an X window
X.SH SYNOPSIS
X.B xtiff
X[
X.IR "\-directory directory"
X]
X[
X.IR "\-display display"
X]
X[
X.IR "\-gamma gamma"
X]
X[
X.IR "\-geometry geometry"
X]
X[
X.IR "\-nopixmap"
X]
X[
X.IR "\-sync"
X]
X.IR file
X.SH DESCRIPTION
X.IR xtiff
Xis a TIFF viewer for X-based on the
X.IR libtiff (3)
Xpackage.
XIt displays a single TIFF file in an X window
Xbig enough to hold the image.
XOn appropriate display hardware
Xit can handle 24-bit RGB color TIFF files,
X8, 4 and 2-bit palette color TIFF files
Xand 8, 4, 2 and 1-bit grayscale TIFF files.
XThe
X.IR \-directory
Xoption allows the user to specify
Xan individual page in a multi-page TIFF file.
X.PP
X.IR xtiff
Xmanages the negotiation between the needs of an image
Xand the visual capabilities made available by an X server.
XIf necessary,
Xit will promote an image to a deeper visual,
Xbut it will not demote an image by quantizing and/or dithering.
XIn that case it will fail to display the image.
X.PP
X.IR xtiff
Xreads the
X.IR "Gray Response Curve" ,
X.IR "Gray Response Unit"
Xand
X.IR "Color Response Curve"
Xtags in a TIFF file.
XThe data in these tags describe gamma compensation or image companding.
XTogether with the
X.IR \-gamma
Xoption or the NTSC default gamma value of 2.2,
Xthe image will be gamma corrected and displayed.
X.PP
XFor example, if a TIFF file has been prepared for a typical display,
Xit has a gamma compensation of 2.2 built into either the image
Xor preferably the
X.IR "Color Response Curve"
Xtag.
XThis is a device-dependent image and,
Xin this case, the value for the
X.IR \-gamma
Xcommand line option should be 1.0.
XIf the
X.IR "Color Response Curve"
Xtag describes a companded but otherwise device-independent image
Xthen the command line gamma should be set according to the monitor.
X.PP
XUnfortunately there is no way of knowing a priori whether or not
Xan image is device-independent without knowing its ancestry.
XIf the image conforms to the TIFF 5.0 specification
Xit should be device-independent;
Xbut many scanner and image processing programs
Xdo not adhere rigorously to the standard.
X.SH BUTTONS
X.IR xtiff
Xwill exit if you press any button while the
X.IR xtiff
Xwindow has input focus.
X.SH OPTIONS
X.TP 8
X.B -directory directory
XSeek to
X.IR directory
Xand display its image.
XThe default directory is 0.
XThis option can be used to display different pages
Xin a multi-page TIFF file.
X.TP 8
X.B -display display
XIndicates the X server used to display an image.
X.TP 8
X.B -gamma gamma
XSpecifies the value used
Xto build compensation tables
Xfor simple gamma correction.
X.TP 8
X.B -geometry geometry
XThis option is only used to indicate the placement of an
X.IR xtiff
Xwindow.
X.IR xtiff
Xcurrently ignores the
X.IR width
Xand
X.IR height
Xportions of the argument.
X.TP 8
X.B -nopixmap
XIndicates that
X.IR xtiff
Xshould not use a pixmap to store the image on a server.
XThis option is necessary
Xbecause some servers impose size limitations on pixmaps.
XThis method is slower because the image must be stored
Xon the client side and transferred for each exposure or refresh.
X.TP 8
X.B -sync
XRun
X.IR xtiff
Xsynchronously.
X.SH SEE ALSO
X.IR libtiff (3),
X.br
X.IR "Tag Image File Format Specification \(em Revision 5.0" ,
XAldus Corporation,
XAugust 8, 1988.
X.br
X.IR "The Spirit of TIFF Class F" ,
XCygnet Technologies,
Xrevised March 29, 1990.
X.SH LIMITATIONS
X.IR xtiff
Xdoes not support the complete repertoire of all possible TIFF files
Xon all possible visual/depth combinations.
X.PP
X.IR xtiff
Xsupports TIFF class B (bilevel),
Xclass G (grayscale),
Xclass P (palette color),
Xclass R (RGB color) and class F (FAX).
X.PP
XOnly the top-left orientation is supported.
XThis is both the X orientation and the TIFF default.
X.PP
XGamma correction is simple and there is no colorimetry support.
X.PP
X.IR xtiff
Xassumes that servers with 24-bit visuals also have 8-bit visuals.
XAn 8-bit image is not promoted to 24-bit on the client side.
X.PP
XThere is no support for
X.IR StaticGray ,
X.IR StaticColor
Xor
X.IR TrueColor
Xvisuals except for 1-bit images.
SHAR_EOF
$TOUCH -am 0507213190 xtiff.man &&
chmod 0666 xtiff.man ||
echo "restore of xtiff.man failed"
set `wc -c xtiff.man`;Wc_c=$1
if test "$Wc_c" != "4005"; then
	echo original size 4005, current size $Wc_c
fi
# ============= xtifficon.h ==============
echo "x - extracting xtifficon.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > xtifficon.h &&
X#define xtifficon_width 32
X#define xtifficon_height 32
Xstatic char xtifficon_bits[] = {
X   0xff, 0x00, 0x00, 0xc0, 0xfe, 0x01, 0x7e, 0xc0, 0xfc, 0x03, 0x7e, 0x60,
X   0xf8, 0x07, 0x06, 0x30, 0xf8, 0x07, 0x1e, 0x18, 0xf0, 0x0f, 0x1e, 0x0c,
X   0xe0, 0x1f, 0x06, 0x06, 0xc0, 0x3f, 0x06, 0x06, 0xc0, 0x3f, 0x06, 0x03,
X   0x80, 0x7f, 0x80, 0x01, 0x00, 0xff, 0xc0, 0x00, 0x00, 0xfe, 0x61, 0x00,
X   0x00, 0xfe, 0x31, 0x00, 0x00, 0xfc, 0x33, 0x7e, 0xfc, 0xf8, 0x1b, 0x7e,
X   0xfc, 0xf0, 0x0d, 0x06, 0x30, 0xf0, 0x0e, 0x1e, 0x30, 0x60, 0x1f, 0x1e,
X   0x30, 0xb0, 0x3f, 0x06, 0x30, 0x98, 0x7f, 0x06, 0x30, 0x98, 0x7f, 0x06,
X   0x30, 0x0c, 0xff, 0x00, 0x00, 0x06, 0xfe, 0x01, 0x00, 0x63, 0xfc, 0x03,
X   0x80, 0x61, 0xfc, 0x03, 0xc0, 0x60, 0xf8, 0x07, 0xc0, 0x60, 0xf0, 0x0f,
X   0x60, 0x60, 0xe0, 0x1f, 0x30, 0x60, 0xe0, 0x1f, 0x18, 0x60, 0xc0, 0x3f,
X   0x0c, 0x60, 0x80, 0x7f, 0x06, 0x00, 0x00, 0xff};
SHAR_EOF
$TOUCH -am 0413180190 xtifficon.h &&
chmod 0644 xtifficon.h ||
echo "restore of xtifficon.h failed"
set `wc -c xtifficon.h`;Wc_c=$1
if test "$Wc_c" != "890"; then
	echo original size 890, current size $Wc_c
fi
exit 0

dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.
