dbs@kodak.enet.dec.com (dan sears) (04/24/91)
Submitted-by: dbs@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@uunet.uu.net argv@ora.com argv@zipcode.com