[comp.sources.misc] v06i015: tif2ps -- convert TIFF to PostScript

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (01/30/89)

Posting-number: Volume 6, Issue 15
Submitted-by: andy@coma.UUCP (Andreas Lampen)
Archive-name: tif2ps/part01

This is part 1 (of 2) of "tif2ps", a program that converts TIFF
(Tag Image File Format - a format for scanned images) to PostScript.

If works on UNIX machines and on PCs.

Enjoy it,
	 Andy

---- Cut here ---- Cut here ---- Cut here ---- Cut here ---- Cut here ----
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	README
#	Makefile
#	defs.h
#	tif.h
#	tif2ps.c
#	genps.c
#	andy.tif.Z.btoa
# This archive created: Thu Dec 29 20:42:57 1988
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(2862 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
cat << \SHAR_EOF > 'README'
This is version 1.0 of tif2ps/tifdump, a program that converts
TIFF-files to PostScript (*).

It is written by: Andreas Lampen
		  Tech. Univ. Berlin, FR 5-6
		  Franklinstr. 28/29
		  D-1000 Berlin 10, West Germany
		  Tel: +49-30-314-73496
		  E-mail: andy@coma.uucp (from US: pyramid!tub!coma!andy) or
			  andy@db0tui62.bitnet

-------------------------------------------------------------------
Copyright (C) 1988 by the author.
Permission is granted to copy and distribute this program
without charge, provided this copyright notice is included
in the copy.
This Software is distributed on an as-is basis. There will be
ABSOLUTELY NO WARRANTY for any part of this software to work
correct. In no case will the author be liable to you for damages
caused by the usage of this software.
-------------------------------------------------------------------

This Distribution contains the files
	README	     -- The file you are actually reading.
	Makefile     -- The Makefile for building and installing
			the programs "tif2ps" and "tifdump"
	Makefile.PC  -- The MSDOS (Microsoft "make") Makefile
	Shapefile    -- The Shapefile for building and installing
			"tif2ps" and "tifdump".
			You can use this together with the "shape"
			configuration management toolkit, which
			will appear in the net soon.
	defs.h	     -- general definitions
	tif.h	     -- TIFF specific definitions
	tif2ps.c     -- The source file containing the main program.
	scantif.c    -- The front end of the converter.
	genps.c	     -- The back end of the converter.
	getopt.c     -- A public domain getopt implementation.
			Only needed for the PC version.
	version.c    -- A source file containing a routine that returns
			the actual version number.
	andy.tif.Z.btoa
		     -- A compressed TIFF file (a small picture of
			the author). Use "atob" and "uncompress"
			to reconstruct the file.
	tif2ps.1     -- The manual page for "tif2ps" and "tifdump"
	
The program has been tested only with TIFF-files generated by a
HP Scanjet up to now.
It was developed on a
	microVAX II running BSD 4.3
and it also runs on
	Sun3 with SunOS 4.0 and on
	IBM PC/AT with MS-DOS 3.20/Microsoft C 5.00.
It should be easy portable to other machines.

For installing "tif2ps" on a UNIX system, you find the installation
instructions in the Makefile. On a PC just type "MAKE MAKEFILE.PC"
(this works with Microsoft "make").

The PC version does only support TIFF files that contain at most
45000 bytes of image data. I assume this is because all image data
are read into main memory with one fread call. Up to now, I was too
lazy to fix that.

Feel free to do any modifications or improvements to the code.
If you do so, please send me your patches. I will try to introduce
your patches into further releases.

Have fun,
	  Andy

---------
(*) PostScript is a trademark of Adobe Systems Incorporated.




SHAR_EOF
if test 2862 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 2862 characters)'
fi
fi
echo shar: "extracting 'Makefile'" '(1056 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
# Makefile for tif2ps
#
# The installation procedure for tif2ps is faily simple.
#
# Where and by whom shall tif2ps and it's manual be installed ?
# (change the following 4 macro definitions if necessary)

INSTALDIR = /usr/local
MANINSTALDIR = /usr/localman/man1
INSTALNAME = bin
INSTALGROUP = bin

#
# If you are on a Motorola 68k based machine (eg. Sun3), replace the
# "CFLAGS" definition by:
#
# CFLAGS = -O -DUNIX -DMOTOROLA

CFLAGS = -O -DUNIX
LDFLAGS = -s

#
# Ready!
# Now save the Makefile and type "make" to build the system and
# or "make install" to build and install it.
#

SOURCE = tif2ps.c scantif.c genps.c
INCLUDE = tif.h defs.h
VERSION = version
OBJECTS = tif2ps.o scantif.o genps.o $(VERSION).o

tif2ps: $(OBJECTS)
	$(CC) -o tif2ps $(LDFLAGS) $(OBJECTS) -lm
	rm -f tifdump
	ln tif2ps tifdump

install:
	install -c -o bin -g bin -m 644 tif2ps.1 $(MANINSTALDIR)
	install -c -o bin -g bin -m 755 tif2ps $(INSTALDIR)
	rm -f $(INSTALDIR)/tifdump
	ln $(INSTALDIR)/tif2ps $(INSTALDIR)/tifdump

$(OBJECTS): $(INCLUDE)

clean :
	rm $(OBJECTS)

SHAR_EOF
if test 1056 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 1056 characters)'
fi
fi
echo shar: "extracting 'defs.h'" '(1056 characters)'
if test -f 'defs.h'
then
	echo shar: "will not over-write existing file 'defs.h'"
else
cat << \SHAR_EOF > 'defs.h'
/*
 * tif2ps/tifdump -- convert TIFF to PostScript
 *
 * written by:
 * Andreas Lampen, TU-Berlin (andy@coma.UUCP)
 *			     (andy@db0tui62.BITNET)
 *
 * Copyright (C) 1988 by the author.
 * Permission is granted to copy and distribute this program
 * without charge, provided this copyright notice is included
 * in the copy.
 * This Software is distributed on an as-is basis. There will be
 * ABSOLUTELY NO WARRANTY for any part of this software to work
 * correct. In no case will the author be liable to you for damages
 * caused by the usage of this software.
 */

