[comp.sources.misc] v06i049: Source Code for TIFF->SunRaster

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

Posting-number: Volume 6, Issue 49
Submitted-by: nobody@cs.buffalo.edu
Archive-name: tif2rast

[Be nice if this came with a description in the place of this remark.  ++bsa]

# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# tiff.mail README.tif2rast Makefile.rast defs.h tif2rast.c scantif.c genrast.c getopt.c version.c tif2rast.1

echo x - tiff.mail
sed -e 's/^X//' > "tiff.mail" << '//E*O*F tiff.mail//'
XHi, dear,
X
X	I am sorry that nobody sent me a single mail except you.
X
X	BUT fortunately, I finally found some nice source codes from the
X   'comp.sources.misc' newgroup.  If you subscribe that newsgroup, try to
X   find 2 lovely programs posted by Andreas Lampen on Feb. 1.  Those 2 
X   programs are used to convert TIFF file to PostScript file.  It will
X   give enough information for reading TIFF file.  I actually modified
X   his programs and rewrote 2 modules to get my TIFF->Sunraster converter
X   works for my university.
X
X        Following is my own copy, please feel free to make modification
X   to fit your own usage.
X
X        BTW, I will soon graduate with a master's degree in Computer 
X   Science.  If you happen to know any graphics/image-processing related
X   job openings in your company, please let me know.  Thanks in advance.
X
X
X   ====================================================================
X
X    wu@cs.buffalo.edu
X    wu@sunybcs.bitnet
X    ..!{boulder,decvax,rutgers}!sunybcs!wu
X
//E*O*F tiff.mail//

echo x - README.tif2rast
sed -e 's/^X//' > "README.tif2rast" << '//E*O*F README.tif2rast//'
XThis is version 1.0 of tif2rast/tifdump, a program that converts
XTIFF-files to Sun Raster files.
X
XThe tiff processing part is written by:
X                  Andreas Lampen
X		  Tech. Univ. Berlin, FR 5-6
X		  Franklinstr. 28/29
X		  D-1000 Berlin 10, West Germany
X		  Tel: +49-30-314-73496
X		  E-mail: andy@coma.uucp (from US: pyramid!tub!coma!andy) or
X			  andy@db0tui62.bitnet
X
Xand the Sun Raster proccessing part is written by
X                  William W.C. Wu
X                  University Computing Services
X                  State University of New York at Buffalo
X                  E-Mail: wu@sunybcs.bitnet
X                          wu@cs.buffalo.edu
X                          ..!{boulder,decvax,rutgers}!sunybcs!wu
X
X-------------------------------------------------------------------
XCopyright (C) 1988 by the author.
XPermission is granted to copy and distribute this program
Xwithout charge, provided this copyright notice is included
Xin the copy.
XThis Software is distributed on an as-is basis. There will be
XABSOLUTELY NO WARRANTY for any part of this software to work
Xcorrect. In no case will the author be liable to you for damages
Xcaused by the usage of this software.
X-------------------------------------------------------------------
X
XThis Distribution contains the files
X	README.tif2rast -- The file you are actually reading.
X	Makefile.rast   -- The Makefile for building and installing
X			   the programs "tif2rast" and "tifdump"
X	defs.h	     	-- general definitions
X	tif.h	     	-- TIFF specific definitions
X	tif2rast.c     	-- The source file containing the main program.
X	scantif.c   	-- The front end of the converter.
X	genrast.c	-- The back end of the converter.
X	getopt.c     	-- A public domain getopt implementation.
X				Only needed for the PC version.
X	version.c    	-- A source file containing a routine that returns
X			   the actual version number.
X	tif2rast.1      -- The manual page for "tif2rast" and "tifdump"
X	
XThe program has been tested only with TIFF-files generated by a
XHP Scanjet up to now.
XIt was developed on a
X	Sun3 with SunOS 4.0 and on
XIt should be easy portable to other machines.
X
XFeel free to do any modifications or improvements to the code.
XIf you do so, please send me your patches. I will try to introduce
Xyour patches into further releases.
X
XHave fun,
X	  William W.C. Wu
X
X
X
X
X
X
//E*O*F README.tif2rast//

echo x - Makefile.rast
sed -e 's/^X//' > "Makefile.rast" << '//E*O*F Makefile.rast//'
X#
X# Makefile for tif2rast
X#
X# The installation procedure for tif2rast is faily simple.
X#
X# Where and by whom shall tif2rast and it's manual be installed ?
X# (change the following 4 macro definitions if necessary)
X
XINSTALDIR = /usr/local
XMANINSTALDIR = /usr/localman/man1
XINSTALNAME = bin
XINSTALGROUP = bin
X
X#
X# If you are on a Motorola 68k based machine (eg. Sun3), replace the
X# "CFLAGS" definition by:
X#
XCFLAGS = -O -DUNIX -DMOTOROLA
X
X# CFLAGS = -O -DUNIX
XLDFLAGS = -s
X
X#
X# Ready!
X# Now save the Makefile and type "make" to build the system and
X# or "make install" to build and install it.
X#
X
XSOURCE = tif2rast.c scantif.c genrast.c
XINCLUDE = tif.h defs.h
XVERSION = version
XOBJECTS = tif2rast.o scantif.o genrast.o $(VERSION).o
X
Xtif2rast: $(OBJECTS)
X	$(CC) -o tif2rast $(LDFLAGS) $(OBJECTS) -lm
X	rm -f tifdump
X	ln tif2rast tifdump
X
X$(OBJECTS): $(INCLUDE)
X
Xclean :
X	rm $(OBJECTS)
X
X
X
//E*O*F Makefile.rast//

