From mipos3!intelca!oliveb!ames!necntc!ncoast!allbery Fri Jan 29 08:03:34 PST 1988
Article 266 of comp.sources.misc:
Path: td2cad!mipos3!intelca!oliveb!ames!necntc!ncoast!allbery
From: everson@compsci.bristol.ac.uk (Phill Everson)
Newsgroups: comp.sources.misc
Subject: v02i019: Image processing programs
Message-ID: <7130@ncoast.UUCP>
Date: 26 Jan 88 04:07:33 GMT
Sender: allbery@ncoast.UUCP
Organization: Dept of Computer Science, University of Bristol, UK.
Lines: 2834
Approved: allbery@ncoast.UUCP
X-Archive: comp.sources.misc/8801/19
Comp.sources.misc: Volume 2, Issue 19
Submitted-By: Phill Everson <everson@compsci.bristol.ac.uk>
Archive-Name: image

Comp.sources.misc: Volume 2, Issue 19
Submitted-By: Phill Everson <everson@compsci.bristol.ac.uk>
Archive-Name: image

# To unbundle, sh this file
 echo README 1>&2
cat >README <<'End of README'
In response to a plea on the net:

This is a family of image processing programs written by
Phill Everson <everson@uk.aucc.bristol.cs: JANET
			   everson%uk.aucc.bristol.cs@nss.cs.ucl.ac.uk: ARPA ? >
with help from Gareth Waddell (notably for the dynamic array library)
at Bristol University in the UK for SUN workstations, both colour and 
black/white.  It includes tools to display images on Colour monitors, 
B/W monitors, to convolve a filter over an image, to create a histogram 
of the greylevels in an image, to normalise an image, to threshold an image, 
to convert an image to Postscript and ... (read the manual page alv(1) 
for other features).

Alv stands for Autonomous Land Vehicle, the research project that these
were originally developed for. Some of the tools have been used MUCH
more than others and so can be regarded as being pretty much correct
(dsp, cdsp, convolve, pixval, imagelw, subarea, subsample, coltable, hist
& invert).
If any of the others seem to be playing up it is possible that 
there is a bug in there somewhere -- some tools were added at the 
request of others who promised to test them and have never been heard 
of since! Please send me any bug reports (&fixes?) to me.

*************************************************************************
To get this system up and on the road:

	1. Edit the Makefile, changing the directory paths for
	   BINDIR, LIBDIR, INCDIR, MANDIR & FILDIR to suit your system.
	2. Type 'make' and everything will be compiled and installed.
	3. Read the manual page alv(1). It can be formatted from this 
	   directory by typing 'nroff -man alv.1 | more'.
*************************************************************************

This family of programs has 3 manual pages; alv(1), alv(3) & alv(5).
alv(1) has a general description of each of the programs and what each 
of them should do. alv(3) is a description of the library created 
and alv(5) is a description of the file format used for an image.
(I've also included the manual page dynamem(3) for a dynamic memory 
allocation library which is used by the alv library and which someone may 
find useful.)

The method that we have found works best is that everyone working
on vision-type programs uses the same file format (see alv(5)) and
most people will use the core tools to display images etc and the
library functions for their own programs.

These are and will be used a lot here, so if anybody adds or modifies them,
please send me details and I'll collect, collate and possibly post notable 
additions at a later date. Thanks.

I hope they're of some use.

				Phill Everson
End of README
 echo Makefile 1>&2
cat >Makefile <<'End of Makefile'
#
# ALV image processing programs
# written by Phill Everson
#            Computer Science Dept.
#            Bristol University UK
#            21st January, 1988
#
# <everson@uk.aucc.bristol.cs: JANET
#  everson%uk.aucc.bristol.cs@nss.cs.ucl.ac.uk: ARPA ? >
#

# BINDIR - location of compiled binaries
# LIBDIR - location of compiled libraries
# INCDIR - location of include files
# MANDIR - location of top level of manual
# FILDIR - location of filters (for convolve)

BINDIR = /usr/kukini/alv/vision/bin
LIBDIR = /usr/kukini/alv/vision/lib
INCDIR = /usr/kukini/alv/vision/include
MANDIR = /usr/kukini/alv/vision/man
FILDIR = /usr/kukini/alv/vision/usr/filters
CFLAGS = -g -I$(INCDIR) 
   ARC = vision.a
 DLIBS = -lsuntool -lsunwindow -lpixrect -L$(LIBDIR) -lalv
 OLIBS = -L$(LIBDIR) -lalv
 PROGS = cdsp dsp convert addhead hist imagelw invert pixval retitle \
		 subarea subsample thresh normalise ffill convolve range striphead 

install: setup all docs filters
	mv $(PROGS) $(BINDIR)

setup:
	cp image.h $(INCDIR)

all: lib cdsp dsp convert addhead hist imagelw invert pixval retitle \
	 subarea subsample thresh normalise ffill convolve range striphead

filters: 
	@cp avg1 lap1 sobel1 xdiff1 $(FILDIR)

archive: clean
	@ar crv $(ARC) *
	@compress $(ARC)
	@mv $(ARC).Z $(ARCHIVE_DIR)
	
docs:
	@cp alv.1 $(MANDIR)/man1
	@cp alv.3 $(MANDIR)/man3
	@cp alv.5 $(MANDIR)/man5
	@cp dynamem.3 $(MANDIR)/man3

cdsp: cdsp.o 
	cc $(CFLAGS) cdsp.o -o cdsp $(DLIBS)

dsp: dsp.o
	cc $(CFLAGS) dsp.o -o dsp $(DLIBS)

hist: hist.o
	cc $(CFLAGS) hist.o -o hist $(DLIBS) -lm

convert: convert.o
	cc $(CFLAGS) convert.o -o convert -L$(LIBDIR) -ldynamem

addhead: addhead.o
	cc $(CFLAGS) addhead.o -o addhead -L$(LIBDIR) -ldynamem

striphead: striphead.o
	cc $(CFLAGS) striphead.o -o striphead $(OLIBS)

convolve.o: convolve.c
	cc $(CFLAGS) -DFILTERS_DIR=$(FILDIR) -c convolve.c

convolve: convolve.o
	cc $(CFLAGS) convolve.o -o convolve $(OLIBS)

invert: invert.o
	cc $(CFLAGS) invert.o -o invert $(OLIBS)

pixval: pixval.o
	cc $(CFLAGS) pixval.o -o pixval $(OLIBS)

retitle: retitle.o
	cc $(CFLAGS) retitle.o -o retitle $(OLIBS)

range: range.o
	cc $(CFLAGS) range.o -o range $(OLIBS)

imagelw: imagelw.o
	cc $(CFLAGS) imagelw.o -o imagelw $(OLIBS)

subsample: subsample.o
	cc $(CFLAGS) subsample.o -o subsample $(OLIBS)

subarea: subarea.o
	cc $(CFLAGS) subarea.o -o subarea $(OLIBS)

thresh: thresh.o
	cc $(CFLAGS) thresh.o -o thresh $(OLIBS) -lm

normalise: normalise.o
	cc $(CFLAGS) normalise.o -o normalise $(OLIBS)

ffill: ffill.o
	cc $(CFLAGS) ffill.o -o ffill $(OLIBS)

lib: alvlib.o dynamem.o
	ar rc libalv.a alvlib.o dynamem.o
	ranlib libalv.a
	ar rc libdynamem.a dynamem.o
	ranlib libdynamem.a
	mv libalv.a libdynamem.a $(LIBDIR)
	touch lib
	
wc: 
	@wc *.c | sort -n

clean:
	@touch dummy.o
	@/bin/rm *.o

troff:
	troff -t -man alv.1 | thack | pspr
	troff -t -man alv.3 | thack | pspr
	troff -t -man alv.5 | thack | pspr
End of Makefile
 echo addhead.c 1>&2
cat >addhead.c <<'End of addhead.c'
#include <stdio.h>

main(argc,argv)
int argc;
char **argv;
{
	int i,j;
	int xsize,ysize;
	unsigned char **pic;
	char *file, *title;
	FILE *fp;

	if (argc!=5) {
		fprintf(stderr,"Usage: %s: x y filename title\n",argv[0]);
		exit(-1);
		}

	xsize=atoi(argv[1]);
	ysize=atoi(argv[2]);
	file =argv[3];
	title =argv[4];

	if (!(fp=fopen(file,"r"))) {
		fprintf(stderr,"Cannot open %s\n",file);
		exit(-1);
		}

	pic = (unsigned char **) dynamem (&pic, sizeof(unsigned char), 2, ysize, xsize);

	putw(xsize<<16|ysize,stdout);

	for (i=0;i<252;i++,*title?title++:0)
		putchar(*title?*title:0);
	
	for (j=0;j<ysize;j++)
		for (i=0;i<xsize;i++)
			pic[j][i]=getc(fp);

	for (j=0;j<ysize;j++)
		for(i=0;i<xsize;i++)
			putchar(pic[j][i]);
	
	fclose(fp);
}
End of addhead.c
 echo alv.1 1>&2
