#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  ImageHeader.h
#	  Makefile.xim
#	  README.xim
#	  RLAHeader.h
#	  alcols.c
#	  declarations.h
#	  gstoxim.c
#	  gstoxim.n
#	  quantizim.c
#	  quantizim.n
#	  rgbtoxim.c
#	  rgbtoxim.n
#	  rlatoxim.c
#	  rlatoxim.n
#	  rletoxim.c
#	  runlen.c
#	  smoothim.c
#	  smoothim.n
#	  xim.c
#	  xim.n
#	  xim.shar.bld
#
sed 's/^X//' << 'SHAR_EOF' > ImageHeader.h &&
X/*  Author: Philip R. Thompson
X*   Address:  phils@athena.mit.edu, 9-526 
X*   Note:  size of header should be 1024 (1K) bytes.
X*   $Header: ImageHeader.h,v 1.2 89/02/13 09:01:36 phils Locked $
X*   $Date: 89/02/13 09:01:36 $
X*   $Source: /mit/phils/utils/RCS/ImageHeader.h,v $
X*/
X
X#define IMAGE_VERSION    3
X
Xtypedef struct ImageHeader {
X    char file_version[8];   /* header version */
X    char header_size[8];    /* Size of file header in bytes  */
X    char image_width[8];    /* Width of the raster image */
X    char image_height[8];   /* Height of the raster imgage */
X    char num_colors[8];     /* Actual number of entries in c_map */
X    char num_channels[8];   /* 0 or 1 = pixmap, 3 = RG&B buffers */
X    char num_pictures[8];   /* Number of pictures in file */
X    char alpha_channel[4];  /* Alpha channel flag */
X    char runlength[4];      /* Runlength encoded flag */
X    char author[48];        /* Name of who made it */
X    char date[32];          /* Date and time image was made */
X    char program[16];       /* Program that created this file */
X    char comment[96];       /* other viewing info. for this image */
X    unsigned char c_map[256][3]; /* RGB values of the pixmap indices */
X} ImageHeader;
X
X
X/* Note:
X* - All data are in chars so as to maintain easily portability
X*   across machines and some human readability.
X* - Images may be stored as pixmaps or in seperate channels, such as
X*   red, green, blue data.
X* - An optional alpha channel is seperate and is found after every
X*   num_channels of data.
X* - Pixmaps, red, green, blue, alpha and other channel data are stored
X*   sequentially after the header.
X* - If num_channels = 1 or 0, a pixmap is assumed and up to num_colors
X*   of colormap in the header are used.
X*/
X
X/*** end ImageHeader.h ***/
SHAR_EOF
chmod 0666 ImageHeader.h || echo "restore of ImageHeader.h fails"
sed 's/^X//' << 'SHAR_EOF' > Makefile.xim &&
X#
X#  @(#) Makefile 1.16   Delta'd: 17:10:56 4/3/90   Mike Lijewski, CNSF
X#
X
XCC = cc
X
X# if you're on a SYSV system, add -DSYSV to CFLAGS.
X# if you trust your optimizer, add -O.
X# if your compiler cannot deal with signed char's add -DNO_SIGNED_CHAR.
X
X#CFLAGS = -DSYSV 
X#CFLAGS = -DBSD -D_BSD -O
XDESTDIR = /usr/local/src/xim
XHDRS = ImageHeader.h RLAHeader.h declarations.h
XLIBES = -lX11 -lm
XMAN = rlatoxim.n rgbtoxim.n gstoxim.n xim.n quantizim.n smoothim.n
XPROGRAMS = quantizim runlen smoothim xim rlatoxim rgbtoxim gstoxim rletoxim
XSRC = runlen.c smoothim.c xim.c rlatoxim.c rgbtoxim.c gstoxim.c\
X      quantizim.c alcols.c rletoxim.c
X
Xall: $(PROGRAMS)
X
Xtar: $(SRC) $(HDRS) $(MAN) Makefile README
X	$@ cf xim.tar $(SRC) $(HDRS) $(MAN) Makefile README
X
Xinstall: strip $(PROGRAMS)
X	mv $(PROGRAMS) $(DESTDIR)
X
Xstrip: $(PROGRAMS)
X	$@ $(PROGRAMS)
X
Xquantizim: quantizim.c alcols.c
X	$(CC) $(CFLAGS) -o $@ $@.c alcols.c $(LIBES)
X
Xxim: xim.c declarations.h
X	$(CC) $(CFLAGS) -o $@ $@.c $(LIBES)
X
Xdepend:
X	makedepend -- $(CFLAGS) -- $(SRC)
X
X# DO NOT DELETE THIS LINE -- make depend depends on it.
X
Xrunlen.o: /usr/include/stdio.h /usr/include/sccs.h /usr/include/strings.h
Xrunlen.o: /usr/include/NLchar.h /usr/include/sys/NLchar.h ImageHeader.h
Xsmoothim.o: /usr/include/stdio.h /usr/include/sccs.h /usr/include/strings.h
Xsmoothim.o: /usr/include/NLchar.h /usr/include/sys/NLchar.h ImageHeader.h
Xxim.o: /usr/include/X11/Xos.h /usr/include/sys/types.h /usr/include/sccs.h
Xxim.o: /usr/include/sys/DOPTIONS.h /usr/include/strings.h
Xxim.o: /usr/include/NLchar.h /usr/include/sys/NLchar.h
Xxim.o: /usr/include/sys/file.h /usr/include/unistd.h /usr/include/sys/fcntl.h
Xxim.o: /usr/include/sys/time.h /usr/include/X11/Xlib.h /usr/include/X11/X.h
Xxim.o: /usr/include/X11/Xutil.h /usr/include/X11/cursorfont.h
Xxim.o: /usr/include/stdio.h ImageHeader.h declarations.h
Xrlatoxim.o: /usr/include/stdio.h /usr/include/sccs.h /usr/include/strings.h
Xrlatoxim.o: /usr/include/NLchar.h /usr/include/sys/NLchar.h ImageHeader.h
Xrlatoxim.o: RLAHeader.h
Xrgbtoxim.o: /usr/include/stdio.h /usr/include/sccs.h /usr/include/strings.h
Xrgbtoxim.o: /usr/include/NLchar.h /usr/include/sys/NLchar.h
Xrgbtoxim.o: /usr/include/sys/file.h /usr/include/unistd.h
Xrgbtoxim.o: /usr/include/sys/types.h /usr/include/sys/DOPTIONS.h
Xrgbtoxim.o: /usr/include/sys/fcntl.h ImageHeader.h
Xgstoxim.o: /usr/include/stdio.h /usr/include/sccs.h /usr/include/strings.h
Xgstoxim.o: /usr/include/NLchar.h /usr/include/sys/NLchar.h
Xgstoxim.o: /usr/include/sys/file.h /usr/include/unistd.h
Xgstoxim.o: /usr/include/sys/types.h /usr/include/sys/DOPTIONS.h
Xgstoxim.o: /usr/include/sys/fcntl.h ImageHeader.h
Xquantizim.o: /usr/include/stdio.h /usr/include/sccs.h /usr/include/strings.h
Xquantizim.o: /usr/include/NLchar.h /usr/include/sys/NLchar.h ImageHeader.h
Xalcols.o: /usr/include/stdio.h /usr/include/sccs.h /usr/include/sys/types.h
Xalcols.o: /usr/include/sys/DOPTIONS.h
SHAR_EOF
chmod 0666 Makefile.xim || echo "restore of Makefile.xim fails"
sed 's/^X//' << 'SHAR_EOF' > README.xim &&
XThis is the README file for the xim package as distributed by
Xmjlx@eagle.cnsf.cornell.edu.  It is similar but not identical to the xim
Xpackage as distributed by Philip R. Thompson (phils@athena.mit.edu).
XIn particular, I have left out some programs which I never use.
X
XContents of this distribution:
X
XREADME		- you're reading it.
Xxim.c		- X display code; only slightly modified version of
X		  the same code as distributed by (phils@athena.mit.edu).
Xxim.n		- man page for xim.
Xrlatoxim.c	- filter used in displaying WaveFront Technologies
X		  RLA files under xim.
Xrlatoxim.n	- man page for rlatoxim.
Xrbgtoxim.c	- filter used in displaying a a straight rgb raster
X		  with xim.
Xrgbtoxim.n	- man page for rbgtoxim.
Xgstoxim.c	- a probably limited-use filter used for taking three
X		  grayscale rasters, assumed to be red, green and
X		  blue and displaying them with xim.
Xgstoxim.n	- man page for gstoxim.
Xquantizim.c	- program for quantizing 24 bit/pixel images down to
X		  8 bits or less.
Xquantizim.n	- man page for quantizim.
Xsmoothim.c	- program for smoothing out and reducing noise in
X		  24 bit images.
Xsmoothim.n	- man page for smoothim.
Xrunlen.c	- converts xim image to simple runlength format.
XImageHeader.h	- header file for xim format.
XRLAHeader.h	- header file for RLA format.
X
XTo make all of these programs, simply type `make'.
SHAR_EOF
chmod 0666 README.xim || echo "restore of README.xim fails"
sed 's/^X//' << 'SHAR_EOF' > RLAHeader.h &&
X/***********************************************************************
X*
X*    @(#) RLAHeader.h 1.1   Delta'd: 10:37:07 7/10/89   Mike Liejwski, CNSF
X*
X*    RLAHeader.h -  this header describes the format of Wavefront
X*                  Technologies, Inc. .rla as described in their
X*                  Technical Memo # 860605.
X*
X*    Michael Lijewski
X*    Cornell National Supercomputer Facility
X*    Cornell University
X*    Ithaca, NY  14850
X*    Internet: mjlx@cornellf.tn.cornell.edu Bitnet: mjlx@cornellf.bitnet
X*
X*
X*    Wavefront .rla file format:
X*
X*    -------------
X*    |    file   |    740 bytes (struct RLA_Header)
X*    |   header  |
X*    -------------
X*    |   offset  |    4 * active_y_res bytes
X*    |    table  |
X*    -------------
X*    |   encoded |
X*    |   channel |    variable length
X*    |    data   |
X*    -------------
X*
X*    offset table:  this table provides the location in the file for the
X*                   start of the data for each scanline.  The offset is
X*                   from the beginning of the file and is determined using
X*                   "ftell".  There is one entry for each scanline of the
X*                   active window.  In xim lingo, this means there is one
X*                   entry for each of the "height" rows of the image.
X*
X*    encoded image data:  the channel data for the image is multiplexed
X*                         into the file so that all the channel data for
X*                         each scanline appears sequentially in the file.
X*
X*    each encoded record appears in the file in the form:
X*    --------------------------------
X*    | length | encoded data string|
X*    -------------------------------
X*    where the length is a 2-byte integer giving the length of the
X*    encoded data string in bytes.  There is one record for each of the
X*    channels for each scanline.  The encoded data string consists of
X*    both unencoded data runs and encoded data runs.
X*
X*    unencoded data run:
X*    --------------------------------------------
X*    | count | (-count) bytes of unencoded data |
X*    --------------------------------------------
X*    where count is negative.  Hence a negative count indicates an
X*    unencoded data run.
X*
X*    encoded data run:
X*    -----------------
X*    | count | value |
X*    -----------------
X*    where the value is repeated (count+1) times.
X*
X************************************************************************/
X
X#ifndef _RLAHeader_H
X#define _RLAHeader_H
X
Xtypedef struct{
X short left,
X       right,
X       bottom,
X       top;
X} WINDOW_S;
X
Xtypedef struct{
X  WINDOW_S window;  /* stored image boundary */
X  WINDOW_S active_window;  /* non-zero area boundary */
X  short frame;  /* frame number */
X  short storage_type;  /* byte or word data */
X  short num_chan;  /* number of image channels */
X  short num_matte;  /* number of matte channels */
X  short num_aux;  /* number of aux channels */
X  short aux_mask;  /* aux channel type mask */
X  char gamma[16];  /* image storage gamma */
X  char red_pri[24];  /* image red primary chromaticity */
X  char green_pri[24];  /* image green primary chromaticity */
X  char blue_pri[24];  /* image blue primary chromaticity */
X  char white_pt[24];  /* image white point chromaticity */
X  long job_num;  /* job number */
X  char name[128];  /* original file name */
X  char desc[128];  /* file description */
X  char program[64];  /* creating program name */
X  char machine[32];  /* creating machine name */
X  char user[32];  /* creating user */
X  char date[20];  /* creation date */
X  char aspect[32];  /* image aspect type */
X  char chan[32];  /* image color space type */
X  char space[128];  /* unused expansion space */
X} RLA_Header;
X   
X#endif
SHAR_EOF
chmod 0666 RLAHeader.h || echo "restore of RLAHeader.h fails"
sed 's/^X//' << 'SHAR_EOF' > alcols.c &&
X/*
X*    @(#) alcols.c 1.2   Delta'd: 13:25:22 1/10/90   Mike Lijewski, CNSF
X*
X*    Copyright (c) 1988  University of Southern California
X*
X*    USC Information Sciences Institute
X*    4676 Admiralty Way
X*    Marina del Rey, California 90292
X*    (vaxa.isi.edu  in  pub/util/X)
X*
X*    This  software  and its  documentation  may be used,  copied,
X*    modified,  and  distributed  for  any  purpose  without  fee,
X*    provided:
X*    --  The above copyright notice appears in all copies.
X*    --  This disclaimer appears in all source code copies.
X*    --  The names of ISI and USC are not used in advertising or
X*        publicity  pertaining  to distribution  of the software
X*        without prior specific written permission from ISI.
X*    ISI provides this software freely as a public service.  It is
X*    NOT a commercial product,  and therefore is not subject to an
X*    an implied  warranty  of  merchantability  or  fitness  for a
X*    particular purpose.  ISI provides it as is, without warranty.
X*
X*    3-16-88     Paul Raveling
X*    4-17-88     Philip Thompson (phils@athena.mit.edu)
X*                    - cleaned up code, made readable.
X*    2-19-89         - use less memory w/ smaller Color struct.
X*/
X
X#include <stdio.h>
X#include <sys/types.h>
X
Xextern int      error();
Xextern int      printf();
Xextern void     free();
X
X#define MAXRGB      255		/* Maximum RGB component value */
X#define MAXDEPTH    8		/* Maximum depth for color cube tree */
X#define MAXNODES    50		/* Maximum number of color tree nodes,
X				 * expressed as fraction of pixmap size */
Xtypedef unsigned char byte;
X
Xtypedef struct _Color
X{
X	byte            pixel;
X	byte            red, green, blue;
X}               Color;
X
Xtypedef struct node
X{				/* Node of color cube description tree */
X	struct node    *parent;	/* Pointer to parent node */
X	struct node    *off;	/* Pointer to 1st offspring node */
X	struct node    *sibling;/* Pointer to next sibling */
X	u_short         minred;	/* Minimum red coordinate */
X	u_short         maxred;	/* Maximum red coordinate */
X	u_short         mingreen;	/* Minimum green coordinate */
X	u_short         maxgreen;	/* Maximum green coordinate */
X	u_short         minblue;/* Minimum blue coordinate */
X	u_short         maxblue;/* Maximum blue coordinate */
X	unsigned        numcols;/* Number of colors in cube */
X	unsigned        numuniq;/* # colors unique to node */
X	unsigned        sumred;	/* Sum of red components */
X	unsigned        sumgreen;	/* Sum of green components */
X	unsigned        sumblue;/* Sum of blue components */
X}               Node;
X
XNode           *cube_root;	/* Root of color cube tree */
Xunsigned        COLTDEPTH = 0;	/* Color tree depth */
Xunsigned        coltdepth;	/* Assigned color tree depth */
Xunsigned        COLTNODES = MAXNODES;	/* tree capacity - as a multiple of
X					 * color count */
Xunsigned        coltnodes;	/* tree capacity (number of nodes) */
Xunsigned        coltvol;	/* Current tree volume in number of nodes */
Xunsigned        num_colreq;	/* Number of colors required  */
X
X
XNode           *
Xinit_node()
X{
X	Node           *cur;
X	extern char    *calloc();
X
X	if ((cur = (Node *) calloc(1, sizeof(Node))) == NULL)
X		error("Can't calloc a Node.");
X	coltvol++;		/* Count 1 more node in tree */
X	return (cur);
X}
X
Xvoid
Xprune(node_ptr)
X	Node           *node_ptr;
X{
X	register Node  *next, *prev, *parent;
X
X	/* Prune all offspring of this node */
X	while (node_ptr->off)
X		prune(node_ptr->off);
X	/* Merge color statistics into parent */
X	parent = node_ptr->parent;
X	parent->numuniq += node_ptr->numuniq;
X	parent->sumred += node_ptr->sumred;
X	parent->sumgreen += node_ptr->sumgreen;
X	parent->sumblue += node_ptr->sumblue;
X
X	/* Remove current node from its sibling list */
X	/* or from its parent's offspring pointer */
X	next = node_ptr->sibling;
X	prev = parent->off;
X
X	if (parent->off == node_ptr)	/* If node is head of sibling list */
X		parent->off = next;	/* change parent's offspring ptr */
X	else
X	{
X		/*
X		 * Find node's predecessor on sibling list and queue around
X		 * node. Note that the check above guarantees existence of a
X		 * predecessor on the sibling list.
X		 */
X		while (prev->sibling != node_ptr)
X			prev = prev->sibling;
X		prev->sibling = next;
X	}
X	/* Release the node's memory */
X	free((char *) node_ptr);
X	coltvol--;		/* Count 1 less node in tree */
X}
X
Xvoid
Xprune_level()
X{
X	register Node  *cur, *parent, *sibling, *offspring;
X	register        level;
X
X#ifdef TRACE
X	printf("ILP:  %d levels, %d nodes\n", coltdepth, coltvol);
X#endif
X	cur = cube_root;
X	level = 0;
X	while (cur)
X	{
X		parent = cur->parent;	/* Save pointers to parent, */
X		offspring = cur->off;	/* offspring, */
X		sibling = cur->sibling;	/* and sibling nodes */
X		if (level == coltdepth)	/* If at maximum depth */
X			prune(cur);	/* prune this node */
X		/* Locate next node */
X		if (offspring)
X		{		/* Descend if possible */
X			cur = offspring;
X			level++;
X			continue;
X		}
X		if (sibling)
X		{		/* Move to sibling if possible */
X			cur = sibling;
X			continue;
X		}
X		cur = parent;	/* else move to next node */
X		level--;	/* via parent */
X		while (cur)
X		{
X			if (cur->sibling)
X			{
X				cur = cur->sibling;
X				break;
X			}
X			cur = cur->parent;
X			level--;
X		}
X	}
X	coltdepth--;		/* Allow 1 less level in tree */
X#ifdef TRACE
X	printf("FLP:  %d levels, %d nodes\n", coltdepth, coltvol);
X#endif
X}
X
X
X/* Input:
X*    rgb_pixmap  Color[]
X*            Pointer to array of Color structures defining
X*            RGB values for a set of pixels (typically a pixmap
X*            or an "ideal" color map).  Only the red/green/blue
X*            data are used as input.
X*    pixmap_size int
X*            Number of Color elements (i.e., number of pixels)
X*            in rgb_pixmap
X*    color_map   Color[]
X*            Pointer to local color map (array of Colors);
X*            No contents are used as input.
X*    colmap_size int
X*            Maximum size (in number of elements) of color map
X*
X*    Non-parameter (global) data:
X*    COLTNODES   int
X*            Maximum size of color tree, as fraction of
X*            pixmap size.  Any value < 2 defaults to 10.
X*            (e.g., 10 => max # of nodes to keep in color tree
X*            during allocation is pixmap_size / 10).
X*    COLTDEPTH   int
X*            Depth to use for color classification tree.
X*            Any value < 2 defaults to log2 of colmap_size,
X*            rounded up, but never to more than MAXDEPTH (8).
X* Output:
X*    allocd_size int
X*    <return value>  Number of colors actually allocated
X*    rgb_pixmap  Color[]
X*            Array of Colors for each pixel.  Pixel values
X*            are supplied in each element, RGB values are
X*            unaltered from original contents
X*    color_map   Color[]
X*            Local color map; Elements are initialized
X*            to both RGB values and corresponding pixel values
X*/
X
Xint 
Xalcols(rgb_pixmap, pixmap_size, color_map, colmap_size)
X	Color           rgb_pixmap[], color_map[];
Xint             pixmap_size, colmap_size;
X{
X	register        i;	/* Pixel index */
X	int             pt;	/* Pruning threshold */
X	int             next_pt;/* Next pruning thesh. */
X	register Node  *cur;	/* Current node */
X	register Node  *next;	/* Next node  */
X	register Node  *prev;	/* Previous node */
X	int             level;	/* Level in tree */
X	int             li;	/* Level index */
X	u_short         red, grn, blu;	/* Pixel value */
X	u_short         mp;	/* Midpoint of a color range */
X
X	/* Initialize tree to describe color cube */
X	if (COLTDEPTH >= 2)	/* If color tree depth is fixed */
X		coltdepth = COLTDEPTH;	/* use global value   */
X	else
X	{			/* select default */
X		coltdepth = 0;
X		for (i = colmap_size; i != 0; i = i >> 1)	/* set coltdepth = log2 */
X			coltdepth++;
X		if ((1 << coltdepth) == colmap_size)
X			coltdepth--;	/* Powers of 2 would be off by 1 */
X		if (coltdepth > MAXDEPTH)	/* Restrict maximum tree
X						 * depth */
X			coltdepth = MAXDEPTH;	/* to compiled max.   */
X	}
X	if (COLTNODES != 0)	/* If pixmap/color tree size ratio OK */
X		coltnodes = COLTNODES;	/* use global value   */
X	else
X		coltnodes = MAXNODES;	/* used compiled max  */
X
X	if (pixmap_size >= 10000)	/* If pixmap isn't small  */
X		coltnodes = pixmap_size / coltnodes;	/* Convert node count */
X	else			/* else override to assure */
X		coltnodes = pixmap_size;	/* good color resolution  */
X
X	printf("Initial # nodes = %d.\n", coltnodes);
X	coltvol = 0;		/* Initial node count = 0 */
X	cube_root = init_node();/* Allocate root node */
X	cube_root->maxred = MAXRGB;
X	cube_root->maxgreen = MAXRGB;	/* Set root color range */
X	cube_root->maxblue = MAXRGB;
X
X	/*
X	 * For each pixel, locate or allocate a node at each level of the
X	 * color cube tree which contains this color and update the count and
X	 * sum values for colors in that node.
X	 */
X	for (i = 0; i < pixmap_size; i++)
X	{
X		if (coltvol > coltnodes)	/* If tree is too large */
X			prune_level();	/* prune 1 level off */
X		red = (u_short) rgb_pixmap[i].red;	/* Get pixel's color */
X		grn = (u_short) rgb_pixmap[i].green;
X		blu = (u_short) rgb_pixmap[i].blue;
X
X		cur = cube_root;/* Start at root node */
X		for (li = 0; li < coltdepth; li++)
X		{		/* For each level of tree */
X			level = li + 1;
X			if (cur->off == NULL)
X			{	/* If nothing on level create one */
X				next = init_node();
X				next->parent = cur;	/* Create 1st element */
X				cur->off = next;
X				/* Set colors of 1st element to contain pixel */
X				mp = cur->minred + (cur->maxred - cur->minred) / 2;
X				if (red <= mp)
X				{
X					next->minred = cur->minred;
X					next->maxred = mp;
X				} else
X				{
X					next->minred = mp + 1;
X					next->maxred = cur->maxred;
X				}
X				mp = cur->mingreen + (cur->maxgreen - cur->mingreen) / 2;
X				if (grn <= mp)
X				{
X					next->mingreen = cur->mingreen;
X					next->maxgreen = mp;
X				} else
X				{
X					next->mingreen = mp + 1;
X					next->maxgreen = cur->maxgreen;
X				}
X				mp = cur->minblue + (cur->maxblue - cur->minblue) / 2;
X				if (blu <= mp)
X				{
X					next->minblue = cur->minblue;
X					next->maxblue = mp;
X				} else
X				{
X					next->minblue = mp + 1;
X					next->maxblue = cur->maxblue;
X				}
X			}	/* Create new level */
X			cur = cur->off;	/* Point to 1st entry on level */
X			while (cur)
X			{	/* Search siblings at this level */
X				prev = cur;
X				if ((red >= cur->minred) && (red <= cur->maxred)
X				    && (grn >= cur->mingreen) && (grn <= cur->maxgreen)
X				    && (blu >= cur->minblue) && (blu <= cur->maxblue))
X					break;
X				cur = cur->sibling;
X			}
X			if (cur == NULL)
X			{	/* for pixel's color create sibling */
X				cur = init_node();
X				prev->sibling = cur;
X				prev = prev->parent;
X				cur->parent = prev;
X
X				/* Set colors of new element to contain pixel */
X				mp = prev->minred + (prev->maxred - prev->minred) / 2;
X				if (red <= mp)
X				{
X					cur->minred = prev->minred;
X					cur->maxred = mp;
X				} else
X				{
X					cur->minred = mp + 1;
X					cur->maxred = prev->maxred;
X				}
X				mp = prev->mingreen + (prev->maxgreen - prev->mingreen) / 2;
X				if (grn <= mp)
X				{
X					cur->mingreen = prev->mingreen;
X					cur->maxgreen = mp;
X				} else
X				{
X					cur->mingreen = mp + 1;
X					cur->maxgreen = prev->maxgreen;
X				}
X				mp = prev->minblue + (prev->maxblue - prev->minblue) / 2;
X				if (blu <= mp)
X				{
X					cur->minblue = prev->minblue;
X					cur->maxblue = mp;
X				} else
X				{
X					cur->minblue = mp + 1;
X					cur->maxblue = prev->maxblue;
X				}
X
X			}	/* Create new sibling */
X			/*
X			 * cur now points to an existing node representing
X			 * the pixel's color.
X			 */
X			cur->numcols++;	/* Count colors in node */
X
X			if (level == coltdepth)
X			{	/* If this is a leaf... */
X				cur->numuniq++;	/* Incr. unique color count */
X				cur->sumred += red;	/* Sum rgb values for */
X				cur->sumgreen += grn;	/* later derivation of */
X				cur->sumblue += blu;	/* mean cube color */
X			}
X		}		/* for each level */
X	}			/* for each pixel */
X
X	/* Set number of color points (number of pixels) in root node. */
X	cube_root->numcols = pixmap_size;
X
X	/* Select colors from the color tree */
X	pt = 0;			/* Initial pruning threshold = 0 */
X
X	do
X	{
X		num_colreq = 0;
X		next_pt = 0x7fffffff;
X		cur = cube_root;
X		do
X		{
X			if (cur->off && (cur->numcols > pt))	/* If offspring */
X				next = cur->off;	/* it won't be pruned */
X			else
X			{	/* Can't descend... */
X				if (cur->sibling)	/* try to move laterally */
X					next = cur->sibling;
X				else
X				{	/* Can't move laterally, Move up and
X					 * across */
X					next = cur;
X					while (next->parent)
X					{
X						next = next->parent;
X						if (next->sibling)
X						{
X							next = next->sibling;
X							break;
X						}
X					}
X					if (next->parent == NULL)	/* Quit ascending */
X						next = NULL;	/* above root node */
X				}
X			}
X			/*
X			 * If current node has a sub-threshold color count,
X			 * then prune it (and its subtree).  Make next node
X			 * current. If new current node is a leaf, increment
X			 * leaf count.
X			 */
X			if (cur->numcols <= pt)
X				prune(cur);
X			else if (cur->numcols < next_pt)
X				next_pt = cur->numcols;
X			cur = next;
X		} while (cur);
X
X		pt = next_pt;	/* Set next pruning threshold */
X		/*
X		 * now determine how many colors would be allocated from
X		 * current tree.
X		 */
X		i = 0;		/* Start at element 0 of color map */
X		cur = cube_root;/* Start at root of tree  */
X		while (cur)
X		{
X			/*
X			 * If current node's unique color count is nonzero,
X			 * then this node would allocate a color.
X			 */
X			if (cur->numuniq)	/* If node has unique colors */
X				i++;	/* count a color def for it */
X			/* Locate next node */
X			if (cur->off)	/* If an offspring exists */
X				cur = cur->off;	/* descend in tree */
X			else
X			{	/* Can't descend...   */
X				if (cur->sibling)	/* try to move laterally */
X					cur = cur->sibling;
X				else
X				{	/* Move up and across */
X					while (cur->parent)
X					{
X						cur = cur->parent;
X						if (cur->sibling)
X						{
X							cur = cur->sibling;
X							break;
X						}
X					}
X					if (cur->parent == NULL)	/* Quit ascending */
X						cur = NULL;	/* above root node */
X				}
X			}
X		}
X		num_colreq = i;	/* Save # colors allocated */
X#ifdef TRACE
X		fprintf(stderr, " # unique colors %d\n", num_colreq);
X#endif TRACE
X	} while (num_colreq > colmap_size);
X
X	/* Set color definitions in color map */
X	cur = cube_root;	/* Start at root of tree  */
X	i = 0;			/* Start at element 0 of color map */
X
X	while (cur)
X	{
X		/*
X		 * If current node's unique color count is nonzero, then
X		 * allocate a color for this node.
X		 */
X		if (cur->numuniq)
X		{		/* If unique colors define it */
X			color_map[i].red = (byte) (cur->sumred / cur->numuniq);
X			color_map[i].green = (byte) (cur->sumgreen / cur->numuniq);
X			color_map[i].blue = (byte) (cur->sumblue / cur->numuniq);
X			cur->numcols = i;	/* Save color map index in
X						 * numcols */
X			i++;	/* incr count of colors allocated */
X		}
X		/* Locate next node */
X		if (cur->off)	/* If an offspring node exists */
X			cur = cur->off;	/* descend in tree */
X		else
X		{		/* Can't descend...   */
X			if (cur->sibling)	/* try to move laterally */
X				cur = cur->sibling;
X			else
X			{	/* Move up and across */
X				while (cur->parent)
X				{
X					cur = cur->parent;
X					if (cur->sibling)
X					{
X						cur = cur->sibling;
X						break;
X					}
X				}
X				if (cur->parent == NULL)	/* Quit trying to ascend */
X					cur = NULL;	/* above root node */
X			}
X		}
X	}
X	num_colreq = i;		/* Save # colors allocated */
X	printf("Final node count = %d\n", coltvol);
X
X	/* Assign color indices to pixels */
X	for (i = 0; i < pixmap_size; i++)
X	{
X		red = (u_short) rgb_pixmap[i].red;
X		grn = (u_short) rgb_pixmap[i].green;
X		blu = (u_short) rgb_pixmap[i].blue;
X		cur = cube_root;/* Start at root node */
X		prev = cur;
X
X		/* Find lowest cube in tree which contains this color */
X		while (cur->off)
X		{
X			cur = cur->off;	/* Go 1 level deeper */
X			while ((cur) && (prev != cur))
X			{	/* siblings */
X				if ((red >= cur->minred) && (red <= cur->maxred)
X				    && (grn >= cur->mingreen) && (grn <= cur->maxgreen)
X				    && (blu >= cur->minblue) && (blu <= cur->maxblue))
X				{
X					prev = cur;	/* Save ptr to matching
X							 * node */
X					break;
X				}
X				cur = cur->sibling;
X			}
X			if (prev != cur)	/* Escape if pixel was */
X				break;	/* not found at this depth */
X		}
X		rgb_pixmap[i].pixel = (byte) prev->numcols;	/* Assign index */
X	}
X	/* Release storage used by the color cube tree */
X	cur = cube_root->off;
X	while (cur)
X	{			/* Prune all offspring of root */
X		next = cur->sibling;
X		prune(cur);
X		cur = next;
X	}
X	free((char *) cube_root);	/* Release root node  */
X	return (num_colreq);	/* Return # colors allocated */
X}
X
X/*** end alcols.c ***/
SHAR_EOF
chmod 0666 alcols.c || echo "restore of alcols.c fails"
sed 's/^X//' << 'SHAR_EOF' > declarations.h &&
X/*
X *  @(#) declarations.h 1.4   Delta'd: 12:25:10 4/2/90   Mike Lijewski, CNSF
X */
X
X#ifndef DECLARATIONS_H
X#define DECLARATIONS_H
X
X#ifdef SYSV
X#include <memory.h>
X#include <string.h>
X#define rindex strrchr
X#endif
X
Xtypedef unsigned char byte;
X
X#if defined(__STDC__) && (__STDC__ == 1)
X#define VOID void
X#else
X#define VOID int
X#endif
X
X/*
X * Fudge factor used by FindColorValue.  If it is set to 0, will try for
X * an exact match.  The higher this is chosen the coarser the match
X * returned.  20 seems to be a good compromise.
X */
X#define FUDGE_FACTOR 20
X
X#if defined(__STDC__) && (__STDC__ == 1)
Xextern int      atoi(char *);
Xextern int      dither_bw(unsigned int, XColor *, int, int);
Xextern int      sscanf(char *, char *,...);
Xextern int      fread(char *, unsigned, int, FILE *);
Xextern int      fprintf(FILE *, char *,...);
Xextern void     error(char *,...);
Xextern void     free(char *);
Xextern int      fseek(FILE *, long, int);
Xextern int      fs_bw(unsigned int , XColor *, int);
Xextern void     bcopy(char *, char *, int);
Xextern void     bw_to_bitmap(byte *, int, int, XColor *);
Xextern void     color_to_bw(byte *, unsigned, XColor *, int *);
Xextern void     edge_enhance(byte *, int, int, unsigned);
Xextern void     exit(int);
Xextern int      grey_value(u_short, u_short, u_short);
Xextern char    *malloc(unsigned int);
Xextern char    *calloc(unsigned int, unsigned int);
Xextern int      mfs_bw(unsigned int, XColor *, int);
Xextern void     normalize_dm(int);
Xextern void     pixmap_dither(byte *, byte[256][3], int, int, int, int *, int *);
Xextern FILE    *popen(char *, char *);
Xextern FILE    *fopen(char *, char *);
Xextern int      pclose(FILE *);
Xextern int      fclose(FILE *);
Xextern void     read_image_buf(FILE *, byte *, unsigned *, int);
Xextern void     rgb_dither(byte *, byte *, byte *, int, int, int, int *, int *);
Xextern void     make_dithermap(int, XColor *, int[256], int[256], int[16][16]);
Xextern char    *rindex(char *, char);
Xextern Colormap GetColormap(XColor *, int, byte *, unsigned int);
Xextern u_long   FindColorValue(Colormap, int, int, int, int, int);
X#else
Xextern int      atoi();
Xextern int      dither_bw();
Xextern int      sscanf();
Xextern int      fread();
Xextern int      fprintf();
Xextern void     error();
Xextern void     free();
Xextern int      fs_bw();
Xextern int      fseek();
Xextern int      bcopy();
Xextern void     bw_to_bitmap();
Xextern void     color_to_bw();
Xextern void     edge_enhance();
Xextern int      exit();
Xextern int      grey_value();
Xextern char    *malloc();
Xextern char    *calloc();
Xextern int      mfs_bw();
Xextern void     normalize_dm();
Xextern void     pixmap_dither();
Xextern FILE    *popen();
Xextern FILE    *fopen();
Xextern int      pclose();
Xextern int      fclose();
Xextern void     read_image_buf();
Xextern void     rgb_dither();
Xextern void     make_dithermap();
Xextern char    *rindex();
Xextern Colormap GetColormap();
Xextern u_long   FindColorValue();
X#endif
X
X#define RND(x)  ((int)((x)+0.5))/* round off a float to an int */
X
Xint             dm4[4][4] =
X{
X    0, 8, 2, 10,
X    12, 4, 14, 6,
X    3, 11, 1, 9,
X    15, 7, 13, 5
X};
X
Xint             dm8[8][8] =
X{
X    0, 32, 8, 40, 2, 34, 10, 42,
X    48, 16, 56, 24, 50, 18, 58, 26,
X    12, 44, 4, 36, 14, 46, 6, 38,
X    60, 28, 52, 20, 62, 30, 54, 22,
X    3, 35, 11, 43, 1, 33, 9, 41,
X    51, 19, 59, 27, 49, 17, 57, 25,
X    15, 47, 7, 39, 13, 45, 5, 37,
X    63, 31, 55, 23, 61, 29, 53, 21
X};
X
Xint             dm16[16][16];
X
X
Xchar           *progName;
Xint             (*bw) () = fs_bw;
Xint             ditherFactor = 8;
Xint             threshold = 32767;
Xint            *dm = &(dm8[0][0]);
Xint             enhance = 0;
XDisplay        *dpy;
Xint             screen;
XWindow          root_win;
XVisual         *visual = NULL;
Xu_long          blackpixel, whitepixel;
X
X#endif
SHAR_EOF
chmod 0666 declarations.h || echo "restore of declarations.h fails"
sed 's/^X//' << 'SHAR_EOF' > gstoxim.c &&
X/***********************************************************************
X*
X*   @(#) gstoxim.c 1.4   Delta'd: 10:50:01 1/10/90   Mike Lijewski, CNSF
X*
X*   gstoxim - takes three files of grayscale data, redFile,
X*             greenFile and blueFile, and transforms them
X*             into an xim file.
X*
X*   Michael Lijewski
X*   Large Scale Applications Support Group
X*   Cornell National Supercomputer Facility
X*   Cornell University
X*   Ithaca, NY  14850
X*   Internet: mjlx@cornellf.tn.cornell.edu Bitnet: mjlx@cornellf.bitnet
X*
X***********************************************************************/
X
X#include <stdio.h>
X#ifdef SYSV
X#include <fcntl.h>
X#include <string.h>
X#define rindex strrchr
X#else
X#include <strings.h>
X#include <sys/file.h>
X#endif
X#include "ImageHeader.h"
X
X#ifdef __STDC__
Xextern int      atoi(char *);
Xextern int      fclose(FILE *);
Xextern int      fprintf(FILE *, char *,...);
Xextern int      fread(char *, unsigned, int, FILE *);
Xextern int      fwrite(char *, unsigned, int, FILE *);
Xextern int      fscanf(FILE *, char *,...);
Xextern int      sprintf(char *, char *,...);
Xextern int      open(char *, int, int);
Xextern int      pclose(FILE *);
Xextern char    *calloc(unsigned, unsigned);
Xextern char    *rindex(char *, char);
Xextern void     error(char *,...);
Xextern void     exit(int);
Xextern FILE    *fopen(char *, char *);
X#else
Xextern int      atoi();
Xextern int      fclose();
Xextern int      open();
Xextern int      pclose();
Xextern char    *calloc();
Xextern char    *rindex();
Xextern void     error();
Xextern void     exit();
Xextern FILE    *fopen();
X#endif
X
X#ifndef TRUE
X#define TRUE 1
X#endif
X#ifndef FALSE
X#define FALSE 0
X#endif
X
Xtypedef unsigned char byte;
X
Xchar           *progName;
X
Xint
Xmain(argc, argv)
X	int             argc;
X	char          **argv;
X{
X	ImageHeader     p_head;	/* picture header */
X	int             i, width = 0, height = 0;
X	int             readWidth = FALSE, readHeight = FALSE;
X	int             (*closeFunc) () = fclose;
X	unsigned        bufSize;
X	byte           *redBuf, *grnBuf, *bluBuf;
X	FILE           *redFP, *greenFP, *blueFP;
X	int             nchannels = 3;	/* always 3 since this is rgb data */
X
X	progName = argv[0];
X
X	for (i = 1; i < argc; i++)
X	{
X		char           *ptr = NULL;
X		if (strncmp(argv[i], "-r", 2) == 0)
X		{
X			ptr = rindex(argv[++i], '.');
X			if (ptr && strcmp(ptr, ".Z") == 0)
X			{
X				char            popen_cmd[80];
X				(void) strcpy(popen_cmd, "zcat ");
X				(void) strcat(popen_cmd, argv[i]);
X				redFP = popen(popen_cmd, "r");
X				closeFunc = pclose;
X			} else if ((redFP = fopen(argv[i], "r")) == NULL)
X				error("Can't read input file: '%s'.", argv[i]);
X			continue;
X		}
X		if (strncmp(argv[i], "-g", 2) == 0)
X		{
X			ptr = rindex(argv[++i], '.');
X			if (ptr && strcmp(ptr, ".Z") == 0)
X			{
X				char            popen_cmd[80];
X				(void) strcpy(popen_cmd, "zcat ");
X				(void) strcat(popen_cmd, argv[i]);
X				greenFP = popen(popen_cmd, "r");
X				closeFunc = pclose;
X			} else if ((greenFP = fopen(argv[i], "r")) == NULL)
X				error("Can't read input file: '%s'.", argv[i]);
X			continue;
X		}
X		if (strncmp(argv[i], "-b", 2) == 0)
X		{
X			ptr = rindex(argv[++i], '.');
X			if (ptr && strcmp(ptr, ".Z") == 0)
X			{
X				char            popen_cmd[80];
X				(void) strcpy(popen_cmd, "zcat ");
X				(void) strcat(popen_cmd, argv[i]);
X				blueFP = popen(popen_cmd, "r");
X				closeFunc = pclose;
X			} else if ((blueFP = fopen(argv[i], "r")) == NULL)
X				error("Can't read input file: '%s'.", argv[i]);
X			continue;
X		}
X		if (strncmp(argv[i], "-w", 2) == 0)
X		{
X			width = atoi(argv[++i]);
X			readWidth = TRUE;
X			continue;
X		}
X		if (strncmp(argv[i], "-h", 2) == 0)
X		{
X			height = atoi(argv[++i]);
X			readHeight = TRUE;
X			continue;
X		}
X		error("Usage: %s [-h n] [-w m] -i redFile -i greenFile \
X-i blueFile", progName);
X	}
X
X	if (readWidth == FALSE || readHeight == FALSE)
X	{
X		if (readWidth == FALSE)
X		{
X			(void) fprintf(stderr, "WIDTH: ");
X			(void) fscanf(stdin, "%d", &width);
X		}
X		if (readHeight == FALSE)
X		{
X			(void) fprintf(stderr, "HEIGHT: ");
X			(void) fscanf(stdin, "%d", &height);
X		}
X	}
X	if (height < 1 || width < 1)
X		error("Active window must be non-NULL");
X
X	bufSize = (unsigned) height *width;
X
X	redBuf = (byte *) calloc(bufSize, 1);
X	grnBuf = (byte *) calloc(bufSize, 1);
X	bluBuf = (byte *) calloc(bufSize, 1);
X	if (redBuf == NULL || grnBuf == NULL || bluBuf == NULL)
X		error("Can't calloc() color buffers.");
X
X	/* read red scanlines */
X	if (fread((char *) redBuf, 1, bufSize, redFP) != bufSize)
X		error("Couldn't read redFile");
X	(void) (closeFunc) (redFP);
X
X	/* read green scanlines */
X	if (fread((char *) grnBuf, 1, bufSize, greenFP) != bufSize)
X		error("Couldn't read greenFile");
X	(void) (closeFunc) (greenFP);
X
X	/* read blue scanlines */
X	if (fread((char *) bluBuf, 1, bufSize, blueFP) != bufSize)
X		error("Couldn't read blueFile");
X	(void) (closeFunc) (blueFP);
X
X	(void) sprintf(p_head.header_size, "%d", sizeof(ImageHeader));
X	(void) sprintf(p_head.file_version, "%d", IMAGE_VERSION);
X	(void) sprintf(p_head.image_width, "%d", width);
X	(void) sprintf(p_head.image_height, "%d", height);
X	(void) sprintf(p_head.num_channels, "%d", nchannels);
X	(void) fprintf(stderr, "Width %d  Height %d  nchannels %d\n",
X		       width, height, nchannels);
X
X	(void) fwrite((char *) &p_head, sizeof(ImageHeader), 1, stdout);
X	(void) fwrite((char *) redBuf, 1, (int) bufSize, stdout);
X	(void) fwrite((char *) grnBuf, 1, (int) bufSize, stdout);
X	(void) fwrite((char *) bluBuf, 1, (int) bufSize, stdout);
X	return (0);
X}
X
X/* VARARGS1 */
Xvoid
Xerror(s1, s2)
X	char           *s1, *s2;
X{
X	extern int      errno, sys_nerr;
X	extern char    *sys_errlist[];
X
X	(void) fprintf(stderr, "%c%s ERROR:%c\n", 7, progName, 7);
X	(void) fprintf(stderr, s1, s2);
X	if (errno > 0 && errno < sys_nerr)
X		(void) fprintf(stderr, " (%s)", sys_errlist[errno]);
X	(void) fprintf(stderr, "\n");
X	exit(1);
X}
SHAR_EOF
chmod 0666 gstoxim.c || echo "restore of gstoxim.c fails"
sed 's/^X//' << 'SHAR_EOF' > gstoxim.n &&
X.\"
X.\"  @(#) gstoxim.n 1.1   Delta'd: 08:16:39 10/25/89   Mike Lijewski, CNSF
X.\"
X.TH GSTOXIM 1 "October 23,  1989"
X.UC 5
X.SH NAME
Xgstoxim \- transforms three files of grayscale images - red, green and
Xblue - into an "xim" file.
X.SH SYNOPSIS
X.B gstoxim
X-height n -width m -i redFile -i greenFile -i blueFile
X
X.SH DESCRIPTION
X.I gstoxim
Xconverts red, green and blue grayscale images to "xim" files.
XYou must input the correct dimensions
Xof the raster image.  You need only specify as many letters of an option
Xas will uniquely identify it.
X
X.SH OPTIONS
XThe input files can be compressed.
X.SH "SEE ALSO"
Xxim(1), rlatoxim(1), rgbtoxim(1)
X
X.SH BUGS
XIf you don't specify either of width or height, you will be prompted
Xfor appropriate input.  Unfortunately, this only works correctly if
Xyou specified the inputs file using the -in option.
X.br
XGstoxim has no way of knowing whether or not the
Xspecified width and height are appropriate.  Let the user
Xbeware.
X.br
X.SH AUTHOR
X.br
XMike Lijewski  (mjlx@cornellf.tn.cornell.edu)
X
SHAR_EOF
chmod 0666 gstoxim.n || echo "restore of gstoxim.n fails"
sed 's/^X//' << 'SHAR_EOF' > quantizim.c &&
X/**********************************************************************/
X/* @(#) quantizim.c 1.2   Delta'd: 13:25:13 1/10/90   Mike Lijewski, CNSF		      */
X/*								      */
X/* file:    quantizim.c                                               */
X/* purpose: To quantize a 2**24 bit image down to 2**8 (256 or less)  */
X/*          with an ImageHeader                                       */
X/* author:  philip thompson, 1988                                     */
X/**********************************************************************/
X#ifndef lint
Xstatic char     quantizim_rcsid[] =
X"$Header: quantizim.c,v 1.4 89/02/20 00:46:11 phils Locked $";
X#endif
X
X#include <stdio.h>
X#ifdef SYSV
X#include <string.h>
X#define rindex strrchr
X#else
X#include <strings.h>
X#endif
X#include "ImageHeader.h"
X
Xextern int      alcols();
Xextern int      atoi();
Xextern int      fread();
Xextern int      fprintf();
Xextern int      sprintf();
Xextern int      fwrite();
Xextern char    *rindex();
Xextern void     exit();
Xextern void     error();
Xextern void     free();
X
Xtypedef unsigned char byte;
Xtypedef struct _Color
X{
X	byte            pixel;
X	byte            red, green, blue;
X}               Color;
X
Xchar           *progName;
X
Xint
Xmain(argc, argv)
X	int             argc;
X	char          **argv;
X{
X	register int    i;
X	int             ncolors = 0, nchannels = 0, alpha = 0;
X	byte           *buffer, *red_buf, *grn_buf, *blu_buf;
X	char           *malloc(), *calloc();
X	int             p_width, p_height, bufsize;	/* image size  */
X	ImageHeader     p_head;	/* picture header */
X	FILE           *out_fp = stdout, *in_fp = stdin, *popen(), *fopen();
X	extern int      pclose(), fclose();
X	int             (*closefunc) () = fclose;
X	Color           cmap[256], *ic;
X	long            D = 0, Dp;
X	float           Dn, maxdn;
X	int             maxd = 0;
X	extern unsigned COLTNODES;
X
X	progName = argv[0];
X	for (i = 1; i < argc; i++)
X	{
X		if (strncmp(argv[i], "-i", 2) == 0)
X		{
X			char           *ptr = rindex(argv[++i], '.');
X			if (ptr && strcmp(ptr, ".Z") == 0)
X			{	/* compressed file */
X				char            popen_cmd[80];
X				(void) strcpy(popen_cmd, "zcat ");
X				(void) strcat(popen_cmd, argv[i]);
X				in_fp = popen(popen_cmd, "r");
X				closefunc = pclose;
X			} else
X				in_fp = fopen(argv[i], "r");
X			if (in_fp == NULL)
X				error("Can't open input file: %s ", argv[i]);
X			continue;
X		}
X		if (strncmp(argv[i], "-o", 2) == 0)
X		{
X			if ((out_fp = fopen(argv[++i], "w")) == NULL)
X				error("Can't open %s\n", argv[i]);
X			continue;
X		}
X		if (strncmp(argv[i], "-co", 3) == 0)
X		{
X			ncolors = atoi(argv[++i]);
X			continue;
X		}
X		if (strncmp(argv[i], "-no", 3) == 0)
X		{
X			COLTNODES = (unsigned) atoi(argv[++i]);
X			continue;
X		}
X		error("Usage: %s [-in file][-out file][-colors #][-nodes #]",
X		      progName);
X	}
X
X	if (fread((char *) &p_head, sizeof(ImageHeader), 1, in_fp) != 1)
X		error("Can't read header.");
X	if (atoi(p_head.header_size) != sizeof(ImageHeader))
X		error("Header size mismatch.");
X	if (atoi(p_head.file_version) != IMAGE_VERSION)
X		error("Incorrect image file Version.");
X	p_width = atoi(p_head.image_width);
X	p_height = atoi(p_head.image_height);
X	nchannels = atoi(p_head.num_channels);
X	alpha = atoi(p_head.alpha_channel);
X	(void) fprintf(stderr, "Made by: %s   Program: %s\n", p_head.author,
X		       p_head.program);
X	(void) fprintf(stderr, "Width: %d  Height: %d\n", p_width, p_height);
X	if (ncolors == 0)
X		ncolors = 256;
X	(void) fprintf(stderr, "max colors: %d\n", ncolors);
X	if (nchannels != 3)
X		error("Image must have 3 channels.");
X
X	bufsize = p_width * p_height;
X	if ((ic = (Color *) calloc((unsigned) bufsize, sizeof(Color))) == NULL)
X		error("Can't calloc() alcols buffer");
X	red_buf = (byte *) malloc((unsigned) bufsize);
X	grn_buf = (byte *) malloc((unsigned) bufsize);
X	blu_buf = (byte *) malloc((unsigned) bufsize);
X	if (red_buf == NULL || grn_buf == NULL || blu_buf == NULL)
X		error("Can't malloc() buffers");
X
X	if (fread((char *) red_buf, 1, (int) bufsize, in_fp) != bufsize)
X		error("error reading RED buffer");
X	if (fread((char *) grn_buf, 1, (int) bufsize, in_fp) != bufsize)
X		error("error reading GREEN buffer");
X	if (fread((char *) blu_buf, 1, (int) bufsize, in_fp) != bufsize)
X		error("error reading BLUE buffer");
X
X	for (i = 0; i < ncolors; i++)
X		cmap[i].pixel = (byte) i;
X	for (i = 0; i < bufsize; i++)
X	{
X		ic[i].red = red_buf[i];
X		ic[i].green = grn_buf[i];
X		ic[i].blue = blu_buf[i];
X	}
X	free((char *) red_buf);
X	free((char *) grn_buf);
X	free((char *) blu_buf);
X
X	(void) fprintf(stderr, "Working ...\n");
X	ncolors = alcols(ic, bufsize, cmap, ncolors);
X
X	nchannels = 1;
X	fprintf(stderr, "ncolors %d  nchannels %d\n", ncolors, nchannels);
X
X	if ((buffer = (byte *) malloc((unsigned) bufsize)) == NULL)
X		error("Can't malloc() buffer.");
X	for (i = 0; i < bufsize; i++)
X		buffer[i] = (byte) ic[i].pixel;
X	for (i = 0; i < ncolors; i++)
X	{
X		p_head.c_map[i][0] = cmap[i].red;
X		p_head.c_map[i][1] = cmap[i].green;
X		p_head.c_map[i][2] = cmap[i].blue;
X	}
X
X	(void) sprintf(p_head.num_colors, "%d", ncolors);
X	(void) sprintf(p_head.num_channels, "%d", nchannels);
X	(void) fwrite((char *) &p_head, sizeof(ImageHeader), 1, out_fp);
X	(void) fwrite((char *) buffer, 1, bufsize, out_fp);
X
X	if (alpha)
X	{			/* if there is an alpha channel copy it over */
X		if (fread((char *) buffer, 1, (int) bufsize, in_fp) != bufsize)
X			error("Can't read ALPHA channel");
X		(void) fwrite((char *) buffer, 1, bufsize, out_fp);
X	}
X	(void) (*closefunc) (in_fp);
X	(void) fclose(out_fp);
X
X	/* Derive stats for color deviation    */
X	for (i = 0; i < bufsize; i++)
X	{
X		register        d, dr, dg, db;
X
X		dr = ic[i].red - cmap[ic[i].pixel].red;
X		dg = ic[i].green - cmap[ic[i].pixel].green;
X		db = ic[i].blue - cmap[ic[i].pixel].blue;
X		d = dr * dr + dg * dg + db * db;
X		D += d;
X		if (d > maxd)
X			maxd = d;
X	}
X	free((char *) ic);
X
X	Dp = (int) ((float) D / (float) bufsize + 0.5);
X	Dn = (int) ((float) Dp / 195075.0 + 0.5);	/* 3*255*255 */
X	maxdn = (float) maxd / 195075.0;
X	fprintf(stderr, "Total quantization error = %ld\n", D);
X	fprintf(stderr, "Mean error per pixel     = %ld\n", Dp);
X	fprintf(stderr, "Normalized error/pixel   = %f\n", Dn);
X	fprintf(stderr, "Maximum error for any pixel = %d\n", maxd);
X	fprintf(stderr, "Normalized maximum error    = %f\n", maxdn);
X	free((char *) buffer);
X	return (0);
X}
X
X/*VARARGS1*/
Xvoid
Xerror(s1, s2)
X	char           *s1, *s2;
X{
X	extern int      errno, sys_nerr;
X	extern char    *sys_errlist[];
X
X	(void) fprintf(stderr, "%c%s ERROR:%c\n", 7, progName, 7);
X	(void) fprintf(stderr, s1, s2);
X	if (errno > 0 && errno < sys_nerr)
X		(void) fprintf(stderr, " (%s)", sys_errlist[errno]);
X	(void) fprintf(stderr, "\n");
X	exit(1);
X}
X
X/*** end quantize.c ***/
SHAR_EOF
chmod 0666 quantizim.c || echo "restore of quantizim.c fails"
sed 's/^X//' << 'SHAR_EOF' > quantizim.n &&
X.TH QUANTIZIM 1 "February 3,  1989"
X.UC 5
X.SH NAME
Xquantizim \- quantize a 24 bit/pixel image to 256 colors or less.
X.SH SYNOPSIS
X.B quantizim
X[-in 
X.I file
X] [-out
X.I file
X] [-colors
X.I n] [-nodes
X.I n
X]
X.SH DESCRIPTION
X.I Quantizim
Xis a program for quantizing 24 bit/pixel images down to 8 bits or less.
XIt does a fairly good job creating a pixmap and colormap from a three channel RG&B data.
XAt the heart of this program is the
X.I alcols
Xcode written at the USC Information Sciences Institute.
XIt uses a tree sorting algorithm for selecting the best 256 (or less) unique colors from over 16 million.
X.SH OPTIONS
X.TP "\w'\f3\-m\f1name 'u"
X.B -in \fIfile\fP
XThis option allows the user to explicitly specify the 24 bit/pixel file on the command line.  The default is to read input from standard in.
X.TP "\w'\f3\-m\f1name 'u"
X.B -out \fIfile\fP
XThis option allows the user to explicitly specify the 8 bit/pixel file on the command line.
XThe default is to write output to standard out.
X.TP "\w'\f3\-m\f1name 'u"
X.B -colors \fInum\fP
XThis allows one to specify the maximum number of colors to quantize down to.
XThe program may return less than the maximum.
XThe default is 256 colors.x.
X.TP "\w'\f3\-m\f1name 'u"
X.B -nodes \fInum\fP
XThe ratio of pixels per node to begin the tree sort with.
XThe default is 50.
XA smaller ratio (more nodes) gives more even shading and uses more memory.
XLess nodes causes more banding but generally less quantization error.
X.PP
X.I Note:
XAll of the command line options can be abbreviated to their shortest unique spelling.
X.br
Xex: %  quantizim -in colord24.xim -out color.xim -co 192 -no 10
X
X.SH "SEE ALSO"
Xxim(n)
Xsmoothim(n)
X.SH BUGS
X- This program takes a lot of memory.
XLarge images around 640x480 may not work on all machines.
X.br
X- The optimum ratio of nodes to image size is not clear.
X.br
X- I wish I knew better how this works.
X.SH COPYRIGHTS
XCopyright (c) 1988, University of Southern California
X.br
XCopyright (c) 1989, Massachusetts Institute of Technology.
X.SH AUTHORS
XPaul Raveling (vaxa.isi.edu) - alcols.c
X.PP
XPhilip R. Thompson (phils@athena.mit.edu) - quantizim.c
X.br
XComputer Resource Laboratory,  
XDept. of Architecture and Planning,  
X.br
XMassachusetts Institute of Technology,  
XCambridge, MA  02139
X
SHAR_EOF
chmod 0666 quantizim.n || echo "restore of quantizim.n fails"
sed 's/^X//' << 'SHAR_EOF' > rgbtoxim.c &&
X/***********************************************************************
X*
X*  @(#) rgbtoxim.c 1.8   Delta'd: 17:29:06 1/9/90   Mike Lijewski, CNSF
X*
X*   rgbtoxim - transforms a raw rgb file into an xim file.
X*
X*   Michael Lijewski
X*   Large Scale Applications Support Group
X*   Cornell National Supercomputer Facility
X*   Cornell University
X*   Ithaca, NY  14850
X*   Internet: mjlx@cornellf.tn.cornell.edu Bitnet: mjlx@cornellf.bitnet
X*
X*   The assumed format of the RGB data is:
X*
X*   <---- width ------>
X*   -------------------
X*   | red scanline    |
X*   -------------------
X*   | green scanline  |
X*   -------------------
X*   | blue scanline   |
X*   -------------------
X*   |        .        |
X*   |        .        |
X*   |        .        |
X*   |                 |
X*   -------------------
X*
X*   where there are "height" sets {red, green, blue} scanlines.
X***********************************************************************/
X
X#include <stdio.h>
X#ifdef SYSV
X#include <fcntl.h>
X#include <string.h>
X#define rindex strrchr
X#else
X#include <strings.h>
X#include <sys/file.h>
X#endif
X#include "ImageHeader.h"
X
X#ifdef __STDC__
Xextern int      atoi(char *);
Xextern int      fclose(FILE *);
Xextern int      fread(char *, unsigned, int, FILE *);
Xextern int      fwrite(char *, unsigned, int, FILE *);
Xextern int      fprintf(FILE *, char *,...);
Xextern int      fscanf(FILE *, char *,...);
Xextern int      sprintf(char *, char *,...);
Xextern int      pclose(FILE *);
Xextern char    *calloc(unsigned int, unsigned int);
Xextern char    *rindex(char *, char);
Xextern void     error(char *,...);
Xextern void     exit(int);
Xextern FILE    *fopen(char *, char *);
X#else
Xextern int      atoi();
Xextern int      fclose();
Xextern int      fread();
Xextern int      fwrite();
Xextern int      fprintf();
Xextern int      fscanf();
Xextern char    *sprintf();
Xextern int      pclose();
Xextern char    *calloc();
Xextern char    *rindex();
Xextern void     error();
Xextern int      exit();
Xextern FILE    *fopen();
X#endif
X
X/*
X *  Some machines do not like signed chars.  If when you compile
X *  this code you get messages to this effect, try compiling with
X *  the NO_SIGNED_CHAR preprocessor variable defined.
X */
X
X#ifdef NO_SIGNED_CHAR
X#define SIGNED
X#else
X#define SIGNED signed
X#endif
X
X#ifndef TRUE
X#define TRUE 1
X#endif
X#ifndef FALSE
X#define FALSE 0
X#endif
X
Xtypedef unsigned char byte;
X
Xchar           *progName;
X
Xint
Xmain(argc, argv)
X    int             argc;
X    char          **argv;
X{
X    ImageHeader     p_head;	/* picture header */
X    int             i, width = 0, height = 0;
X    int             readWidth = FALSE, readHeight = FALSE;
X    int             (*closeFunc) () = fclose;
X    unsigned        bufsize;
X    byte           *red_buf, *grn_buf, *blu_buf;
X    FILE           *input = stdin, *output = stdout;
X    int             nchannels = 3;	/* always 3 since this is rgb data */
X
X    progName = argv[0];
X
X    for (i = 1; i < argc; i++)
X    {
X	char           *ptr = NULL;
X	if (strncmp(argv[i], "-i", 2) == 0)
X	{
X	    ptr = rindex(argv[++i], '.');
X	    if (ptr && strcmp(ptr, ".Z") == 0)
X	    {
X		char            popen_cmd[80];
X		(void) strcpy(popen_cmd, "zcat ");
X		(void) strcat(popen_cmd, argv[i]);
X		input = popen(popen_cmd, "r");
X		closeFunc = pclose;
X	    } else
X		input = fopen(argv[i], "r");
X	    if (input == NULL)
X		error("Can't read input file: '%s'.", argv[i]);
X	    continue;
X	}
X	if (strncmp(argv[i], "-o", 2) == 0)
X	{
X	    if ((output = fopen(argv[++i], "w")) == NULL)
X		error("Can't open '%s'\n", argv[i]);
X	    continue;
X	}
X	if (strncmp(argv[i], "-w", 2) == 0)
X	{
X	    width = atoi(argv[++i]);
X	    readWidth = TRUE;
X	    continue;
X	}
X	if (strncmp(argv[i], "-h", 2) == 0)
X	{
X	    height = atoi(argv[++i]);
X	    readHeight = TRUE;
X	    continue;
X	}
X	error("Usage: %s -height n -width m [-in file][-out file]",
X	      progName);
X    }
X
X    if (readWidth == FALSE || readHeight == FALSE)
X    {
X	if (readWidth == FALSE)
X	{
X	    (void) fprintf(stderr, "WIDTH: ");
X	    (void) fscanf(stdin, "%d", &width);
X	}
X	if (readHeight == FALSE)
X	{
X	    (void) fprintf(stderr, "HEIGHT: ");
X	    (void) fscanf(stdin, "%d", &height);
X	}
X    }
X    if (height < 1 || width < 1)
X	error("Active window must be non-NULL");
X
X    bufsize = (unsigned) height *width;
X
X    red_buf = (byte *) calloc(bufsize, 1);
X    grn_buf = (byte *) calloc(bufsize, 1);
X    blu_buf = (byte *) calloc(bufsize, 1);
X    if (red_buf == NULL || grn_buf == NULL || blu_buf == NULL)
X	error("Can't calloc() color buffers.");
X
X    for (i = 0; i <= bufsize - width; i += width)
X    {
X	/* read red scanline */
X	if (fread((char *) &red_buf[i], width, 1, input) != 1)
X	    error("Couldn't read red scanline");
X
X	/* read green scanline */
X	if (fread((char *) &grn_buf[i], width, 1, input) != 1)
X	    error("Couldn't read green scanline");
X
X	/* read blue scanline */
X	if (fread((char *) &blu_buf[i], width, 1, input) != 1)
X	    error("Couldn't read blue scanline");
X    }
X    (void) (*closeFunc) (input);
X
X    (void) sprintf(p_head.header_size, "%d", sizeof(ImageHeader));
X    (void) sprintf(p_head.file_version, "%d", IMAGE_VERSION);
X    (void) sprintf(p_head.image_width, "%d", width);
X    (void) sprintf(p_head.image_height, "%d", height);
X    (void) sprintf(p_head.num_channels, "%d", nchannels);
X    (void) fprintf(stderr, "Width %d  Height %d  nchannels %d\n",
X		   width, height, nchannels);
X
X    (void) fwrite((char *) &p_head, sizeof(ImageHeader), 1, output);
X    (void) fwrite((char *) red_buf, 1, (int) bufsize, output);
X    (void) fwrite((char *) grn_buf, 1, (int) bufsize, output);
X    (void) fwrite((char *) blu_buf, 1, (int) bufsize, output);
X    (void) fclose(output);
X    return (0);
X}
X
X/* VARARGS1 */
Xvoid
Xerror(s1, s2)
X    char           *s1, *s2;
X{
X    extern int      errno, sys_nerr;
X    extern char    *sys_errlist[];
X
X    (void) fprintf(stderr, "%c%s ERROR:%c\n", 7, progName, 7);
X    (void) fprintf(stderr, s1, s2);
X    if (errno > 0 && errno < sys_nerr)
X	(void) fprintf(stderr, " (%s)", sys_errlist[errno]);
X    (void) fprintf(stderr, "\n");
X    exit(1);
X}
SHAR_EOF
chmod 0666 rgbtoxim.c || echo "restore of rgbtoxim.c fails"
sed 's/^X//' << 'SHAR_EOF' > rgbtoxim.n &&
X.\"
X.\"  @(#) rgbtoxim.n 1.4   Delta'd: 11:16:44 7/19/89   Mike Lijewski, CNSF
X.\"
X.TH RGBTOXIM 1 "July 19,  1989"
X.UC 5
X.SH NAME
Xrgbtoxim \- converts from a raw RGB raster to an "xim" file.
X.SH SYNOPSIS
X.B rgbtoxim
X-height n -width m
X[-in 
X.I rgbfile
X] [-out
X.I ximfile
X]
X
X.SH DESCRIPTION
X.I rgbtoxim
Xconverts RGB rasters to "xim" files.  You must input the correct dimensions
Xof the raster image.  You need only specify as many letters of an option
Xas will uniquely identify it.
X
X.SH OPTIONS
X.TP "\w'\f3\-m\f1name 'u"
X.B -in \fIfile\fP
XThis option allows the user to explicitly specify the input file on the command line.
XThe default is to read input from standard in.  This may be a compressed file.
X.TP "\w'\f3\-m\f1name 'u"
X.B -out \fIfile\fP
XThis option allows the user to explicitly specify the output file on the command line.
XThe default is to write output to standard out.
X
X.SH "SEE ALSO"
Xxim(1), rlatoxim(1)
X
X.SH BUGS
XIf you don't specify either of width or height, you will be prompted
Xfor appropriate input.  Unfortunately, this only works correctly if
Xyou specified the input file using the -in option.
X.br
XRgbtoxim has no way of knowing whether or not the
Xspecified width and height are appropriate to the rgbfile.  Let the user
Xbeware.
X.br
X.SH AUTHOR
X.br
XMike Lijewski  (mjlx@cornellf.tn.cornell.edu)
X
SHAR_EOF
chmod 0666 rgbtoxim.n || echo "restore of rgbtoxim.n fails"
sed 's/^X//' << 'SHAR_EOF' > rlatoxim.c &&
X/***********************************************************************
X*
X*   @(#) rlatoxim.c 1.9   Delta'd: 14:38:18 1/24/90   Mike Lijewski, CNSF
X*
X*   rlatoxim - transforms a Wavefront Technologies, Inc. .rla
X*              format file into an xim file.
X*
X*   Michael Lijewski
X*   Large Scale Applications Support Group
X*   Cornell National Supercomputer Facility
X*   Cornell University
X*   Ithaca, NY  14850
X*   Internet: mjlx@cornellf.tn.cornell.edu Bitnet: mjlx@cornellf.bitnet
X*
X*   This code was adapted from rletoxim.c, which was written by
X*   Philip Thompson (phils@athena.mit.edu), and contained the
X*   following  copyright:
X*
X*   I provide this software freely as a public service.  It is NOT a
X*   commercial product, and therefore is not subject to an an implied
X*   warranty of merchantability or fitness for a particular purpose.  I
X*   provide it as is, without warranty. This software was not sponsored,
X*   developed or connected with any grants, funds, salaries, etc.
X*
X*   This software is furnished  only on the basis that any party who
X*   receives it indemnifies and holds harmless the parties who furnish
X*   it against any claims, demands, or liabilities connected with using
X*   it, furnishing it to others, or providing it to a third party.
X*
X***********************************************************************/
X
X#include <stdio.h>
X#ifdef SYSV
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#endif
X#include "ImageHeader.h"
X#include "RLAHeader.h"
X
Xchar           *progName;
X
X/*
X * Some machines do not like signed chars.  If when you compile this code you
X * get messages to this effect, try compiling with the NO_SIGNED_CHAR
X * preprocessor variable defined.
X */
X
X#ifdef NO_SIGNED_CHAR
X#define SIGNED
X#else
X#define SIGNED signed
X#endif
X
X#define MIN(x, y) ((x) > (y) ? (y) : (x))
X
Xtypedef unsigned char byte;
X
X#ifdef __STDC__
Xextern int      fread(char *, unsigned, int, FILE *);
Xextern int      fwrite(char *, unsigned, int, FILE *);
Xextern int      fprintf(FILE *, char *,...);
Xextern int      sprintf(char *, char *,...);
Xextern int      fclose(FILE *);
Xextern char    *calloc(unsigned int, unsigned int);
Xextern void     bcopy(char *, char *, int);
Xextern void     error();
Xextern void     exit(int);
Xextern FILE    *fopen(char *, char *);
X#else
Xextern int      fread();
Xextern int      fwrite();
Xextern int      fprintf();
Xextern int      sprintf();
Xextern int      fclose();
Xextern char    *calloc();
Xextern int      bcopy();
Xextern void     error();
Xextern int      exit();
Xextern FILE    *fopen();
X#endif
X
X/*
X * swapShort - swap n short int's from big-endian to little-endian format.
X */
Xvoid
X#ifdef __STDC__
XswapShort(register char *bp, register unsigned n)
X#else
XswapShort(bp, n)
X    register char  *bp;
X    register unsigned n;
X#endif
X{
X    register char   c;
X    register char  *ep = bp + n;
X
X    while (bp < ep)
X    {
X	c = *bp;
X	*bp = *(bp + 1);
X	bp++;
X	*bp++ = c;
X    }
X}
X
X/*
X * swapLong - swap n long's from big-endian to little-endian format.
X */
Xvoid
X#ifdef __STDC__
XswapLong(register char *bp, register unsigned n)
X#else
XswapLong(bp, n)
X    register char  *bp;
X    register unsigned n;
X#endif
X{
X    register char  *sp, c;
X    register char  *ep = bp + n;
X
X    while (bp < ep)
X    {
X	sp = bp + 3;
X	c = *sp;
X	*sp = *bp;
X	*bp++ = c;
X	sp = bp + 1;
X	c = *sp;
X	*sp = *bp;
X	*bp++ = c;
X	bp += 2;
X    }
X}
X
X/*
X * swapRLAHeader - put RLAHeader into little-endian format.
X */
Xvoid
X#ifdef __STDC__
XswapRLAHeader(char *rlaheader)
X#else
XswapRLAHeader(rlaheader)
X    char           *rlaheader;
X#endif
X{
X    /* swap first 14 shorts in header */
X    swapShort(rlaheader, 28);
X    /* swap lone long in header */
X    swapLong(rlaheader + 140, 4);
X}
X
X/*
X * decodeRecord - decode the encoded RLA record.
X */
Xint
X#ifdef __STDC__
XdecodeRecord(SIGNED char *record, int length, SIGNED char *colorbuf)
X#else
XdecodeRecord(record, length, colorbuf)
X    SIGNED char    *record;	/* encoded record */
X    int             length;	/* number of bytes in record */
X    SIGNED char    *colorbuf;	/* where to write decoded record */
X#endif
X{
X    int             i;
X    int             j = 0;
X
X    while (length > 0)
X    {
X	if (*record < 0)
X	{
X	    /* unencoded data string */
X	    i = -(int) *record++;
X	    length -= i + 1;
X	    while (i > 0)
X	    {
X		*colorbuf++ = *record++;
X		j++;
X		i--;
X	    }
X	}
X	else
X	{
X	    /* repeat string */
X	    i = (int) *record++ + 1;
X	    length -= 2;
X	    while (i > 0)
X	    {
X		*colorbuf++ = *record;
X		j++;
X		i--;
X	    }
X	    record++;
X	}
X    }
X    return (j);			/* return number of bytes in decoded record */
X}
X
X
Xint
Xmain(argc, argv)
X    int             argc;
X    char          **argv;
X{
X    ImageHeader     pHeader;	/* picture header */
X    RLA_Header      rlaHeader;	/* WaveFront RLA header */
X    short           recordLength;	/* assumming sizeof(short) == 2 */
X    int             i, j, width, height, totalWidth, totalHeight;
X    int             totalWindow = 1;	/* displaying total window is
X					 * the default */
X    int             position = 0;	/* position in input file */
X    unsigned long  *offsetTable;/* assumming sizeof(long) == 4 */
X    unsigned        bufSize;
X    byte           *encodedRecord;
X    byte           *redBuf, *grnBuf, *bluBuf;
X    FILE           *inFp = stdin, *outFp = stdout;
X    int             nChannels;	/* number of color channels */
X    int             line;	/* the scanline we are on */
X
X    union
X    {
X	long            Long;
X	char            Char[sizeof(long)];
X    }               SwapTest;
X    int             swapOn = 0;
X
X    /* test for Endian-ness */
X    SwapTest.Long = 1;
X    if (SwapTest.Char[0] == 1)
X	/* this is a Little-Endian machine; set swapOn flag */
X	swapOn = 1;
X
X    progName = argv[0];
X
X    for (i = 1; i < argc; i++)
X    {
X	if (strncmp(argv[i], "-i", 2) == 0)
X	{
X	    if ((inFp = fopen(argv[++i], "r")) == NULL)
X		error("Can't read input file: %s.", argv[i]);
X	    continue;
X	}
X	if (strncmp(argv[i], "-o", 2) == 0)
X	{
X	    if ((outFp = fopen(argv[++i], "w")) == NULL)
X		error("Can't open %s\n", argv[i]);
X	    continue;
X	}
X	if (strncmp(argv[i], "-a", 2) == 0)
X	{
X	    /* we'll only display the active window */
X	    totalWindow = 0;
X	    continue;
X	}
X	error("Usage: %s [-a] [-in file] [-out file]", progName);
X    }
X
X    if (fread((char *) &rlaHeader, sizeof(rlaHeader), 1, inFp) != 1)
X	error("Unable to read RLA Header");
X    if (swapOn)
X	swapRLAHeader((char *) &rlaHeader);
X    position += sizeof(rlaHeader);
X
X    height = rlaHeader.active_window.top - rlaHeader.active_window.bottom + 1;
X    width = rlaHeader.active_window.right - rlaHeader.active_window.left + 1;
X    totalHeight = rlaHeader.window.top - rlaHeader.window.bottom + 1;
X    totalWidth = rlaHeader.window.right - rlaHeader.window.left + 1;
X
X    if (height < 1 || width < 1)
X	error("Window must be non-NULL");
X
X    offsetTable = (unsigned long *) calloc((unsigned) height, (unsigned) 4);
X    if (offsetTable == NULL)
X	error("Couldn't calloc() space for offset table");
X    if (fread((char *) offsetTable, 4 * height, 1, inFp) != 1)
X	error("Couldn't read offset table");
X    if (swapOn)
X	swapLong((char *) offsetTable, (unsigned) (4 * height));
X    position += (4 * height);
X
X    if (totalWindow)
X	bufSize = (unsigned) (totalWidth * totalHeight);
X    else
X	bufSize = (unsigned) (width * height);
X
X    nChannels = (int) rlaHeader.num_chan;
X
X    if ((encodedRecord = (byte *) calloc((unsigned) (2 * width),
X					 (unsigned) 1)) == NULL)
X	error("Couldn't calloc() space for encoded record");
X
X    if (nChannels == 3)
X    {
X	redBuf = (byte *) calloc(bufSize, 1);
X	grnBuf = (byte *) calloc(bufSize, 1);
X	bluBuf = (byte *) calloc(bufSize, 1);
X	if (redBuf == NULL || grnBuf == NULL || bluBuf == NULL)
X	    error("Can't calloc() color buffers.");
X    }
X    else
X	error("We only handle 3-channel images currently");
X
X    if (totalWindow)
X    {
X	/*
X         *  do NOT try to simplify this expression.  I am relying on
X         *  the implicit truncation of integer arithmetic to do the
X         *  rigth thing.
X         */
X	i = totalWidth * ((totalHeight + height) / 2) + (totalWidth - width) / 2;
X	j = totalWidth;
X    }
X    else
X    {
X	i = width * (height - 1);
X	j = width;
X    }
X
X    for (line = 0; i >= 0; i -= j, line++)
X    {
X	/* read length of red record */
X	if (fread((char *) &recordLength, sizeof(short), 1, inFp) != 1)
X	    error("Couldn't read length of red record");
X	if (swapOn)
X	    swapShort((char *) &recordLength, 2);
X	position += recordLength + 2;
X
X	/* read encoded record */
X	if (fread((char *) encodedRecord, recordLength, 1, inFp) != 1)
X	    error("Couldn't read encoded red record");
X
X	/* decode record */
X	if (decodeRecord((SIGNED char *) encodedRecord, recordLength,
X			 (SIGNED char *) &redBuf[i]) != width)
X	    error("Decoded red record is of incorrect length");
X
X	/* read length of green record */
X	if (fread((char *) &recordLength, sizeof(short), 1, inFp) != 1)
X	    error("Couldn't read length of green record");
X	if (swapOn)
X	    swapShort((char *) &recordLength, 2);
X	position += recordLength + 2;
X
X	/* read encoded record */
X	if (fread((char *) encodedRecord, recordLength, 1, inFp) != 1)
X	    error("Couldn't read encoded green record");
X
X	/* decode record */
X	if (decodeRecord((SIGNED char *) encodedRecord, recordLength,
X			 (SIGNED char *) &grnBuf[i]) != width)
X	    error("Decoded green record is of incorrect length");
X
X	/* read length of blue record */
X	if (fread((char *) &recordLength, sizeof(short), 1, inFp) != 1)
X	    error("Couldn't read length of blue record");
X	if (swapOn)
X	    swapShort((char *) &recordLength, 2);
X	position += recordLength + 2;
X
X	/* read encoded record */
X	if (fread((char *) encodedRecord, recordLength, 1, inFp) != 1)
X	    error("Couldn't read encoded blue record");
X
X	/* decode record */
X	if (decodeRecord((SIGNED char *) encodedRecord, recordLength,
X			 (SIGNED char *) &bluBuf[i]) != width)
X	    error("Decoded blue record is of incorrect length");
X
X	/* read past any matte or auxiliary data */
X	if (i == 0 || (line == height - 1))
X	    /* we are done reading channel data */
X	    break;
X	else
X	{
X	    int             n = offsetTable[line + 1] - position;
X	    if (n != 0)
X	    {
X		/*
X		 * we must read in chunks of no more that 2*width bytes,
X		 * since we'll be reading into encodedRecord which just
X		 * happens to have length 2*width, and is the only stray
X		 * buffer we have available.
X		 */
X		if (n <= 2 * width)
X		{
X		    /* read it all in one fell swoop */
X		    if (fread((char *) encodedRecord, n, 1, inFp) != 1)
X			error("Couldn't read past matte & aux data");
X		}
X		else
X		{
X		    int             j = n;
X		    while (j > 0)
X		    {
X			if (fread((char *) encodedRecord, MIN(j, 2 * width), 1,
X				  inFp) != 1)
X			    error("Couldn't read past matte & aux data");
X			j -= 2 * width;
X		    }
X		}
X	    }
X	    /* update our position in file */
X	    position = offsetTable[line + 1];
X	}
X
X    }
X
X#ifdef SYSV
X    memcpy(pHeader.author, rlaHeader.user, 32);
X    memcpy(pHeader.program, rlaHeader.program, 16);
X    memcpy(pHeader.date, rlaHeader.date, 20);
X#else
X    bcopy(rlaHeader.user, pHeader.author, 32);
X    bcopy(rlaHeader.program, pHeader.program, 16);
X    bcopy(rlaHeader.date, pHeader.date, 20);
X#endif
X
X    (void) fclose(inFp);
X
X    (void) sprintf(pHeader.header_size, "%d", sizeof(ImageHeader));
X    (void) sprintf(pHeader.file_version, "%d", IMAGE_VERSION);
X    if (totalWindow)
X    {
X	(void) sprintf(pHeader.image_width, "%d", totalWidth);
X	(void) sprintf(pHeader.image_height, "%d", totalHeight);
X    }
X    else
X    {
X	(void) sprintf(pHeader.image_width, "%d", width);
X	(void) sprintf(pHeader.image_height, "%d", height);
X    }
X    (void) sprintf(pHeader.num_channels, "%d", nChannels);
X    (void) fprintf(stderr, "Width %d  Height %d  nChannels %d\n",
X		   width, height, nChannels);
X
X    (void) fwrite((char *) &pHeader, sizeof(ImageHeader), 1, outFp);
X    if (nChannels == 3)
X    {
X	(void) fwrite((char *) redBuf, 1, (int) bufSize, outFp);
X	(void) fwrite((char *) grnBuf, 1, (int) bufSize, outFp);
X	(void) fwrite((char *) bluBuf, 1, (int) bufSize, outFp);
X    }
X    (void) fclose(outFp);
X    return (0);
X}
X
X/*
X *  error
X */
X/* VARARGS1 */
Xvoid
Xerror(s1, s2)
X    char           *s1, *s2;
X{
X    extern int      errno, sys_nerr;
X    extern char    *sys_errlist[];
X
X    (void) fprintf(stderr, "%c%s ERROR:%c\n", 7, progName, 7);
X    (void) fprintf(stderr, s1, s2);
X    if (errno > 0 && errno < sys_nerr)
X	(void) fprintf(stderr, " (%s)", sys_errlist[errno]);
X    (void) fprintf(stderr, "\n");
X    exit(1);
X}
SHAR_EOF
chmod 0666 rlatoxim.c || echo "restore of rlatoxim.c fails"
sed 's/^X//' << 'SHAR_EOF' > rlatoxim.n &&
X.\"
X.\"  @(#) rlatoxim.n 1.5   Delta'd: 14:42:09 1/24/90   Mike Lijewski, CNSF
X.\"
X.TH RLATOXIM 1 "July 7,  1989"
X.UC 5
X.SH NAME
Xrlatoxim \- converting from Wavefront Technologies "rla" files to "xim" format.
X.SH SYNOPSIS
X.B rlatoxim
X[-a]
X[-in 
X.I rlafile
X] [-out
X.I ximfile
X]
X
X.SH DESCRIPTION
X.I rlatoxim
Xconverts color "rla" files to "xim" files.  Rla files are always produced
Xby Wavefront software in Big-Endian byte format.  Rlatoxim will work
Xcorrectly from Big- or Little Endian machines.
X
X.SH OPTIONS
X.TP "\w'\f3\-m\f1name 'u"
X.B -in \fIfile\fP
XThis option allows the user to explicitly specify the input file on the command line.  The default is to read input from standard in.
X.TP "\w'\f3\-m\f1name 'u"
X.B -out \fIfile\fP
XThis option allows the user to explicitly specify the output file on the command line.
XThe default is to write output to standard out.
X.TP "\w'\f3\-m\f1name 'u"
X.B -a
XThis option displays the image using only the active part of the image. The
Xdefault is to display the active image centered in the full window.
X
X.SH "SEE ALSO"
Xxim(1), xtoxim(1)
X
X.SH BUGS
XThe rla format contains much information including matte and image channels
Xwhich the xim format ignores.
X.br
XWe currently only handle "rla" files containing 3-channel rgb data.
X.br
XRla images have their origins in the bottom-left while xim have theirs in the top-left.
X.SH AUTHOR
X.br
XMike Lijewski  (mjlx@cornellf.tn.cornell.edu)
X
SHAR_EOF
chmod 0666 rlatoxim.n || echo "restore of rlatoxim.n fails"
sed 's/^X//' << 'SHAR_EOF' > rletoxim.c &&
X/***********************************************************************
X*
X*  @(#) rletoxim.c 1.7   Delta'd: 11:40:57 10/19/89   Mike Lijewski, CNSF
X*
X*   rletoxim - transforms a run length encoded rgb file into an xim file.
X*
X***********************************************************************/
X
X#include <stdio.h>
X#ifdef SYSV
X#include <fcntl.h>
X#include <string.h>
X#define rindex strrchr
X#else
X#include <strings.h>
X#include <sys/file.h>
X#endif
X#include "ImageHeader.h"
X
Xextern int atoi();
Xextern int fclose();
Xextern int pclose();
Xextern char *calloc();
Xextern char *rindex();
Xextern void error();
Xextern void exit();
Xextern FILE *fopen();
X
X/*
X *  Some machines do not like signed chars.  If when you compile
X *  this code you get messages to this effect, try compiling with
X *  the NO_SIGNED_CHAR preprocessor variable defined.
X */
X
X#ifdef NO_SIGNED_CHAR
X#define SIGNED
X#else
X#define SIGNED signed
X#endif
X                          
X#ifndef TRUE
X#define TRUE 1
X#endif
X#ifndef FALSE
X#define FALSE 0
X#endif
X
Xtypedef unsigned char byte;
X
Xchar  *progName;
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X    ImageHeader p_head; /* picture header */
X    int i, width =  0, height = 0;
X    int ierr, blen;
X    int readWidth = FALSE, readHeight = FALSE;
X    int (*closeFunc)() = fclose;
X    unsigned bufsize;
X    short scrap;
X    byte *red_buf, *grn_buf, *blu_buf;
X    byte *enc_red, *enc_grn, *enc_blu;
X    FILE *input = stdin, *output = stdout;
X    int nchannels = 3;  /* always 3 since this is rgb data */
X
X    progName = argv[0];
X
X    for(i = 1; i < argc; i++){
X        char *ptr = NULL;
X        if(strncmp(argv[i], "-i", 2) == 0){
X            ptr = rindex(argv[++i], '.');
X            if(ptr && strcmp(ptr, ".Z") == 0){
X                char popen_cmd[80];
X                (void)strcpy(popen_cmd, "zcat ");
X                (void)strcat(popen_cmd, argv[i]);
X                input = popen(popen_cmd, "r");
X		closeFunc = pclose;
X            }
X            else
X               input = fopen(argv[i], "r");
X            if(input == NULL)
X                error("Can't read input file: '%s'.", argv[i]);
X            continue;
X        }
X        if(strncmp(argv[i], "-o", 2) == 0){
X            if((output = fopen(argv[++i], "w")) == NULL)
X                error("Can't open '%s'\n", argv[i]);
X            continue;
X        }
X        if(strncmp(argv[i], "-w", 2) == 0){
X            width = atoi(argv[++i]);
X            readWidth = TRUE;
X            continue;
X        }
X        if(strncmp(argv[i], "-h", 2) == 0){
X            height = atoi(argv[++i]);
X            readHeight = TRUE;
X            continue;
X        }
X        error("Usage: %s -height n -width m [-in file][-out file]",
X               progName);
X    }
X
X    if(readWidth == FALSE || readHeight == FALSE){
X        if(readWidth == FALSE){
X            (void)fprintf(stderr, "WIDTH: ");
X            (void)fscanf(stdin, "%d", &width);
X        }
X        if(readHeight == FALSE){
X            (void)fprintf(stderr, "HEIGHT: ");
X            (void)fscanf(stdin, "%d", &height);
X        }
X    }
X
X    if(height < 1 || width < 1)
X        error("Active window must be non-NULL");
X
X    bufsize = (unsigned)height * width;
X
X    red_buf = (byte *)calloc(bufsize, 1);
X    grn_buf = (byte *)calloc(bufsize, 1);
X    blu_buf = (byte *)calloc(bufsize, 1);
X    enc_red = (byte *)calloc(width*2, 1);
X    enc_grn = (byte *)calloc(width*2, 1);
X    enc_blu = (byte *)calloc(width*2, 1);
X    if( red_buf == NULL || grn_buf == NULL || blu_buf == NULL ||
X        enc_red == NULL || enc_grn == NULL || enc_blu == NULL)
X        error("Can't calloc() color buffers.");
X
X    for(i = 0; i <= bufsize - width; i += width){
X        /* read red scanline */
X        ierr = fread(&scrap,2,1,input);
X        blen = scrap;
X        if(fread(&enc_red[0], blen, sizeof(char), input) != 1 || ierr != 1)
X            error("Couldn't read red scanline");
X        decode(&red_buf[i],&enc_red[0],blen);
X
X        /* read green scanline */
X        ierr = fread(&scrap,2,1,input);
X        blen = scrap;
X        if(fread(&enc_grn[0], blen, sizeof(char), input) != 1 || ierr != 1)
X            error("Couldn't read green scanline");
X        decode(&grn_buf[i],&enc_grn[0],blen);
X
X        /* read blue scanline */
X        ierr = fread(&scrap,2,1,input);
X        blen = scrap;
X        if(fread(&enc_blu[0], blen, sizeof(char), input) != 1 || ierr != 1)
X            error("Couldn't read blue scanline");
X        decode(&blu_buf[i],&enc_blu[0],blen);
X    }
X    (void)(*closeFunc)(input);
X
X    (void)sprintf(p_head.header_size,"%d", sizeof(ImageHeader));
X    (void)sprintf(p_head.file_version,"%d", IMAGE_VERSION);
X    (void)sprintf(p_head.image_width,"%d", width);
X    (void)sprintf(p_head.image_height,"%d", height);
X    (void)sprintf(p_head.num_channels,"%d", nchannels);
X    (void)fprintf(stderr, "Width %d  Height %d  nchannels %d\n",
X                           width, height, nchannels);
X
X    (void)fwrite((char *)&p_head, sizeof(ImageHeader), 1, output);
X    (void)fwrite((char *)red_buf, 1, (int)bufsize, output);
X    (void)fwrite((char *)grn_buf, 1, (int)bufsize, output);
X    (void)fwrite((char *)blu_buf, 1, (int)bufsize, output);
X    (void)fclose(output);
X    exit(0);
X}
X
X/* VARARGS1 */
Xvoid
Xerror(s1, s2) 
Xchar *s1, *s2;
X{
X    extern int errno, sys_nerr;
X    extern char *sys_errlist[];
X
X    (void)fprintf(stderr, "%c%s ERROR:%c\n",7,progName ,7);
X    (void)fprintf(stderr, s1, s2);
X    if(errno > 0 && errno < sys_nerr)
X        (void)fprintf(stderr," (%s)", sys_errlist[errno]);
X    (void)fprintf(stderr, "\n");
X    exit(1);
X}
Xdecode(rawval,encval,enclen)
Xint enclen;
Xbyte rawval[], encval[];
X{
X    int i, j, icount, curpos = 0;
X
X    for (i=0; i<enclen; i+=2) {
X		icount = encval[i] + 1;
X		for (j=0; j<icount; j++, curpos++) rawval[curpos] = encval[i+1];
X    }
X}
SHAR_EOF
chmod 0666 rletoxim.c || echo "restore of rletoxim.c fails"
sed 's/^X//' << 'SHAR_EOF' > runlen.c &&
X/* runlen.c
X*
X*  @(#) runlen.c 1.2   Delta'd: 13:25:22 1/10/90   Mike Lijewski, CNSF
X*
X*  purpose: To simple runlength encoding of an xim file.
X*  author:  philip thompson, 1987
X*  Copyright (c) 1989, Massachusetts Institute of Technology
X*                Philip R. Thompson
X*                Computer Resource Laboratory (CRL)
X*                Dept. of Architecture and Planning
X*                M.I.T., Rm 9-526
X*                Cambridge, MA  02139
X*   This  software and its documentation may be used, copied, modified,
X*   and distributed for any purpose without fee, provided:
X*       --  The above copyright notice appears in all copies.
X*       --  This disclaimer appears in all source code copies.
X*       --  The names of M.I.T. and the CRL are not used in advertising
X*           or publicity pertaining to distribution of the software
X*           without prior specific written permission from me or CRL.
X*   I provide this software freely as a public service.  It is NOT a
X*   commercial product, and therefore is not subject to an an implied
X*   warranty of merchantability or fitness for a particular purpose.  I
X*   provide it as is, without warranty.
X*/
X
X#include <stdio.h>
X#ifdef SYSV
X#include <string.h>
X#define rindex strrchr
X#else
X#include <strings.h>
X#endif
X#include "ImageHeader.h"
X
Xextern int      atoi();
Xextern void     error();
Xextern int      fread();
Xextern int      fwrite();
Xextern int      fprintf();
Xextern int      sprintf();
Xextern int      fclose();
Xextern int      pclose();
Xextern char    *rindex();
Xextern void     exit();
X
Xtypedef unsigned char byte;
X
Xchar           *progName;
X
Xint
Xmain(argc, argv)
X	int             argc;
X	char          **argv;
X{
X	int             i, compress_flag;	/* counters, flags, etc. */
X	byte            runlength, lastcolor, *scanLine;
X	char           *malloc();
X	FILE           *out_fd = stdout, *in_fd = stdin, *fopen(), *popen();
X	int             buf_width;	/* image width */
X	ImageHeader     p_head;	/* picture header */
X
X	progName = argv[0];
X	for (i = 1; i < argc; i++)
X	{
X		char           *ptr = NULL;
X		if (strncmp(argv[i], "-i", 2) == 0)
X		{		/* compressed file ? */
X			ptr = rindex(argv[++i], '.');
X			if (ptr && strcmp(ptr, ".Z") == 0)
X			{
X				char            popen_cmd[80];
X				(void) strcpy(popen_cmd, "zcat ");
X				(void) strcat(popen_cmd, argv[i]);
X				in_fd = popen(popen_cmd, "r");
X				compress_flag = 1;
X			} else if ((in_fd = fopen(argv[i], "r")) == NULL)
X				error("Can't open input file: %s ", argv[i]);
X			continue;
X		}
X		if (strncmp(argv[i], "-o", 2) == 0)
X		{
X			if ((out_fd = fopen(argv[++i], "w")) == NULL)
X				error("Can't open %s\n", argv[i]);
X			continue;
X		}
X		error("Usage: %s [-in <file>] [-out <file>]", progName);
X	}
X
X	if (fread((char *) &p_head, sizeof(ImageHeader), 1, in_fd) != 1)
X		error("Unable to read file header", "\0");
X	if (atoi(p_head.header_size) != sizeof(ImageHeader))
X		error("Header size mismatch", "\0");
X	if ((atoi(p_head.file_version)) != IMAGE_VERSION)
X		error("Incorrect Image_file Version.", "\0");
X	buf_width = atoi(p_head.image_width);
X	if ((atoi(p_head.runlength)) != 0)
X		error("File is already runlength encoded");
X	(void) fprintf(stderr, "Author: %s \nDate: %s\n", p_head.author,
X		       p_head.date);
X	(void) sprintf(p_head.runlength, "%d", 1);
X	(void) fwrite((char *) &p_head, sizeof(ImageHeader), 1, out_fd);
X
X	if ((scanLine = (byte *) malloc((unsigned) buf_width)) == NULL)
X		error("scanLine: malloc error", "\0");
X
X	while (fread((char *) scanLine, 1, buf_width, in_fd) > 0)
X	{
X		runlength = 0;
X		lastcolor = scanLine[0];
X		for (i = 1; i < buf_width; i++)
X			if (runlength == 255 || scanLine[i] != lastcolor)
X			{
X				(void) fwrite((char *) &runlength, 1, 1, out_fd);
X				(void) fwrite((char *) &lastcolor, 1, 1, out_fd);
X				runlength = 0;
X				lastcolor = scanLine[i];
X			} else
X				runlength++;
X		(void) fwrite((char *) &runlength, sizeof(byte), 1, out_fd);
X		(void) fwrite((char *) &lastcolor, sizeof(byte), 1, out_fd);
X	}
X	if (compress_flag)
X		(void) pclose(in_fd);
X	else
X		(void) fclose(in_fd);
X	(void) fclose(out_fd);
X	return (0);
X}
X
X/* VARARGS1 */
Xvoid
Xerror(s1, s2)
X	char           *s1, *s2;
X{
X	extern int      errno, sys_nerr;
X	extern char    *sys_errlist[];
X
X	(void) fprintf(stderr, "%c%s ERROR:%c\n", 7, progName, 7);
X	(void) fprintf(stderr, s1, s2);
X	if (errno > 0 && errno < sys_nerr)
X		(void) fprintf(stderr, " (%s)", sys_errlist[errno]);
X	(void) fprintf(stderr, "\n");
X	exit(1);
X}
X
X/*** end runlen.c ***/
SHAR_EOF
chmod 0666 runlen.c || echo "restore of runlen.c fails"
sed 's/^X//' << 'SHAR_EOF' > smoothim.c &&
X/*
X*
X*    @(#) smoothim.c 1.2   Delta'd: 13:25:23 1/10/90   Mike Lijewski, CNSF
X*
X*    Copyright (c) 1988  University of Southern California
X*    USC Information Sciences Institute
X*    4676 Admiralty Way
X*    Marina del Rey, California 90292
X*
X*  Function:
X*    This is a somewhat experimental program to enhance pixmaps
X*    which have some degree of noise in their data.  Today's
X*    algorithm does weighted averaging of pixels in a 5x5 cell
X*    around each target pixel, but only for those pixels within
X*    some given RGB range of the target.
X*
X*    thresh is the RGB distance threshold, defaulted to 50.
X*    Neighboring pixels are averaged only if their RGB displacement
X*    from the target pixel is less than thresh.
X*
X*  Module history:
X*    3-19-88     Paul Raveling Created enhance from a copy of propix.
X*    1-31-89     Philip Thompson - greatly stripped and modified.
X*                Copyright (c) 1989, M.I.T.
X*                Computer Resource Laboratory
X*                Dept. of Architecture and Planning
X*/
X
X#include <stdio.h>
X#ifdef SYSV
X#include <string.h>
X#include <memory.h>
X#define rindex strrchr
X#else
X#include <strings.h>
X#endif
X#include "ImageHeader.h"
X
Xextern int      atoi();
Xextern void     error();
Xextern int      fprintf();
Xextern int      fread();
Xextern int      fwrite();
Xextern void     free();
Xextern char    *rindex();
Xextern void     bcopy();
Xextern void     exit();
Xextern void     rgbtocol();
Xextern void     scancol5();
X
Xtypedef unsigned char byte;
Xtypedef struct _Color
X{
X	byte            red, green, blue;
X}               Color;
X
Xint             T = 50;		/* Distance threshold for pixel averaging */
Xchar           *progName, *malloc(), *calloc();
X
Xint
Xmain(argc, argv)
X	int             argc;
X	char          **argv;
X{
X	register        i;
X	Color          *colpix = NULL;	/* Pixmap as a Color array  */
X	Color          *newcpx = NULL;	/* New copy of pixel Color data */
X	byte           *red_buf, *grn_buf, *blu_buf;
X	FILE           *out_fp = stdout, *in_fp = stdin, *popen(), *fopen();
X	extern int      pclose(), fclose();
X	int             (*closefunc) () = fclose;
X	int             p_width, p_height, bufsize;	/* image size  */
X	int             ncolors = 0, nchannels = 0;
X	ImageHeader     p_head;	/* picture header */
X
X	progName = argv[0];
X	for (i = 1; i < argc; i++)
X	{
X		if (strncmp(argv[i], "-i", 2) == 0)
X		{
X			char           *ptr = rindex(argv[++i], '.');
X			if (ptr && strcmp(ptr, ".Z") == 0)
X			{	/* compressed file */
X				char            popen_cmd[80];
X				(void) strcpy(popen_cmd, "zcat ");
X				(void) strcat(popen_cmd, argv[i]);
X				in_fp = popen(popen_cmd, "r");
X				closefunc = pclose;
X			} else
X				in_fp = fopen(argv[i], "r");
X			if (in_fp == NULL)
X				error("Can't open input file: %s ", argv[i]);
X			continue;
X		}
X		if (strncmp(argv[i], "-o", 2) == 0)
X		{
X			if ((out_fp = fopen(argv[++i], "w")) == NULL)
X				error("Can't open %s\n", argv[i]);
X			continue;
X		}
X		if (strncmp(argv[i], "-t", 2) == 0)
X		{
X			T = atoi(argv[++i]);
X			continue;
X		}
X		fprintf(stderr, "Usage: %s [-in file][-out file][-thresh #]",
X			progName);
X	}
X	if (fread((char *) &p_head, sizeof(ImageHeader), 1, in_fp) != 1)
X		error("Can't read header.");
X	if (atoi(p_head.header_size) != sizeof(ImageHeader))
X		error("Header size mismatch", "\0");
X	if (atoi(p_head.file_version) != IMAGE_VERSION)
X		error("Incorrect image file Version", "\0");
X	p_width = atoi(p_head.image_width);
X	p_height = atoi(p_head.image_height);
X	nchannels = atoi(p_head.num_channels);
X	(void) fprintf(stderr, "Made by: %s   Program: %s\n", p_head.author,
X		       p_head.program);
X	(void) fprintf(stderr,
X		       "Width: %d  Height: %d\n ncolors: %d  nchannels %d\n",
X		       p_width, p_height, ncolors, nchannels);
X	bufsize = p_width * p_height;
X	if (nchannels <= 1)
X		error("Image must be in 24 bit (3 channel) format.");
X
X	colpix = (Color *) calloc((unsigned) bufsize, sizeof(Color));
X	if (colpix == NULL)
X		error("Insufficient memory for copy of image\n");
X
X	red_buf = (byte *) malloc((unsigned) bufsize);
X	grn_buf = (byte *) malloc((unsigned) bufsize);
X	blu_buf = (byte *) malloc((unsigned) bufsize);
X	if ((red_buf == NULL) || (grn_buf == NULL) || (blu_buf == NULL))
X		error("Can't malloc rgb buffers");
X	if (fread((char *) red_buf, 1, (int) bufsize, in_fp) != bufsize)
X		error("error reading RED buffer");
X	if (fread((char *) grn_buf, 1, (int) bufsize, in_fp) != bufsize)
X		error("error reading GREEN buffer");
X	if (fread((char *) blu_buf, 1, (int) bufsize, in_fp) != bufsize)
X		error("error reading BLUE buffer");
X	(void) (*closefunc) (in_fp);
X
X	rgbtocol(red_buf, grn_buf, blu_buf, bufsize, colpix);
X	free((char *) red_buf);
X	free((char *) grn_buf);
X	free((char *) blu_buf);
X
X	fprintf(stderr, "Processing image...\n");
X	newcpx = (Color *) calloc((unsigned) bufsize, sizeof(Color));
X	if (newcpx == NULL)
X		error("Insufficient memory for copy of image\n");
X	scancol5(colpix, newcpx, p_width, p_height);
X	free((char *) colpix);
X
X	red_buf = (byte *) malloc((unsigned) bufsize);
X	grn_buf = (byte *) malloc((unsigned) bufsize);
X	blu_buf = (byte *) malloc((unsigned) bufsize);
X	if ((red_buf == NULL) || (grn_buf == NULL) || (blu_buf == NULL))
X		error("Can't malloc buffer\n");
X	for (i = 0; i < bufsize; i++)
X	{
X		red_buf[i] = newcpx[i].red;
X		grn_buf[i] = newcpx[i].green;
X		blu_buf[i] = newcpx[i].blue;
X	}
X	/* Write the file */
X	(void) fwrite((char *) &p_head, sizeof(ImageHeader), 1, out_fp);
X	(void) fwrite((char *) red_buf, 1, bufsize, out_fp);
X	(void) fwrite((char *) grn_buf, 1, bufsize, out_fp);
X	(void) fwrite((char *) blu_buf, 1, bufsize, out_fp);
X	(void) fclose(out_fp);
X	return (0);
X}
X
Xvoid
Xrgbtocol(red, grn, blu, bufsize, colpix)
X	byte           *red, *grn, *blu;
X	int             bufsize;
X	Color          *colpix;
X{
X	register int    i;
X	register Color *pc;
X
X	for (i = 0, pc = colpix; i < bufsize; i++, pc++)
X	{
X		pc->red = red[i];
X		pc->green = grn[i];
X		pc->blue = blu[i];
X	}
X}
X
X
X/******
X  Functions: scancol5 ()
X
X    Scan the current pixmap to process each pixel as the
X    "target pixel" at the center of a 5x5 array of pixels.
X
X    This is a "template" for image processing functions.
X    it supplies reasonably optimized logic for addressing
X    the pixels in place; just add the required manipulations.
X
X    At present, the scan only deals with target pixels which
X    have a full set of neighbors.  Pixels in the top, bottom,
X    left, and right pairs of rows and columns of pixels are omitted
X    from the scan.
X
X  Input:    No parameters in function invocation;
X        Global data:
X    colpix      Color   *
X            Pointer to pixel data as Color array
X    pix     struct ii_pixmap  *
X            Pointer to pixmap descriptor
X  Output:   None as return value;
X        Global data:
X    colpix      Color   *
X            Pointer to pixel data as Color array
X  Notes:
X    Separate pointers address the target pixel and its neighbors.
X    Their names are:
X
X        -----------------------------------------
X        |  p00  |  p01  |  p02  |  p03  |  p04  |
X        |-------|-------|-------|-------|-------|
X        |  p10  |  p11  |  p12  |  p13  |  p14  |
X        |-------|-------|-------|-------|-------|
X        |  p20  |  p21  |   p   |  p23  |  p24  |
X        |-------|-------|-------|-------|-------|
X        |  p30  |  p31  |  p32  |  p33  |  p34  |
X        |-------|-------|-------|-------|-------|
X        |  p40  |  p41  |  p42  |  p43  |  p44  |
X        -----------------------------------------
X    Use of separate pointers is likely to involve some degree
X    of iteration when editing the processing algorithm, but
X    it eliminates it during execution.  Honest, this is
X    deliberate!
X    The name of the target pixel pointer in the destination
X    color array is:
X      tp    Target pixel in destination color array
X*/
X
Xvoid
Xscancol5(colpix, newcpx, width, height)
X	Color          *colpix, *newcpx;
X	int             width, height;
X{
X	register Color *p;	/* Pointer to target pixel */
X	Color          *p00, *p01, *p02, *p03, *p04;	/* Pointers to
X							 * neighbors: */
X	Color          *p10, *p11, *p12, *p13, *p14;
X	Color          *p20, *p21, *p23, *p24;
X	Color          *p30, *p31, *p32, *p33, *p34;
X	Color          *p40, *p41, *p42, *p43, *p44;
X	Color          *tp;	/* Pointer to dest. target */
X	int             iy;	/* Counter for # rows to scan  */
X	int             ny;	/* Total # rows to scan    */
X	int             ix;	/* Counter for # col's to scan */
X	int             nx;	/* Total # columns to scan */
X	int             sumw;	/* Sum of weights      */
X	int             wsumr;	/* Weighted sum of reds    */
X	int             wsumg;	/* Weighted sum of greens  */
X	int             wsumb;	/* Weighted sum of blues   */
X	int             dr;	/* Delta Red   between 2 pixels */
X	int             dg;	/* Delta Green between 2 pixels */
X	int             db;	/* Delta Blue  between 2 pixels */
X	int             ri;	/* Rounding increment      */
X
X	p00 = colpix;
X	p01 = &colpix[1];
X	p02 = &colpix[2];	/* Set pointers to row 0   */
X	p03 = &colpix[3];
X	p04 = &colpix[4];
X	p10 = &colpix[width];
X	p11 = &colpix[width + 1];
X	p12 = &colpix[width + 2];	/* Set pointers to row 1   */
X	p13 = &colpix[width + 3];
X	p14 = &colpix[width + 4];
X	p20 = &colpix[2 * width];
X	p21 = &colpix[2 * width + 1];
X	p = &colpix[2 * width + 2];	/* Set pointers to row 2   */
X	tp = &newcpx[2 * width + 2];	/* Set ptr to 1st dest. pixel  */
X	p23 = &colpix[2 * width + 3];
X	p24 = &colpix[2 * width + 4];
X	p30 = &colpix[3 * width];
X	p31 = &colpix[3 * width + 1];
X	p32 = &colpix[3 * width + 2];	/* Set pointers to row 3   */
X	p33 = &colpix[3 * width + 3];
X	p34 = &colpix[3 * width + 4];
X	p40 = &colpix[4 * width];
X	p41 = &colpix[4 * width + 1];
X	p42 = &colpix[4 * width + 2];	/* Set pointers to row 4   */
X	p43 = &colpix[4 * width + 3];
X	p44 = &colpix[4 * width + 4];
X#ifdef SYSV
X	memcpy((char *) newcpx, (char *) colpix, (width * height * sizeof(Color)));
X#else
X	bcopy((char *) colpix, (char *) newcpx, (width * height * sizeof(Color)));
X#endif
X
X/* Initialize pointers and counters  */
X	nx = width - 4;		/* Set to scan (width-4) columns,  */
X	ny = height - 5;	/* (height-4) rows         */
X/*  Scan pixmap data    */
X	for (iy = 0; iy < ny; ++iy)
X	{			/* For each row of pixels... */
X		for (ix = 0; ix < nx; ++ix)
X		{		/* For each pixel in row... */
X			/*
X			 * Compute weighted average of target pixel color
X			 * components with neighboring pixels of
X			 * approximately the same color. Weights assume that
X			 * the importance of neighboring pixels is inversely
X			 * proportional to the square of their distance from
X			 * the target pixel.
X			 */
X			sumw = 0;
X			wsumr = 0;	/* Preset sum of weights and   */
X			wsumg = 0;	/* weighted averages to 0  */
X			wsumb = 0;
X
X/*  Determine RGB distances between pixels p & q    */
X#define dcr(q)  dr=(p->red)-(q->red);if (dr<0) dr= -dr;
X#define dcg(q)  dg=(p->green)-(q->green);if (dg<0) dg= -dg;
X#define dcb(q)  db=(p->blue)-(q->blue);if (db<0) db= -db;
X
X/*  Account for pixel q in weighted averages    */
X#define av(q,w)   sumw+=w;\
X          wsumr+=w*(q->red);wsumg+=w*(q->green);wsumb+=w*(q->blue);
X
X/*  Conditionally average pixel q with pixel p  */
X#define ca(q,w)   dcr(q);dcg(q);dcb(q);if((dr+dg+db)<T){av(q,w)}
X
X			/* Do it to it */
X			ca(p00, 5)
X				ca(p01, 8)
X				ca(p02, 10)	/* Top row in 5x5 cell     */
X				ca(p03, 8)
X				ca(p04, 5)
X				ca(p10, 8)
X				ca(p11, 20)
X				ca(p12, 40)	/* Row between target & top    */
X				ca(p13, 20)
X				ca(p14, 8)
X				ca(p20, 10)
X				ca(p21, 40)
X				av(p, 80)	/* Target pixel row        */
X				ca(p23, 40)
X				ca(p24, 10)
X				ca(p30, 8)
X				ca(p31, 20)
X				ca(p32, 40)	/* Row between target &
X						 * bottom */
X				ca(p33, 20)
X				ca(p34, 8)
X				ca(p40, 5)
X				ca(p41, 8)
X				ca(p42, 10)	/* Bottom row in 5x5 cell  */
X				ca(p43, 8)
X				ca(p44, 5)
X				ri = (sumw >> 1) - 1;	/* Derive rounding
X							 * increment   */
X
X			/*
X			 * Destination copy of target pixel = weighted RGB
X			 * average derived above
X			 */
X			tp->red = (wsumr + ri) / sumw;
X			tp->green = (wsumg + ri) / sumw;
X			tp->blue = (wsumb + ri) / sumw;
X
X			++p00;	/* Advance to next pixel       */
X			++p01;
X			++p02;
X			++p03;
X			++p04;
X			++p10;
X			++p11;
X			++p12;
X			++p13;
X			++p14;
X			++p20;
X			++p21;
X			++p;
X			++tp;
X			++p23;
X			++p24;
X			++p30;
X			++p31;
X			++p32;
X			++p33;
X			++p34;
X			++p40;
X			++p41;
X			++p42;
X			++p43;
X			++p44;
X		}
X
X		/* Skip pixels at beginning and end of row as target pixels  */
X		p00 += 4;
X		p01 += 4;
X		p02 += 4;
X		p03 += 4;
X		p04 += 4;
X		p10 += 4;
X		p11 += 4;
X		p12 += 4;
X		p13 += 4;
X		p14 += 4;
X		p20 += 4;
X		p21 += 4;
X		p += 4;
X		tp += 4;
X		p23 += 4;
X		p24 += 4;
X		p30 += 4;
X		p31 += 4;
X		p32 += 4;
X		p33 += 4;
X		p34 += 4;
X		p40 += 4;
X		p41 += 4;
X		p42 += 4;
X		p43 += 4;
X		p44 += 4;
X	}
X}
X
X/*VARARGS1*/
Xvoid
Xerror(s1, s2)
X	char           *s1, *s2;
X{
X	extern int      errno, sys_nerr;
X	extern char    *sys_errlist[];
X
X	(void) fprintf(stderr, "%c%s ERROR:%c\n", 7, progName, 7);
X	(void) fprintf(stderr, s1, s2);
X	if (errno > 0 && errno < sys_nerr)
X		(void) fprintf(stderr, " (%s)", sys_errlist[errno]);
X	(void) fprintf(stderr, "\n");
X	exit(1);
X}
X
X/* end smooth.c */
SHAR_EOF
chmod 0666 smoothim.c || echo "restore of smoothim.c fails"
sed 's/^X//' << 'SHAR_EOF' > smoothim.n &&
X.TH SMOOTHIM 1 "February 3,  1989"
X.UC 5
X.SH NAME
Xsmoothim \- smooth out and reduce noise in a 24 bit/pixel image.
X.SH SYNOPSIS
X.B smoothim
X[-in 
X.I file
X] [-out
X.I file
X] [-thresh
X.I level]
X
X.SH DESCRIPTION
X.I Smoothim
Xis a program for reducing the noise often found in scanned or digitized  images.
XWe use it here primarily for reducing noise from digitized video images.
XAt the heart of this program is the
X.I scancols
Xalgorithm written at the USC Information Sciences Institute.
XIt does a weighted averaging of pixels in a 5x5 cell around each target pixel, but only for those pixels within some given RGB range of the target.
XA decrease in overall image sharpness may result.
X.SH OPTIONS
X.TP "\w'\f3\-m\f1name 'u"
X.B -in \fIfile\fP
XThis option allows the user to explicitly specify the 24 bit/pixel file on the command line.
XThe default is to read input from standard in.
X.TP "\w'\f3\-m\f1name 'u"
X.B -out \fIfile\fP
XThis option allows the user to explicitly specify the output file on the command line.
XThe default is to write output to standard out.
X.TP "\w'\f3\-m\f1name 'u"
X.B -thresh \fIdist\fP
Xdist is the RGB distance threshold, defaulted to 50.
XNeighboring pixels are averaged only if their RGB displacement
Xfrom the target pixel is less than dist.
XHigher distances have a more pronounced effect, but may increase blurring of the image.
X.PP
X.I Note:
XAll of the command line options can be abbreviated to their shortest unique spelling.
X.br
Xex: %  smoothin -in colord24.xim -out smooth.xim -th=25
X
X.SH "SEE ALSO"
Xxim(1), quantizim(1)
X
X.SH BUGS
XThis program takes a lot of memory.
X.SH COPYRIGHTS
XCopyright 1989, Massachusetts Institute of Technology.
XCopyright 1988, University of Southern California
X.SH AUTHORS
XPaul Raveling (vaxa.isi.edu) - scancols.c
X.PP
XPhilip R. Thompson (phils@athena.mit.edu) - smoothim.c
X.br
XComputer Resource Laboratory,  
XDept. of Architecture and Planning,  
X.br
XMassachusetts Institute of Technology,  
XCambridge, MA  02139
X
SHAR_EOF
chmod 0666 smoothim.n || echo "restore of smoothim.n fails"
sed 's/^X//' << 'SHAR_EOF' > xim.c &&
X/*
X *
X *  @(#) xim.c 1.19   Delta'd: 17:30:55 4/3/90   Mike Lijewski, CNSF
X *
X *  File:   xim.c
X *  Author: Philip Thompson
X *
X *  Modified extensively by Mike Lijewski.
X *
X *  Purpose: To view a variety of images on X displays and make them
X *       suitable for printing as bitmaps.  "Xim" displays images up to
X *       24-bits deep with an 'ImageHeader' on 8-bit color and bitmap
X *       displays.  Various dithering and halftoning techniques are used
X *       to achieve this image portability.
X *
X *  Copyright (c) 1988  Philip R. Thompson
X *                Computer Resource Laboratory (CRL)
X *                Dept. of Architecture and Planning
X *                M.I.T., Rm 9-526
X *                Cambridge, MA  02139
X *
X *   This  software and its documentation may be used, copied, modified,
X *   and distributed for any purpose without fee, provided:
X *       --  The above copyright notice appears in all copies.
X *       --  This disclaimer appears in all source code copies.
X *       --  The names of M.I.T. and the CRL are not used in advertising
X *           or publicity pertaining to distribution of the software
X *           without prior specific written permission from me or CRL.
X *   I provide this software freely as a public service.  It is NOT a
X *   commercial product, and therefore is not subject to an an implied
X *   warranty of merchantability or fitness for a particular purpose.  I
X *   provide it as is, without warranty. This software was not sponsored,
X *   developed or connected with any grants, funds, salaries, etc.
X *
X *   This software is furnished  only on the basis that any party who
X *   receives it indemnifies and holds harmless the parties who furnish
X *   it against any claims, demands, or liabilities connected with using
X *   it, furnishing it to others, or providing it to a third party.
X *
X *   Philip R. Thompson (phils@athena.mit.edu)
X */
X
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/cursorfont.h>
X#include <stdio.h>
X#include "ImageHeader.h"
X#include "declarations.h"
X
Xint
Xmain(argc, argv)
X    int             argc;
X    char          **argv;
X{
X    register        i, j, k;
X    register byte  *buffer, *grn_buf, *blu_buf, *icon_buf;
X    unsigned        buf_size;
X    int             icon_width, icon_height, iconfact, iconfact_old = 0;
X    int             buf_width, buf_height, ncolors, nchannels, npics;
X    int             buf_width_old = 0, buf_height_old = 0;
X    int             modN[256], divN[256];
X    int             existing_window = 0;
X    char           *win_name = NULL, *display_name = NULL;
X    char            text[8];	/* buffer for keyboard read */
X    Bool            inverse_flag = False, mono_flag = False, cdither_flag = False;
X    Bool            runlen_flag = False;
X    Bool            done = False;	/* main loop done ? */
X    FILE           *in_fp = stdin, *popen(), *fopen();
X    int             (*closeFunc) () = fclose;
X    ImageHeader     p_head;
X    XColor          colors[256], fg_color, bg_color;
X    Window          image_win, icon_win;
X    Colormap        colormap;
X    XEvent          event;
X    XExposeEvent   *expose;
X    XCrossingEvent *xcrossing;
X    GC              image_gc, icon_gc;
X    XGCValues       gc_val;
X    XSetWindowAttributes xswa;
X    XImage         *image = NULL, *icon_image = NULL;
X    XSizeHints      sizehints;
X    XWMHints        wmhints;
X    XWindowChanges  image_changes, icon_changes;
X
X    progName = argv[0];
X
X    /*
X     * parse arguments
X     */
X    for (i = 1; i < argc; i++)
X    {
X	char           *ptr = NULL;
X	if (strncmp(argv[i], "-dis", 4) == 0)
X	{
X	    display_name = argv[++i];
X	    continue;
X	}
X	if (strcmp(argv[i], "-in") == 0)
X	{			/* compressed file ? */
X	    ptr = rindex(argv[++i], '.');
X	    if (ptr && strcmp(ptr, ".Z") == 0)
X	    {
X		char            popen_cmd[80];
X		(VOID) strcpy(popen_cmd, "zcat ");
X		(VOID) strcat(popen_cmd, argv[i]);
X		in_fp = popen(popen_cmd, "r");
X		closeFunc = pclose;
X	    }
X	    else
X		in_fp = fopen(argv[i], "r");
X
X	    if (in_fp == NULL)
X		error("Can't open input file: %s ", argv[i]);
X	    win_name = argv[i];
X	    continue;
X	}
X	if (strncmp(argv[i], "-mf", 3) == 0)
X	{
X	    if ((ptr = rindex(argv[i], '=')) != NULL)
X		(VOID) sscanf(ptr + 1, "%d", &threshold);
X	    bw = mfs_bw;
X	    mono_flag = True;
X	    continue;
X	}
X	if (strncmp(argv[i], "-fs", 3) == 0)
X	{			/* default */
X	    if ((ptr = rindex(argv[i], '=')) != NULL)
X		(VOID) sscanf(ptr + 1, "%d", &threshold);
X	    bw = fs_bw;
X	    mono_flag = True;
X	    continue;
X	}
X	if (strncmp(argv[i], "-dit", 4) == 0)
X	{
X	    if ((ptr = rindex(argv[i], '=')) != NULL)
X	    {
X		(VOID) sscanf(ptr + 1, "%d", &ditherFactor);
X		dm = &(dm4[0][0]);
X	    }
X	    bw = dither_bw;
X	    cdither_flag = True;
X	    continue;
X	}
X	if (strncmp(argv[i], "-en", 3) == 0)
X	{
X	    if ((ptr = rindex(argv[i], '=')) != NULL)
X		(VOID) sscanf(ptr + 1, "%d", &enhance);
X	    else
X		enhance = 9;
X	    continue;
X	}
X	if (strncmp(argv[i], "-ru", 3) == 0)
X	{
X	    runlen_flag = True;
X	    continue;
X	}
X	if (strncmp(argv[i], "-re", 3) == 0)
X	{
X	    inverse_flag = True;
X	    continue;
X	}
X	if (strncmp(argv[i], "-mo", 3) == 0)
X	{
X	    mono_flag = True;
X	    continue;
X	}
X	if (strncmp(argv[i], "-cm", 3) == 0)
X	{
X	    continue;
X	}
X	error("Usage: %s [-in <file>][-display <host>][-reverse][-cmap]\
X    \n[-mono][-dither[=4] | -mfs][-enhance[=1-9]][-runlen]\n", progName);
X    }
X
X    /*
X     * Open the display & set defaults
X     */
X    if ((dpy = XOpenDisplay(display_name)) == NULL)
X	error("Can't open display '%s'", XDisplayName(display_name));
X    screen = DefaultScreen(dpy);
X    root_win = DefaultRootWindow(dpy);
X    visual = DefaultVisual(dpy, screen);
X    blackpixel = BlackPixel(dpy, screen);
X    whitepixel = WhitePixel(dpy, screen);
X
X    if (DisplayPlanes(dpy, screen) == 1)
X	mono_flag = True;
X
X    if (cdither_flag)
X    {
X	if (mono_flag)
X	{
X	    cdither_flag = False;	/* mono flag wins */
X	    if (ditherFactor != 4 && ditherFactor != 8)
X		error("Dither size must be 4 or 8 in monochrome.");
X	}
X	else if (ditherFactor < 2 || ditherFactor > 8)
X	    error("Dither level must be from 2 to 8 in color");
X    }
X/*
X * This is the label we jump to if a right button is pressed, indicating
X * that there is more than one image in the file.
X */
Xdisplay_next:
X
X    /*
X     * Read header and verify image file formats
X     */
X    if (fread((char *) &p_head, sizeof(ImageHeader), 1, in_fp) != 1)
X	error("Unable to read file header");
X    if (atoi(p_head.header_size) != sizeof(ImageHeader))
X	error("Header size mismatch");
X    if (atoi(p_head.file_version) != IMAGE_VERSION)
X	error("Incorrect Image_file Version.");
X    buf_width = atoi(p_head.image_width);
X    buf_height = atoi(p_head.image_height);
X    if (atoi(p_head.runlength))
X	runlen_flag = True;
X    (VOID) fprintf(stderr, "Author: %s\nDate: %s\n", p_head.author,
X		   p_head.date);
X    (VOID) fprintf(stderr, "Size: %d x %d   ", buf_width, buf_height);
X    ncolors = atoi(p_head.num_colors);
X    nchannels = atoi(p_head.num_channels);
X    npics = atoi(p_head.num_pictures);
X    buf_size = (unsigned) (buf_width * buf_height);
X
X    /*
X     * Get or make the color table.
X     */
X    if (nchannels >= 3 || cdither_flag)
X    {
X	(VOID) fprintf(stderr, "nchannels %d\n", nchannels);
X	if (mono_flag)		/* make map of grey values 0-65535 */
X	    for (i = 0; i < ncolors; i++)
X	    {
X		colors[i].pixel = (u_long) i;
X		colors[i].red = colors[i].green =
X		    colors[i].blue = (u_short) (i << 8);
X	    }
X	else
X	{
X	    /* make color dither map with correct depth */
X	    for (i = ditherFactor; i > 1; i--)
X		if ((i * i * i) <= DisplayCells(dpy, screen))
X		    break;
X	    ncolors = i * i * i;
X	    ditherFactor = i;
X	    make_dithermap(ditherFactor, colors, divN, modN, dm16);
X	}
X    }
X    else
X    {
X	/* use provided colormap */
X	(VOID) fprintf(stderr, "ncolors %d\n", ncolors);
X	for (i = 0; i < ncolors; i++)
X	{
X	    colors[i].pixel = (u_long) i;
X	    colors[i].red = (u_short) (p_head.c_map[i][0] << 8);
X	    colors[i].green = (u_short) (p_head.c_map[i][1] << 8);
X	    colors[i].blue = (u_short) (p_head.c_map[i][2] << 8);
X	    colors[i].flags = DoRed | DoGreen | DoBlue;
X	}
X    }
X
X    if (inverse_flag)
X	for (i = 0; i < ncolors; i++)
X	{
X	    colors[i].red = ~colors[i].red;
X	    colors[i].green = ~colors[i].green;
X	    colors[i].blue = ~colors[i].blue;
X	}
X
X    /*
X     * Allocate and read the data buffer(s)
X     */
X    if ((buffer = (byte *) malloc(buf_size)) == NULL)
X	error("Can't malloc() image buffer.");
X    read_image_buf(in_fp, buffer, &buf_size, runlen_flag);
X    if (nchannels >= 3)
X    {
X	grn_buf = (byte *) malloc(buf_size);
X	blu_buf = (byte *) malloc(buf_size);
X	if (grn_buf == NULL || blu_buf == NULL)
X	    error("Can't malloc() channel buffers.");
X	read_image_buf(in_fp, grn_buf, &buf_size, runlen_flag);
X	read_image_buf(in_fp, blu_buf, &buf_size, runlen_flag);
X    }
X
X    /*
X     * Allocate the icon with max. dimension of 100 or 50
X     */
X    iconfact = RND(buf_height / 100.0) > RND(buf_width / 100.0) ?
X	RND(buf_height / 100.0) : RND(buf_width / 100.0);
X    if (iconfact == 0)
X	iconfact = 1;
X    if ((icon_width = buf_width / iconfact) % 2)	/* even for XPutImage */
X	icon_width -= 1;
X    icon_height = buf_height / iconfact;
X    if ((icon_buf = (byte *) malloc((unsigned) icon_width * icon_height)) == NULL)
X	error("Can't malloc() icon buffer");
X
X    /*
X     * process and store the image and icon.
X     */
X    if (mono_flag)
X    {				/* make a bitmap image, but first */
X	if (nchannels >= 3)
X	{			/* convert to 8-bit grey values */
X	    for (i = 0; i < buf_size; i++)
X		buffer[i] = (byte) grey_value((u_short) buffer[i],
X				(u_short) grn_buf[i], (u_short) blu_buf[i]);
X	    if (npics <= 1)
X	    {
X		free((char *) grn_buf);
X		free((char *) blu_buf);
X	    }
X	}
X	else
X	    color_to_bw(buffer, buf_size, colors, &ncolors);
X	if (bw == dither_bw)
X	    normalize_dm(ditherFactor);
X	for (i = 0, k = 0; i < icon_height; i++)	/* sample image for icon */
X	    for (j = 0; j < icon_width; j++, k++)
X		icon_buf[k] = buffer[(i * buf_width + j) * iconfact];
X	if (enhance)
X	{
X	    edge_enhance(buffer, buf_width, buf_height, buf_size);
X	    edge_enhance(icon_buf, icon_width, icon_height,
X			 (unsigned) icon_width * icon_height);
X	}
X	/* Translate pixmap into a bitmap for monochrome display. */
X	bw_to_bitmap(buffer, buf_width, buf_height, colors);
X	bw_to_bitmap(icon_buf, icon_width, icon_height, colors);
X	colormap = DefaultColormap(dpy, screen);
X	icon_image = XCreateImage(dpy, visual, 1, XYBitmap, 0,
X			  (char *) icon_buf, icon_width, icon_height, 8, 0);
X	if (icon_image == NULL)
X	    error("XCreateImage: Couldn't create icon image");
X    }
X    else
X    {
X	/* use color image */
X	if (nchannels >= 3)
X	{
X	    if (enhance)
X	    {
X		edge_enhance(buffer, buf_width, buf_height, buf_size);
X		edge_enhance(grn_buf, buf_width, buf_height, buf_size);
X		edge_enhance(blu_buf, buf_width, buf_height, buf_size);
X	    }
X	    rgb_dither(buffer, grn_buf, blu_buf, buf_width,
X		       buf_height, ditherFactor, divN, modN);
X	    if (npics <= 1)
X	    {
X		free((char *) grn_buf);
X		free((char *) blu_buf);
X	    }
X	}
X	else if (cdither_flag)
X	    pixmap_dither(buffer, p_head.c_map, buf_width, buf_height,
X			  ditherFactor, divN, modN);
X
X	colormap = GetColormap(colors, ncolors, buffer,
X			       buf_size);
X	icon_image = XCreateImage(dpy, visual, 8, ZPixmap, 0,
X			  (char *) icon_buf, icon_width, icon_height, 8, 0);
X	if (icon_image == NULL)
X	    error("XCreateImage: Couldn't create icon image.");
X	for (i = 0; i < icon_height; i++)
X	    for (j = 0; j < icon_width; j++)
X	    {
X		if (!XPutPixel(icon_image, j, i,
X			       buffer[(i * buf_width + j) * iconfact]))
X		    error("Trouble building icon image.");
X	    }
X
X    }
X    image = XCreateImage(dpy, visual, (mono_flag ? 1 : 8),
X		       (mono_flag ? XYBitmap : ZPixmap), 0, (char *) buffer,
X			 buf_width, buf_height, 8, 0);
X    if (image == NULL)
X	error("XCreateImage: Couldn't create image");
X
X    if ( !existing_window )  /* if we don't have an existing window */
X    {
X        /*
X         * Define window attributes.
X         */
X        xswa.event_mask = ExposureMask | ButtonPressMask |
X            ColormapChangeMask | LeaveWindowMask | EnterWindowMask;
X        xswa.background_pixel = blackpixel;
X        xswa.border_pixel = whitepixel;
X        xswa.colormap = colormap;
X        xswa.cursor = XCreateFontCursor(dpy, XC_gumby);
X        xswa.event_mask = ExposureMask;
X
X        image_win = XCreateWindow(dpy, root_win, 0, 0, buf_width,
X                                  buf_height, 5, DefaultDepth(dpy, screen),
X                                  InputOutput, visual, CWBackPixel |
X                                  CWEventMask | CWCursor |
X                                  CWBorderPixel | CWColormap, &xswa);
X        icon_win = XCreateWindow(dpy, root_win, 0, 0, icon_width,
X                                 icon_height, 1, DefaultDepth(dpy, screen),
X                                 InputOutput, visual, CWBackPixel |
X                                 CWBorderPixel, &xswa);
X    }
X    else
X    {
X        /*
X         * We have an existing window.  The only attributes which may have
X         * to change are the width, height and colormap of the window.
X         * Otherwise, we can use the attributes structure which was
X         * previously defined.
X         */
X        unsigned long changemask;  /* the change mask */
X
X        /* always assume the colormap changed */
X        xswa.colormap = colormap;
X        XChangeWindowAttributes(dpy, image_win, CWColormap, &xswa);
X        XChangeWindowAttributes(dpy, icon_win, CWColormap, &xswa);
X
X        /* first do image window */
X        changemask = 0;
X        if ( buf_width_old != buf_width )
X        {
X            image_changes.width = buf_width;
X            changemask |= CWWidth;
X        }
X        if ( buf_height_old != buf_height )
X        {
X            image_changes.height = buf_height;
X            changemask |= CWHeight;
X        }
X        if ( changemask )  /* changemask has been set */
X            XConfigureWindow(dpy, image_win, changemask, &image_changes);
X
X        /* then icon window */
X        changemask = 0;
X        if ( iconfact_old != iconfact )
X        {
X            /*
X             * I assume that both icon_width and icon_height may have
X             * changed.  I don't think it to important to check.
X             */
X            icon_changes.width  = icon_width;
X            icon_changes.height = icon_height;
X            changemask = CWWidth | CWHeight;
X            XConfigureWindow(dpy, icon_win, changemask, &icon_changes);
X        }
X    }
X
X    /*
X     * set window manager hints if window doesn't already exist
X     */
X    if ( !existing_window )
X    {
X        /* only set this stuff once */
X        sizehints.flags = PPosition | PSize;
X        sizehints.width = buf_width;
X        sizehints.height = buf_height;
X        sizehints.x = 0;
X        sizehints.y = 0;
X        XSetStandardProperties(dpy, image_win, "X Imager", win_name,
X                               None, argv, argc, &sizehints);
X
X        wmhints.flags = IconWindowHint;
X        wmhints.icon_window = icon_win;
X        wmhints.icon_x = DisplayWidth(dpy, screen) - 200;
X        wmhints.icon_y = 2;
X        XSetWMHints(dpy, image_win, &wmhints);
X        
X        gc_val.function = GXcopy;
X        gc_val.plane_mask = AllPlanes;
X        gc_val.foreground = blackpixel;
X        gc_val.background = whitepixel;
X        image_gc = XCreateGC(dpy, image_win, GCFunction | GCPlaneMask |
X                             GCForeground | GCBackground, &gc_val);
X        icon_gc = XCreateGC(dpy, icon_win, GCFunction | GCPlaneMask |
X                            GCForeground | GCBackground, &gc_val);
X    }
X    
X        
X    /*
X     * map the image window
X     */
X    if ( !existing_window )
X        XMapWindow(dpy, image_win);
X    else
X        XPutImage(dpy, image_win, image_gc, image, 0, 0, 0, 0,
X                  image->width, image->height);
X
X    if (!mono_flag && ncolors >= DisplayCells(dpy, screen))
X    {
X        i = DisplayCells(dpy, screen);
X        bg_color.red = colors[i].red;
X        bg_color.green = colors[i].green;
X        bg_color.blue = colors[i].blue;
X        fg_color.red = colors[++i].red;	/* force the last */
X        fg_color.green = colors[i].green;	/* two colors and */
X        fg_color.blue = colors[i].blue;	/* sacrifice cursor */
X        XRecolorCursor(dpy, xswa.cursor, &fg_color, &bg_color);
X    }
X
X    /*
X     * Select events to listen for
X     */
X    XSelectInput(dpy, image_win, (ButtonPressMask | ColormapChangeMask |
X	  ExposureMask | LeaveWindowMask | EnterWindowMask | KeyPressMask));
X    XSelectInput(dpy, icon_win, ExposureMask | KeyPressMask);
X
X    expose = (XExposeEvent *) & event;
X    xcrossing = (XCrossingEvent *) & event;
X
X    /*
X     * MAIN LOOP
X     */
X    while (!done)
X    {
X	XNextEvent(dpy, &event);
X	switch ((int) event.type)
X	{
X	    int             modulo;	/* Temporary var. for
X					 * expose->x % 4 */
X	case Expose:
X	    if (expose->window == icon_win && expose->count == 0)
X	    {
X		XPutImage(dpy, icon_win, icon_gc, icon_image, 0, 0,
X			  0, 0, icon_width, icon_height);
X		break;
X	    }
X	    modulo = expose->x % 4;
X	    if (modulo != 0 && !mono_flag)
X	    {
X		expose->x -= modulo;
X		expose->width += modulo;
X	    }
X	    if (expose->width % 4 != 0 && !mono_flag)
X		expose->width += 4 - (expose->width % 4);
X	    XPutImage(dpy, image_win, image_gc, image,
X		      expose->x, expose->y, expose->x, expose->y,
X		      expose->width, expose->height);
X	    break;
X	case ButtonPress:
X	    switch ((int) event.xbutton.button)
X	    {
X	    case Button1:
X                /*
X                 * Try to display another image in same input file,
X                 * making sure to free any memory from previous image.
X                 * We do not destroy either the image or icon windows,
X                 * but instead just change whatever is different.  In
X                 * practice this means the we may have to change the
X                 * width and height of the window.
X                 */
X                existing_window = 1;
X                buf_width_old = buf_width;
X                buf_height_old = buf_height;
X                iconfact_old = iconfact;
X
X                /*
X                 * Clear the old window so user's can see that we are
X                 * doing something in case calculating the next image
X                 * to display takes a bit of time.  In general they
X                 * are time consuming.  But when AIX/370 gets a vectorizing
X                 * C compiler... .
X                 */
X                XClearWindow(dpy, image_win);
X
X                /* plug memory leaks */
X                XFree((char *)image);
X                XFree((char *)icon_image);
X                free((char *)icon_buf);
X                free((char *)buffer);
X
X                goto display_next;
X		break;
X	    case Button2:
X		(VOID) fprintf(stderr, "(x,y): %d %d\n",
X			       event.xbutton.x, event.xbutton.y);
X		break;
X	    case Button3:
X		done = True;
X		break;
X	    }
X	case KeyPress:
X	    if (XLookupString(&event, text, sizeof(text), 0, 0) == 1
X		&& (text[0] == 'q' || text[0] == 'Q'))
X		done = True;
X	    break;
X	case LeaveNotify:
X	case EnterNotify:
X	case ColormapNotify:
X	    break; 
X	case MappingNotify:
X	    XRefreshKeyboardMapping(&event);
X	    break;
X	default:
X	    (VOID) fprintf(stderr, "Bad X event.\n");
X	}
X    }
X    (VOID) (*closeFunc) (in_fp);
X    XDestroyWindow(dpy, image_win);
X    XDestroyWindow(dpy, icon_win);
X    XCloseDisplay(dpy);
X    return 0;
X}
X
XColormap
XGetColormap(colors, ncolors, buf, bufsize)
X    XColor         *colors;
X    int             ncolors;
X    byte           *buf;
X    unsigned int    bufsize;
X{
X    register        i;
X    int             fudged = 0;
X    Colormap        cmap;
X
X    if (ncolors > DisplayCells(dpy, screen))
X	ncolors = DisplayCells(dpy, screen);
X
X    cmap = DefaultColormap(dpy, screen);
X    for (i = 0; i < ncolors; i++)
X    {
X        if ( !XAllocColor(dpy, cmap, &colors[i]) )
X        {
X            /*
X             *  calling FindColorValue can be a BIG performance
X             *  penalty.  Fortunately, if your application isn't a
X             *  color hog - trying to use most of the  256 available
X             *  colors - you will never call it.
X             */
X            fudged++;
X            colors[i].pixel = FindColorValue(cmap, ncolors, colors[i].red,
X                                             colors[i].green, colors[i].blue,
X                                             FUDGE_FACTOR);
X        }
X    }
X
X    if (fudged)
X        (VOID) fprintf(stderr, "Fudged %d color(s) using fudge factor %d\n",
X                       fudged, FUDGE_FACTOR);
X
X    for (i = 0; i < bufsize; i++)
X        buf[i] = (byte) colors[buf[i]].pixel;
X
X    return cmap;
X}
X
X
X/*
X * Find the the closest color in the colormap, within a fudge factor.
X */
Xu_long
XFindColorValue(cmap, ncolors, red, green, blue, factor)
X    Colormap        cmap;
X    int             ncolors, red, green, blue, factor;
X{
X    register        i, red2, blue2, green2;
X    XColor          qcolor;
X    u_long          value = 0;
X    long            dist, least = 1e5;
X
X    for (i = 0; i < ncolors; i++)
X    {
X	qcolor.pixel = (u_long) i;
X	XQueryColor(dpy, cmap, &qcolor);
X	red2 = (int) (qcolor.red >> 8);
X	green2 = (int) (qcolor.green >> 8);
X	blue2 = (int) (qcolor.blue >> 8);
X	dist = ((red2 - red) * (red2 - red)) +
X	    ((green2 - green) * (green2 - green)) +
X	    ((blue2 - blue) * (blue2 - blue));
X	if (dist < factor)
X	    return qcolor.pixel;
X	else
X            if (dist < least)
X            {
X                least = dist;
X                value = qcolor.pixel;
X            }
X    }
X    return value;
X}
X
X/*
X *  This edge enhancing is taken from the ACM Transaction on Graphics
X *  Vol. 6, No. 4, October 1987.  Dot diffusion is not implemented.
X */
X
XVOID
Xedge_enhance(buf, width, height, bufsize)
X    register byte  *buf;
X    int             width, height;
X    unsigned        bufsize;
X{
X    register        i, x, y, lbyt, hbyt, tmp;
X    register byte  *tbuf;
X    register float  phi;
X
X    if ((tbuf = (byte *) malloc(bufsize)) == NULL)
X	error("Can't malloc() core for edge enhancementi.\n");
X#ifndef SYSV
X    bcopy((char *) buf, (char *) tbuf, (int) bufsize);
X#else
X    memcpy((char *) tbuf, (char *) buf, (int) bufsize);
X#endif
X
X    lbyt = width - 1;
X    hbyt = width + 1;
X    i = lbyt;
X    if (enhance == 9)
X    {				/* is much faster, default */
X	for (y = 2; y < height; y++)
X	{
X	    i += 2;
X	    for (x = 2; x < width; x++, i++)
X	    {
X		tmp = (9 * tbuf[i]) - (tbuf[i - hbyt] + tbuf[i - width] +
X		tbuf[i - lbyt] + tbuf[i - 1] + tbuf[i + 1] + tbuf[i + lbyt] +
X				       tbuf[i + width] + tbuf[i + hbyt]);
X		if (tmp > 255)
X		    buf[i] = 255;
X		else if (tmp < 0)
X		    buf[i] = 0;
X		else
X		    buf[i] = (byte) tmp;
X	    }
X	}
X    }
X    else
X    {				/* allows greater control */
X	phi = enhance / 10.0;
X	for (y = 2; y < height; y++)
X	{
X	    i += 2;
X	    for (x = 2; x < width; x++, i++)
X	    {
X		tmp = (tbuf[i - hbyt] + tbuf[i - width] + tbuf[i - lbyt] +
X		       tbuf[i - 1] + tbuf[i] + tbuf[i + 1] +
X		   tbuf[i + lbyt] + tbuf[i + width] + tbuf[i + hbyt]) / 9.0;
X		tmp = RND((tbuf[i] - (phi * tmp)) / (1.0 - phi));
X		if (tmp > 255)
X		    buf[i] = 255;
X		else if (tmp < 0)
X		    buf[i] = 0;
X		else
X		    buf[i] = (byte) tmp;
X	    }
X	}
X    }
X    free((char *) tbuf);
X}
X
Xint            *error1, *error2;
X
X/*
X * Grey to monochrome conversion. Performed in place - overwrites
X * the source pixmap and transforms it into a bitmap in the process.
X */
X
XVOID
Xbw_to_bitmap(buf, width, height, map)
X    register byte  *buf;
X    int             width, height;
X    XColor         *map;
X{
X    register byte  *mbuffer, mvalue;	/* monochrome buffer */
X    register byte  *mpbuffer;	/* monochrome pixel buffer */
X    register        row, col, bit;
X
X    error1 = (int *) malloc((unsigned) (width + 1) * sizeof(int));
X    error2 = (int *) malloc((unsigned) (width + 1) * sizeof(int));
X    mbuffer = (byte *) calloc((unsigned) width * height / 8, sizeof(byte));
X    if ((error1 == NULL) || (error2 == NULL) || (mbuffer == NULL))
X	error("calloc() in bw_to_bitmap conversion");
X    mpbuffer = mbuffer = buf;
X
X    if (XBitmapBitOrder(dpy) == LSBFirst)
X    {
X	for (row = 0; row < height; row++)
X	    for (col = 0; col < width;)
X	    {
X		mvalue = 0x00;
X		for (bit = 0; (bit < 8) && (col < width); bit++, col++)
X		    if ((*bw) (*mpbuffer++, map, col, row))
X			mvalue |= (0x01 << bit);	/* for Vax */
X		*mbuffer++ = mvalue;
X	    }
X    }
X    else
X    {
X	for (row = 0; row < height; row++)
X	    for (col = 0; col < width;)
X	    {
X		mvalue = 0x00;
X		for (bit = 0; (bit < 8) && (col < width); bit++, col++)
X		    if ((*bw) (*mpbuffer++, map, col, row))
X			mvalue |= (0x80 >> bit);	/* for RT, Sun  */
X		*mbuffer++ = mvalue;
X	    }
X    }
X    free((char *) buf);
X    buf = mbuffer;
X    free((char *) error1);
X    free((char *) error2);
X}
X
X/*
X * code for dithering
X */
X
Xint
Xdither_bw(pixel, map, count, line)
X    unsigned int    pixel;
X    XColor         *map;
X    int             count, line;
X{
X    if (map[pixel].red > dm[((line % ditherFactor) * ditherFactor) +
X			    (count % ditherFactor)])
X	return 0;
X    else
X	return 1;
X}
X
X
X/*
X * code for floyd steinberg
X */
X
Xint
Xfs_bw(pixel, map, count)
X    unsigned int    pixel;
X    XColor         *map;
X    int             count;
X{
X    int             onoff, *te;
X    int             intensity, pixerr;
X
X    if (count == 0)
X    {
X	te = error1;
X	error1 = error2;
X	error2 = te;
X	error2[0] = 0;
X    }
X    intensity = map[pixel].red + error1[count];
X    if (intensity > 65535)
X	intensity = 65535;
X    else if (intensity < 0)
X	intensity = 0;
X    if (intensity < threshold)
X    {
X	onoff = 1;
X	pixerr = intensity;
X    }
X    else
X    {
X	onoff = 0;
X	pixerr = intensity - 65535;
X    }
X    error1[count + 1] += (int) (((unsigned)(3 * pixerr)) >> 3);
X    error2[count + 1] = (int) ((unsigned)pixerr >> 2);
X    error2[count] += (int) (((unsigned)(3 * pixerr)) >> 3);
X    return onoff;
X}
X
X
X/*
X * code for modified floyd steinberg
X */
X
Xint
Xmfs_bw(pixel, map, count)
X    unsigned int    pixel;
X    XColor         *map;
X    int             count;
X{
X    int             onoff, *te;
X    int             intensity, pixerr;
X
X    if (count == 0)
X    {
X	te = error1;
X	error1 = error2;
X	error2 = te;
X	error2[0] = 0;
X    }
X    intensity = map[pixel].red + error1[count];
X    if (intensity > 65535)
X	intensity = 65535;
X    else if (intensity < 0)
X	intensity = 0;
X
X    if (intensity < threshold)
X    {
X	onoff = 1;
X	pixerr = threshold - intensity;
X    }
X    else
X    {
X	onoff = 0;
X	pixerr = threshold - intensity;
X    }
X    error1[count + 1] += (int) (3 * pixerr) / 8;
X    error2[count + 1] = (int) pixerr / 4;
X    error2[count] += (int) (3 * pixerr) / 8;
X    return onoff;
X}
X
X
X/*
X * Map rg&b channels to 8 bits through dithering.  This color dithering
X * code has been adapted and greatly simplified from the original work by
X * author: Spencer W. Thomas
X *           Computer Science Dept. (cs.utah.edu)
X *           University of Utah
X * Copyright (c) 1986, University of Utah
X */
X
XVOID
Xrgb_dither(red, grn, blu, width, height, levels, divN, modN)
X    register byte  *red, *grn, *blu;
X    int             width, height, levels, *divN, *modN;
X{
X    register        i, x, y, col = 0, row = 0, levelsq;
X
X    levelsq = levels * levels;
X    for (i = 0, y = 0; y < height; y++, row = y % 16)
X    {
X	for (x = 0; x < width; x++, col = x % 16, i++)
X	{
X	    red[i] = (byte) (
X			 (modN[red[i]] > dm16[col][row] ? divN[red[i]] + 1 :
X			  divN[red[i]]) +
X			 (modN[grn[i]] > dm16[col][row] ? divN[grn[i]] + 1 :
X			  divN[grn[i]]) * levels +
X			 (modN[blu[i]] > dm16[col][row] ? divN[blu[i]] + 1 :
X			  divN[blu[i]]) * levelsq);
X	}
X    }
X}
X
XVOID
Xpixmap_dither(buf, cmap, width, height, levels, divN, modN)
X    register byte  *buf;
X    byte            cmap[256][3];
X    int             width, height, levels, *divN, *modN;
X{
X    register        x, y, col = 0, row = 0, levelsq;
X    register byte   red, grn, blu, *loc;
X
X    levelsq = levels * levels;
X    for (loc = buf, y = 0; y < height; y++, row = y % 16)
X    {
X	for (x = 0; x < width; x++, col = x % 16, loc++)
X	{
X	    red = cmap[*loc][0];
X	    grn = cmap[*loc][1];
X	    blu = cmap[*loc][2];
X	    *loc = (byte) (
X		  (modN[red] > dm16[col][row] ? divN[red] + 1 : divN[red]) +
X		    (modN[grn] > dm16[col][row] ? divN[grn] + 1 : divN[grn])
X			      * levels +
X		    (modN[blu] > dm16[col][row] ? divN[blu] + 1 : divN[blu])
X			      * levelsq);
X	}
X    }
X}
X
X
X/*
X *  Create a color map and dithering matrix for the specified
X *  intensity levels.
X */
X
XVOID
Xmake_dithermap(levels, colors, divN, modN, magic)
X    int             levels, divN[256], modN[256], magic[16][16];
X    XColor         *colors;
X{
X    float           N, magicfact;
X    register        i, j, k, l, levelsq, ncolors;
X
X    levelsq = levels * levels;	/* squared */
X    ncolors = levelsq * levels;	/* and cubed */
X    N = 255.0 / (levels - 1.0);	/* Get size of each step */
X
X    /* Set up the color map entries.  */
X    for (i = 0; i < ncolors; i++)
X    {
X	colors[i].pixel = (u_long) i;
X	colors[i].red = (u_short) (RND((i % levels) * N) << 8);
X	colors[i].green = (u_short) (RND(((i / levels) % levels) * N) << 8);
X	colors[i].blue = (u_short) (RND(((i / levelsq) % levels) * N) << 8);
X	colors[i].flags = DoRed | DoGreen | DoBlue;
X    }
X    for (i = 0; i < 256; i++)
X    {
X	divN[i] = (int) (i / N);
X	modN[i] = i - (int) (N * divN[i]);
X    }
X    magicfact = (N - 2.0) / 16.0;
X    for (i = 0; i < 4; i++)
X	for (j = 0; j < 4; j++)
X	    for (k = 0; k < 4; k++)
X		for (l = 0; l < 4; l++)
X		    magic[4 * k + i][4 * l + j] = RND(dm4[i][j] * magicfact +
X					    (dm4[k][l] / 16.0) * magicfact);
X}
X
X
X/*
X * Normalize dither matrix to 65535 maximum value.
X */
X
XVOID
Xnormalize_dm(dimension)
X    int             dimension;
X{
X    int             i, matsize;
X    float           normalValue;
X
X    matsize = dimension * dimension;
X    normalValue = 65536.0 / (float) matsize;
X    for (i = 0; i < matsize; i++)
X    {
X	dm[i] = RND(dm[i] * normalValue);
X    }
X}
X
X
X/*
X *  Transformation from RGB to the Y (or luminence) factor from
X *  YIQ encoding.
X */
Xint
X#if defined(__STDC__) && (__STDC__ == 1)
Xgrey_value(u_short red, u_short green, u_short blue)
X#else
Xgrey_value(red, green, blue)
X    u_short         red, green, blue;
X#endif
X{
X    return RND((float) red * 0.30 + (float) green * 0.55 +
X		(float) blue * 0.15);
X}
X
XVOID
Xcolor_to_bw(buf, bufsize, colors, ncolors)
X    register byte  *buf;
X    unsigned        bufsize;
X    XColor         *colors;
X    int            *ncolors;
X{
X    register unsigned i;
X    byte            tval[256];
X
X    /* determine b/w intensity level and place in pixel */
X    for (i = 0; i < *ncolors; i++)
X	tval[i] = (byte) grey_value(colors[i].red, colors[i].green,
X			    colors[i].blue) / 256;
X    for (i = 0; i < bufsize; i++)
X	buf[i] = tval[buf[i]];
X    *ncolors = 256;
X    for (i = 0; i < *ncolors; i++)
X    {
X	colors[i].pixel = (u_long) i;
X	colors[i].red = colors[i].green = colors[i].blue =
X	    (u_short) (i << 8);
X	colors[i].flags = DoRed | DoGreen | DoBlue;
X    }
X}
X
X
XVOID
Xread_image_buf(infile, buf, bufsize, encoded)
X    FILE           *infile;
X    register byte  *buf;
X    unsigned       *bufsize;
X    int             encoded;
X{
X    register int    i, runlen, nbytes;
X    register unsigned j;
X    register byte  *line;
X    long            marker;
X
X    if (!encoded)
X	j = fread((char *) buf, 1, (int) *bufsize, infile);
X    else
X    {
X	if ((line = (byte *) malloc((unsigned) BUFSIZ)) == NULL)
X	    error("Can't malloc() fread string.");
X	/* Unrunlength encode data */
X	marker = ftell(infile);
X	j = 0;
X	while (((nbytes = fread((char *) line, 1, BUFSIZ, infile)) > 0) &&
X	       (j < *bufsize))
X	{
X	    for (i = 0; (i < nbytes) && (j < *bufsize); i++)
X	    {
X		runlen = (int) line[i] + 1;
X		i++;
X		while (runlen--)
X		    buf[j++] = line[i];
X	    }
X	    marker += i;
X	}
X	/* return to the begining of the next image's bufffer */
X	if (fseek(infile, marker, 0) == -1)
X	    error("Can't fseek to location in image buffer.");
X	free((char *) line);
X    }
X    if (j != *bufsize)
X    {
X	(VOID) fprintf(stderr, "%cUnable to complete pixmap: %u / %u (%d%%)\n",
X		       7, j, *bufsize, (int) (j * 100.0 / *bufsize));
X	*bufsize = j;
X    }
X}
X
X/* VARARGS1 */
XVOID
Xerror(s1, s2)			/* A most tragic and fatal error.  */
X    char           *s1, *s2;
X{
X    extern int      errno, sys_nerr;
X    extern char    *sys_errlist[];
X
X    (VOID) fprintf(stderr, "%c%s: Error =>\n%c", 7, progName, 7);
X    (VOID) fprintf(stderr, s1, s2);
X    if ((errno > 0) && (errno < sys_nerr))
X	(VOID) fprintf(stderr, " (%s)", sys_errlist[errno]);
X    (VOID) fprintf(stderr, "\n");
X    exit(1);
X}
SHAR_EOF
chmod 0666 xim.c || echo "restore of xim.c fails"
sed 's/^X//' << 'SHAR_EOF' > xim.n &&
X.\"
X.\"  @(#) xim.n 1.4   Delta'd: 09:36:45 4/6/90   Mike Lijewski, CNSF
X.\"
X.TH XIM 1 "February 3,  1989"
X.UC 5
X.SH NAME
Xxim \- display 8 and 24 bit images on color and monochrome terminals
X.SH SYNOPSIS
X.B xim
X[-in 
X.I file
X] [-display
X.I host
X] [-mono] [-reverse] [-fs] [-mfs]
X[-dither[=\fIn\fP]] [-enhance=[1-9]] [-runlen] [-cmap] [-debug]
X.SH DESCRIPTION
X.I Xim
Xis an X program that displays 8 and 24 bit deep color images on 8 bit color and monochrome terminals.
XThe program will do the necessary image processing to make the image fit the particular display's depth.
XIt is intended to make the viewing of images across on a variety of displays fast, easy and network "transparent" in the spirit of X Windows.
X.PP
XColor dithering is used to display images using the
X.I n
Xcolors a host will support.
XAdditionally, various options are available for displaying processing images into bitmaps.
XThis bitmap conversion is useful for making images suitable for printing on conventional printers via "xdpr".
XEdge enhancement options are also available for improving spatial resolution.
X
X.SH OPTIONS
X.TP "\w'\f3\-m\f1name 'u"
X.B -in \fIfile\fP
XSpecify what file to read.  Otherwise, default is stdin.
X.TP
X.B  -display \fIhost\fP
XThis option specifies the X server to connect and the screen on which to display the image.   See
X.I X(1).
X.TP
X.B -mono
XConvert an image to a monochrome (bitmap) image.  This is only valid
Xon color displays since this is automatic on displays with depths less than 4 bits.
X.TP
X.B -dither, -dither=4 or =8 \fR(mono)\fP
XUse a matrix dithering algorithm for digital halftoning to a bitmap image.
XIn mono mode a 4x4 or 8x8 (default) dithering matrix pattern maybe specified.
X.TP
X.B -dither or -dither=2-8 \fR(color)\fP
XIn color mode, a value maybe specified from 2 to 8 where
X.I n**3
Xwill be the number of colors needed in the colormap (ie. 6 = 216 colors).
XThis also forces 8 bit images to fit to the display's depth.
X.TP
X.B -fs
XUse the Floyd Steinberg algorithm for digital halftoning into bitmaped images.  This is the default.
X.TP
X.B -mfs
XUse a modified Floyd Steinberg algorithm for a threshold b/w conversion with greater contrast.
X.TP
X.B -enhance or -enhance=1-9
XEdge enhance monochrome or 24 bit color images.
XDegrees of enhancement from 1 to 9 maybe specified.
X9 is the default, and is faster than 1 to 8.
X.TP
X.B -cmap
XForce the installation of the colormap.
XThis is faster since the data maps directly to the colormap entries and no attempt is made to allocate the colormap from the current map. (color only)
X.TP
X.B -reverse
XDraw the bitmap or color images in reverse video.
X.TP
X.B -debug
XList various debugging messages, colortable mappings, matrix values,
Xetc...
X.PP
X.I Note:
XAll of the command line options can be abbreviated to their shortest unique spelling.
X.br
Xex: %  xim -in color.xim.Z -dit=4 -en -dis unix:0 -deb
X
X.SH FEATURES
X.LP
XThe program's interaction is loosely based on "xwud".
XA right button press exits the program as well as does pressing a  'q'
Xor 'Q' at the keyboard.
XThe middle button displays the coordinates of the mouse.
XThe left button advances to the next image, if any.
X.LP
XWhen dithering color, Xim will make a common colormap to fit the particular display's depth.
XWith 8 bit images this is an option that will prevent installation of an image's own colormap, and is useful for viewing several images at once.
X.PP
XEdge enhancement will only work on 24 bit images or on color to monochrome conversions.
XIt may not give desired results on some types of images, such as those with noise or those that have been previously dithered.
XThe default enhancement value of 9 allows for simplifications in the enhancement algorithm and is significantly faster.
X.SH IMAGE FORMAT
XXim reads image files that are in the "xim" format used here at the lab.
XImages come either as pixmaps or color channel separations.
XThey may be compressed (for those Unix systems with the the "compress" and "zcat" commands) or runlength encoded to save space on other systems.
XThe header on each file is 1024 bytes in size and contains the necessary information about formats, sizes, authors, encoding flags, and the colormap of the pixmap(s).
XMultiple pixmaps may follow the header.
XImages are in characters (no shorts, ints or longs) so as to be easily portable across machines, and be somewhat humanly readable.
X.PP
XIn the multi-channel format, the rgb (& alpha) buffers follow the header respectively, and the colormap in the header is not used.
XXim will only use the first three (RG & B) channels of information,
XIf the number of channels is 0 or 1, 8 bit pixmaps are assumed and the colormap is used.
X
X.SH "SEE ALSO"
XX(1), xtoxim(1), ximtops(1), smoothim(1), quantizim(1)
X.SH BUGS
X.LP
X24-bit displays aren't supported yet.
XI don't have one, but if someone else should ...
X.LP
XDoesn't do any gamma or color display corrections.
X.LP
XDisplays with less than less than 256 addressable colors may not automatically invoke dithering on images with a greater number of colors (ie. 256 color image on a 192 color display).
X
X.SH COPYRIGHT
XCopyright 1989, Massachusetts Institute of Technology.
X.SH AUTHOR
X.br
XPhilip R. Thompson  (phils@athena.mit.edu)
X.br
XComputer Resource Laboratory,  
XDept. of Architecture and Planning,  
XMassachusetts Institute of Technology,  
XCambridge, MA  02139
X
SHAR_EOF
chmod 0666 xim.n || echo "restore of xim.n fails"
sed 's/^X//' << 'SHAR_EOF' > xim.shar.bld &&
X:
X 
Xrm ximstuff
X/usr/local/share/src/shar2/xshar * > ximstuff
SHAR_EOF
chmod 0766 xim.shar.bld || echo "restore of xim.shar.bld fails"
exit 0