/*
 * defs.h -- general type and constant definitions
 * 
 * $Header: defs.h[1.0] Thu Dec 29 20:10:13 1988 andy@coma published $
 */

typedef char           CHAR;
typedef int            INT;
typedef unsigned int   UINT;
typedef short          SHORT;
typedef unsigned short USHORT;
typedef long           LONG;
typedef unsigned long  ULONG;
typedef double         DOUBLE;

#define ERROR -1
#define OK     0

#define VOID   void
#define LOCAL  static
#define STATIC static
#define EXPORT
SHAR_EOF
if test 1056 -ne "`wc -c < 'defs.h'`"
then
	echo shar: "error transmitting 'defs.h'" '(should have been 1056 characters)'
fi
fi
echo shar: "extracting 'tif.h'" '(5243 characters)'
if test -f 'tif.h'
then
	echo shar: "will not over-write existing file 'tif.h'"
else
cat << \SHAR_EOF > 'tif.h'
/*
 * tif2ps/tifdump -- convert TIFF to PostScript
 *
 * written by:
 * Andreas Lampen, TU-Berlin (andy@coma.UUCP)
 *			     (andy@db0tui62.BITNET)
 *
 * Copyright (C) 1988 by the author.
 * Permission is granted to copy and distribute this program
 * without charge, provided this copyright notice is included
 * in the copy.
 * This Software is distributed on an as-is basis. There will be
 * ABSOLUTELY NO WARRANTY for any part of this software to work
 * correct. In no case will the author be liable to you for damages
 * caused by the usage of this software.
 */

/*
 * tif.h -- type and constant definitions
 * 
 * $Header: tif.h[1.0] Thu Dec 29 20:10:15 1988 andy@coma published $
 */

/*
 * installation dependent definitions
 */

#define MAXIFDS 16
#define MAXVAL  128

/*===========================
 * General Types
 *===========================*/

/* Input file descriptor */
typedef struct {
  FILE    *fdes;
  USHORT  order;              /* Byte order */
} DATAFILE;

/*===========================
 * Picture Data Types
 *===========================*/

/* strips */
typedef struct {
  ULONG    byteCount;
  CHAR     *data;
} STRIP;

/* general image data */
typedef struct {
  USHORT subfileType;
  USHORT imWidth;
  USHORT imLength;
  ULONG  rowsPerStrip;		/* may be SHORT -- not implemented */
  USHORT stripsPerImage;	/* number of strips */
  STRIP  *strips;		/* List of pointers to Strips */
  USHORT samplesPerPixel;	/* always 1 -- handle only monochrome picts. */
  USHORT bitsPerSample;		/* should be capable to hold multiple values */
				/* for color pictures */
  USHORT planConf;		/* Planar Configuration */
  USHORT compression;		/* should be capable to hold multiple values */
				/* for color pictures */
  ULONG  gr3Options;
  ULONG  gr4Options;
  USHORT fillOrder;
  USHORT threshholding;
  USHORT cellWidth;
  USHORT cellLength;  
} IMAGE;
}/* photometrics */
typedef struct {
  USHORT minSampleValue;
  USHORT maxSampleValue;
  USHORT photometInterpr;	/* Photometric Interpretation */
  USHORT grayResponseUnit;
  USHORT *grayResponseCurve;	/* Array of grayvalues */
} PHMETRIC;

/* correspondence to the physical world */
typedef struct {
  DOUBLE   xRes;                 /* XResolution */
  DOUBLE   yRes;                 /* YResolution */
  USHORT   resUnit;              /* ResolutionUnit */
  USHORT   orientation;
} PHYS;

/* document context */
typedef struct {
  CHAR     *docName;
  CHAR     *pageName;
  DOUBLE   xPos;		/* XPosition -- lower left corner */
  DOUBLE   yPos;		/* YPosition -- lower left corner */
  DOUBLE   xMax;		/* XMaximum -- upper right corner */
  DOUBLE   yMax;		/* YMaximum -- upper right corner */
  USHORT   pageNo;		/* page number */
  USHORT   noOfPages;		/* total number of pages */
} CONTEXT;

/* a whole picture */
typedef struct {
  IMAGE    image;
  PHMETRIC photoMetric;
  PHYS     physWorld;
  CONTEXT  context;
} PICTURE;
	
/*===========================
 * TIFF Types
 *===========================*/

/* IFD Entry */
typedef struct {
  USHORT   tag;			/* entry Tag */
  USHORT   type;		/* entry type */
  ULONG    length;		/* entry length */
  ULONG    valoffset;		/* value or value offset */
  CHAR     *value;		/* pointer to value */
} ENTRY;

/* Image File Directory (IFD) */
typedef struct {
  USHORT   entrycount;		/* number of entries in IFD */
  ENTRY    *entrylist;		/* list of IFD entries */
  ULONG    nextifd;		/* Offset of next IFD */
} IFD;

/* TIF-file Header */
typedef struct {
  USHORT  byteorder;		/* Byte order "II" or "MM" */
  USHORT  version;		/* TIFF Version (current 42) */
  ULONG   offset;		/* offset of first IFD */
} HEADER;
  
/* general structure */
typedef struct {
  HEADER  header;               /* Header of TIF-file */
  IFD     ifdlist[MAXIFDS];	/* List of IFDs */
} TIFF;

/*==============================
 * constants
 *==============================*/

#define TIFFBYTE     1
#define TIFFASCII    2
#define TIFFSHORT    3
#define TIFFLONG     4
#define TIFFRATIONAL 5

#define INTELTIFF    0x4949
#define MOTOROLATIFF 0x4d4d

/*** Fields ***/