cat >alv.1 <<'End of alv.1'
.\" .TH name section cent-foot
.TH ALV 1 "4th December 1987"
.SH NAME
.\" name \- function
alv \- standard ALV tools
.SH SYNOPSIS
.\" Bold keywords, Italic variables, [] options, | alternatives.
wind_opts = [
.BI -X n
] [
.BI -Y n
] [
.BI -x n
] [
.BI -y n
]
.br
std_opts = 
.RB [ -H ]
[
.BI -T title
]
.RI [ filename ]
.br
.B dsp
.RB [ -m ]
.RB [ wind_opts ]
.RB [ std_opts ]
.br
.B cdsp
.RB [ -m ]
.RB [ wind_opts ]
.RB [ std_opts ]
.br
.B imagelw
.RB [ wind_opts ]
.RB [ std_opts ]
.RB [ -t ]
.RB [ -m ]
.RB [ -c ]
.RB [ - ]
.br
.B hist
.RB [ -l ]
.RB [ -v ]
.RB [ wind_opts ]
.RB [ std_opts ]
.br
.B thresh
[
.BI -t n
]
.RB [ std_opts ]
.br
.B invert
.RB [ std_opts ]
.br
.B normalise
.RB [ std_opts ]
.br
.B range
[
.BI -l n
]
[
.BI -h n
]
.RB [ std_opts ]
.br
.B convolve
[
.BI -f filtername
]
.RB [ -e ]
.RB [ -F ]
.RB [ std_opts ]
.br
.B subsample
.I xsize
.I ysize
.RB [ std_opts ]
.br
.B subarea
[
.BI -x n
]
[
.BI -y n
]
[
.BI -X n
]
[
.BI -Y n
]
.RB [ std_opts ]
.br
.B pixval
[
.BI -x n
]
[
.BI -y n
]
[
.BI -X n
]
[
.BI -Y n
]
.RB [ std_opts ]
.br
.B ffill
.I "xpos ypos"
[ 
.BI -b n 
]
.RB [ std_opts ]
.br
.B retitle
.RB [ std_opts ]
.br
.B convert
.I xsize
.I ysize
.I filename
.I title
.br
.B addhead
.I xsize
.I ysize
.I filename
.I title
.br
.B striphead
.RB [ std_opts ]
.br

.SH DESCRIPTION
.\" Italic files, commands, IR manual-entry (manual-section)
These tools comprise
the majority of those
needed for work on the
.I ALV
and
.I Bubble
projects.
They use a standard
file format, see 
.IR alv (5).
.I Dsp
and
.I cdsp
display pictures
on a monochrome
and colour display
respectively. (Place the mouse in the window
created by 
.I coltable 
on a Colour Sun to see
the image in false colour).
.I Imagelw
displays the picture on the
Apple Laserwriter in
The Sun Lounge.
.I Hist
displays histogram
displays, either
linearly or logorithmically.
.I Thresh
thresholds data on a
picture using either
a specified threshold
value or an automatically
generated one.
.I Invert
inverts all the data in
an image.
.I Normalise
normalises the histogram
of an image.
.I Range 
stretches the grey level distribution
of an image.
.I Convolve
performs a convolution
on an image using 
a specified filter.
.I Subsample
reduces the picture
size by subsampling
the original picture
(but can also be used
to enlarge).
.I Subarea
creates a new picture
which is a part of the
original picture.
.I Pixval
enables a decimal valued
print of an area of an
image to be generated.
.I Ffill
flood fills an image based
around a small point, with
a specified boundary colour.
.I Retitle
gives a picture a new title.
.I Convert
converts a file stored in the old 
alv file format to the new.
.I Addhead
adds a header, thus converting
it to the standard file format, 
to a file produced
by, for example, the 
.I "ALV Framegrabber."
.I Striphead
removes a header from an image.
.SH OPTIONS
.\" Itemised list of options
.TP 4
Window Options
-Xn           window x size is n
.br
-Yn           window y size is n
.br
-xn           window x offset is n
.br
-yn           window y offset is n
.br
.TP 4
Standard Options
-H            give help list
.br
-Ttitle       output-image title
.br
filename      read from filename
.br
.TP 4
Dsp/Cdsp Options
-m            use backing pixrect
.br
.TP 4
Imagelw Options
-T            produce TeX special file
.br
-m            send mail on completion of print
.br
-c            automatically scale picture to fit page
.br
-             write Postscript program to standard output
.br
.TP 4
Hist Options
-l            logarithmic scaling
.br
-v            vertical lines off
.br
.TP 4
Thresh Options
-tn           threshold value
.br
.TP 4
Normalise Options
-ln           least normalise value
.br
-hn           highest normalise value
.br
.TP 4
Convolve Options
-ffiltername  use filter filtername
.br
-e            enhanced scaling
.br
-F            list all filters
.br
.TP 4
Pixval Options
-Xn           x size
.br
-Yn           y size
.br
-xn           x offset
.br
-yn           y offset
.br
.TP 4
Ffill Options
-bn           boundary grey level
.br
.\".SH FILES
.\" List of all files used by the program
.SH "SEE ALSO"
.\" List of references, textual, and MAN pages.
alv(3), alv(5).
.\".SH DIAGNOSTICS
.\" List of error messages and return codes the user may expect
.SH BUGS
.\" Known Limitations or Desirable additions to the command
The code to pick out the filename from the command arguments 
list is unreliable in some cases. (It will core dump). 
This can be avoided by using cat to pipe the file into the
command.
End of alv.1
 echo alv.3 1>&2
cat >alv.3 <<'End of alv.3'
.\" .TH name section cent-foot left-foot cent-head
.TH ALV 3 "4th December 1987"
.SH NAME
.\" name \- function
alv \- standard library functions
.SH SYNOPSIS
.\" Bold keywords, Italic variables, [] options, | alternatives.
typedef struct img {
.br
	unsigned char **image;
.br
	short xsize, ysize;
.br
	char title[252];
.br
} IMAGE;
.sp
int winxsize, winysize,
.br
    winxoff,  winyoff;
.br
int helpflag;
.br
char *newtitle;
.sp
IMAGE *readimage(fp)
.br
FILE *fp;
.sp
writeimage(fp,image)
.br
FILE *fp;
.br
IMAGE *image;
.sp
IMAGE *newimage(xsize,ysize,title)
.br
int xsize,ysize;
.br
char *title
.sp
subsample(image1,image2)
.br
IMAGE *image1,*image2;
.sp
subarea(image1,image2,xoff,yoff)
.br
IMAGE *image1,*image2;
.br
int xoff,yoff;
.sp
stdopts(argc,argv)
.br
int *argc;
.br
char **argv;
.sp
windopts(argc,argv)
.br
int *argc;
.br
char **argv;
.SH DESCRIPTION
.\" Italic files, commands, IR manual-entry (manual-section)
.I Readin
reads in an image from
the specified file, and
creates an image structure
with all the relevant
data contained in it.
.I Writeout
writes the specified
image to the specified
file.
.I Newimage
creates a new
image of the specified
dimensions.
.I Subsample
reproduces the whole
of
.I image1
in
.I image2
suitably scaled (up or
down) so as to make
it fit into the available
room in
.IR image2 .
.I Subarea
reproduces the relevant
part of
.I image1
in
.I image2
so that
.I image2
has the same resolution as
.I image1
and is as full as possible
(note that it is possible
to use this also to increase
the size of an image).
.I Stdopts
parses the
.B -t
and
.B -h options
setting
.I helpflag
and
.IR newtitle .
.I Windopts
parses the
.BR -x , -y , -X ,
.B -Y
options setting
the variables
.IR winxsize , winysize , winxoff ,
.IR winyoff .
.\".SH FILES
.\" List of all files used by the program
.SH "SEE ALSO"
.\" List of references, textual, and MAN pages.
alv(1),alv(3).
.\".SH DIAGNOSTICS
.\" List of error messages and return codes the user may expect
.\".SH BUGS
.\" Known Limitations or Desirable additions to the command
End of alv.3
 echo alv.5 1>&2
cat >alv.5 <<'End of alv.5'
.\" .TH name section cent-foot left-foot cent-head
.TH ALV 5 "4th December 1987"
.SH NAME
.\" name \- function
alv \- common file format
.SH SYNOPSIS
.\" Bold keywords, Italic variables, [] options, | alternatives.
typedef struct img {
.br
	unsigned char **image;
.br
	short xsize, ysize;
.br
	char title[252];
.br
} IMAGE;
.SH DESCRIPTION
.\" Italic files, commands, IR manual-entry (manual-section)
This is the newly approved
"standard" file format for 
image processing work
done by the
.I alv
group at Bristol University.
The file consists of a 256-byte
header followed by
.I ysize
rows each
.I xsize
in length.
The header consists of a
two-byte value for
.IR xsize ,
a two-byte value for
.IR ysize ,
and a 252-byte title,
which may be interpreted
as appropriate by any tool.
.\".SH OPTIONS
.\" Itemised list of options
.\".SH FILES
.\" List of all files used by the program
.SH "SEE ALSO"
.\" List of references, textual, and MAN pages.
alv(1),alv(3)
.\".SH DIAGNOSTICS
.\" List of error messages and return codes the user may expect
.\".SH BUGS
.\" Known Limitations or Desirable additions to the command
End of alv.5
 echo alvlib.c 1>&2
cat >alvlib.c <<'End of alvlib.c'
#include <stdio.h> 
#include "image.h" 

int winxsize=0,winysize=0,
	winxoff=0, winyoff=0;
int helpflag;
char *newtitle=0;

IMAGE *readimage(fp)
FILE *fp;
{
	int i, j, xsize, ysize;
	char title[252];
	IMAGE *img, *newimage();

	i=getw(fp);

	for(j=0;j<252;j++)
		title[j]=getc(fp);

	img = newimage(xsize=(i>>16),ysize=(i&65535),title);

	for(j=0;j<ysize;j++)
		for(i=0;i<xsize;i++)
			(img->image[j][i])=getc(fp);     /* UGH! */

	return img;
}

writeimage(fp,image)
FILE *fp;
IMAGE *image;
{
	int i,j;

	putw(image->xsize<<16|image->ysize,fp);

	for(j=0;j<252;j++)
		putc(image->title[j],fp);

	for(j=0;j<image->ysize;j++)
		for(i=0;i<image->xsize;i++)
			putc(image->image[j][i],fp);

}