echo x - defs.h
sed -e 's/^X//' > "defs.h" << '//E*O*F defs.h//'
X/*
X * tif2ps/tifdump -- convert TIFF to PostScript
X *
X * written by:
X * Andreas Lampen, TU-Berlin (andy@coma.UUCP)
X *			     (andy@db0tui62.BITNET)
X *
X * Copyright (C) 1988 by the author.
X * Permission is granted to copy and distribute this program
X * without charge, provided this copyright notice is included
X * in the copy.
X * This Software is distributed on an as-is basis. There will be
X * ABSOLUTELY NO WARRANTY for any part of this software to work
X * correct. In no case will the author be liable to you for damages
X * caused by the usage of this software.
X */
X
X/*
X * defs.h -- general type and constant definitions
X * 
X * $Header: defs.h[1.0] Thu Dec 29 20:10:13 1988 andy@coma published $
X */
X
Xtypedef char           CHAR;
Xtypedef int            INT;
Xtypedef unsigned int   UINT;
Xtypedef short          SHORT;
Xtypedef unsigned short USHORT;
Xtypedef long           LONG;
Xtypedef unsigned long  ULONG;
Xtypedef double         DOUBLE;
X
X#define ERROR -1
X#define OK     0
X
X#define VOID   void
X#define LOCAL  static
X#define STATIC static
X#define EXPORT
//E*O*F defs.h//

echo x - tif2rast.c
sed -e 's/^X//' > "tif2rast.c" << '//E*O*F tif2rast.c//'
X
X#include <stdio.h>
X#include <strings.h>
X#include <sys/time.h>
X#include <setjmp.h>
X#include <signal.h>
X#include "defs.h"
X#include "tif.h"
X
Xextern CHAR *optarg;
Xextern INT  optind;
X
XCHAR    *progname, *version();
X
Xmain (ac, av)
X     INT   ac;
X     CHAR  **av;
X{
X  INT     getopt(), c, nfiles, i, cleanup();
X  VOID    usage(), logerr(), dodump(), genps();
X  DOUBLE  xoffset = 0., yoffset= 0., scalefactor = 1., height = 0.;
X  DOUBLE  xresfactor, yresfactor, atof();
X  PICTURE picts[8]; /* maximal 8 pictures */
X  TIFF    tiff;
X  jmp_buf env;
X
X  if (!rindex (av[0], '/')) progname = av[0];
X    else progname = rindex (av[0], '/') + 1;
X
X  if (ac < 2)
X    {
X      usage ();
X      exit (-1);
X    }
X
X  while ((c = getopt (ac, av, "v:")) != EOF) {
X      switch (c) {
X      case 'v': /* print current version of this program */
X	printf ("This is %s version %s.\n", av[0], version());
X	exit (0);
X      default:
X	usage ();
X	exit (-1);
X      }
X   }  /* end of command line parsing */
X
X  (VOID) signal (SIGINT, cleanup);
X
X  nfiles = ac - optind;
X  for (i = 0; i < nfiles; i++)
X    {
X      if (scantif (av[i+optind], picts, &tiff) == ERROR)
X	{ logerr (progname, "cannot read file"); exit (-1); }
X      if (!strcmp (progname, "tifdump"))
X	{
X	  printf ("This is %s version %s.\n\n", progname, version());
X	  dodump (av[i+optind], &tiff);
X	  continue;
X	}
X      /* else do initializations */
X      /* a loop through all pictures should be inserted here */
X
X      /* adjust bytecount ???? perhaps not correct */
X      /* manages only single strip pictures */
X      if (picts[0].image.strips[0].byteCount == 0)
X	picts[0].image.strips[0].byteCount = 
X	  (picts[0].image.imWidth * picts[0].image.imLength) / 
X	    (8 / picts[i].image.bitsPerSample);
X
X      switch (picts[0].physWorld.resUnit)
X	{
X	case 1: /* special */
X	  xresfactor = 1. / picts[0].physWorld.xRes;
X	  yresfactor = 1. / picts[0].physWorld.yRes;
X	  break;
X	case 2: /* inches */
X	  xresfactor = 72. / picts[0].physWorld.xRes;
X	  yresfactor = 72. / picts[0].physWorld.yRes;
X	  break;
X	case 3: /* centimetres */
X	  xresfactor = 28.3465 / picts[0].physWorld.xRes;
X	  yresfactor = 28.3465 / picts[0].physWorld.yRes;
X	  break;
X	}
X      
X      if (height != 0.)
X	scalefactor = (height / (picts[0].image.imLength * yresfactor));
X      
X      if (xoffset != 0.)
X	picts[0].context.xPos = xoffset;
X      if (yoffset != 0.)
X	picts[0].context.yPos = yoffset;
X      
X      picts[0].context.xMax = 
X	(picts[0].image.imWidth * xresfactor * scalefactor) +
X	  picts[0].context.xPos;
X      picts[0].context.yMax = 
X	(picts[0].image.imLength * yresfactor * scalefactor) + 
X	  picts[0].context.yPos;
X      
X      genrast (av[i+optind], picts);
X    }
X} /* end of main */
X
XLOCAL INT cleanup ()
X{
X#ifdef MSDOS
X  cprintf ("cleanup...\n");
X#else
X  fprintf (stderr, "cleanup...\n");
X#endif
X  exit (-1);
X}
X
XLOCAL VOID usage ()
X{
X  printf ("usage: %s [-h <height>] [-s <scalefactor>]\n", progname);
X  printf ("\t\t[-v] [-x <x-offset>] [-y <y-offset>] file1 ...\n");
X}
X
XEXPORT VOID logerr (routine, msg)
X     CHAR *routine, *msg;
X{
X#ifdef MSDOS
X  cprintf ("%s(%s): %s\n", progname, routine, msg);
X#else
X  fprintf (stderr, "%s(%s): %s\n", progname, routine, msg);
X#endif
X}
X
XEXPORT CHAR *date()
X{
X  LONG seconds, time();
X#ifndef MSDOS
X  CHAR *asctime();  
X#endif
X
X#ifdef MSDOS
X  time (&seconds);
X  return (ctime (&seconds));
X#else 
X  seconds = time ((LONG *) 0);
X  return (asctime (localtime (&seconds)));
X#endif
X}
X
XEXPORT CHAR *caller()
X{
X  STATIC CHAR name[128];
X#ifdef MSDOS
X  strcpy (name, ""); /* cannot get hostname and login name */
X#else
X  CHAR *getlogin (), host[128];
X
X  (VOID) gethostname (host, 128);
X  (VOID) sprintf (name, "%s@%s\0", getlogin(), host);
X#endif
X  return (name);
X}
//E*O*F tif2rast.c//

