v12i053: xtiff, Part01/02

dan sears dbs at kodak.enet.dec.com
Wed Apr 24 16:58:14 AEST 1991


Submitted-by: dbs at kodak.enet.dec.com (dan sears)
Posting-number: Volume 12, Issue 53
Archive-name: xtiff/part01

xtiff 2.0

xtiff is a tool for viewing a TIFF file in an X window.  We wrote it to
handle as many different kinds of TIFF files as possible on as many different
kinds of displays as possible while remaining simple, portable and efficient.
xtiff requires X11 R4 and Sam Leffler's libtiff package (which can be found
on ucbvax.berkeley.edu).

This release of xtiff contains two versions: an Xlib version and an Athena
Widgets version.  The Xlib version starts up faster than the Athena Widgets
version, but the latter has certain features that make it useful.  These
include:

    + command buttons for browsing through multi-page TIFF files
    + panning with the mouse or arrow keys

In comparison, the Xlib version only displays a TIFF file in an X window
big enough to hold the image.  If an X server doesn't support pixmaps
large enough for the image, xtiff will punt.

In writing both versions of xtiff, we paid close attention to what was
actually going across the network by using Greg McFarlane's xmon X11
protocol monitor.  With the Xlib version we minimized the packets sent
over the network, but in the Athena Widgets version that was more difficult
since the toolkit has a fair amount of overhead.  Both versions allow the
user to choose whether the image data is stored in the client or in the
server.  This feature shows a dramatic tradeoff in performance versus
memory requirements for the server.

xtiff has two chief limitations: its handling of the colormap can only
be described as brutal and it does not attempt to display images that
are deeper than the available visuals through dithering or median cut
algorithms.

---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# existing files will NOT be overwritten unless -c is specified
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#    456 -rw-r--r-- xtiff/xlib/Imakefile
#    269 -rw-r--r-- xtiff/xlib/README
#     21 -rw-r--r-- xtiff/xlib/patchlevel.h
#  29418 -rw-r--r-- xtiff/xlib/xtiff.c
#   3973 -rw-r--r-- xtiff/xlib/xtiff.man
#    890 -rw-r--r-- xtiff/xlib/xtifficon.h
#   1636 -rw-r--r-- xtiff/README
#    313 -rw-r--r-- xtiff/athena/README
#  42696 -rw-r--r-- xtiff/athena/xtiff.c
#   5315 -rw-r--r-- xtiff/athena/xtiff.man
#    890 -rw-r--r-- xtiff/athena/xtifficon.h
#    468 -rw-r--r-- xtiff/athena/Imakefile
#     21 -rw-r--r-- xtiff/athena/patchlevel.h
#
if test -r _shar_seq_.tmp; then
	echo 'Must unpack archives in sequence!'
	echo Please unpack part `cat _shar_seq_.tmp` next
	exit 1
fi
# ============= xtiff/xlib/Imakefile ==============
if test ! -d 'xtiff'; then
    echo 'x - creating directory xtiff'
    mkdir 'xtiff'
fi
if test ! -d 'xtiff/xlib'; then
    echo 'x - creating directory xtiff/xlib'
    mkdir 'xtiff/xlib'
fi
if test -f 'xtiff/xlib/Imakefile' -a X"$1" != X"-c"; then
	echo 'x - skipping xtiff/xlib/Imakefile (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xtiff/xlib/Imakefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtiff/xlib/Imakefile' &&
#
# Imakefile -- to generate a Makefile for xtiff, use:
#   /usr/local/X11/mit/config/imake \
#       -I/usr/local/X11/mit/config \
#       -DTOPDIR=/usr/local/X11/mit \
#       -DCURDIR=/usr/local/X11/mit \
#       -DDESTDIR=/usr/local/X11/mit
#
X
X   SYS_LIBRARIES = -lm
X LOCAL_LIBRARIES = $(XLIB)
X         DEPLIBS = $(DEPXLIB)
X            TIFF = ../2.3/libtiff
X EXTRA_LIBRARIES = $(TIFF)/libtiff.a
X  EXTRA_INCLUDES = -I$(TIFF)
X
SimpleProgramTarget(xtiff)
SHAR_EOF
chmod 0644 xtiff/xlib/Imakefile ||
echo 'restore of xtiff/xlib/Imakefile failed'
Wc_c="`wc -c < 'xtiff/xlib/Imakefile'`"
test 456 -eq "$Wc_c" ||
	echo 'xtiff/xlib/Imakefile: original size 456, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= xtiff/xlib/README ==============