IMAGE *newimage(xsize,ysize,title)
int xsize,ysize;
char *title;
{
IMAGE *img;
int i;

	if ((img=(IMAGE *)malloc(sizeof(IMAGE)))==NULL)
		return 0;
	if ((img->image = (unsigned char **) dynamem (&(img->image), sizeof(unsigned char), 2, ysize, xsize))==NULL)
		return 0;
	img->xsize=xsize;
	img->ysize=ysize;
	for (i=0;i<252;i++)
		img->title[i]=0;
	strcpy(img->title,title);
	return img;
}

subsample(image1,image2)
IMAGE *image1,*image2;
{
int cvx,cvy,lcx,lcy,hcx,hcy;
register int i,j,i1,j1;
int total;

	cvx=(100*image1->xsize)/image2->xsize;
	cvy=(100*image1->ysize)/image2->ysize;

	for (j=0;j<image2->ysize;j++)
		for (i=0;i<image2->xsize;i++)
		{
			hcx=i*cvx/100;
			hcy=j*cvy/100;
			lcx=(i-1)*cvx/100+1;
			lcy=(j-1)*cvy/100+1;
			lcx=(lcx<0)?0:(lcx>hcx)?hcx:lcx;
			lcy=(lcy<0)?0:(lcy>hcy)?hcy:lcy;

			total=0;
			for (j1=lcy;j1<=hcy;j1++)
				for (i1=lcx;i1<=hcx;i1++)
					total+=image1->image[j1][i1];
			image2->image[j][i]=total/((hcx+1-lcx)*(hcy+1-lcy));
		}
}

subarea(image1,image2,xoff,yoff)
IMAGE *image1,*image2;
int xoff,yoff;
{
int xmin,ymin,
	xmax,ymax;
int i,j;

	xmin=(xoff<0)?0:xoff;
	ymin=(yoff<0)?0:yoff;
	xmax=image2->xsize+xoff;
	ymax=image2->ysize+yoff;
	xmax=(xmax>image1->xsize)?image1->xsize:xmax;
	ymax=(ymax>image1->ysize)?image1->ysize:ymax;

	for (j=ymin;j<ymax;j++)
		for (i=xmin;i<xmax;i++)
			image2->image[j-yoff][i-xoff]=image1->image[j][i];
}

stdopts(argc,argv)
char **argv;
int *argc;
{
int testflag;
char **p;

	helpflag=0;
	for (argv++;*argv;argv++)
		if (**argv=='-') {
			testflag=1;
			switch ((*argv)[1]) {
			case 'H': helpflag = 1;
					  break;
			case 'T': newtitle= *argv+2;
					  break;
			default:
				testflag=0;
			}
			if (testflag)
			{
				for (p=argv;*p;p++)
					p[0] = p[1];
				(*argc)--;
				argv--;
			}
		}
}

windopts(argc,argv)
char **argv;
int *argc;
{
int testflag;
char **p;

	for (argv++;*argv;argv++)
		if (**argv=='-') {
			testflag=1;
			switch ((*argv)[1]) {
			case 'X': winxsize=atoi(*argv+2);
					  break;
			case 'Y': winysize=atoi(*argv+2);
					  break;
			case 'x': winxoff=atoi(*argv+2);
					  break;
			case 'y': winyoff=atoi(*argv+2);
					  break;
			default:
				testflag=0;
			}
			if (testflag)
			{
				for (p=argv;*p;p++)
					p[0] = p[1];
				(*argc)--;
				argv--;
			}
		}
}
End of alvlib.c
 echo avg1 1>&2
cat >avg1 <<'End of avg1'
7 7

1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
End of avg1
 echo cdsp.c 1>&2
cat >cdsp.c <<'End of cdsp.c'
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include "image.h"
#include <stdio.h>

int boxsize = 1, mflag = 0;
static void getcoords();
static void repaint_canvas();
IMAGE *image;

main(argc, argv)
int argc;
char **argv;

{
	Frame frame;
	Canvas canvas;
	Pixwin *pw;
	Cursor cursor;
	char cmsname[CMS_NAMESIZE];
	u_char red[256], green[256], blue[256];
	int i, j, x, y;
	FILE *fp, *fopen();
	u_char *pi;
	char *imagefile=NULL;

	stdopts(&argc,argv);
	windopts(&argc,argv);

	for (argv++;*argv;*argv++)
		if (**argv=='-' && (*argv)[1]=='m') 
			mflag = 1;
		else imagefile= *argv;

	if (imagefile==NULL)
		fp=stdin;
	else if (!(fp = fopen(imagefile,"r"))) {
		fprintf(stderr,"Cannot open %s\n",imagefile);
		exit(-1);
		}

	image = readimage(fp);

	/* Initialise variables used to set colour map segment */
	for (i = 0; i < 256; i++) {
		red[i] = i;
		green[i] = i;
		blue[i] = i;
	}

	cursor = cursor_create(CURSOR_CROSSHAIR_COLOR, 255,
			       CURSOR_SHOW_CURSOR, FALSE,
			       CURSOR_SHOW_CROSSHAIRS, TRUE,
			       CURSOR_CROSSHAIR_LENGTH, 20,
			       CURSOR_CROSSHAIR_GAP, 5,
			       0);

	/* create frame and canvas */
	frame = window_create(NULL, FRAME,
				  FRAME_LABEL, (newtitle)?newtitle:image->title,
				  WIN_X, winxoff,
				  WIN_Y, winyoff,
			      WIN_HEIGHT, (winxsize)?winxsize:image->ysize * boxsize + 22,
			      WIN_WIDTH, (winysize)?winysize:image->xsize * boxsize + 10,
			      0);

	if (mflag)
		canvas = window_create(frame, CANVAS,
				       CANVAS_HEIGHT, image->ysize * boxsize,
				       CANVAS_WIDTH, image->xsize * boxsize,
				       WIN_CURSOR, cursor,
				       WIN_EVENT_PROC, getcoords,
				       0);
	else
		canvas = window_create(frame, CANVAS,
				       CANVAS_HEIGHT, image->ysize * boxsize,
				       CANVAS_WIDTH, image->xsize * boxsize,
				       WIN_CURSOR, cursor,
				       WIN_EVENT_PROC, getcoords,
				       CANVAS_RETAINED, FALSE,
				       CANVAS_REPAINT_PROC, repaint_canvas,
				       0);

	/* get the canvas pixwin to draw into */
	pw = canvas_pixwin(canvas);

	/* Set colour map segment */
	pw_setcmsname(pw, "grays");
	pw_putcolormap(pw, 0, 256, red, green, blue);

	if (mflag) {
		/* Enable batching for efficiency */
		pw_batch_on(pw);

		/* Draw gray boxes */
		pi = image->image[0];
		for (y = 0; y < image->ysize; y++)
			for (x = 0; x < image->xsize; x++) {
				pw_put(pw, x, y, *pi);
				pi++;
			}
		pw_batch_off(pw);
	}

	window_main_loop(frame);
}

static void
repaint_canvas(canvas, pw, repaint_area)
Canvas canvas;
Pixwin *pw;
Rectlist *repaint_area;
{
	u_char *pi;
	int x, y;
	int xstart, ystart, xstop, ystop;

	xstart = repaint_area->rl_bound.r_left / boxsize;
	ystart = repaint_area->rl_bound.r_top / boxsize;
	xstop = xstart + 1 + repaint_area->rl_bound.r_width / boxsize;
	ystop = ystart + 1 + repaint_area->rl_bound.r_height / boxsize;

	xstop = (xstop > image->xsize) ? image->xsize : xstop;
	ystop = (ystop > image->ysize) ? image->ysize : ystop;

	/* Enable locking for efficiency */

	/* Draw gray boxes */
	for (y = ystart; y < ystop; y++) {
		pi = &(image->image[y][xstart]);
		pw_lock(pw, &(repaint_area->rl_bound));
		for (x = xstart; x < xstop; x++) {
			/* Fill in a square box */
			pw_put(pw, x, y, *pi);
			pi++;
		}
		pw_unlock(pw);
	}
}

static void
getcoords(canvas, event, arg)
Canvas canvas;
Event *event;
caddr_t arg;
{
	if ((event_id(event) == MS_LEFT) && event_is_down(event)) {
		printf("%s: locator x,y : %d %d \n", (newtitle)?newtitle:image->title,
		       event_x(event) / boxsize, event_y(event) / boxsize);
	}
}
End of cdsp.c
 echo coltable.c 1>&2
cat >coltable.c <<'End of coltable.c'
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <stdio.h>
#include <math.h>

#define MINC 0