#define SUBFILETYPE        	255
#define IMAGEWIDTH         	256
#define IMAGELENGTH        	257
#define BITSPERSAMPLE      	258
#define COMPRESSION        	259
#define PHOTOMETRICINTERPR	262
#define THRESHHOLDING      	263
#define CELLWIDTH          	264
#define CELLLENGTH         	265
#define FILLORDER          	266
#define DOCUMENTNAME       	269
#define IMAGEDESCRIPTION   	270
#define MAKE               	271
#define MODEL              	272
#define STRIPOFFSETS       	273
#define ORIENTATION        	274
#define SAMPLESPERPIXEL    	277
#define ROWSPERSTRIP       	278
#define STRIPBYTECOUNTS    	279
#define MINSAMPLEVALUE     	280
#define MAXSAMPLEVALUE     	281
#define XRESOLUTION        	282
#define YRESOLUTION        	283
#define PLANARCONFIGURATION	284
#define PAGENAME           	285
#define XPOSITION          	286
#define YPOSITION          	287
#define FREEOFFSETS        	288
#define FREEBYTECOUNTS     	289
#define GRAYRESPONSEUNIT   	290
#define GRAYRESPONSECURVE  	291
#define GROUP3OPTIONS      	292
#define GROUP4OPTIONS      	293
#define RESOLUTIONUNIT     	296
#define PAGENUMBER         	297
#define COLORRESPONSEUNIT  	300
#define COLORRESPONSECURVES	301
SHAR_EOF
if test 5243 -ne "`wc -c < 'tif.h'`"
then
	echo shar: "error transmitting 'tif.h'" '(should have been 5243 characters)'
fi
fi
echo shar: "extracting 'tif2ps.c'" '(5124 characters)'
if test -f 'tif2ps.c'
then
	echo shar: "will not over-write existing file 'tif2ps.c'"
else
cat << \SHAR_EOF > 'tif2ps.c'
/*
 * tif2ps/tifdump -- convert TIFF to PostScript
 *
 * written by:
 * Andreas Lampen, TU-Berlin (andy@coma.UUCP)
 *			     (andy@db0tui62.BITNET)
 *
 * Copyright (C) 1988 by the author.
 * Permission is granted to copy and distribute this program
 * without charge, provided this copyright notice is included
 * in the copy.
 * This Software is distributed on an as-is basis. There will be
 * ABSOLUTELY NO WARRANTY for any part of this software to work
 * correct. In no case will the author be liable to you for damages
 * caused by the usage of this software.
 */

/*
 * tif2ps.c -- main program 
 *
 * $Header: tif2ps.c[1.0] Thu Dec 29 20:11:01 1988 andy@coma published $
 */

#include <stdio.h>
#ifdef MSDOS
#include <string.h>
#include <time.h>
#else
#include <strings.h>
#include <sys/time.h>
#endif
#include <setjmp.h>
#include <signal.h>
#include "defs.h"
#include "tif.h"

extern CHAR *optarg;
extern INT  optind;

CHAR    *progname, *version();

main (ac, av)
     INT   ac;
     CHAR  **av;
{
  INT     getopt(), c, nfiles, i, cleanup();
  VOID    usage(), logerr(), dodump(), genps();
  DOUBLE  xoffset = 0., yoffset= 0., scalefactor = 1., height = 0.;
  DOUBLE  xresfactor, yresfactor, atof();
  PICTURE picts[8]; /* maximal 8 pictures */
  TIFF    tiff;
  jmp_buf env;

#ifdef MSDOS
  if (!strrchr (av[0], '\\')) progname = av[0];
    else progname = strrchr (av[0], '\\') + 1;
#else
  if (!rindex (av[0], '/')) progname = av[0];
    else progname = rindex (av[0], '/') + 1;
#endif

  if (ac < 2)
    {
      usage ();
      exit (-1);
    }

  while ((c = getopt (ac, av, "h:s:vx:y:")) != EOF)
    {
      switch (c)
	{
	case 'h': /* picture height */
	  if (scalefactor != 1.)
	    logerr (progname, "only one of 'h' or 's' can be given");
	  else
	    height = atof (optarg) * 72;
	  break;
	case 's': /* scale factor */
	  if (height != 0.)
	    logerr (progname, "only one of 'h' or 's' can be given");
	  else
	    scalefactor = atof (optarg);
	  break;
	case 'v': /* print current version of this program */
	  printf ("This is %s version %s.\n", av[0], version());
	  exit (0);
	case 'x': /* xposition (in inches) */
	  xoffset = atof (optarg) * 72;
	  break;
	case 'y': /* yposition (in inches) */
	  yoffset = atof (optarg) * 72;
	  break;
	default:
	  usage ();
	  exit (-1);
	}
    }  /* end of command line parsing */

  (VOID) signal (SIGINT, cleanup);

  nfiles = ac - optind;
  for (i = 0; i < nfiles; i++)
    {
      /* (VOID) setjmp (env); --- not used */
      if (scantif (av[i+optind], picts, &tiff) == ERROR)
	{ logerr (progname, "cannot read file"); exit (-1); }
      if (!strcmp (progname, "tifdump"))
	{
	  printf ("This is %s version %s.\n\n", progname, version());
	  dodump (av[i+optind], &tiff);
	  continue;
	}
      /* else do initializations */
      /* a loop through all pictures should be inserted here */

      /* adjust bytecount ???? perhaps not correct */
      /* manages only single strip pictures */
      if (picts[0].image.strips[0].byteCount == 0)
	picts[0].image.strips[0].byteCount = 
	  (picts[0].image.imWidth * picts[0].image.imLength) / 
	    (8 / picts[i].image.bitsPerSample);

      switch (picts[0].physWorld.resUnit)
	{
	case 1: /* special */
	  xresfactor = 1. / picts[0].physWorld.xRes;
	  yresfactor = 1. / picts[0].physWorld.yRes;
	  break;
	case 2: /* inches */
	  xresfactor = 72. / picts[0].physWorld.xRes;
	  yresfactor = 72. / picts[0].physWorld.yRes;
	  break;
	case 3: /* centimetres */
	  xresfactor = 28.3465 / picts[0].physWorld.xRes;
	  yresfactor = 28.3465 / picts[0].physWorld.yRes;
	  break;
	}
      
      if (height != 0.)
	scalefactor = (height / (picts[0].image.imLength * yresfactor));
      
      if (xoffset != 0.)
	picts[0].context.xPos = xoffset;
      if (yoffset != 0.)
	picts[0].context.yPos = yoffset;
      
      picts[0].context.xMax = 
	(picts[0].image.imWidth * xresfactor * scalefactor) +
	  picts[0].context.xPos;
      picts[0].context.yMax = 
	(picts[0].image.imLength * yresfactor * scalefactor) + 
	  picts[0].context.yPos;
      
      genps (av[i+optind], picts);
    }
} /* end of main */