if test -f 'xtiff/xlib/README' -a X"$1" != X"-c"; then
	echo 'x - skipping xtiff/xlib/README (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xtiff/xlib/README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtiff/xlib/README' &&
xtiff is a tool for viewing a TIFF file in an X window.  It was written to
handle as many different kinds of TIFF files as possible while remaining
simple, portable and efficient.  xtiff requires Sam Leffler's libtiff package
which can be found on ucbvax.berkeley.edu.
SHAR_EOF
chmod 0644 xtiff/xlib/README ||
echo 'restore of xtiff/xlib/README failed'
Wc_c="`wc -c < 'xtiff/xlib/README'`"
test 269 -eq "$Wc_c" ||
	echo 'xtiff/xlib/README: original size 269, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= xtiff/xlib/patchlevel.h ==============
if test -f 'xtiff/xlib/patchlevel.h' -a X"$1" != X"-c"; then
	echo 'x - skipping xtiff/xlib/patchlevel.h (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xtiff/xlib/patchlevel.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtiff/xlib/patchlevel.h' &&
#define PATCHLEVEL 5
SHAR_EOF
chmod 0644 xtiff/xlib/patchlevel.h ||
echo 'restore of xtiff/xlib/patchlevel.h failed'
Wc_c="`wc -c < 'xtiff/xlib/patchlevel.h'`"
test 21 -eq "$Wc_c" ||
	echo 'xtiff/xlib/patchlevel.h: original size 21, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= xtiff/xlib/xtiff.c ==============
if test -f 'xtiff/xlib/xtiff.c' -a X"$1" != X"-c"; then
	echo 'x - skipping xtiff/xlib/xtiff.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xtiff/xlib/xtiff.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtiff/xlib/xtiff.c' &&