main(argc,argv)
int argc;
char ** argv;

   {
    Frame frame;
    Canvas canvas;
    Pixwin *pw;
    char cmsname[CMS_NAMESIZE];
    u_char red[256], green[256], blue[256];
    int i,ii,j,x,y;
    int delt,rem,region;
    int range ;
    float factor;
    char *tabname;

    range = 255 - MINC;
    delt = 43;
    factor = ((double)range)/(delt-1);
    tabname = (argv[0][0] == 'i') ? "icols" : "cols";
 
    /* Initialise variables used to set colour map segment */
    for (ii=0 ; ii<256 ; ii++)
    {
       i = (argv[0][0] == 'i') ? 255 - ii : ii ;

       region = ii/delt;
       rem = ii % delt;

       switch (region) {

       case 0 :
          red[i]   =  range +MINC ;
          green[i] =  range - rem* factor +MINC ;
          blue[i]  =  range - rem* factor +MINC;
          break;

       case 1 :
          red[i] = range +MINC;
          green[i] = rem * factor +MINC ;
          blue[i] = 0 +MINC ;
          break;

       case 2:
          red[i] = range - rem* factor +MINC ;
          green[i] = range +MINC ;
          blue[i] = 0 +MINC ;
          break;

       case 3:
          red[i] = 0 +MINC ;
          green[i] = range +MINC ;
          blue[i] = rem * factor +MINC ;
          break;
   
       case 4:
          red[i] = 0 +MINC ;
          green[i] = range - rem * factor +MINC ;
          blue[i] = range +MINC ;
          break;

       case 5:
       default:
          red[i] = rem * factor +MINC ;
          blue[i] = range +MINC ;
          green[i] = 0 +MINC ;
          break;
 
       } /* end switch */

    /* cludge to give more yellow etc */
    red[i] = sqrt((double)(red[i]-MINC))*sqrt((double)range) +MINC;
    blue[i] = sqrt((double)(blue[i]-MINC))*sqrt((double)range) +MINC;
    green[i] = sqrt((double)(green[i]-MINC))*sqrt((double)range) +MINC;
    }

    /* create frame and canvas */
    frame = window_create(NULL, FRAME,
	WIN_HEIGHT,    50,
	WIN_WIDTH,     100,
	0);
    canvas = window_create(frame,CANVAS, 0);


    /* get the cancas pixwin to draw into */
    pw = canvas_pixwin(canvas);

    /* Set colour map segment */
    pw_setcmsname(pw, tabname);
    pw_putcolormap(pw, 0, 256, red, green, blue);

    pw_batch_on(pw);

    window_main_loop(frame);
 
    exit(0);
   }
End of coltable.c
 echo convert.c 1>&2
cat >convert.c <<'End of convert.c'
#include <stdio.h>

main(argc,argv)
int argc;
char **argv;
{
	int i,j;
	int xsize,ysize;
	unsigned char **pic;
	char *file, *title;
	FILE *fp;

	if (argc!=5) {
		fprintf(stderr,"Usage: %s: x y filename title\n",argv[0]);
		exit(-1);
		}

	xsize=atoi(argv[1]);
	ysize=atoi(argv[2]);
	file =argv[3];
	title =argv[4];

	if (!(fp=fopen(file,"r"))) {
		fprintf(stderr,"Cannot open %s\n",file);
		exit(-1);
		}

	pic = (unsigned char **) dynamem (&pic, sizeof(unsigned char), 2, ysize, xsize);

	putw(xsize<<16|ysize,stdout);

	for (i=0;i<252;i++,*title?title++:0)
		putchar(*title?*title:0);
	
	for (i=0;i<xsize;i++)
		for (j=0;j<ysize;j++)
			pic[j][i]=getc(fp);

	for (j=0;j<ysize;j++)
		for(i=0;i<xsize;i++)
			putchar(pic[j][i]);
	
	fclose(fp);
}
End of convert.c
 echo convolve.c 1>&2
cat >convolve.c <<'End of convolve.c'
#include <stdio.h>
#include "image.h"

char *filtername=NULL;
int eflag = 0,
	fflag = 0;

typedef struct {
	char **image;
	short xsize,ysize;
	char title[252];
} FILTER;

main(argc,argv)
char **argv;
{
	char *imagefile=NULL;
	FILE *fp;
	IMAGE *image, *outimage;
	FILTER *filter, *loadfilter();

	stdopts(&argc,argv);

	if (helpflag) {
		help(*argv);
		exit(0);
	}
	
	for(argv++;*argv;argv++) 
		if ((**argv)=='-')
			switch ((*argv)[1]) {
			case 'e':
				eflag=1;
				break;
			case 'f':
				filtername=argv[0]+2;
				break;
			case 'F':
				fflag=1;
				break;
			}
		else imagefile= *argv;
	
	if (fflag) 
		execlp("ls","ls","-C","FILTERS_DIR");
	
	if (filtername) 
		filter=loadfilter(filtername);
	
	if (imagefile) {
		if (!(fp=fopen(imagefile,"r"))) {
			fprintf(stderr,"Couldn't open %s\n",imagefile);
			exit(-1);
		}
	}
	else fp = stdin;
	
	image=readimage(fp);
	outimage=newimage(image->xsize,image->ysize,(newtitle)?newtitle:image->title);
	if (filtername) {
		strcat(outimage->title," | ");
		strcat(outimage->title,filtername);
	}

	runfilter(filter,image,outimage);

	writeimage(stdout,outimage);
}

FILTER *
loadfilter(name)
char *name;
{
	char buf[BUFSIZ];
	FILE *fp;
	FILTER *filter;
	int xsize,ysize,ival;
	register int i,j;

	strcpy(buf,"FILTERS_DIR");
	strcat(buf,"/");
	strcat(buf,name);

	if (!(fp=fopen(buf,"r"))) {
		fprintf(stderr,"Couldn't open filter %s\n",name);
		exit(-1);
	}
	
	fscanf(fp,"%d %d",&xsize,&ysize);
	filter=(FILTER *)newimage(xsize,ysize,name);

	for(j=0;j<ysize;j++)
		for(i=0;i<xsize;i++) {
			fscanf(fp,"%d",&ival);
			filter->image[j][i]=ival;
		}
	
	return filter;
}

runfilter(filter,image,outimage)
IMAGE *image, *outimage;
FILTER *filter;
{
	int nflag = 0,
		scale,
		total;
	short max= -32768,
		  min=  32767,
		  **tempimage;
	int mfy = filter->ysize>>1,
		mfx = filter->xsize>>1;
	register int fi,fj,i,j;
	int sneg=0,
		spos=0,
		fred;

	for(j=0;j<filter->ysize;j++)
		for(i=0;i<filter->xsize;i++)
			if (filter->image[j][i]<0) {
				nflag=1;
				sneg -= filter->image[j][i];
			}
			else spos += filter->image[j][i];

	scale = (sneg > spos) ? sneg : spos;
	scale = (nflag) ? scale*2 : scale;

	if (!eflag)
		for(j=0;j<image->ysize-filter->ysize;j++)
			for(i=0;i<image->xsize-filter->ysize;i++) {
				total=0;
				for(fj=0;fj<filter->ysize;fj++)
					for(fi=0;fi<filter->xsize;fi++) {
						fred = image->image[j+fj][i+fi];
						total += fred * filter->image[fj][fi];
					}
				outimage->image[j+mfy][i+mfx] = total / scale + ((nflag) ? 128 : 0);
			}
	else {
		if (!(tempimage=(short **)
				dynamem(&tempimage,sizeof(short),2,image->ysize,image->xsize))) {
			fprintf(stderr,"Get some more VM !!!\n");
			exit(-1);
		}
		for(j=0;j<image->ysize-filter->ysize;j++)
			for(i=0;i<image->xsize-filter->ysize;i++) {
				total=0;
				for(fj=0;fj<filter->ysize;fj++)
					for(fi=0;fi<filter->xsize;fi++) {
						fred = image->image[j+fj][i+fi];
						total += filter->image[fj][fi] * fred;
					}
				tempimage[j+mfy][i+mfx] = total;
				max=(max>total)?max:total;
				min=(min<total)?min:total;
			}

		scale=(max>-min)?max:-min;
		scale=(nflag)?scale*2:scale;

		for (j=0; j< image->ysize; j++)
			for (i=0; i<image->xsize;i++)
				outimage->image[j][i]=tempimage[j][i]*256/scale+((nflag)?128:0);
	}
}

help(name)
char *name;
{
	printf("Convolution Filter\n");
	printf("------------------\n");
	printf("\nUsage: %s [file]\n",name);
	printf("\nOptions:\n");
	printf("  -F       list filters\n");
	printf("  -ffilter use filter\n");
	printf("  -e       enhanced scaling\n");
	printf("  -h       help\n");
}
End of convolve.c
 echo defs.h 1>&2
cat >defs.h <<'End of defs.h'
#define YES	 1
#define NO   0
#define FILTERS_DIR		"/usr/aloha/alv/everson/usr/filters"
#define ERROR(S)	{ fprintf(stderr,"%s: %s\n",progname,S); exit(1); }
#define FIL_MAX 	31			/* max dimension of a filter */
#define XSIZE		256
#define	YSIZE		240

int filter[FIL_MAX][FIL_MAX];			/* filter array */
char progname[10];		/* program name */
short old_maxch,		/* max pixel value in the picture */
      old_minch,		/* min pixel value in the picture */
      maxch,			/* max pixel value in image */
	  minch,			/* min pixel value in image */
      abs_minch;		/* min absolute pixel value in image */

unsigned char **pic,
			  **image;;
short **eimage;

int pic_trunc;				/* truncation value */
int xsize,
	ysize,
	m_fil,				/* height of filter */
    n_fil,				/* width of filter */
    fil_scale;			/* scaling factor used to scale image to character
						   values after running the filter */
extern int negfilter,
		   enhanced;
End of defs.h
 echo dsp.c 1>&2
cat >dsp.c <<'End of dsp.c'
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <stdio.h>
#include "image.h"
#include "pattern3.h"

int boxsize = 3;
static void getcoords();
static void repaint_canvas();
IMAGE *image;
int *p_pat;
int mflag = 0;
Pixrect *pattern;