echo x - scantif.c
sed -e 's/^X//' > "scantif.c" << '//E*O*F scantif.c//'
X/*
X * tif2ps/tifdump -- convert TIFF to PostScript
X *
X * written by:
X * Andreas Lampen, TU-Berlin (andy@coma.UUCP)
X *			     (andy@db0tui62.BITNET)
X *
X * Copyright (C) 1988 by the author.
X * Permission is granted to copy and distribute this program
X * without charge, provided this copyright notice is included
X * in the copy.
X * This Software is distributed on an as-is basis. There will be
X * ABSOLUTELY NO WARRANTY for any part of this software to work
X * correct. In no case will the author be liable to you for damages
X * caused by the usage of this software.
X */
X
X/*
X * scantif.c -- read tif-file
X *
X * $Header: scantif.c[1.0] Thu Dec 29 20:10:59 1988 andy@coma published $
X */
X
X#include <stdio.h>
X#include "defs.h"
X#include "tif.h"
X
XSTATIC IMAGE nullimage = {0, 0, 0, -1L, 0, 0L, 1, 1, 0, 1, 0L, 0L, 1, 1, 0, 0};
XSTATIC PHMETRIC nullphmetric = { 0, 1, 0, 0, 0 };
XSTATIC PHYS nullphys = { 0., 0., 2, 1 };
XSTATIC CONTEXT nullcontext = { '\0', '\0', 0., 0., 0., 0., 1, 1 };
X
X#define FIELDSBASE 255
XCHAR *fields[] = {
X  "SubfileType        ",	/* 255  (ff) */
X  "ImageWidth         ",	/* 256 (100) */
X  "ImageLength        ",	/* 257 (101) */
X  "BitsPerSample      ",	/* 258 (102) */
X  "Compression        ",	/* 259 (103) */
X  "                   ",	/* 260 (104) unused */
X  "                   ",	/* 261 (105) unused */
X  "PhotometricInterpr.",	/* 262 (106) */
X  "Threshholding      ",	/* 263 (107) */
X  "CellWidth          ",	/* 264 (108) */
X  "CellLength         ",	/* 265 (109) */
X  "FillOrder          ",	/* 266 (10a) */
X  "                   ",	/* 267 (10b) unused */
X  "                   ",	/* 268 (10c) unused */
X  "DocumentName       ",	/* 269 (10d) */
X  "ImageDescription   ",	/* 270 (10e) */
X  "Make               ",	/* 271 (10f) */
X  "Model              ",	/* 272 (110) */
X  "StripOffsets       ",	/* 273 (111) */
X  "Orientation        ",	/* 274 (112) */
X  "                   ",	/* 275 (113) unused */
X  "                   ",	/* 276 (114) unused */
X  "SamplesPerPixel    ",        /* 277 (115) */
X  "RowsPerStrip       ",	/* 278 (116) */
X  "StripByteCounts    ",	/* 279 (117) */
X  "MinSampleValue     ",	/* 280 (118) */
X  "MaxSampleValue     ",	/* 281 (119) */
X  "XResolution        ",	/* 282 (11a) */
X  "YResolution        ",	/* 283 (11b) */
X  "PlanarConfiguration",        /* 284 (11c) */
X  "PageName           ",	/* 285 (11d) */
X  "XPosition          ",	/* 286 (11e) */
X  "YPosition          ",	/* 287 (11f) */
X  "FreeOffsets        ",	/* 288 (120) */
X  "FreeByteCounts     ",	/* 289 (121) */
X  "GrayResponseUnit   ",	/* 290 (122) */
X  "GrayResponseCurve  ",	/* 291 (123) */
X  "Group3Options      ",	/* 292 (124) */
X  "Group4Options      ",	/* 293 (125) */
X  "                   ",	/* 294 (126) unused */
X  "                   ",	/* 295 (127) unused */
X  "ResolutionUnit     ",	/* 296 (128) */
X  "PageNumber         ",	/* 297 (129) */
X  "                   ",	/* 298 (12a) unused */
X  "                   ",	/* 299 (12b) unused */
X  "ColorResponseUnit  ",	/* 300 (12c) */
X  "ColorResponseCurves",	/* 301 (12d) */
X};
X
XCHAR *malloc();
XVOID logerr();
X
XEXPORT INT scantif (filename, pics, tiff)
X     CHAR    *filename;
X     PICTURE *pics;  /* array of picture buffers -- out */
X     TIFF    *tiff;
X{
X  DATAFILE infile;
X  INT      ifdcount=0;
X  VOID     EnterPicValue(), GetImageData();
X  USHORT   entrycount, wordtemp, nrofentries;
X  ULONG    location, dblwordtemp;
X  ENTRY    *entry, stripOffsets, stripByteCounts;
X
X#ifdef MSDOS
X  if ((infile.fdes = fopen (filename, "rb")) == NULL)
X#else
X  if ((infile.fdes = fopen (filename, "r")) == NULL)
X#endif
X    { logerr ("scantif", "cannot open input file"); return ERROR; }
X
X  /* read the first word, and determine the byte order
X   */
X  infile.order = INTELTIFF;
X  if (GtData (&infile, 0L, 1, TIFFSHORT, (char *)&wordtemp))
X    { logerr ("scantif", "can't read first word"); goto error; }
X  infile.order = wordtemp;
X
X  /* read the 8-byte header
X   */
X  if (GtTiffHdr (&infile, &(tiff->header)))
X    { logerr ("scantif", "can't read header"); goto error; }
X
X  location = tiff->header.offset;
X 		
X  /* loop through the IFD's
X   */
X  do {
X    /* if ifd location is 0, quit
X     */
X    if (location == 0L)
X      {
X	(VOID) fclose (infile.fdes);
X	return OK;
X      }
X	
X    /* read the number of entries
X     */
X    if (GtData (&infile, location, 1, TIFFSHORT, (char *)&nrofentries))
X      { logerr ("scantif", "can't read # of entries"); goto error; }
X    tiff->ifdlist[ifdcount].entrycount = nrofentries;
X
X    if ((tiff->ifdlist[ifdcount].entrylist = 
X	 (ENTRY *)malloc (nrofentries * sizeof (ENTRY))) == (ENTRY *)0)
X      { logerr ("scantif", "not enough memory"); goto error; }
X
X    location += 2;
X
X    pics[ifdcount].image = nullimage;
X    pics[ifdcount].photoMetric = nullphmetric;
X    pics[ifdcount].physWorld = nullphys;
X    pics[ifdcount].context = nullcontext;
X    
X    /* loop through the entries
X     */
X    for (entrycount = 0; entrycount < nrofentries; entrycount++) {
X      /* read the entry, and dump it
X       */
X      entry = &(tiff->ifdlist[ifdcount].entrylist[entrycount]);
X      if (GtTiffEntry (&infile, location, entry))
X	goto error;
X      /* adjust the current location
X       */
X      location += (sizeof (ENTRY) - sizeof (CHAR *));
X
X      if (entry->tag == STRIPOFFSETS)
X	stripOffsets = *entry;
X      else
X	{
X	  if (entry->tag == STRIPBYTECOUNTS)
X	    stripByteCounts = *entry;
X	  else
X	    EnterPicValue (entry, &(pics[ifdcount]));
X	}
X    } /* end of entry loop */
X
X    /* read the data */
X    GetImageData (&infile, &(pics[ifdcount].image), &stripOffsets, &stripByteCounts);
X
X    /* read the location of the next ifd */
X    if (GtData(&infile, location, 1, TIFFLONG, (char *)&dblwordtemp))
X      { logerr ("scantif", "can't read location of the next ifd"); goto error;}
X    location = dblwordtemp;
X    ifdcount++;
X
X  } while (1); /* end of ifd loop */
X
X error: ;
X  (VOID) fclose (infile.fdes);
X  return ERROR;
X}
X
XEXPORT VOID dodump (filename, tiff)
X     CHAR *filename;
X     TIFF *tiff;
X{
X  INT    ifdcount=0, i;
X  USHORT maxitems, item;
X  IFD    *ifdptr;
X  CHAR   *bufptr;
X
X  printf ("File: %s\n", filename);
X
X  /* print header */
X  switch (tiff->header.byteorder)
X    {
X    case INTELTIFF:
X      printf ("    Byte Order: INTELTIFF\n");
X      break;
X    case MOTOROLATIFF:
X      printf ("    Byte Order: MOTOROLATIFF\n");
X      break;
X    default:
X      printf ("    Byte Order: ***illegal***\n");
X    }
X  printf ("    Version: %d\n", tiff->header.version);
X  printf ("    Ifd Offset: %d\n", tiff->header.offset);
X
X  /* print IFDs */
X  do {
X    ifdptr = &(tiff->ifdlist[ifdcount]);
X    printf ("    IFD Number %d\n", ifdcount);
X    printf ("\tNumber of entries: %d\n", ifdptr->entrycount);
X    for (i=0; i<ifdptr->entrycount; i++)
X      {
X	printf ("\t%s (%d) type=%d length=%3d val=",
X		(ifdptr->entrylist[i].tag >= 32768) ? "-------------------" :
X		fields[ifdptr->entrylist[i].tag-FIELDSBASE],
X		ifdptr->entrylist[i].tag, ifdptr->entrylist[i].type,
X		ifdptr->entrylist[i].length);
X
X	bufptr = ifdptr->entrylist[i].value;
X	maxitems = ifdptr->entrylist[i].length;
X	switch (ifdptr->entrylist[i].type)
X	  {
X	  case TIFFBYTE:
X	    for (item = 0; item < maxitems; item++)
X	      printf ("%x", (unsigned)(*bufptr++));
X	    printf ("\n");
X	    break;
X	  case TIFFASCII:
X	    if (maxitems == 0)
X	      break;
X	    printf ("%.*s\n", maxitems, bufptr);
X	    break;
X	  case TIFFSHORT:
X	    for (item = 0; item < maxitems; item++, bufptr += 2)
X	      printf ("%u ", *((USHORT *)bufptr));
X	    printf ("\n");
X	    break;
X	  case TIFFLONG:
X	    for (item = 0; item < maxitems; item++, bufptr += 4)
X	      printf ("%lu ", *((ULONG *)bufptr));
X	    printf ("\n");
X	    break;
X	  case TIFFRATIONAL:
X	    for (item = 0; item < maxitems; item++) {
X	      printf ("% lu ", *((ULONG *)bufptr));
X	      bufptr += 4;
X	      printf ("%lu ", *((ULONG *)bufptr));
X	      bufptr += 4;
X	    }
X	    printf ("\n");
X	    break;
X	  default:
X	    logerr ("dodump", "internal error");
X	    break;
X	  }
X      }
X  }
X  while (tiff->ifdlist[ifdcount++].nextifd);
X  printf ("Ok -- that's all ! Bye Bye...\n");
X}
X
X/**********************************************************************/
X
X/*
X/* The following six routiones (swap, swaw, GtTiffSizeof, GtData,
X/* GtTiffHdr, GtTiffEntry) are not originally written by me.
X/* I copied them in a slightli modified form from a "tiffdump"
X/* program, I received from Microsoft. There was no copyright
X/* notice so I think the code is in the public domain.
X/*       Andreas Lampen
X/**/
X
X/* swap bytes -- overlapping arrays are handled properly
X */
X
XLOCAL VOID swab (lpSrc, lpDst, nbytes)
X     register CHAR *lpSrc, *lpDst;	/* assumed to be word-aligned */
X     USHORT        nbytes;              /* assumed to be even */
X{
X  register USHORT words;
X  union {
X    CHAR c[2];
X    USHORT w;
X  } wrd;
X  
X  words = nbytes/2;
X  
X  if (lpDst <= lpSrc || lpDst >= lpSrc + nbytes) {
X    for (; words--; lpSrc += 2) {
X      wrd.w = *(USHORT *)lpSrc;
X      *lpDst++ = *(CHAR *)(wrd.c + 1);	/* W2 doesn't like wrd.c[1] */
X      *lpDst++ = *(CHAR *)(wrd.c);
X    }
X  }
X  else {		/* we'll have to go backward */
X    lpSrc += nbytes - sizeof(USHORT);
X    lpDst += nbytes - 1;
X    for (; words--; lpSrc -= 2) {
X      wrd.w = *(USHORT *)lpSrc;
X      *lpDst-- = *(CHAR *)(wrd.c);
X      *lpDst-- = *(CHAR *)(wrd.c + 1);
X    }
X  }
X}
X
X/* swap words -- overlapping ranges are handled properly
X */
XLOCAL VOID swaw (lpSrc, lpDst, nbytes)
X     register CHAR *lpSrc, *lpDst;	/* assumed to be word-aligned */
X     USHORT  	   nbytes;	       	/* assumed to be multiple of 4 */
X{
X  register USHORT dwords;
X  union {
X    CHAR c[4];
X    ULONG dw;
X  } dwrd;
X  
X  dwords = nbytes/4;
X  
X  if (lpDst <= lpSrc || lpDst >= lpSrc + nbytes) {
X    for (; dwords--; lpSrc += 4) {
X      dwrd.dw = *(ULONG *)lpSrc;
X      *lpDst++ = *(CHAR *)(dwrd.c + 3);
X      *lpDst++ = *(CHAR *)(dwrd.c + 2);
X      *lpDst++ = *(CHAR *)(dwrd.c + 1);
X      *lpDst++ = *(CHAR *)(dwrd.c);
X    }
X  }
X  else {		/* we'll have to go backward */
X    lpSrc += nbytes - sizeof(ULONG);
X    lpDst += nbytes - 1;
X    for (; dwords--; lpSrc -= 4) {
X      dwrd.dw = *(ULONG *)lpSrc;
X      *lpDst-- = *(CHAR *)(dwrd.c);
X      *lpDst-- = *(CHAR *)(dwrd.c + 1);
X      *lpDst-- = *(CHAR *)(dwrd.c + 2);
X      *lpDst-- = *(CHAR *)(dwrd.c + 3);
X    }
X  }
X}
X
XLOCAL INT GtTiffSizeof (n, p)
X     USHORT n;	/* TIFFBYTE or ... */
X     USHORT *p;	/* output */
X{
X  SHORT err = OK;
X  
X  switch (n) {
X  case TIFFBYTE:
X  case TIFFASCII:
X    *p = 1;
X    break;
X  case TIFFSHORT:
X    *p = 2;
X    break;
X  case TIFFLONG:
X    *p = 4;
X    break;
X  case TIFFRATIONAL:
X    *p = 8;
X    break;
X  default:
X    *p = 1;
X    err = ERROR;
X    break;
X  }
X  return err;
X}
X
X/* get data -- handles file/table and byte-order problems
X * 64K max
X */
XLOCAL INT GtData (pInfile, pos, n, dtype, lpData)
X     DATAFILE *pInfile; /* data location - open file or locked-down table */
X     ULONG  pos;       /* file/table position, with respect to its beginning */
X     USHORT n;	       /* number of data elements to read */
X     USHORT dtype;     /* data type: TIFFSHORT, etc */
X     CHAR   *lpData;   /* where to put the data */
X{
X  INT    err;
X  USHORT tsize, BytesToRead;
X
X  /* read the data
X   */
X  if (err = GtTiffSizeof (dtype, &tsize))
X    return err;
X
X  BytesToRead = tsize * n;
X  if (err = fseek (pInfile->fdes, (long) pos, 0))
X    { logerr ("GtData", "fseek error"); return ERROR; }
X
X  if ((fread (lpData, 1, (INT)BytesToRead, pInfile->fdes)) == 0)
X    { logerr ("GtData", "fread error"); return ERROR; }
X
X  /* change the byte order, if necessary
X   */
X#ifdef MOTOROLA
X  if (pInfile->order == INTELTIFF) {
X#else
X  if (pInfile->order == MOTOROLATIFF) {
X#endif
X    if (dtype == TIFFSHORT)
X      swab (lpData, lpData, BytesToRead);
X    else if (dtype == TIFFLONG)
X      swaw (lpData, lpData, BytesToRead);
X    else if (dtype == TIFFRATIONAL)
X      swaw (lpData, lpData, BytesToRead);
X  }
X
X  return OK;
X}
X  
X/* get TIFF 8-byte header
X * currently only probably portable.  depends somewhat on compiler's 
X * structure organization.
X */
XLOCAL INT GtTiffHdr (pInfile, pHdr)
X     DATAFILE *pInfile;
X     HEADER *pHdr;
X{
X  SHORT err;
X  
X  /* get the first 2 words
X   */
X  if (err = GtData (pInfile, (ULONG) 0, 2, TIFFSHORT, (CHAR *)&pHdr->byteorder))
X    { logerr ("GtTiffHdr", "A"); return err; }
X  
X  /* get the double word (IFD offset)
X   */
X  if (err = GtData (pInfile, (ULONG)4, 1, TIFFLONG, (CHAR *)&pHdr->offset))
X    { logerr ("GtTiffHdr", "B"); return err; }
X
X  return OK;
X}
X
X/* get TIFF directory entry
X */
XLOCAL INT GtTiffEntry (pInfile, EntryOffset, pDe)
X     DATAFILE	*pInfile;
X     ULONG	EntryOffset;
X     ENTRY	*pDe;
X{
X  SHORT  err;
X  USHORT tsize, BytesToRead, maxitems;
X  ULONG  valpos;
X  
X  /* get the 2 words beginning with deTag
X   */
X  if (err = GtData (pInfile, EntryOffset, 2, TIFFSHORT, (CHAR *)&pDe->tag))
X    return err;
X
X  /* get the 2 dwords, beginning with deLength
X   */
X  if (err = GtData (pInfile, EntryOffset + 4L, 2, TIFFLONG,(CHAR *)&pDe->length))
X    return err;
X
X  /* get value
X   */
X  if (err = GtTiffSizeof (pDe->type, &tsize))
X    return err;
X
X  if ((BytesToRead = tsize * pDe->length) == 0)
X    return OK; /* no need to read data */
X
X  if ((pDe->value = malloc (BytesToRead)) == (CHAR *)0)
X    { logerr ("GtTiffEntry", "not enough memory"); return err; }
X
X  maxitems = (USHORT)(pDe->length);
X  /* careful here: we can't just use valoffset to grab data out of, since
X   * may already have been byte-reversed!
X   */
X  if (BytesToRead <= 4)
X    valpos = EntryOffset + 8L;	/* valoffset starts on byte 8, wit de */
X  else
X    valpos = pDe->valoffset;
X  if (err = GtData (pInfile, valpos, maxitems, pDe->type, pDe->value))
X    return err;
X
X  return OK;
X}
X
XLOCAL VOID EnterPicValue (entry, picture)
X     ENTRY   *entry;
X     PICTURE *picture;
X{
X  CHAR *bufptr;
X  ULONG num, denom;
X  SHORT i;
X
X  switch (entry->tag)
X    {
X    case SUBFILETYPE:
X      picture->image.subfileType = *((USHORT *)entry->value);
X      break;
X    case IMAGEWIDTH:
X      picture->image.imWidth = *(USHORT *)entry->value;
X      break;
X    case IMAGELENGTH:
X      picture->image.imLength = *(USHORT *)entry->value;
X      break;
X    case ROWSPERSTRIP:
X      picture->image.rowsPerStrip = *(ULONG *)entry->value;
X      break;
X    case SAMPLESPERPIXEL:
X      /* ignored */
X      break;
X    case BITSPERSAMPLE:
X      picture->image.bitsPerSample = *(USHORT *)entry->value;
X      break;
X    case PLANARCONFIGURATION:
X      picture->image.planConf = *(USHORT *)entry->value;
X      break;
X    case COMPRESSION:
X      picture->image.compression = *(USHORT *)entry->value;
X      break;
X    case GROUP3OPTIONS:
X      picture->image.gr3Options = *(ULONG *)entry->value;
X      break;
X    case GROUP4OPTIONS:
X      picture->image.gr4Options = *(ULONG *)entry->value;
X      break;
X    case FILLORDER:
X      picture->image.fillOrder = *(USHORT *)entry->value;
X      break;
X    case THRESHHOLDING:
X      picture->image.threshholding = *(USHORT *)entry->value;
X      break;
X    case CELLWIDTH:
X      picture->image.cellWidth = *(USHORT *)entry->value;
X      break;
X    case CELLLENGTH:
X      picture->image.cellLength = *(USHORT *)entry->value;
X      break;
X    case MINSAMPLEVALUE:
X      picture->photoMetric.minSampleValue = *(USHORT *)entry->value;
X      break;
X    case MAXSAMPLEVALUE:
X      picture->photoMetric.maxSampleValue = *(USHORT *)entry->value;
X      break;
X    case PHOTOMETRICINTERPR:
X      picture->photoMetric.photometInterpr = *(USHORT *)entry->value;
X      break;
X    case GRAYRESPONSEUNIT:
X      picture->photoMetric.grayResponseUnit = *(USHORT *)entry->value;
X      break;
X    case GRAYRESPONSECURVE:
X      bufptr = entry->value;
X      picture->photoMetric.grayResponseCurve = 
X	(USHORT *)malloc ((UINT)(entry->length+1) * sizeof (USHORT)); 
X      for (i=0; i < entry->length; i++, bufptr += 2)
X	picture->photoMetric.grayResponseCurve[i] = *(USHORT *)bufptr;
X      picture->photoMetric.grayResponseCurve[entry->length] = -1;
X      break;
X    case XRESOLUTION:
X      num = *(ULONG *)entry->value;
X      bufptr = entry->value+4;
X      denom = *(ULONG *)bufptr;
X      picture->physWorld.xRes = (DOUBLE)num/(DOUBLE)denom;
X      break;
X    case YRESOLUTION:
X      num = *(ULONG *)entry->value;
X      bufptr = entry->value+4;
X      denom = *(ULONG *)bufptr;
X      picture->physWorld.yRes = (DOUBLE)num/(DOUBLE)denom;
X      break;
X    case RESOLUTIONUNIT:
X      picture->physWorld.resUnit = *(USHORT *)entry->value;
X      break;
X    case ORIENTATION:
X      picture->physWorld.orientation = *(USHORT *)entry->value;
X      break;
X    case DOCUMENTNAME:
X      picture->context.docName = (CHAR *) entry->value;
X      break;
X    case PAGENAME:
X      picture->context.pageName = (CHAR *) entry->value;
X      break;
X    case XPOSITION:
X      num = *(ULONG *)entry->value;
X      bufptr = entry->value+4;
X      denom = *(ULONG *)bufptr;
X      picture->context.xPos = (DOUBLE)num/(DOUBLE)denom;
X      break;
X    case YPOSITION:
X      num = *(ULONG *)entry->value;
X      bufptr = entry->value+4;
X      denom = *(ULONG *)bufptr;
X      picture->context.yPos = (DOUBLE)num/(DOUBLE)denom;
X      break;
X    case PAGENUMBER:
X      picture->context.pageNo = *(USHORT *)entry->value;
X      bufptr = entry->value+2;
X      picture->context.noOfPages = *(USHORT *)bufptr;
X      break;
X    }
X}
X
XLOCAL VOID GetImageData (infile, image, stripOffsets, stripByteCounts)
X     DATAFILE *infile;
X     IMAGE    *image;
X     ENTRY    *stripOffsets, *stripByteCounts;
X{
X  ULONG offset;
X
X  if (stripOffsets->length != 1)
X    { logerr ("GetImageData", "cannot handle multiple strips"); return; }
X
X  if ((image->strips = (STRIP *)malloc (2 * sizeof (STRIP))) == (STRIP *)0)
X    { logerr ("GetImageData", "not enough memory"); return; }
X
X  image->strips[0].byteCount = *(ULONG *)stripByteCounts->value;
X  offset = *(ULONG *)stripOffsets->value;
X
X  if (fseek (infile->fdes, (LONG) offset, 0) == ERROR)
X    { logerr ("GetImageData", "fseek error"); return; }
X
X  if ((image->strips[0].data = 
X       malloc ((UINT)image->strips[0].byteCount)) == (CHAR *)0)
X    { logerr ("GetImageData", "not enough memory"); return; }
X
X  if (fread (image->strips[0].data, sizeof (CHAR),
X	     (INT)image->strips[0].byteCount, infile->fdes) == 0)
X    { logerr ("GetImageData", "fread error"); return; }
X
X  image->strips[1].byteCount = 0;
X  image->strips[1].data = (char *)0;
X}
//E*O*F scantif.c//

echo x - genrast.c
sed -e 's/^X//' > "genrast.c" << '//E*O*F genrast.c//'
X
X#include <rasterfile.h>
X#include <stdio.h>
X#include "defs.h"
X#include "tif.h"
X
Xstruct rasterfile ras;
X
Xint bytes_per_row = 0;
X
Xgenrast(filename, picts)
X     char    *filename;
X     PICTURE *picts;
X{
X  int i;
X
X  /* calculate raster header and swap bytes */
X  bytes_per_row = (int) (picts[0].image.imWidth / 8);
X  ras.ras_magic = RAS_MAGIC;
X  ras.ras_width = picts[0].image.imWidth;
X  ras.ras_height = picts[0].image.imLength;
X  ras.ras_depth = 1;
X  ras.ras_length = (bytes_per_row * picts[0].image.imLength);
X  ras.ras_type = 1;
X  ras.ras_maptype = 0;
X  ras.ras_maplength = 0;
X  
X  /* write out rasterfile header */
X  fwrite((char *) &ras,sizeof(struct rasterfile),1,stdout);
X  for (i = 0; i < picts[0].image.strips[0].byteCount; i++) 
X    printf("%c", picts[0].image.strips[0].data[i]);
X}
X
X
//E*O*F genrast.c//

echo x - getopt.c
sed -e 's/^X//' > "getopt.c" << '//E*O*F getopt.c//'
X/*
X *	I got this off net.sources from Henry Spencer.
X *	It is a public domain getopt(3) like in System V.
X *
X *	I made some minor modifications while porting it to MS-DOS.
X *		andy@coma
X */
X#include <stdio.h>
X#include <string.h>
X
X#define	ARGCH    (int)':'
X#define BADCH	 (int)'?'
X#define EMSG	 ""
X#define	ENDARGS  "--"
X
X/*
X * get option letter from argument vector
X */
Xint	optind = 1,		/* index into parent argv vector */
X	optopt;			/* character checked for validity */
Xchar	*optarg;		/* argument associated with option */
X
X#define tell(s)	fputs(*nargv,stderr);fputs(s,stderr); \
X		(void)fputc(optopt,stderr);(void)fputc('\n',stderr); \
X                return(BADCH);
X
Xint getopt(nargc,nargv,ostr)
Xint	nargc;
Xchar	**nargv,
X	*ostr;
X{
X	static char	*place = EMSG;	/* option letter processing */
X	register char	*oli;		/* option letter list index */
X
X	if(!*place) {			/* update scanning pointer */
X		if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
X		if (*place == '-') {	/* found "--" */
X			++optind;
X			return(EOF);
X		}
X	}				/* option letter okay? */
X	if ((optopt = (int)*place++) == ARGCH || !(oli = strchr (ostr,optopt))) {
X		if(!*place) ++optind;
X		tell(": illegal option -- ");
X	}
X	if (*++oli != ARGCH) {		/* don't need argument */
X		optarg = NULL;
X		if (!*place) ++optind;
X	}
X	else {				/* need an argument */
X		if (*place) optarg = place;	/* no white space */
X		else if (nargc <= ++optind) {	/* no arg */
X			place = EMSG;
X			tell(": option requires an argument -- ");
X		}
X	 	else optarg = nargv[optind];	/* white space */
X		place = EMSG;
X		++optind;
X	}
X	return(optopt);			/* dump back option letter */
X}
//E*O*F getopt.c//

echo x - version.c
sed -e 's/^X//' > "version.c" << '//E*O*F version.c//'
X#include "defs.h"
XCHAR *version () {
X  STATIC CHAR ConfID[] =  "1.0 (Sun Feb 12 21:55:10 1989 by wu@sunybcs)";
X  return ConfID;
X}
//E*O*F version.c//

echo x - tif2rast.1
sed -e 's/^X//' > "tif2rast.1" << '//E*O*F tif2rast.1//'
X...
X... tif2rast/tifdump -- convert TIFF to Sun raster
X...
X... written by:
X... Andreas Lampen, TU-Berlin (andy@coma.UUCP)
X...			     (andy@db0tui62.BITNET)
X... William W.C. Wu, State University of New York at Buffalo
X...                  (wu@sunybcs.bitnet)
X...                  (wu@cs.buffalo.edu)
X...
X... Copyright (C) 1988 by the author.
X... Permission is granted to copy and distribute this program
X... without charge, provided this copyright notice is included
X... in the copy.
X... This Software is distributed on an as-is basis. There will be
X... ABSOLUTELY NO WARRANTY for any part of this software to work
X... correct. In no case will the author be liable to you for damages
X... caused by the usage of this software.
X...
X.TH TIF2RAST 1
X.SH NAME
Xtif2Rast, tifdump \- convert TIFF files to Sun Raster
X.SH SYNOPSIS
X.B tif2rast
X.RB [ \-h
X.IR height ]
X.RB [ \-s ]
X.IR scalefactor ]
X.RB [ \-v ]
X.RB [ \-x
X.IR x-offset ]
X.RB [ \-y
X.IR y-offset ]
Xfile1 ...
X.LP
X.B tifdump 
X.RB [ \-v ]
Xfile1 ...
X.SH DESCRIPTION
X\fITif2rast\fR converts a TIFF file to Sun Raster file, and writes the result
Xto standard output.
X\fITif2rast\fR recognizes the following options:
X.TP
X.BI \-v
Xprints the version identification of \fItif2rast\fR.
X.LP
X\fITifdump\fR produces a human readable dump of the given TIFF-files.
XThe result is written to standard output.
X.SH BUGS
XThis version of \fItif2rast\fR has not been tested very extensively yet.
XSo don't be too angry if it produces core dumps or incorrect Sun Raster
Xfiles.
XIn that case, please drop a short error report to the author.
X.br
X.PP
XData compression is not yet supported.
X.PP
X.SH AUTHOR 1
XAndreas Lampen, TU Berlin
X.sp
X.ta 0.7i 
XUUCP:	unido!coma!andy
X.br
XBITNET:	andy@db0tui62
X.PP
X.SH AUTHOR 2
XWilliam W.C. Wu, State University of New York at Buffalo
X.sp
X.ta 0.7i 
XUUCP:	..!{boulder,decvax,rutgers}!sunybcs!wu
X.br
XBITNET:	wu@sunybcs.bitnet
X.br
XINTERNET: wu@cs.buffalo.edu
//E*O*F tif2rast.1//

exit 0