LOCAL INT cleanup ()
{
#ifdef MSDOS
  cprintf ("cleanup...\n");
#else
  fprintf (stderr, "cleanup...\n");
#endif
  exit (-1);
}

LOCAL VOID usage ()
{
  printf ("usage: %s [-h <height>] [-s <scalefactor>]\n", progname);
  printf ("\t\t[-v] [-x <x-offset>] [-y <y-offset>] file1 ...\n");
}

EXPORT VOID logerr (routine, msg)
     CHAR *routine, *msg;
{
#ifdef MSDOS
  cprintf ("%s(%s): %s\n", progname, routine, msg);
#else
  fprintf (stderr, "%s(%s): %s\n", progname, routine, msg);
#endif
}

EXPORT CHAR *date()
{
  LONG seconds, time();
#ifndef MSDOS
  CHAR *asctime();  
#endif

#ifdef MSDOS
  time (&seconds);
  return (ctime (&seconds));
#else 
  seconds = time ((LONG *) 0);
  return (asctime (localtime (&seconds)));
#endif
}

EXPORT CHAR *caller()
{
  STATIC CHAR name[128];
#ifdef MSDOS
  strcpy (name, ""); /* cannot get hostname and login name */
#else
  CHAR *getlogin (), host[128];

  (VOID) gethostname (host, 128);
  (VOID) sprintf (name, "%s@%s\0", getlogin(), host);
#endif
  return (name);
}
SHAR_EOF
if test 5124 -ne "`wc -c < 'tif2ps.c'`"
then
	echo shar: "error transmitting 'tif2ps.c'" '(should have been 5124 characters)'
fi
fi
echo shar: "extracting 'genps.c'" '(3878 characters)'
if test -f 'genps.c'
then
	echo shar: "will not over-write existing file 'genps.c'"
else
cat << \SHAR_EOF > 'genps.c'
/*
 * tif2ps/tifdump -- convert TIFF to PostScript
 *
 * written by:
 * Andreas Lampen, TU-Berlin (andy@coma.UUCP)
 *			     (andy@db0tui62.BITNET)
 *
 * Copyright (C) 1988 by the author.
 * Permission is granted to copy and distribute this program
 * without charge, provided this copyright notice is included
 * in the copy.
 * This Software is distributed on an as-is basis. There will be
 * ABSOLUTELY NO WARRANTY for any part of this software to work
 * correct. In no case will the author be liable to you for damages
 * caused by the usage of this software.
 */

/*
 * genps.c -- generate PostScript output
 * 
 * $Header: genps.c[1.0] Thu Dec 29 20:10:57 1988 andy@coma published $
 */

#include <stdio.h>
#include <math.h>
#include "defs.h"
#include "tif.h"

extern CHAR *progname;
extern USHORT pages;

EXPORT VOID genps (filename, picts)
     CHAR    *filename;
     PICTURE *picts;
{
  USHORT xsamples, ysamples, c1, c2, noOfGrayVals;
  LONG   i;
  CHAR   *version(), *date(), *caller();
  VOID   logerr();

  /* a loop through all pictures should be inserted here */
  
  printf ("%%!PS-Adobe-2.0\n");
  printf ("%%%%Title: %s\n",
	   picts[0].context.docName[0] ? picts[0].context.docName : filename);
  printf ("%%%%Creator: %s %s\n", progname, version());
  printf ("%%%%CreationDate: %s", date());
  printf ("%%%%For: %s\n", caller());
  printf ("%%%%Page: %d of %d\n", 
	   picts[0].context.pageNo, picts[0].context.noOfPages);
  printf ("%%%%BoundingBox: %.2f %.2f %.2f %.2f\n",
	   picts[0].context.xPos, picts[0].context.yPos,
	   picts[0].context.xMax, picts[0].context.yMax);
  printf ("%%%%EndComments\n");

  /* the calculation of a reasonable number of rows should be inserted here */
  printf ("/DataString 2 string def\n");
  printf ("%%%%EndProlog\n");

  printf ("/vmstat save def\n");
  printf ("initgraphics\n");
  printf ("( :: %s/TIFF->PostScript - job starts ::\\n) print flush\n", caller ());
  printf ("( :: printing %s ::\\n) print flush\n", filename);

  /* Image */
  printf ("gsave\n");

  if (picts[0].image.bitsPerSample > 1)
    {
      /* define new grayscale */
      noOfGrayVals = (SHORT) pow ((DOUBLE)2, 
				  (DOUBLE)picts[0].image.bitsPerSample);
      printf ("{ %d mul round cvi\n[ ", noOfGrayVals-1);
      for (i = 0 ; i < noOfGrayVals; i++)
	printf ("%d ", picts[0].photoMetric.grayResponseCurve[i]);
      printf ("]\nexch get %d div 1.0 exch sub } settransfer\n",
	       picts[0].photoMetric.grayResponseCurve[0]);
    }

  printf ("%.2f %.2f translate\n",
	   picts[0].context.xPos, picts[0].context.yPos);
  printf ("%.2f %.2f scale\n", 
	   picts[0].context.xMax - picts[0].context.xPos,
	   picts[0].context.yMax - picts[0].context.yPos);

  /* adjust transformation matrix */

  /* do image data */
  xsamples = (picts[0].image.strips[0].byteCount / picts[0].image.imLength) * 
    (8 / picts[0].image.bitsPerSample);
  ysamples = picts[0].image.imLength;
  printf ("%d %d %d ", 
	   xsamples, ysamples, picts[0].image.bitsPerSample);

  switch (picts[0].physWorld.orientation)
    {
    case 1:
      printf ("[ %d 0 0 %d 0 %d ]\n", xsamples, -ysamples, ysamples);
      break;
    case 4:
      printf ("[ %d 0 0 %d 0 0 ]\n", xsamples, ysamples);
      break;
    default:
      logerr ("genps", "invalid orientation");
      return;
    }

  printf ("{ currentfile DataString readhexstring pop } image \n");
  for (i=0; i < picts[0].image.strips[0].byteCount; i++)
    {
      c1 = (picts[0].image.strips[0].data[i] & 0360) >> 4; /* upper 4 bits */
      c2 = (picts[0].image.strips[0].data[i] & 017); /* lower 4 bits */
      printf ("%c%c", (c1 <= 9) ? (c1+'0') : (c1+'W'),
	                       (c2 <= 9) ? (c2+'0') : (c2+'W'));
    }

  printf ("\ngrestore\n");

  printf ("showpage\n");
  printf ("vmstat restore\n");
  printf ("%%%%Trailer\n");

  printf ("( :: Job finished ::\\n) print flush\n");
}