main(argc, argv)
int argc;
char **argv;
{
	Frame frame;
	Canvas canvas;
	Pixwin *pw;
	char cmsname[CMS_NAMESIZE];
	int i, j, x, y;
	FILE *fp, *fopen();
	u_char *pi;
	char *imagefile=NULL;

	stdopts(&argc,argv);
	windopts(&argc,argv);

	for (argv++;*argv;*argv++)
		if (*argv[0]=='-' && (*argv)[1]=='m') 
			mflag = 1;
		else imagefile= *argv;

	if (imagefile==NULL)
		fp=stdin;
	else if (!(fp = fopen(imagefile,"r"))) {
		fprintf(stderr,"Cannot open %s\n",imagefile);
		exit(-1);
		}
	image = readimage(fp);

	/* create frame and canvas */
    frame = window_create(NULL, FRAME,
				  FRAME_LABEL, (newtitle)?newtitle:image->title,
                  WIN_X, winxoff,
                  WIN_Y, winyoff,
                  WIN_HEIGHT, (winxsize)?winxsize:image->ysize * boxsize + 22,
                  WIN_WIDTH, (winysize)?winysize:image->xsize * boxsize + 10,
                  0);


	if (mflag)
		canvas = window_create(frame, CANVAS,
				       CANVAS_HEIGHT, image->ysize * boxsize,
				       CANVAS_WIDTH, image->xsize * boxsize,
				       WIN_EVENT_PROC, getcoords,
				       0);
	else
		canvas = window_create(frame, CANVAS,
				       CANVAS_FAST_MONO, TRUE,
				       CANVAS_HEIGHT, image->ysize * boxsize,
				       CANVAS_WIDTH, image->xsize * boxsize,
				       WIN_EVENT_PROC, getcoords,
				       CANVAS_RETAINED, FALSE,
				       CANVAS_REPAINT_PROC, repaint_canvas,
				       0);


	/* get the canvas pixwin to draw into */
	pw = canvas_pixwin(canvas);

	/* create dot pattern */
	pattern = mem_create(boxsize, boxsize * 50, 1);
	p_pat = &pat[0];
	for (y = 0; y < boxsize * 10; y++)
		for (x = 0; x < boxsize; x++, p_pat++)
			pr_rop(pattern, x, y, 1, 1,
			       (*p_pat) ? PIX_CLR : PIX_SET,
			       (Pixrect *) 0, 0, 0);

	if (mflag) {
		/* Draw gray boxes */
		for (y = 0; y < image->ysize; y++) {
			pi = image->image[y];
			for (x = 0; x < image->xsize; x++) {
				/* Fill in a square box */
				pw_rop(pw, x * boxsize, y * boxsize,
				       boxsize, boxsize,
				       PIX_SRC, pattern, 0, boxsize * ((*pi + 26) / 27));
				pi++;
			}
		}
	}

	window_main_loop(frame);
}

static void
repaint_canvas(canvas, pw, repaint_area)
Canvas canvas;
Pixwin *pw;
Rectlist *repaint_area;

{
	u_char *pi;
	int x, y;
	int xstart, ystart, xstop, ystop;

	xstart = repaint_area->rl_bound.r_left / boxsize;
	ystart = repaint_area->rl_bound.r_top / boxsize;
	xstop = xstart + 1 + repaint_area->rl_bound.r_width / boxsize;
	ystop = ystart + 1 + repaint_area->rl_bound.r_height / boxsize;

	xstop = (xstop > image->xsize) ? image->xsize : xstop;
	ystop = (ystop > image->ysize) ? image->ysize : ystop;

	/* Enable locking for efficiency */

	/* Draw gray boxes */
	for (y = ystart; y < ystop; y++) {
		pi = &(image->image[y][xstart]);
		pw_lock(pw, &(repaint_area->rl_bound));
		for (x = xstart; x < xstop; x++) {
			/* Fill in a square box */
			pw_rop(pw, x * boxsize, y * boxsize,
			       boxsize, boxsize,
			  PIX_SRC, pattern, 0, boxsize * ((*pi + 26) / 27));
			pi++;
		}
		pw_unlock(pw);
	}
}

static void
getcoords(canvas, event, arg)
Canvas canvas;
Event *event;
caddr_t arg;

{
	if ((event_id(event) == MS_LEFT) && event_is_down(event)) {
		printf("%s: locator x,y : %d %d  greylevel = %d\n", (newtitle)?newtitle:image->title,
		       event_x(event) / boxsize, event_y(event) / boxsize,
		 image->image[event_y(event) / boxsize][event_x(event) / boxsize]);
	}
}
End of dsp.c
 echo dynamem.3 1>&2
cat >dynamem.3 <<'End of dynamem.3'
.\" .TH name section cent-foot left-foot cent-head
.TH DYNAMEM 3 "28 August 1987"
.SH NAME
.\" name \- function
dynamem, freeup \- multidimensional dynamic array handling
.SH SYNOPSIS
.\" Bold keywords, Italic variables, [] options, | alternatives.
.br
.B char *dynamem(pointer,element_size,
.br
.B				 number_dimensions,dimensions ...)
.br
.B char **pointer;

.br
.B freeup(pointer)
.br
.B char *pointer;

.SH DESCRIPTION
.\" Italic files, commands, IR manual-entry (manual-section)
.I dynamem 
is the multidimensional analogue to malloc().
It is passed a number of arguments: a pointer which on
exiting the procedure will point to the begining of the
array, the element size, the number of dimensions 
required, followed by a list of the dimension sizes. 
To declare a 4 dimensional array normally one would code:
.DS L

int array[10][11][12][13];

.DE
however, this array is then fixed at compile time. This
same array can be declared dynamically at run time 
using the following code:
.DS L

int ****array;

array = (int ****) dynamem(&array, sizeof(int), 4, 10, 11, 12, 13);

.DE
(Note that the number of levels of indirection in the cast
is equal to the number of dimensions in the array.)
This enables array sizes to be fixed via, for example, 
command line arguments. 
.PP
.I freeup
is the 
.I dynamem
analogue to free(). When passed an array previously 
dynamically declared by 
.I dynamem
the function returns this memory to the system.
.PP
.I dynamem
attempts to set up the array required in the same way that 
it would be set up by the compiler at compile time. Thus
a multidimensional dynamically array declared using 
.I dynamem
can be used in exactly the same way as a fixed array declared
by the compiler. There is obviously some overhead in the actual
setting up of the array; however, this is minimal: 
when dynamically allocating 2 arrays of 346000
unsigned characters and one of the same number of shorts all in
two dimensions, the run time of a convolution of a 7x7 Lapacian-
Marr filter over an image of size 720 by 480 varied as follows:
.sp 1
time convolve -fbfilt -X720 -Y480 -e < bubble2 > test.1
.br
	  222.0 real       213.4 user         1.6 sys  
.sp 1
time convolve -fbfilt -e < bubble2 > test.2
.br
	  225.2 real       212.5 user         2.7 sys  
.sp 1
which is probably adequate. From this we can see that 
it takes 1.1 secs for the fixed array to be set up
and zeroed and only 0.9 secs for the array to be
dynamically declared using
.IR dynamem ; 
however, using dynamem the array is not initialized to
0 and this is the reason for the 0.2 speed increase.
.SH FILES
.\" List of all files used by the program
/users/alv/everson/usr/lib/dynamem.a
.SH "SEE ALSO"
.\" List of references, textual, and MAN pages.
malloc(3), convolve(1)
.SH DIAGNOSTICS
.\" List of error messages and return codes the user may expect
.br
.I dynamem
returns NULL if it is unable to allocate sufficient
memory for the array.
End of dynamem.3
 echo dynamem.c 1>&2
cat >dynamem.c <<'End of dynamem.c'

/*
 * dynamem allocates a d dimensional array, whose dimensions are stored in a
 * list starting at d1. Each array element is of size s. p is a pointer with
 * d levels of indirection to the memory area 
 */

char *
dynamem(p, s, d, d1)
char **p;
int s, d, d1;
{
	int max,		/* size of array to be declared */
	*q;			/* pointer to dimension list */
	char **r,		/* pointer to begining of the array of the
				 * pointers for a dimension */
	**s1, *t, *tree;	/* base pointer to begining of first array */
	int i,			/* loop counters */
	 j;

	r = &tree;
	q = &d1;		/* first dimension */
	max = 1;
	for (i = 0; i < d - 1; i++, q++) {	/* for each of the dimensions
						 * but the last */
		max *= (*q);
		if ((r[0] = (char *) malloc((unsigned) max * sizeof (char **))) == 0) {
			freeup(tree);
			return 0;
		}
		r = (char **) r[0];	/* step through to begining of next
					 * dimension array */
	}
	max *= s * (*q);	/* grab actual array memory */
	if ((r[0] = (char *) malloc((unsigned) max)) == 0) {
		freeup(tree);
		return 0;
	}

	/*
	 * r is now set to point to the begining of each array so that we can
	 * use it to scan down each array rather than having to go across and
	 * then down 
	 */
	r = (char **) tree;	/* back to the begining of list of arrays */
	q = &d1;		/* back to the first dimension */
	max = 1;
	for (i = 0; i < d - 2; i++, q++) {	/* we deal with the last
						 * array of pointers later on */
		max *= (*q);	/* number of elements in this dimension */
		for (j = 1, s1 = r + 1, t = r[0]; j < max; j++)	/* scans down array for
								 * first and subsequent
								 * elements */

			/*
			 *  modify each of the pointers so that it points to
			 * the correct position (sub-array) of the next
			 * dimension array. s1 is the current position in the
			 * current array. t is the current position in the
			 * next array. t is incremented before s is, but it
			 * starts off one behind. *(q+1) is the dimension of
			 * the next array. 
			 */
			*s1++ = (t += sizeof (char **) * *(q + 1));
		r = (char **) r[0];	/* step through to begining of next
					 * dimension array */
	}
	max *= (*q);		/* max is total number of elements in the
				 * last pointer array */
	for (j = 1, s1 = r + 1, t = r[0]; j < max; j++)	/* same as previous
							 * loop, but different
							 * size factor */
		*s1++ = (t += s * *(q + 1));
	return tree;		/* return base pointer */
}

/*
 * freeup releases all memory that we have already declared analogous to
 * free() when using malloc() 
 */
freeup(r)
char *r;
{
	char **p;

	for (p = &r; p; p = (char **) *p)
		free(*p);
}
End of dynamem.c
 echo ffill.c 1>&2