/*
X * xtiff - view a TIFF file in an X window
X *
X * Dan Sears
X * Chris Sears
X *
X * Revision 1.6  90/12/16
X *      Changed the handling of the -geometry argument to use the
width/height.
X *      Resizing is allowed.  Bit gravity is NorthWestGravity.
X * Revision 1.5  90/11/23
X *      Fixed an ICCCM bug.  The window manager frees colormaps not the
client.
X * Revision 1.4  90/09/27
X *      Fixed a bug with colormapping nopixmapped and pixmapped
bitmaps.
X * Revision 1.3  90/06/18
X *      Fixed a bug in handling different color masks and byte orders
X *          for DirectColor visuals.
X * Revision 1.2  90/05/29
X *      Fixed a bug with MINISWHITE images.
X * Revision 1.1  90/05/16
X *      Fixed a few minor bugs.
X * Revision 1.0  90/05/07
X *      Initial release.
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 * There is no support for or use of 3/3/2 DirectColor visuals.
X * TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE are not
supported.
X *
X * Only TIFFTAG_BITSPERSAMPLE values that are 1, 2, 4 or 8 are
supported.
X */
X
#include <math.h>
#include <stdio.h>
#include <tiffio.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include "xtifficon.h"
X
#define TIFF_GAMMA  2.2
#define ROUND(x)    (u_short) ((x) + 0.5)
#define SCALE(x, s) (((x) * 65535L) / (s))
#define MCHECK(m)   if (!m) { fprintf(stderr, "malloc failed\n");
exit(0); }
X
void                GetTIFFHeader();
void                CheckAndCorrectColormap();
void                SimpleGammaCorrection();
void                InitializeX();
void                GetTIFFImage();
void                CreateXImage();
int                 SearchVisualList();
void                EventLoop();
int                 XTiffErrorHandler();
X
/*
X * X data structures
X */
Colormap            xColormap;
Display *           xDisplay;
Window              xWindow;
Pixmap              xImagePixmap, xTiffIconPixmap;
Visual *            xVisual;
XXImage *            xImage;
GC                  xWinGc, xBitmapGc;
XXGCValues           xGcValues;
int                 xScreen, xSyncFlag = False, xImageDepth, xNVisuals,
X                    xPixmapFlag = True, xRedMask, xGreenMask,
xBlueMask;
char *              xGeometry = NULL, *xDisplayName = NULL;
XXVisualInfo *       xVisualList;
X
/*
X * TIFF data structures
X */
TIFF *              tfFile;
u_short             tfBitsPerSample, tfSamplesPerPixel,
tfPlanarConfiguration,
X                    tfPhotometricInterpretation, tfGrayResponseUnit,
X                    tfImageDepth, tfImageWidth, tfImageHeight,
tfBytesPerRow;
int                 tfDirectory = 0;
double              tfUnitMap, tfGrayResponseUnitMap[] = {
X                        -1, -10, -100, -1000, -10000, -100000
X                    };
X
/*
X * display data structures
X */
double              dGamma = TIFF_GAMMA, *dRed, *dGreen, *dBlue;
X
/*
X * shared data structures
X */
u_short *           redMap = NULL, *greenMap = NULL, *blueMap = NULL,
X                    *grayMap = NULL, colormapSize;
u_char *            imageMemory;
char *              fileName, *programName;
X
void
main(argc, argv)
X    register int argc;
X    register char **argv;
{
X    register int i;
X
X    programName = argv[0];
X
X    if (argc == 1) {
X        fprintf(stderr, "Usage: %s file\noptions:\n", programName);
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
void
GetTIFFHeader()
{
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_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    MCHECK(dRed); MCHECK(dGreen); MCHECK(dBlue);
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 * Many programs get TIFF colormaps wrong.  They use 8-bit colormaps
instead of
X * 16-bit colormaps.  This function is a heuristic to detect and
correct this.
X */
void
CheckAndCorrectColormap()
{
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
void
SimpleGammaCorrection()
{
X    register int i;
X
X    for (i = 0; i < colormapSize; i++) {
X        if (((tfPhotometricInterpretation == PHOTOMETRIC_MINISWHITE)
X            && (i == colormapSize - 1))
X            || ((tfPhotometricInterpretation ==
PHOTOMETRIC_MINISBLACK)
X            && (i == 0)))
X            redMap[i] = greenMap[i] = blueMap[i] = 0;
X        else {
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
X    free(dRed); free(dGreen); free(dBlue);
}
X
void
InitializeX(xargc, xargv)
X    int xargc;
X    char **xargv;
{
X    register int i;
X    int win_x = 0, win_y = 0, win_w = tfImageWidth, win_h =
tfImageHeight;
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    XSetErrorHandler(XTiffErrorHandler);
X    XSynchronize(xDisplay, xSyncFlag);
X    xScreen = DefaultScreen(xDisplay);
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.  bitmap_unit is
32.
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        MCHECK(colors);
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            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        MCHECK(colors);
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.  This causes colormap flashing.
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.bit_gravity = NorthWestGravity;
X    window_attributes.event_mask = ExposureMask | ButtonPressMask;
X
X    if (xGeometry != NULL)
X        (void) XParseGeometry(xGeometry, &win_x, &win_y, &win_w,
&win_h);
X
X    xWindow = XCreateWindow(xDisplay, RootWindow(xDisplay, xScreen),
X        win_x, win_y, win_w, win_h, /* border_width */ 3,
X        xImageDepth == 1 ? CopyFromParent : xImageDepth, InputOutput,
X        xVisual, CWColormap | CWBackPixel | CWBorderPixel |
CWEventMask
X        | CWBitGravity, &window_attributes);
X
X    xGcValues.function = GXcopy;
X    xGcValues.plane_mask = AllPlanes;
X    if (tfPhotometricInterpretation == PHOTOMETRIC_MINISBLACK) {
X        xGcValues.foreground = XWhitePixel(xDisplay, xScreen);
X        xGcValues.background = XBlackPixel(xDisplay, xScreen);
X    } else {
X        xGcValues.foreground = XBlackPixel(xDisplay, xScreen);
X        xGcValues.background = XWhitePixel(xDisplay, xScreen);
X    }
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;
X    size_hints.x = win_x; size_hints.y = win_y;
X    size_hints.width = win_w; size_hints.height = win_h;
X
X    XSetStandardProperties(xDisplay, xWindow, fileName, fileName,
X        xTiffIconPixmap, xargv, xargc, &size_hints);
X
X    if (colors != NULL)
X        free(colors);
}
X
int
SearchVisualList(image_depth, visual_class, visual)
X    register int image_depth, visual_class;
X    Visual **visual;
{
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            *visual = vis->visual;
X            xImageDepth = vis->depth;
X            xRedMask = vis->red_mask;
X            xGreenMask = vis->green_mask;
X            xBlueMask = vis->blue_mask;
X            return True;
X        }
X    }
X
X    return False;
}
X
void
GetTIFFImage()
{
X    register u_char *scan_line, *output_p, *input_p;
X    register int i, j, s;
X    int pixel_map[3], red_shift, green_shift, blue_shift;
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 = (u_char *)
X            malloc(tfImageWidth * tfImageHeight * 4);
X        MCHECK(imageMemory);
X
X        /*
X         * Handle different color masks for different frame buffers.
X         */
X        if (ImageByteOrder(xDisplay) == LSBFirst) { /* DECstation 5000
*/
X            red_shift = pixel_map[0] = xRedMask == 0xFF000000 ? 3
X                : (xRedMask == 0xFF0000 ? 2 : (xRedMask == 0xFF00 ? 1 :
0));
X            green_shift = pixel_map[1] = xGreenMask == 0xFF000000 ? 3
X                : (xGreenMask == 0xFF0000 ? 2 : (xGreenMask == 0xFF00 ?
1 : 0));
X            blue_shift = pixel_map[2] = xBlueMask == 0xFF000000 ? 3
X                : (xBlueMask == 0xFF0000 ? 2 : (xBlueMask == 0xFF00 ? 1
: 0));
X        } else { /* Ardent */
X            red_shift = pixel_map[0] = xRedMask == 0xFF000000 ? 0
X                : (xRedMask == 0xFF0000 ? 1 : (xRedMask == 0xFF00 ? 2 :
3));
X            green_shift = pixel_map[0] = xGreenMask == 0xFF000000 ? 0
X                : (xGreenMask == 0xFF0000 ? 1 : (xGreenMask == 0xFF00 ?
2 : 3));
X            blue_shift = pixel_map[0] = xBlueMask == 0xFF000000 ? 0
X                : (xBlueMask == 0xFF0000 ? 1 : (xBlueMask == 0xFF00 ? 2
: 3));
X        }
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 + red_shift) = *input_p++;
X                    *(output_p + green_shift) = *input_p++;
X                    *(output_p + blue_shift) = *input_p++;
X                    output_p += 4;
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) +
pixel_map[s];
X                    for (j = 0; j < tfImageWidth; j++, output_p += 4)
X                        *output_p = *input_p++;
X                }
X            }
X        }
X    } else {
X        if (xImageDepth == tfImageDepth) {
X            output_p = imageMemory = (u_char *)
X                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 = (u_char *)
X                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 = (u_char *)
X                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 = (u_char *)
X                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
void
CreateXImage()
{
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    if (xImageDepth == 1)
X        xImage->bitmap_bit_order = MSBFirst;
X    if (xImageDepth <= 8)
X        xImage->byte_order = MSBFirst;
X
X    if (xPixmapFlag == True) {
X        xImagePixmap = XCreatePixmap(xDisplay, RootWindow(xDisplay,
xScreen),
X            xImage->width, xImage->height, xImageDepth);
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().  This is idiomatic.
X         */
X        if (xImageDepth == 1) {         /* just pass the bits through
*/
X            xGcValues.foreground = 1;   /* foreground describes set
bits */
X            xGcValues.background = 0;   /* background describes clear
bits */
X            xBitmapGc = XCreateGC(xDisplay, xImagePixmap,
X                GCForeground | GCBackground, &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 (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
void
EventLoop()
{
X    XEvent event, button;
X
X    for (;;) {
X        XNextEvent(xDisplay, &event);
X
X        switch (event.type) {
X        case Expose:    /* Let an application quit as fast as possible
*/
X            if (!XCheckTypedEvent(xDisplay, ButtonPress, &button)) {
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            }
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                XFreePixmap(xDisplay, xImagePixmap);
X            } else
X                XDestroyImage(xImage);
X            XFreePixmap(xDisplay, xTiffIconPixmap);
X            XDestroyWindow(xDisplay, xWindow);
X            XCloseDisplay(xDisplay);
X            exit(0);
X        default:
X            break;
X        }
X    }
}
X
int
XXTiffErrorHandler(display, error_event)
X    Display *display;
X    XErrorEvent *error_event;
{
X    char message[80];
X
X    /*
X     * Some X servers limit 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);
}
SHAR_EOF
chmod 0644 xtiff/xlib/xtiff.c ||
echo 'restore of xtiff/xlib/xtiff.c failed'
Wc_c="`wc -c < 'xtiff/xlib/xtiff.c'`"
test 29418 -eq "$Wc_c" ||
	echo 'xtiff/xlib/xtiff.c: original size 29418, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= xtiff/xlib/xtiff.man ==============
if test -f 'xtiff/xlib/xtiff.man' -a X"$1" != X"-c"; then
	echo 'x - skipping xtiff/xlib/xtiff.man (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xtiff/xlib/xtiff.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtiff/xlib/xtiff.man' &&
.TH XTIFF 1 "May 7, 1990" "X Version 11"
.SH NAME
xtiff \- view a TIFF file in an X window
.SH SYNOPSIS
.B xtiff
[
.IR "\-directory directory"
]
[
.IR "\-display display"
]
[
.IR "\-gamma gamma"
]
[
.IR "\-geometry geometry"
]
[
.IR "\-nopixmap"
]
[
.IR "\-sync"
]
.IR file
.SH DESCRIPTION
.IR xtiff
is a TIFF viewer for X based on the
.IR libtiff (3)
package.
It displays a single TIFF file in an X window
big enough to hold the image.
On appropriate display hardware
it can handle 24-bit RGB color TIFF files,
8, 4 and 2-bit palette color TIFF files
and 8, 4, 2 and 1-bit grayscale TIFF files.
The
.IR \-directory
option allows the user to specify
an individual page in a multi-page TIFF file.
.PP
.IR xtiff
manages the negotiation between the needs of an image
and the visual capabilities made available by an X server.
If necessary,
it will promote an image to a deeper visual,
but it will not demote an image by quantizing and/or dithering.
In that case it will fail to display the image.
.PP
.IR xtiff
reads the
.IR "Gray Response Curve" ,
.IR "Gray Response Unit"
and
.IR "Color Response Curve"
tags in a TIFF file.
The data in these tags describe gamma compensation or image companding.
Together with the
.IR \-gamma
option or the NTSC default gamma value of 2.2,
the image will be gamma corrected and displayed.
.PP
For example, if a TIFF file has been prepared for a typical display,
it has a gamma compensation of 2.2 built into either the image
or preferably the
.IR "Color Response Curve"
tag.
This is a device-dependent image and,
in this case, the value for the
.IR \-gamma
command line option should be 1.0.
If the
.IR "Color Response Curve"
tag describes a companded but otherwise device-independent image
then the command line gamma should be set according to the monitor.
.PP
Unfortunately there is no way of knowing a priori whether or not
an image is device-independent without knowing its ancestry.
If the image conforms to the TIFF 5.0 specification
it should be device-independent;
but many scanner and image processing programs
do not adhere rigorously to the standard.
.SH BUTTONS
.IR xtiff
will exit if you press any button while the
.IR xtiff
window has input focus.
.SH OPTIONS
.TP 8
.B -directory directory
Seek to
.IR directory
and display its image.
The default directory is 0.
This option can be used to display different pages
in a multi-page TIFF file.
.TP 8
.B -display display
Indicates the X server used to display an image.
.TP 8
.B -gamma gamma
Specifies the value used
to build compensation tables
for simple gamma correction.
.TP 8
.B -geometry geometry
This option is only used to indicate the placement of an
.IR xtiff
window.
.TP 8
.B -nopixmap
Indicates that
.IR xtiff
should not use a pixmap to store the image on a server.
This option is necessary
because some servers impose size limitations on pixmaps.
This method is slower because the image must be stored
on the client side and transferred for each exposure or refresh.
.TP 8
.B -sync
Run
.IR xtiff
synchronously.
.SH SEE ALSO
.IR libtiff (3),
.br
.IR "Tag Image File Format Specification \(em Revision 5.0" ,
Aldus Corporation,
August 8, 1988.
.br
.IR "The Spirit of TIFF Class F" ,
Cygnet Technologies,
revised March 29, 1990.
.SH LIMITATIONS
.IR xtiff
does not support the complete repertoire of all possible TIFF files
on all possible visual/depth combinations.
.PP
.IR xtiff
supports TIFF class B (bilevel),
class G (grayscale),
class P (palette color),
class R (RGB color) and class F (FAX).
.PP
Only the top-left orientation is supported.
This is both the X orientation and the TIFF default.
.PP
Gamma correction is simple and there is no colorimetry support.
.PP
.IR xtiff
assumes that servers with 24-bit visuals also have 8-bit visuals.
An 8-bit image is not promoted to 24-bit on the client side.
.PP
There is no support for
.IR StaticGray ,
.IR StaticColor
or
.IR TrueColor
visuals except for 1-bit images.
There is no support for 3/3/2 DirectColor visuals.
SHAR_EOF
chmod 0644 xtiff/xlib/xtiff.man ||
echo 'restore of xtiff/xlib/xtiff.man failed'
Wc_c="`wc -c < 'xtiff/xlib/xtiff.man'`"
test 3973 -eq "$Wc_c" ||
	echo 'xtiff/xlib/xtiff.man: original size 3973, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= xtiff/xlib/xtifficon.h ==============
if test -f 'xtiff/xlib/xtifficon.h' -a X"$1" != X"-c"; then
	echo 'x - skipping xtiff/xlib/xtifficon.h (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xtiff/xlib/xtifficon.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtiff/xlib/xtifficon.h' &&
#define xtifficon_width 32
#define xtifficon_height 32
static 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, 0x7e, 0x7e, 0xfc, 0x33, 0x7e, 0x7e, 0xf8, 0x1b,
0x06,
X   0x18, 0xf0, 0x0d, 0x1e, 0x18, 0xf0, 0x0e, 0x1e, 0x18, 0x60, 0x1f,
0x06,
X   0x18, 0xb0, 0x3f, 0x06, 0x18, 0x98, 0x7f, 0x06, 0x18, 0x98, 0x7f,
0x00,
X   0x00, 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
chmod 0644 xtiff/xlib/xtifficon.h ||
echo 'restore of xtiff/xlib/xtifficon.h failed'
Wc_c="`wc -c < 'xtiff/xlib/xtifficon.h'`"
test 890 -eq "$Wc_c" ||
	echo 'xtiff/xlib/xtifficon.h: original size 890, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= xtiff/README ==============
if test -f 'xtiff/README' -a X"$1" != X"-c"; then
	echo 'x - skipping xtiff/README (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xtiff/README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtiff/README' &&
xtiff 2.0
X
xtiff is a tool for viewing a TIFF file in an X window.  We wrote it to
handle as many different kinds of TIFF files as possible on as many
different
kinds of displays as possible while remaining simple, portable and
efficient.
xtiff requires X11 R4 and Sam Leffler's libtiff package (which can be
found
on ucbvax.berkeley.edu).
X
This release of xtiff contains two versions: an Xlib version and an
Athena
Widgets version.  The Xlib version starts up faster than the Athena
Widgets
version, but the latter has certain features that make it useful. 
These
include:
X
X    + command buttons for browsing through multi-page TIFF files
X    + panning with the mouse or arrow keys
X
In comparison, the Xlib version only displays a TIFF file in an X
window
big enough to hold the image.  If an X server doesn't support pixmaps
large enough for the image, xtiff will punt.
X
In writing both versions of xtiff, we paid close attention to what was
actually going across the network by using Greg McFarlane's xmon X11
protocol monitor.  With the Xlib version we minimized the packets sent
over the network, but in the Athena Widgets version that was more
difficult
since the toolkit has a fair amount of overhead.  Both versions allow
the
user to choose whether the image data is stored in the client or in the
server.  This feature shows a dramatic tradeoff in performance versus
memory requirements for the server.
X
xtiff has two chief limitations: its handling of the colormap can only
be described as brutal and it does not attempt to display images that
are deeper than the available visuals through dithering or median cut
algorithms.
SHAR_EOF
chmod 0644 xtiff/README ||
echo 'restore of xtiff/README failed'
Wc_c="`wc -c < 'xtiff/README'`"
test 1636 -eq "$Wc_c" ||
	echo 'xtiff/README: original size 1636, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= xtiff/athena/README ==============
if test ! -d 'xtiff/athena'; then
    echo 'x - creating directory xtiff/athena'
    mkdir 'xtiff/athena'
fi
if test -f 'xtiff/athena/README' -a X"$1" != X"-c"; then
	echo 'x - skipping xtiff/athena/README (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xtiff/athena/README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtiff/athena/README' &&
xtiff 2.0
X
xtiff is a tool for viewing a TIFF file in an X window.  It was written
to
handle as many different kinds of TIFF files as possible while
remaining
simple, portable and efficient.  xtiff requires X11 R4, the Athena
Widgets
and Sam Leffler's libtiff package (which can be found on
ucbvax.berkeley.edu).
SHAR_EOF
chmod 0644 xtiff/athena/README ||
echo 'restore of xtiff/athena/README failed'
Wc_c="`wc -c < 'xtiff/athena/README'`"
test 313 -eq "$Wc_c" ||
	echo 'xtiff/athena/README: original size 313, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= xtiff/athena/xtiff.c ==============
if test -f 'xtiff/athena/xtiff.c' -a X"$1" != X"-c"; then
	echo 'x - skipping xtiff/athena/xtiff.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xtiff/athena/xtiff.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtiff/athena/xtiff.c' &&
/*
X * xtiff - view a TIFF file in an X window
X *
X * Dan Sears
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 * Revision 1.0  90/05/07
X *      Initial release.
X * Revision 2.0  90/12/20
X *      Converted to use the Athena Widgets and the Xt Intrinsics.
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 * There is no support for or use of 3/3/2 DirectColor visuals.
X * TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE are not
supported.
X *
X * Only TIFFTAG_BITSPERSAMPLE values that are 1, 2, 4 or 8 are
supported.
X */
X
#include <math.h>
#include <stdio.h>
#include <tiffio.h>
#include <X11/Intrinsic.h>
#include <X11/Xproto.h>
#include <X11/Shell.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/List.h>
#include <X11/Xaw/Label.h>
#include <X11/StringDefs.h>
#include <X11/cursorfont.h>
#define XK_MISCELLANY
#include <X11/keysymdef.h>
#include "xtifficon.h"
X
#define TIFF_GAMMA      "2.2"     /* default gamma from the TIFF 5.0
spec */
#define ROUND(x)        (u_short) ((x) + 0.5)
#define SCALE(x, s)     (((x) * 65535L) / (s))
#define MCHECK(m)       if (!m) { fprintf(stderr, "malloc failed\n");
exit(0); }
#define MIN(a, b)       (((a) < (b)) ? (a) : (b))
#define MAX(a, b)       (((a) > (b)) ? (a) : (b))
#define VIEWPORT_WIDTH  700
#define VIEWPORT_HEIGHT 500
#define KEY_TRANSLATE   20
X
#ifdef __STDC__
void main(int argc, char **argv);
void OpenTIFFFile(void);
void GetTIFFHeader(void);
void SetNameLabel(void);
void CheckAndCorrectColormap(void);
void SimpleGammaCorrection(void);
void GetVisual(void);
Boolean SearchVisualList(int image_depth, int visual_class, Visual
**visual);
void GetTIFFImage(void);
void CreateXImage(void);
XXtCallbackProc SelectProc(Widget w, caddr_t unused_1, caddr_t
unused_2);
void QuitProc(void);
void NextProc(void);
void PreviousProc(void);
void PageProc(int direction);
void EventProc(Widget widget, caddr_t unused, XEvent *event);
void ResizeProc(void);
int XTiffErrorHandler(Display *display, XErrorEvent *error_event);
void Usage(void);
#else
void main();
void OpenTIFFFile();
void GetTIFFHeader();
void SetNameLabel();
void CheckAndCorrectColormap();
void SimpleGammaCorrection();
void GetVisual();
Boolean SearchVisualList();
void GetTIFFImage();
void CreateXImage();
XXtCallbackProc SelectProc();
void QuitProc();
void NextProc();
void PreviousProc();
void PageProc();
void EventProc();
void ResizeProc();
int XTiffErrorHandler();
void Usage();
#endif
X
int xtVersion = XtSpecificationRelease;     /* XTIFF depends on R4 or
higher */
X
/*
X * Xt data structures
X */
Widget shellWidget, formWidget, listWidget, labelWidget, imageWidget;
X
enum { ButtonQuit = 0, ButtonPreviousPage = 1, ButtonNextPage = 2 };
X
String buttonStrings[] = { "Quit", "Previous", "Next" };
X
static XrmOptionDescRec shellOptions[] = {
X    { "-help", "*help", XrmoptionNoArg,  (caddr_t) "True" },
X    { "-gamma", "*gamma", XrmoptionSepArg, NULL },
X    { "-usePixmap", "*usePixmap", XrmoptionSepArg, NULL },
X    { "-viewportWidth", "*viewportWidth", XrmoptionSepArg, NULL },
X    { "-viewportHeight", "*viewportHeight", XrmoptionSepArg, NULL },
X    { "-translate", "*translate", XrmoptionSepArg, NULL },
X    { "-verbose", "*verbose", XrmoptionSepArg, NULL }
};
X
typedef struct {
X    Boolean help;
X    float gamma;
X    Boolean usePixmap;
X    int viewportWidth;
X    int viewportHeight;
X    int translate;
X    Boolean verbose;
} AppData, *AppDataPtr;
X
AppData appData;
X
XXtResource clientResources[] = {
X    {
X        "help", XtCBoolean, XtRBoolean, sizeof(Boolean),
X        XtOffset(AppDataPtr, help), XtRImmediate, (XtPointer) False
X    }, {
X        "gamma", "Gamma", XtRFloat, sizeof(float),
X        XtOffset(AppDataPtr, gamma), XtRString, (XtPointer) TIFF_GAMMA
X    }, {
X        "usePixmap", "UsePixmap", XtRBoolean, sizeof(Boolean),
X        XtOffset(AppDataPtr, usePixmap), XtRImmediate, (XtPointer)
True
X    }, {
X        "viewportWidth", "ViewportWidth", XtRInt, sizeof(int),
X        XtOffset(AppDataPtr, viewportWidth), XtRImmediate,
X        (XtPointer) VIEWPORT_WIDTH
X    }, {
X        "viewportHeight", "ViewportHeight", XtRInt, sizeof(int),
X        XtOffset(AppDataPtr, viewportHeight), XtRImmediate,
X        (XtPointer) VIEWPORT_HEIGHT
X    }, {
X        "translate", "Translate", XtRInt, sizeof(int),
X        XtOffset(AppDataPtr, translate), XtRImmediate, (XtPointer)
KEY_TRANSLATE
X    }, {
X        "verbose", "Verbose", XtRBoolean, sizeof(Boolean),
X        XtOffset(AppDataPtr, verbose), XtRImmediate, (XtPointer) False
SHAR_EOF
true || echo 'restore of xtiff/athena/xtiff.c failed'
fi
echo 'End of  part 1'
echo 'File xtiff/athena/xtiff.c is continued in part 2'
echo 2 > _shar_seq_.tmp
exit 0

--
Dan Heller
O'Reilly && Associates       Z-Code Software    Comp-sources-x:
Senior Writer                President          comp-sources.x at uunet.uu.net
argv at ora.com                 argv at zipcode.com



More information about the Comp.sources.x mailing list