SHAR_EOF
if test 3878 -ne "`wc -c < 'genps.c'`"
then
	echo shar: "error transmitting 'genps.c'" '(should have been 3878 characters)'
fi
fi
echo shar: "extracting 'andy.tif.Z.btoa'" '(8835 characters)'
if test -f 'andy.tif.Z.btoa'
then
	echo shar: "will not over-write existing file 'andy.tif.Z.btoa'"
else
cat << \SHAR_EOF > 'andy.tif.Z.btoa'
xbtoa Begin
+.\KbP,JA2!.[?E!<*!9!$Hg.L(>4YFD+J[`;foc5$T5GTR_t4%8pF:Eo]an,p/.0OOE/V"YE(CL_,
)e9Igf'`#Mogk<fV7ATBVP+m;IF>mt1u))6ciK)l>#1dZ1L<1-K0Ed.ok#p>3[%4:m#F/0GS,<HfKJ
l^u#-@fomN7]DYb_T!oc&E"e8R%=)%C3M=E%k[P\Mij/V0I!_`K5<*b*3/D+MO0M-:j@LPN#9/6]95
(\[:U,R1Q?(c'l''aGhR.SkU02jhSA<FUl*s258]]+[:^_3#<psJIs")NEUMm`hstm16+KdDpPgY7m
EQfGA@2/<[WJOI$=0gZOp3XNF;Ko7$q"F-LH&,-;9cX8%cPBrMIU,RHBo`qF/o*BBP8_SS>)eoGrJe
WKr?jUnJTnF8-Kkf7BZqQ<J[_"__'lq.XNhEopp<h/MF,L.d@MU57ZXO`fh0CG;@DTkU-%Qm-4aR:r
7?TuEp5@P*mh?]I.P2r0\(0rA'9M_/Y9L']u1+EKBNQlcC12>IfNLpZC'QDk24(QjufQC)3f.1)]:!
:5I&Rr:n7>a9@K,\CF\damMh[ik_WR16G,^i))686^gj)O+fHn@9DWFHAt,-Z-a%[htul(:\(C>oK+
ZNn(O]R\Llm3[SL4mFGm@jMf]JR`bja)Nm3DG,p_8f%+DVXVm!GH]0FG>CWCOl"Yma@=lV&1hQ#&OU
<^Sj0Jqu.pA:rh6q!k&`oop@fS.9CoB[0>Np*Q'"<e,Y&['JIAP=q&?a^6Ll6#',!tF'!:,uQ@hk$D
/>_,?Ghme_+bJFGjcS3"K>I[<S7G@"Mk%K<DYL>\L&/eAR1i1NftuW%I.<RhWYSqo_nl6&XntR+/10
*$]WneQr`\7*g20>tK\ihdk`dUD`j3X,G*Y[HWU1!F@q%ca*2gb]SV`_#(FWs=h;r;;D$:lkULX\_(
A>'>:)i)<_S,@%U`ifBGCar/ol/;'M@8:N-L6HXCMhBen&pVa%3HoS6M;V`IOc85Q]t!nD05f<WEcr
0J'R8=O(M_/j*:ibMs7G-4n2uHB-&UjVS2aNU:q(#oXR-5ei2Bt71Qqa>#u2Y^=@p=Hsf?_?=H41+0
2)QfK"rFn#f9]>'+39S3>3B,oO=Gb6KB]nWD3<Y2JUXlsG7p8(u[gd)@+"\,Yj+9:pqOjLqFnMp17D
[_CiDLh3p7;?'r,-HC,P@00A&q)/pPa8i>?@H,l)U>r>1H)F&Yit.YqZ_,aOmoc`Kgglq?-.HI=Jpc
8%`['TGnaPdVFP>Ye-AMT?r*gcF1YKR^PdB\70MUAt:NmS163j)/8BZk6C6W5$s*^u#_ZN.*)?WBAX
_'f4dp_XnPHnQniu^!kNKL/q)1qf]@A(_<$R,,2pcS"ueOcHj(6]gZc4E4LkmS]Ak+:0nVN3q=`@pM
BLdOlAO3&j3Be7`N`LQH?B)K]^;NnDKiUB6C!mR#pK?,&7/-1FPRVn.ma'Ic(Q+k*G.T(78Ju$OPGn
NkaTX0]-S8fX7q:?s>\VXKn0d9`T+!>Bea\-A('=\n*)2"<bLLfP,ho`n<4_5^?<"`uqP>@)fp<?o4
o8q+!:Ecp]0eG;\RFBpp/f(^MIfM2cT@=kWkZB3*3]!B'fRu&g(S5XZ"In^$#WGD?935.M2t@j6A[Z
9@??2)_Dj)G6-OQDo!jS*,grF=_Z^t]"aIiK+ko%P%36M`Y5lIF;(1FbEcK$cpgT+Vh9V]Zt6H5q8?
n!@p76:P<F;Kg6ks'g3M5dIqTCPs@&!a0CcZi>q6[I%+,XnQsfOfLug0T\<Vo=Pe&r=.bWt`D(3mru
;+9A4:1XR\SofUH_AO<D%Q\q64cA?kG;34KM32fq/9q8%'CFabS=J/]/E=U^I%cP!dV!_6H/drJr?o
bNl?M9QZJED&0p7/sBFZ[TO.fg6u:3f_q1*A`\D!.SI:u5ij!2,B+05FE8Ym5ZHQ)\.Tqb,%Y;*F&^
)JBfuUm)T0@?=bHDTU@+9O>$&q9gfn=8,F6;AH-;qj9hVGV8IUf!kilj._q$1mudV7`Ga7$?]Ot[-m
XSp9\N0rZjt.QLhHZ*FNolpob!lGH\^XfBl*Z.#[3\\M]94\E7Cl>t1^&f>XOqjnVg0N0g.N7I#I($
.Q7t%B:&p`/*L^9Q@$JS':.nB&6`Dq*q_Jl3T1U@XI"=VCuc%@urbgF'f^3<G4I`Ui(o[gg?N&3g>6
VN$0`@)d>d]I&p8)P1nOtccaI]^p5Ju/E.COf;J/L,"X."75HH:*t$;Q$/aC\K2HomMoq*J014A4bB
C>kr>:4]S6IVCQ+(&[n":Q:-o\2K+*KIhiSZ1(o=0k(^=(_Lpme-4,F(Q`Y&JaEl0*BO3?j[R%$R/C
YF?^lS!V-:k;9R/;4I7)JMU0*JHJe<a-Y?c;Y@%SgM3ZYH+g-3:7?`>RR7CnZ=VV<W?3>3c+N1oE]'
U9N>lUP9=E?q1sW<(V]bo!M8gOR?L7f[=!INDg:C>5Tr;!fWr<ll^Fi@@g8*^TgJcmq.B+^Ydmu0T)
8aSJpVspZW+Gu#N8+'kZjdYYY9b=1_bR1eYLdXNXE$g*#%j\(1RiuG$/PDT[h>mr5NU5s["/.\Y#fL
-Jt^9,(6gMQ9k11;':4FepRV%Xok>>TRP0l@=.5E;n7GjI_^!c/dc6VT2D'3ni12h-Sk(^P-Gn1*Ic
uVUo,k%pDGc-XmEneeUA.,2Jr3.!I\ih-[L:\XEIY?!9uu[n;GAm:2)F&aI2SqcL/AgtVO+>_F'?&o
1+=Hq1AcJk!DQ&L@Ql67c:-_^g#dKSCj/i7nHlbPkONE7D0i->*P;bn>)kC:a*fg+j'k>0^-"1D0F2
uZT'o!.'.@P59g(.e*B-dT-?J>'lJbV*MohG/V,eJ+q"2,L#?;5$qCXe-FWEG*/__DcFSrpnVa#%pG
3+R7]Bq,]1]_I-F8nh5!nu1=o*d9sQCH\bSZV@uJICT`0Ge@C@jF)<Osn@=D)3Gfs"Z19&20=38J$M
2R1UpH&Q&9W;Ya-ls7Ci;;1G[p8B:f;p]jO9_cdN"I&+#`$cGHq<ugkkJA2*jJT,&75s#tD;RqL4EU
jKo+WIun<9m%9Bi6Y]LO>rg$h7jKM1A`VAP)*N6N"/C$F:$Kk]Kdd01D(:"pY,@p,W46-*]ckBuP<t
UE0W+,oF.4o#*B?'N,2\*:\R\&s@q1[tH7;)9`mMY_,5uYUrqNHJ5V1e"T&Wj*B)d1BDPn)!Deo1F8
mV6]PRr?,qDULPL7#*0F?+AeZ*opDDW&HBiJi-<Nsl_&]/68SHXJOF[p8efW64)k6=IQ2sLc:a)$9+
7`qnD.7Hqnqd&rFUQV7\=`gK3&R(2E473RHBKJV"c>Rp(pI\*B`s0hL`@<-C!>atH?G#6e0`G-*9r*
5X[FtLOVeG69FsQHfr0SgQu!Kq8/!a6iUMqR=<Gum*S:O4hR6t*:`4fqN2\dn*E[6F2dAR8=&\^5q+
qs!JWHH,!!nep\L<M]di_cF+@d5.k(/ZgYrs>\*icVj)tT3kUfM-<P&+&Spu$<j<KQITC;-KFqk.f:
=!^P]8Q]XYjAU*087f4A<<>NcWCS*-LhRMYP)DS+g5(u3U2>pu@@r>o5ZemejHT-N3TbIJp;Dgp\W]
oK5VSQU0m4YCe64^2GhQedlX;Z0Yu$.nQ3-)M7p-r4JU>@i<d\UY.Z"ONB:%=3+rTR/?J0W(E-YfG%
g"*s;hK,5VL?(,$?$e0.&iG!M+UqhK6S9!fB%iRV/8Xk)2PKsK"7-cj'=p'?V89qAb$4fW?X,sC!Zu
U+:0_@0P3)^M'/4(Lle*q\VUaf-@NCe7@%<P![=P1O--2WonJPHB,dK4$X242k@'3=,+!jj)?7N*X4
!Kl##kTOSSor"PW)<t!EA3h(iAgO&h0=Z"eGAJ:\*aD/qaMu3@ElgBuVl&g*nE)\Hq%P,"^3d4Q[JM
!`$@1*f"?)O.fodR9C6pSiath_H1![Q#Y7U1&:&m-)**l.3R%^EU"-8hDnUZBj$f,E3rT4(7J2qG[X
7AQn>nBQ0:n*Pt???SO5qCr^TCrFF,38M:#`u!?b<b)(u'D/#Rrg5c:%HZ'K<A?_oKL4$%c?a'n(DT
c&S_&''(fYm>="0jnIMc/N!#Z6BK$+I8,iJqtCl15<CXT6_6$pot*CML:a(Q1CZEH3-n:M5PN<IV*\
c=5&NM#9o8,-m$6tLDV\9&qm<[*XaZ;eZj^!$6,;,P4$=;!3cKi$E#;`M\u;`F1!9J=HY$,U6t%n(o
gKnAr2CS-r0B4Pu]W5[jVQ\NU2n/WG/3Hd>quS7o?if\PsQ5LG,eiXI@5#jmb]<qPktjDN@bK[WSH!
Gopc.9+=c:*j\3W(g(^N?fZ3;>,80&f;g'^,)MGGqGUX:[oH9tTGr'Je#8^ALM,5M>Z`s,kM][O&NF
BtDgN1_fbtuiaE,NLAkD_6U7k,O,pK):X>]o(4r##j)HR3t@__M(Q8fqj6?^?pQhdL%;qHk_EN@%AH
cpK97%1Dt,D0T.ZL9`/Ms#k&b&P&b./lgXJXD7mUNMCOL:]]HHD@H\9!_DcZpnh%gS&)E,p\fYXe:K
DdKje%ng=]#/YmG+Gr^#Z.Q213$VcP"SJ"!l885u/5DHOLS4Xm;FX!O-['0S505$n7nj=/e&0r)0iB
\a5@RIPJN\#fh)kpJ^l:3rMRLBp_nsZu:iC>cc7hNjRNT-CBU04B[:H-BA*ef5nX&)u8VN0=H*g3)"
Z'"r/?XkUsSWS((\j@I,8$+jHfii;DM'n@"&/$=9N\M]le597m@4Ut4'RL^JJ2anK#dFss$,Tq,KP.
P<MMQ5(7#HfD<AR/K\]@'"#+-=-Zq)]lSI![l'H83K<FE>kDn4%2MH%5u!a28()p9!>cBU)S"hcqe2
A/>4DF]hN@:0LD\am,.#Z-]_9728O$b_8+q%^.pVk:X1O=>9CRF%4jO]7Zk."&H_d,S$'nY('CO)u'
Y@`Q69'Z,K5Jek.kRH.;@-[#d^+fpf1iHLugKr1A[J`gcL1=I/+QPac;FVYt6XPq!5<(dfX9Cn<%qU
HUpE^K])IHm'u_I6ia,oJb6?HSsJ\7'c!K<UGIT?I=(q-YMY,B2LZ_=Mr!3'&+^=Fn"m*TPQnho&*j
EA/UN2>E:Y9It'ZfMhq5Xa[Rmg;Q5]nAkJ$9Et4)+e3u-LE#X5)FTO&0:.K]FN3&/5nK8VhrGb8AS4
kQ,$9+7&#!J8LH]%O+^M`<-,[28U,#/Y<aN/JALbg\,#'n'_/$DA?o1hPS$:0]77,22\hcmj)+8)C_
?TTX!=&m)S"B-QRVbA&piLWDo9s$$V4^h0fplA=(O;.397*0r[cBG:#@!^U?I7^s?0oP]UcSh35c-9
\p'$h;_JZ.AbMMc3<BHhtKR2P2+R\tYC\hA4/0l5?*ls8:$aPeA_U+%Md)N`?%fMn^7?fu]c210orO
dfu"AaJ(d.ihT4bRk;B/hpCc<t[^j>(g.^![JO)f*#pl>.a(nV&(/)@Q2^_Y\!KrBY.5.&qGo:IZ]G
4jb)qIY6*X:;+ksB$0+AB,ans!7O/s`,6/-ea$-Oe-0$B,_A<f_]QdVeP[gXN6YtN`0"16=S9u-grd
(t=%E1\(;u=\,;:EB_oAuGM^sLqe4ag>ek+?(LbM>0K2mhm[KU-]n8WlLAoeA4d=lDX)`#rK)l":=]
NDS`$<SjiC`ENSB_"[GO_c$>6XqaIfK/%W#p:f\`Z9!rf)#NpE.&rDK$WO>]YlQXI;LS?V'FY5Lm50
hlaIe3Ym@4d*!$$ns-[fZ#=B,@K=T(?ACJSAEnF([e1^qK,C"J7&oe0q8D4M,j:]S^,9E3'(sZhFS@
%(m@7QFXLM)eNdLA?rS;U$`h'WgWp.[tr*S8kn:DSeQ>f>A7EkmKm!<L*c\:&VYJZ#o4;T2(P2Do,5
N?#-]Q"de_*:,/0>i;$@X*'"9NAT%K?.n;6)A8XpQ;tY`p2LXm/EtCt&q3UH8UG$3)PT+?)Qk%&G`F
bSh8pV+)M6iS^b\:%*F9"+$/ePQ*ReN(+8E2Ki0,]eqJ49*+4*ua^'r,cYm@OA6[`Vnj$>OIrT/U8!
7WfMPDDU65&VRX_TM6`f$.$BZm6DIh'gRm[GBGmn@I^-XEe^ChDF7Mma8+eP!R3;p"+N)OlkVS*,OI
LoJRfN;CRB1j<"Ir?+^3rK*edlF:,E$W+8OU*Rf^o.%hV;j-8Ieic$>[g8b76!L\/!A`hA:FbEKR`T
QA;Y#':p!4pk9jYB@Gn1_Z'-_.'sA(Kfk%O$86!Uaq[R%?\h4<Y\<l`9O^@-c0\7N^4U$b_Q>akduC
1NJdV8];/jrWB1D($+8A?4;HYD]RF0/j]K7)Y!_Jhe*la-Ar@XkZD[Wlf7B@_QS#m6fPPA5&Tf!)!e
^'-0n;;Y,+!%K"V%7@ijGrPVV`&D,$<j0G+pO)j#lTJMQ5ZC=u@QMuD=1IIQb3FT#Gaisptb%e90A1
tU]?bA#D%X;iUK3!op`/?af2`R:@<5Gqu]B5I2+e#:590oW*`%Hek7eJb'Q<W_(q8i5u8nF1u`oSc>
$0gcLSBHl4@#e>dO.dYdn@`2F#e/@^&9n/5&+bT_eoZLc7LB8gB@SM:<*Ml81^;2,66H!?Z(N#d6qn
)H5hsRI!jTO!)4lUYRS@rW'm&gKCm2RsuNV@=OiJm[OLK@9$0/2.Pdi>L_XkFaXa+*<Lpc1S4JH[bk
-QZo-8Jj,OaIMuVBe%A;7sXc*a;`M/].\q@8Zr0;S:O>3QO'F#/qt#6[<1oAn$j/8*/ST'M]WP.fcc
th7h=X6MD7ElSX[3k.m;p9'U<!Wa<'<f6bjt"D6koQ59;!P*boB2AeQeN:HE#6!$NN0#gW<ZPj\6bP
4[*?gsQ*dC+k:4i/-CPH%:pE>91q(X6#*3[g7MGr?DgR/,H4^Dk]>oSDPH:g!<b$#8=to%U_1fJBkt
uTVGP/NGJlu1MP"J1ee2SeRu<t]Q+VON3PeW1*Nu_KCT$q7Y3J`"+1)3Ph9$;EJS!7r.BV9=;i"*HV
OOU"faSs@%&8\$Z(9O9)&E.UrLdFa[Mq)FK!n"(Vun>aFj\THd?:ZW'NE:&%p"H1M-L.`_F;%n8&.6
e>%Y"E73^"0"CM3LtA&*1FP_;3X!e5iuVU=*co[F\ML&_8m'k$3+E]_d\.s0@=@,FA,70j,f85u!&<
J2f6oD.=g7Vi"jQ*o=:]H<3Vh\>@YSAO93C'.Bm=@1\I=R`;$dc&,%5a):_(c:`^$)BP%!qk:ZrSt#
Th$2LgFC:4b9iA"bm#m(gNbiE,WV^298,Xd)Ban.'Yt.BDU+!Vo75PhcaMPbbFG$Sp'0qQ6>aM&GrN
#@1pLK)$5M-&mVDTTG8a'PP]#1EgnF@O*FKkrQucPNZ'G^A;e?95^>ipZ4H,>(D+\O5U>qD"`6bK]+
Rq:@R./EaEh+4igM6-6l#9H!S$_R""_@n>nHu1&*)XjH;5Wb8#AioI#6pg!<pIe!A=,_80C3E,CoK=
9[%2hnA2Me+!Oig#jWoPE"!PISpqjq,=69oL#;7@V*nhVqb0n_)Li!S1h<Vta!A<%5uA&[-!#[fdUW
G!K/3Ueems3-(fQeBBG#AjMG<UaCk,]2LV=X?peABY-fPJ;1)C<lOn]m,DL^`E0a#b]hdX2+rrFg1#
+V%oC!lpa?(#,.1^UR7$*tELM)+`,5D;LR8El@C?0l=h%ld:Fj(AS"ip')NJA<`$#6b/ln5M77(:"!
Bn<$M.ASTt1$l?):6<m!co0Y@08E#N;iCI7\8VRX6N+h8fDJI!.7>N\?`o(hNJuP]/1^bTW/VMW3!'
C90-t^0gJP[?8idsm\T_/.O"BZ\%8Ocs,Y2qW@7EeS%*`Ih"Ac(jUC+4m^\8]>@TcVkGq.ZE:d/ijT
^fhGN%6$`ioO.(O@%#Z+jRL9]7uTg7!hu-.D:443,n#89'5=2uZB#>fEE#GB@Ci1@?8NUaZ!;[_Iut
bs8&&JP5U7sOK]=c5keff.OD5:7h8d8iJlLb>&hrilBG@'"q#&R$ku&6+VBH;c_m^U%A#&jZ:FI.,Y
uIFCC7\gbOYPkTb`9U(,$*\]>`J+o[;j%mR4MZt8Et:-Y4[45P%3F3MC5)m.ajsu2oPb?gsX/D@H(,
X&IO9T-8ilSO;/C;+qb6u=!n_Oa'0Vh;55\RIOGX7LXkp@m6khH%coAn%\HnjL3<Y[#)klN*G<_V]/
V*mT8?.q(U?FE;.=P&c\E[]0mLj:RshY5B'p77`8h(Z6:Ga,<'?CpH-%tp.WIj7gPqA+"GP"`nCjgO
]7WBYK2G)U$Fi=SR=1hM6u?(CSq:u6-&m*n5@)N[Um3XC.g6A.du#iR=]17[0K)t.(,;'mY$9nL6_Q
)cjD*A4Y!E*&,-P'"]@U,(N11+UYRUYp!>G_LA0^Z.'%2V`iCUgP^.]SUDP3]&G9Z:%,F0Gep>]:(Y
5i#/k2e&h%tGn*6,t09fIg?>jE@M82?=;,W@$V2r@!Vg&#jhJaO#b0R"_>Y/]+)eb`(3h63`HlR'-Z
S9TJ.G+"q0F`*"_pn0n\lp^U#&McbQ]1LVc:.L@n4+jNJu7o!LXPlA^1!p!I)BS1/57LDqZ0Y%@r,S
.qV@hsk#^p`B9,>o2JXaiqN*"t0,VPhe0*E,?W(l)gZe7Kl!'4LK5P"hoI-h)l=.[jp;E^2Lj#p.`f
K7P35B;!YSJsds2j^Q/tP`Mr?X3?^=MSm)?(icm_OV_2V-sT3A5b)$f8lSN&;2uL5!jWc-F+*tRZ=u
4R't:CI
xbtoa End N 6931 1b13 E a8 S cff7c R 33ef638d
SHAR_EOF
if test 8835 -ne "`wc -c < 'andy.tif.Z.btoa'`"
then
	echo shar: "error transmitting 'andy.tif.Z.btoa'" '(should have been 8835 characters)'
fi
fi
exit 0
#	End of shell archive

-- 
Andreas Lampen, TU Berlin
UUCP:   andy@coma (unido!coma!andy)
BITNET: andy@db0tui62