cat >ffill.c <<'End of ffill.c'
#include <stdio.h>
#include "image.h"

IMAGE *image;

main(argc,argv)
char **argv;
{
	FILE *fp;
	int xpos = -1, ypos = -1;
	int boundary = 0;
	char *imagefile=NULL;

	stdopts(&argc,argv);

	for (argv++;*argv;*argv++)
		if (**argv=='-')
			switch ((*argv)[1]) {
			case 'b':
				boundary=atoi(argv[0]+2);
				break;
			}
		else if (xpos<0)
			xpos=atoi(*argv+2);
		else if (ypos<0)
			ypos=atoi(*argv+2);
		else
			imagefile = *argv;

	if (imagefile==NULL)
		fp=stdin;
	else if (!(fp=fopen(imagefile,"r"))) {
		fprintf(stderr,"Cannot open %s\n",imagefile);
		exit(-1);
		}

	image=readimage(fp);

	if (!newtitle)
		sprintf(image->title,"%s | ffill %d %d %d\n",image->title,xpos,ypos,boundary);
	else
		strcpy(image->title,newtitle);
	ffill(xpos,ypos,boundary);

	writeimage(stdout,image);
	
}

ffill(x,y,n)
{
int i,j,k;

	if (x<0 || x>=image->xsize || y<0 || y>=image->ysize|| ftest(x,y)==n)
		return;
	fset (x,y,n);
	for (i=x-1;i>=0;i--) {
		if (ftest(i,y)!=n)
			fset(i,y,n);
		else 
			break;
		}
	for (j=x+1;j<image->xsize;j++)
		if (ftest(j,y)!=n)
			fset(j,y,n);
		else 
			break;
	for (k=i+1;k<j;k++)
	{
		if (y>0 && ftest(k,y-1)!=n)
			ffill(k,y-1,n);
		if (y<image->ysize-1 && ftest(k,y+1)!=n)
			ffill(k,y+1,n);
	}
}

ftest(x,y)
{
	return image->image[y][x];
}

fset(x,y,n)
{
	image->image[y][x]=n;
}

End of ffill.c
 echo hist.c 1>&2
cat >hist.c <<'End of hist.c'
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <stdio.h>
#include <math.h>
#include "image.h"

static short histicon[] = 
{
#include "hist.icon"
};
DEFINE_ICON_FROM_IMAGE(icon,histicon);

#define GREYLEVELS	256
#define HSIZE	128
#define HEADER	10
#define BOTTOM	20
#define BOXSIZE	3
#define MIN(a,b)	((a) < (b) ? (a) : (b))
#define MAX(a,b)	((a) > (b) ? (a) : (b))

IMAGE *image;
int vflag=1,
	lflag=0;
Frame frame;
Canvas canvas;
Menu menu;
Pixwin *pw;
int hist[GREYLEVELS],
	n=0;

main(argc,argv)
int argc;
char **argv;
{
	double mean(),
		   lhist[GREYLEVELS],
		   ldummy,
		   lmaxh= -10000.0;
	register short i,j;
	int c,
		mo,
		len,
		dummy,
		maxh=0,
		maxc=0,
		minc=GREYLEVELS;
    Pixrect *pattern;
	char *imagefile=NULL;
	char message[BUFSIZ];
	FILE *fp;

	stdopts(&argc,argv);
	windopts(&argc,argv);

	for (argv++;*argv;*argv++)
		if (**argv=='-')
			switch ((*argv)[1]) {
			case 'l':
				lflag=1;
				break;
			case 'v':
				vflag=0;
				break;
			}
		else imagefile = *argv;

	if (imagefile==NULL)
		fp=stdin;
	else if (!(fp=fopen(imagefile,"r"))) {
		fprintf(stderr,"Cannot open %s\n",imagefile);
		exit(-1);
		}

	image=readimage(fp);
	
	for (i=0;i<GREYLEVELS;i++)
		hist[i]=0;

	for(j=0;j<image->ysize;j++) 
		for (i=0;i<image->xsize;i++) {
			c = MAX(image->image[j][i],0);
			c = MIN(c,GREYLEVELS);
			if (c>maxc) 
				maxc = c;
			else if (c<minc) 
				minc = c;
			hist[c]++;
			if (maxh<hist[c])
				maxh=hist[c];
			n++;
		}

	fprintf(stderr,"mean pixel = %3g\n",mean());
	fprintf(stderr,"median pixel = %d\n",median());
	fprintf(stderr,"mode pixel = %d\n",mo=mode());
	fprintf(stderr,"max pixel = %d\nmin pixel = %d\n",maxc,minc);

	strcpy(message,(lflag==1)?"logarithmic histogram" : "histogram");
	strcat(message,": ");
	strcat(message,image->title);

   	/* create frame and canvas */
   	frame = window_create(NULL, FRAME,
			 FRAME_LABEL, message, 
			 WIN_X, winxoff,
			 WIN_Y, winyoff,
			 WIN_HEIGHT, (winxsize)?winxsize:HSIZE+28+HEADER+BOTTOM,
			 WIN_WIDTH, (winysize)?winysize:(GREYLEVELS*BOXSIZE)+10,
			 FRAME_ICON,&icon,
			 0);
   	canvas = window_create(frame, CANVAS,
			  CANVAS_FAST_MONO, TRUE,
			  CANVAS_HEIGHT, HSIZE+HEADER+BOTTOM,
			  CANVAS_WIDTH, GREYLEVELS*BOXSIZE,
			  0);
  	
	/* get the cancas pixwin to draw into */
   	pw = canvas_pixwin(canvas);

  	/* Enable batching for efficiency */
   	pw_batch_on(pw);

   	if (!lflag) { 
   		for (i = 0; i < GREYLEVELS; i++) {
			dummy = hist[i]*HSIZE/maxh;
			if (!dummy && hist[i]) 
				dummy = 1;
     		if (vflag) {
				pw_vector(pw,i*BOXSIZE,HSIZE+HEADER-dummy,i*BOXSIZE,HSIZE+HEADER,PIX_SET,1);
				pw_vector(pw,i*BOXSIZE+BOXSIZE,HSIZE+HEADER-dummy,i*BOXSIZE+BOXSIZE,HSIZE+HEADER,PIX_SET,1);
				}
			pw_rop(pw,i*BOXSIZE,HSIZE+HEADER-dummy,BOXSIZE,1,PIX_SET,(Pixrect *)0,0,0);
   			}	
		}
	else {
		for (i=0;i<GREYLEVELS;i++) {
			lhist[i] = log((double)hist[i]+1.0);		/* add 1 to avoid log(0) */
			if (lmaxh<lhist[i])
				lmaxh=lhist[i];
			}
		for (i=0;i<GREYLEVELS;i++) {
			ldummy = lhist[i]*HSIZE /lmaxh; 
			if (dummy!=0.0 && lhist[i]==0.0)
				ldummy = 1.0;
     		if (vflag) {
				pw_vector(pw,i*BOXSIZE,HSIZE+HEADER-(int)ldummy,i*BOXSIZE,HSIZE+HEADER,PIX_SET,1);
				pw_vector(pw,i*BOXSIZE+BOXSIZE,HSIZE+HEADER-(int)ldummy,i*BOXSIZE+BOXSIZE,HSIZE+HEADER,PIX_SET,1);
				}
			pw_rop(pw,i*BOXSIZE,HSIZE+HEADER-(int)ldummy,BOXSIZE,1,
			PIX_SET,(Pixrect *)0,0,0);
			}
		}

	/* print bottom axis */
	pw_vector(pw,0,HSIZE+HEADER,image->xsize*BOXSIZE,HSIZE+HEADER,PIX_SET,1);
	for(i=0;i<GREYLEVELS;i++) {
		len = (i%100==0) ? 10 :
			  (i%50==0)  ? 8 :
			  (i%10==0)  ? 6 :
			  (i%2==0)   ? 5 : 0;
		if (len)
			pw_vector(pw,i*BOXSIZE,HSIZE+HEADER,i*BOXSIZE,HSIZE+HEADER+len,PIX_SET,1);
		}

	pw_batch_off(pw);
   	window_main_loop(frame);

	exit(0);
}

double mean()
{
	int i;
	double m=0;

	for (i=0;i<GREYLEVELS;i++)  {
		m += hist[i]*i;	
		}
	return m/n;
}
	
median()
{
	int i=0,
		count=0;
	
	while (count<n/2) 
		count += hist[i++];
	return i-1;
}

mode()
{
	int i=0;
	int mo=0,
		m=0;

	for(i=0;i<GREYLEVELS;i++)
		if (hist[i]>m) {
			m=hist[i];
			mo=i;
			}

	return mo;
}

End of hist.c
 echo hist.icon 1>&2
cat >hist.icon <<'End of hist.icon'
/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
 */
	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001,
	0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
	0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
	0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
	0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
	0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
	0x8000,0x0000,0x2000,0x0001,0x8000,0x0000,0x2000,0x0001,
	0x8000,0x0000,0x2000,0x0001,0x8000,0x0000,0x2000,0x0001,
	0x8002,0x0800,0x2008,0x0001,0x8002,0x0800,0x2008,0x0001,
	0x8002,0x0800,0x2008,0x0001,0x8002,0x0800,0x2008,0x0001,
	0x800A,0x0A00,0x2008,0x8081,0x800A,0x0A00,0x2008,0x8081,
	0x800A,0x0A00,0x2008,0x8081,0x800A,0x0A00,0x2008,0x8081,
	0x800A,0x0A00,0x2808,0x8081,0x800A,0x0A00,0x2808,0x8081,
	0x800A,0x0A00,0x2808,0x8081,0x800A,0x0A00,0x2808,0x8081,
	0x800A,0x8A00,0x2888,0x8281,0x800A,0x8A00,0x2888,0x8281,
	0x800A,0x8A00,0x2888,0x8281,0x800A,0x8A00,0x2888,0x8281,
	0x800A,0x8A00,0xA8A8,0x8281,0x800A,0x8A00,0xA8A8,0x8281,
	0x800A,0x8A00,0xA8A8,0x8281,0x800A,0x8A02,0xA8A8,0x8A81,
	0x802A,0x8A8A,0xAAAA,0x8A81,0x802A,0x8A8A,0xAAAA,0x8A81,
	0x802A,0x8A8A,0xAAAA,0x8A81,0x802A,0x8A8A,0xAAAA,0x8A81,
	0x80AA,0xAAAA,0xAAAA,0xAA81,0x80AA,0xAAAA,0xAAAA,0xAA81,
	0x80AA,0xAAAA,0xAAAA,0xAA81,0x80FF,0xFFFF,0xFFFF,0xFF81,
	0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
	0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
	0xA010,0x0040,0x0000,0x0001,0xA000,0x0040,0x0000,0x0001,
	0xAC70,0x71F1,0xC34B,0x0E35,0xB210,0x8842,0x24CC,0x912B,
	0xA210,0x8042,0x2448,0x012B,0xA210,0x7042,0x2448,0x0F2B,
	0xA210,0x0842,0x2448,0x112B,0xA210,0x8842,0x24C8,0x112B,
	0xA210,0x7031,0xC348,0x0F2B,0x8000,0x0000,0x0040,0x0001,
	0x8000,0x0000,0x0440,0x0001,0x8000,0x0000,0x0380,0x0001,
	0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
	0x8000,0x0000,0x0000,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF
End of hist.icon
 echo image.h 1>&2
cat >image.h <<'End of image.h'
typedef struct img {
	unsigned char **image;
	short xsize, ysize;
	char title[252];
} IMAGE;

IMAGE *readimage(), *newimage();

extern int winxsize,winysize,
	       winxoff, winyoff;
extern int helpflag;
extern char *newtitle;
End of image.h
 echo imagelw.c 1>&2
cat >imagelw.c <<'End of imagelw.c'
#include <stdio.h>
#include <ctype.h> 
#include "image.h"
#define MIDX        285             /* center of output page */
#define MIDY        396

IMAGE *image;

main (argc,argv)
int argc;
char **argv;
{
    int c,x=0,y=0,r=0;
	register int i,j;
	double sx=1.0,sy=1.0,atof();
    char *hex();
    char title[512],buf[512];
    FILE *fp,*p1;
    int sflag=0,mflag=0,oflag=0,cflag=0;
	char *imagefile=NULL;
    
	stdopts(&argc,argv);
	windopts(&argc,argv);

	for (argv++;*argv;*argv++)
		if (**argv=='-')
			switch ((*argv)[1]) {
			case 't':
				sflag=1;
				break;
			case 'm':
				mflag=1;
				break;
			case 'c':
				cflag=1;
				break;
			case '\0':
				oflag=1;
				break;
			}
		else
			imagefile = *argv;

	if (imagefile==NULL)
		fp=stdin;
	else if (!(fp=fopen(imagefile,"r"))) {
		fprintf(stderr,"Cannot open %s\n",imagefile);
		exit(-1);
		}

	image=readimage(fp);
	
    if (oflag || sflag)
		p1=stdout;
	else if((p1=popen(strcat("lpr -Plw -v",((mflag)?" -m":"")),"w"))==NULL) {
            fprintf(stderr,"Cannot open pipe to lpr\n");
            exit(-1);
            }
    
	fprintf(p1,"/picstr %d string def\n",image->xsize);

    if (image->title[0]) {
		fprintf(p1,"/Helvetica-Bold findfont\n");
        fprintf(p1,"12 scalefont setfont\n");
		fprintf(p1,"285 (%s) stringwidth pop 2 div sub 720 moveto\n",image->title);
		fprintf(p1,"(%s) show\n",image->title);
        }
	if (cflag) {
		sx=7.91*300/image->xsize;
		sy=8.5*300/image->ysize;				/* avoid title area */
		sx=sy=(sx>sy) ? sy:sx;
		x= -sx*image->xsize*72/300/2;
		y= -sy*image->ysize*72/300/2;
		}
	if (sflag) 
		fprintf(p1," 0 0 translate\n");
	else fprintf(p1,"%d %d translate\n",MIDX+x,MIDY-36+y);

	fprintf(p1,"%d %d scale\n",(int)(image->xsize/300.0*72.0*sx),(int)(image->ysize/300.0*72.0*sy));
	fprintf(p1,"%d %d 8\n",image->xsize,image->ysize);
	fprintf(p1,"[ %d 0 0 -%d 0 %d ]\n",image->xsize,image->ysize,image->ysize);
    fprintf(p1,"{currentfile\npicstr readhexstring pop}\nimage\n");

	for(j=0;j<image->ysize;j++)
		for(i=0;i<image->xsize;i++)
			fputs(hex(image->image[j][i]),p1);

	if (!sflag)
		fprintf(p1,"showpage\n");
    if (!(oflag || sflag))
        pclose(p1);
}

char *hex(d)
{
    static char a[10];

    sprintf(a,"%02x",d);
    return(a);
}
End of imagelw.c
 echo invert.c 1>&2
cat >invert.c <<'End of invert.c'
#include <stdio.h>
#include "image.h"

main(argc,argv)
char **argv;
{
	int c;
	register int i,j;
	char *imagefile=NULL;
	IMAGE *image;
	FILE *fp;
	
	stdopts(&argc,argv);
	if (argc-1>=1)
		imagefile= *++argv;

	if (imagefile==NULL)
		fp=stdin;
	else if (!(fp=fopen(imagefile,"r"))) {
		fprintf(stderr,"Cannot open %s\n",imagefile);
		exit(-1);
		}

	image=readimage(fp);

	if (!newtitle)
		strcat(image->title," | invert");
	else
		strcpy(image->title,newtitle);

	for(j=0;j<image->ysize;j++)
		for(i=0;i<image->xsize;i++)
			image->image[j][i]=abs(255 - image->image[j][i]);


	writeimage(stdout,image);
	fclose(fp);
}
End of invert.c
 echo lap1 1>&2
cat >lap1 <<'End of lap1'
3 3

 0 -1  0
-1  4 -1
 0 -1  0
End of lap1
 echo normalise.c 1>&2
cat >normalise.c <<'End of normalise.c'
#include <stdio.h>
#include "image.h"

#define GREYLEVELS 	256

IMAGE *image;

main(argc, argv)
char **argv;
{

	int c, low= -1, high= -1;
	char buff[BUFSIZ];
	register int i,j;
	char *imagefile = NULL;
	FILE *fp;

	stdopts(&argc, argv);

	imagefile = (*argv++)?*argv:NULL;

	if (imagefile == NULL)
		fp = stdin;
	else if (!(fp = fopen(imagefile, "r"))) {
		fprintf(stderr, "Cannot open %s\n", imagefile);
		exit(-1);
	}

	image = readimage(fp);

	if (!newtitle)
		strcat(image->title," | normalise");
	else
		strcpy(image->title,newtitle);

	norm(image);

	writeimage(stdout,image);
}

norm(image)
IMAGE *image;
{
	register int i,j;
	int x;
	int totpix=image->xsize * image->ysize;
	int hist[GREYLEVELS][2];
	int sum;

	for (i = 0; i < GREYLEVELS; i++) 
		hist[i][0] = hist[i][1] = 0;

	for (j=0;j<image->ysize;j++)
		for (i=0;i<image->xsize;i++) 
			hist[image->image[j][i]][0]++;

	sum = 0;
	for (i = 0; i < GREYLEVELS; i++) {
		sum += hist[i][0];
		x = sum * GREYLEVELS/ totpix;
		x = (x > 255) ? 255 : x;
		hist[i][1] = x;
	}

	for(j=0;j<image->ysize;j++)
		for(i=0;i<image->xsize;i++)
			image->image[j][i]=hist[image->image[j][i]][1];
}
End of normalise.c
 echo pattern3.h 1>&2
cat >pattern3.h <<'End of pattern3.h'
/* file pattern.h */
int pat[] = 
{	0,0,0,
	0,0,0,
	0,0,0,
		0,0,0,
		0,1,0,
		0,0,0,
	0,0,0,
	1,0,1,
	0,0,0,
		0,0,1,
		0,1,0,
		1,0,0,
	0,1,0,
	1,0,1,
	0,1,0,
		1,0,1,
		0,1,0,
		1,0,1,
	1,1,1,
	0,1,0,
	1,0,1,
		1,1,1,
		1,1,0,
		1,0,1,
	1,1,1,
	1,0,1,
	1,1,1,
		1,1,1,
		1,1,1,
		1,1,1};
End of pattern3.h
 echo pixval.c 1>&2
cat >pixval.c <<'End of pixval.c'
#include <stdio.h>
#include <string.h>
#include "image.h"

IMAGE *image,
	  *image1;

main (argc,argv)
int argc;
char **argv;
{
	register int i,j;
	char *imagefile=NULL;
	FILE *fp;

	stdopts(&argc,argv);
	windopts(&argc,argv);

	if (argc>1)
		imagefile = argv[1];

	if (imagefile==NULL)
		fp=stdin;
	else if (!(fp=fopen(imagefile,"r"))) {
		fprintf(stderr,"Cannot open %s\n",imagefile);
		exit(-1);
		}

	image=readimage(fp);
	image1=newimage(winxsize,winysize,"");

	subarea(image,image1,winxoff,winyoff);
	
	for (j=0;j<image1->ysize;j++) {
		for(i=0;i<image1->xsize;i++)
			printf("%4d",image1->image[j][i]);
		putchar('\n');
		}
}
End of pixval.c
 echo range.c 1>&2
cat >range.c <<'End of range.c'
#include <stdio.h>
#include "image.h"

IMAGE *image;

main(argc, argv)
char **argv;
{

	int c, low= 0, high= 255;
	char buff[BUFSIZ];
	register int i,j;
	char *imagefile = NULL;
	FILE *fp;

	stdopts(&argc, argv);

	for (argv++; *argv; *argv++)
		if (**argv == '-')
			switch ((*argv)[1]) {
			case 'l':
				low = atoi(argv[0] + 2);
				break;
			case 'h':
				high = atoi(argv[0] + 2);
				break;
			}
		else
			imagefile = *argv;

	if (imagefile == NULL)
		fp = stdin;
	else if (!(fp = fopen(imagefile, "r"))) {
		fprintf(stderr, "Cannot open %s\n", imagefile);
		exit(-1);
	}

	image = readimage(fp);

	if (!newtitle)
	{
		strcat(image->title," | range");
		sprintf(buff," -l%d",low);
		strcat(image->title,buff);
		sprintf(buff," -h%d",high);
		strcat(image->title,buff);
	}
	else
		strcpy(image->title,newtitle);

	for(j=0;j<image->ysize;j++)
		for(i=0;i<image->xsize;i++) {
			c = (image->image[j][i] - low) * 255 / (high - low);
			c = (c < 0) ? 0 : c;
			image->image[j][i]= (c > 255) ? 255 : c;
			}

	writeimage(stdout,image);
}
End of range.c
 echo retitle.c 1>&2
cat >retitle.c <<'End of retitle.c'
#include <stdio.h>
#include "image.h"

main(argc,argv)
char **argv;
{
IMAGE *image1,*image2;
FILE *fp;

	stdopts(&argc,argv);
	if (helpflag)
	{
		help(*argv);
		exit(0);
	}
	if (argc>1)
	{
		if (!(fp=fopen(argv[1],"r")))
		{
			fprintf(stderr,"%s: cannot open %s\n",argv[0],argv[1]);
			exit(-1);
		}
		image1=readimage(fp);
	}
	else
		image1=readimage(stdin);

	if (newtitle)
	{
		image2=newimage(image1->xsize,image1->ysize,newtitle);
		image2->image=image1->image;
		writeimage(stdout,image2);
	}
	else
		writeimage(stdout,image1);
}

help(name)
char *name;
{
	printf("Retitling Filter\n");
	printf("----------------\n");
	printf("\nUsage: %s [file]\n",name);
	printf("\nOptions:\n");
	printf("  -h      help\n");
	printf("  -ttitle new title\n");
}
End of retitle.c
 echo sobel1 1>&2
cat >sobel1 <<'End of sobel1'
5 5

 1  2  0 -2 -1
 2  4  0 -4 -2
 2  6  0 -6 -2
 2  4  0 -4 -2
 1  2  0 -2 -1


End of sobel1
 echo striphead.c 1>&2
cat >striphead.c <<'End of striphead.c'
#include <stdio.h>
#include "image.h"

IMAGE *image;

main(argc,argv)
int argc;
char **argv;
{
	int i,j;
	int xsize,ysize;
	unsigned char **pic;
	char *file, *title;
	FILE *fp;

	stdopts(&argc,argv);

	file = (*argv++)?*argv:NULL;

	if (file==NULL) {
		if (!(fp=fopen(file,"r"))) {
			fprintf(stderr,"Cannot open %s\n",file);
			exit(-1);
			}
		}
	else fp=stdin;

	image=readimage(fp);

	for (j=0;j<image->ysize;j++)
		for (i=0;i<image->xsize;i++)
			putchar(image->image[j][i]);

	fclose(fp);
}
End of striphead.c
 echo subarea.c 1>&2
cat >subarea.c <<'End of subarea.c'
#include <stdio.h>
#include "image.h"

main(argc,argv)
char **argv;
{
FILE *fp;

	stdopts(&argc,argv);
	windopts(&argc,argv);

	if (helpflag)
	{
		help(*argv);
		exit(0);
	}
	if (argc<1)
	{
		fprintf(stderr,"Usage: %s [filename]\n",argv[0]);
		exit(-1);
	}
	if (winxoff<0 || winyoff<0 || winxsize<0 || winysize<0)
	{
		fprintf(stderr,"Negative Values not permitted !!\n");
		exit(-1);
	}
	if (argc==1)
		subar(stdin);
	else
		if (!(fp=fopen(argv[1],"r")))
		{
			fprintf(stderr,"%s: cannot open %s\n",argv[0],argv[1]);
			exit(-1);
		}
		else
		{
			subar(fp);
			fclose(fp);
		}
}

subar(fp)
FILE *fp;
{
IMAGE *image1,*image2;

	image1=readimage(fp);

	if (newtitle)
		image2=newimage(winxsize,winysize,newtitle);
	else
	{
		image2=newimage(winxsize,winysize,image1->title);
		strcat(image2->title," | subarea");
	}

	subarea(image1,image2,winxoff,winyoff);

	writeimage(stdout,image2);
}

help(name)
char *name;
{
	printf("Subsample Filter\n");
	printf("----------------\n");
	printf("\nUsage: %s -xn -yn -Xn -Yn [file]\n",name);
	printf("\nOptions:\n");
	printf("  -h      help\n");
	printf("  -ttitle new title\n");
}
End of subarea.c
 echo subsample.c 1>&2
cat >subsample.c <<'End of subsample.c'
#include <stdio.h>
#include "image.h"

main(argc,argv)
char **argv;
{
int newx,newy;
FILE *fp;

	stdopts(&argc,argv);
	if (helpflag)
	{
		help(*argv);
		exit(0);
	}
	if (argc<3)
	{
		fprintf(stderr,"Usage: %s newx newy [filename]\n",argv[0]);
		exit(-1);
	}
	newx=atoi(argv[1]);
	newy=atoi(argv[2]);
	if (newx<=0 || newy<=0)
	{
		fprintf(stderr,"Negative Values not permitted !!\n");
		exit(-1);
	}
	if (argc==3)
		subsamp(stdin,newx,newy);
	else
		if (!(fp=fopen(argv[3],"r")))
		{
			fprintf(stderr,"%s: cannot open %s\n",argv[0],argv[3]);
			exit(-1);
		}
		else
		{
			subsamp(fp,newx,newy);
			fclose(fp);
		}
}

subsamp(fp,x,y)
FILE *fp;
{
IMAGE *image1,*image2;

	image1=readimage(fp);

	if (newtitle)
		image2=newimage(x,y,newtitle);
	else
	{
		image2=newimage(x,y,image1->title);
		strcat(image2->title," | subsample");
	}

	subsample(image1,image2);

	writeimage(stdout,image2);
}

help(name)
char *name;
{
	printf("Subsample Filter\n");
	printf("----------------\n");
	printf("\nUsage: %s xsize ysize [file]\n",name);
	printf("\nOptions:\n");
	printf("  -h      help\n");
	printf("  -ttitle new title\n");
}
End of subsample.c
 echo thresh.c 1>&2
cat >thresh.c <<'End of thresh.c'
#include <math.h>
#include <stdio.h>
#include "image.h"

#define MAX 255
#define MIN 0
main(argc, argv)
int argc;
char **argv;
{
	register int i,j;
	char buff[BUFSIZ];
	int thresh;
	FILE *fp;
	IMAGE *image, *image2;

	stdopts(&argc,argv);

	if (argc>1 && argv[1][0]=='-' && argv[1][1]=='t')
		thresh = atoi(argv[1]+2);
	else
		thresh = -1;
	
	for (*argv++;*argv;argv++)
		if (**argv!='-')
			break;

	if (*argv)
	{
		if (!(fp=fopen(*argv,"r")))
		{
			fprintf(stderr,"Cannot Open %s\n",*argv);
			exit(-1);
		}
	}
	else
		fp=stdin;

	image=readimage(fp);
	fclose(fp);
	image2=newimage(image->xsize,image->ysize,(newtitle)?newtitle:image->title);

	if (!newtitle)
	{
		strcat(image2->title," | thresh");
		if (thresh >= 0) {
			sprintf(buff," -t%d",thresh);
			strcat(image2->title,buff); 
		}
	}
	else strcpy(image2->title,newtitle);
	
	if (thresh == -1)
		thresh=autothresh(image);

	for (j=0;j<image->ysize;j++)
		for (i=0;i<image->xsize;i++)
			image2->image[j][i]=image->image[j][i]<thresh?MIN:MAX;

	writeimage(stdout,image2);
}

autothresh(image)
IMAGE *image;
{
	register int x, y;
	int mean, sumx = 0, sumxsqrd = 0;
	double sd, nsd = 1.5;

	for (y = 0; y < image->ysize; y++) 
		for (x = 0; x < image->xsize; x++) {
			sumx += image->image[y][x];
			sumxsqrd += image->image[y][x] * image->image[y][x];
		}

	mean = sumx / (image->xsize * image->ysize);
	sd = sqrt((double) sumxsqrd / (image->xsize * image->ysize) - (mean * mean));
	x=nsd*sd;
	fprintf(stderr,"Threshold = %d\n",(int)(mean + x /* (nsd * sd)*/));
	return (int)(mean + x /*(nsd * sd)*/);
}
End of thresh.c
 echo xdiff1 1>&2
cat >xdiff1 <<'End of xdiff1'
7 7

1 1 1 0 -1 -1 -1
1 1 1 0 -1 -1 -1
1 1 1 0 -1 -1 -1
1 1 1 0 -1 -1 -1
1 1 1 0 -1 -1 -1
1 1 1 0 -1 -1 -1
1 1 1 0 -1 -1 -1
End of xdiff1


