[comp.sources.sun] v01i089: ALV - An Image Processing Toolkit, Part05/10

mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (12/12/89)

Submitted-by: everson@compsci.bristol.ac.uk
Posting-number: Volume 1, Issue 89
Archive-name: alv/part05



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 10)."
# Contents:  doc/man/man1/dsp.1 doc/tutorial.ms src/Makefile
#   src/convolve.c src/dynamem.c src/hist.c src/rasremap.c
#   src/scr2ras.c src/transform.c
# Wrapped by everson@kukini on Tue Oct 17 07:45:11 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'doc/man/man1/dsp.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'doc/man/man1/dsp.1'\"
else
echo shar: Extracting \"'doc/man/man1/dsp.1'\" \(5380 characters\)
sed "s/^X//" >'doc/man/man1/dsp.1' <<'END_OF_FILE'
X.TH DSP 1 "29th May 1989"
X.SH NAME
dsp \- display raster on SUN screen
X.SH SYNOPSIS
X.B dsp
X[
X.B -c
X]
X[
X.B -b
X]
X[
X.BI -8 programname
X]
X[
X.B "infile"
X]
X.SH DESCRIPTION
X.I Dsp
displays an raster in a window on a SUN screen running 
X.I sunview (1).
The filename of the image is displayed in the window's frame label.
X.PP
XFirstly, the program checks to see whether the raster has a colourmap
associated with it. If it does the program uses it to display the
raster, if not then
X.I dsp
assumes it is working with a greylevel image in which 0 represents
white and the largest greylevel represents black.
X.PP
If the raster is a greylevel image, then program determines whether the
workstation supports colour (so that it can simulate a greyscale
display). If it does and the depth of the raster is greater than that
of the screen's frame buffer then the raster is displayed together with
window and level sliders. If the workstation is black & white and the
image to be displayed is 8 bits deep, then the program simulates the 8
bits of greylevel intensity by using a user specified dithering
technique to convert the raster to 1 bit deep before displaying it.
See 
X.I "Using ALV on a Black and White Workstation" 
for further details.
X.PP
The window and level sliders displayed above a greylevel raster on a colour
workstation are used to map the N bits of input raster onto the 8 bits
of screen frame buffer. The
X.I window
setting is the number of greylevels of the input raster which are mapped
into the 256 greylevels of the frame buffer and the
X.I level
setting is the position of the midpoint of this window in the input
raster greylevels. Greylevels outside this window are mapped to be
maximum or minimum greylevel of the screen frame buffer as
appropriate.  The initial setting of the level slider is equal to the
mean greylevel of the input raster and the initial window is set to
X512.
X.PP
Two scrollbars are associated with the raster, one vertical and the
other horizontal. These can be used to scroll an undisplayed portion of
the image onto the window display. If the window is resized, then the
appropriate extra portions of the raster are also displayed. Thus,
rasters of sizes larger than screen size can be usefully displayed.
X.PP
On a colour workstation, when the
X.I dsp
window is iconized a small sub-sampled copy of the displayed raster is
used as its icon, provinding the displayed raster is more than 1 bit deep.
X.PP
Interactive thresholding of 8 bit deep rasters is available by
combining the use of this program with
X.I winlev8 (1)
X.PP
If any of the mouse buttons are pressed over the raster, then the
coordinates of the mouse point together with the greylevel intensity of
the original raster at that point is displayed in the frame label
repeatedly, until the mouse is moved out of the
X.I dsp
window.
X.SH OPTIONS
X.PP
The 
X.B -c
and
X.B -b
options force the program to treat the workstation as being colour or
black & white respectively.
X.PP
The 
X.BI -8 programname
option specifies which program 
X.I dsp
should invoke to convert rasters for display on a black & white
workstation.  The default program is
X.I ras8to1 (1).
Currently, other alternatives are
X.I dither (1) ,
X.I rasfilter8to1 (1)
X(see BUGS section below)
and
X.I halftone (1).
Any program in the invoker's path which reads an 8 bit deep raster on its standard input
and writes a 1 bit raster to its standard output can be used.
X.PP
X.I Dsp
takes standard 
X.I sunview (1)
options for positioning the window etc.
X.PP
The global option
X.I "mono-override | mono-overwrite"
allows the full 256 colourmap entries of an image to be used in the display
of an image. In
X.I dsp   
the 0, 254 and 255 entries of the colourmap are by default set to a
monochrome colourmap so that the remainder of the screen is not   
obviously affected by displaying the raster. Pixels with these values
in the colour map are set equal to the displayable value nearest them.
Setting this option overrides this and allows the 0 and 255 colourmap
entries to be set to the values intended for display of the image.  
X.SH FILES
X.IP ~/.alv_profile
Global switches and standard command line arguments for each tool.
X.SH "ENVIROMENT VARIABLES"
X.IP ALV
If set, the pathname of an alternative profile.
X.SH "SEE ALSO"
X.BI alv (1) ,
X.BI sunview (1) , 
X.BI ras8to1 (1) ,
X.BI rasfilter8to1 (1) , 
X.BI dither (1) ,
X.BI halftone (1) ,
X.BI winlev8 (1) ,
X.BI winlev (1) ,
X.BI alv_profile (5) ,
X.BI rasterfile (5) ,
X.B "Using ALV on a Black and White Workstation".
X.SH DIAGNOSTICS
X.IP "Input depth not supported on this workstation"
X.I Dsp
can only display rasters of less than or equal to 8 bits deep on a black
X& white workstation.
X.IP "mem_create returned NULL"
There was insufficient memory available to allocate space for an raster
in memory.
X.IP "Can't open file"
The file does not have the correct access permissions to the file, or
it does not exist.
X.IP "Can't get file descriptor to write to child"
You have too many windows open under 
X.I sunview (1).
X.IP "Displaying Colour raster on black and white workstation"
X.I dsp
will attempt display the raster; however, only the 0 and 1 entries in the image
will be displayed.
X.SH BUGS
There is a bug in the Sun program 
X.I rasfilter8to1 (1). 
On large (720x480x8 pixel) images it hangs. Suggested work-round is to use the
X.I -8 
option to specify some other program, such as 
X.I ras8to1 (1). 
END_OF_FILE
if test 5380 -ne `wc -c <'doc/man/man1/dsp.1'`; then
    echo shar: \"'doc/man/man1/dsp.1'\" unpacked with wrong size!
fi
# end of 'doc/man/man1/dsp.1'
fi
if test -f 'doc/tutorial.ms' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'doc/tutorial.ms'\"
else
echo shar: Extracting \"'doc/tutorial.ms'\" \(3655 characters\)
sed "s/^X//" >'doc/tutorial.ms' <<'END_OF_FILE'
X.SH 
Tutorial
X.LP
This is a short simple tutorial to (hopefully) show you how to use the
ALV toolkit commands and also how to interface to the toolkit when
writing your own programs. A sample image is included in the
distribution and this will be used to demonstrate a few of the
toolkit's facilities.
X.LP
XFirst of all, decode the sample image, which has been encoded to permit
its transfer via email.
X.DS L
In the images directory type "make"
X.DE
You should now have a file named "sample_image" in the directory.  This
image is a picture of University Walk in Bristol University, UK showing
part of The Queen's Building (Engineering Faculty and home of the
Computer Science Dept.) in the background.
X.LP
The screen display facilities of the toolkit only work in 
X.I Sunview 
at present, so 
X.DS L
type "suntools" 
X.DE
to enter 
X.I Sunview 
if you are not already in the windowing enviroment.
X.LP
To display the image on the screen of your workstation 
X.DS L
type "dsp sample_image"
X.DE
and the image will be displayed on your screen. THe program dsp checks
to see whether you are running the toolkit on a colour or on a black &
white Sun Workstation and displays using 256 Greylevels or a dithering
technique as appropriate. To exit the display program it will have to
be killed by pressing the right mouse button on the top black frame bar
of the image and selecting the "Quit" menu entry.
X.LP
To show a histogram of the greylevels present in an image use the "hist"
command. For example,
X.DS L
type "hist sample_image"
X.DE
to show the histogram plot of the sample image. Some additional data is
written to the invoking window (via the standard error stream).
X.LP
To convolve the sample image with a linear filter, say a Laplacian
filter,  and then to display the results
X.DS L
type "convolve -flap1 -e sample_image | dsp"
X.DE
The "-f" option states which filter to use and the "-e" option tells
the convolve program to use enhanced scaling on the output. (Basically
this involves another pass over the image to stretch the Greylevel
range in the output to the maximum available). 
X.LP
This command line also demonstrates one of the main design features of
the 
X.I ALV 
toolkit - communication between processes via Unix pipes. The
X"|" symbol above connects the ouput of the "convolve" command (the
convolved image) with the input of the "dsp" command with the net
result of dislaying the convolved image on the screen. Most of the
toolkit's commands can be joined together like this and there is no
X(theoretical) limit to the number of commands that can be linked in this
way. For example, typing 
X.DS L
X"convolve -fxdiff1 -e sample_image | rasrange -l64 -h192 | rasscale -s0.5 | dsp"
X.DE
causes the sample image to be convolved with a 5*5 X-differentiating
linear filter with enhanced scaling, then ranged so that what was
greylevel 64 becomes greylevel 0 and what was greylevel 192 becomes
greylevel 255, scaled to half size and then
displayed on the screen. Far more complex piplines than this can be
constructed! For further information about using the commands consult the 
X.I ALV
command manual pages. 
X.LP
If you wish to construct your own tools, the file 
X.I src/generic.c
may be usefully used as a template. This contains all the code necessary 
for accessing the 
X.I ~/.alv_profile ,
for parsing the command-line arguments and for reading the raster into memory.
To compile this requires the files 
X.I src/defs.h
and 
X.I src/support.h
together with the 
X.I pixrect
library
X.I lpixrect .
If you do write any other filters which you find useful, please
consider mailing them to me so that I can redistribute them to other
users of the toolkit.
END_OF_FILE
if test 3655 -ne `wc -c <'doc/tutorial.ms'`; then
    echo shar: \"'doc/tutorial.ms'\" unpacked with wrong size!
fi
# end of 'doc/tutorial.ms'
fi
if test -f 'src/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/Makefile'\"
else
echo shar: Extracting \"'src/Makefile'\" \(5249 characters\)
sed "s/^X//" >'src/Makefile' <<'END_OF_FILE'
X#Modify the following to point to your desired installation points
BINDIR=/usr/local/alv/bin
MANDIR=/usr/local/alv/doc/man
XFILDIR=/usr/local/alv/filters
X
X#You might want to change this to rasfilter8to1, but ras8to1 is better!
XFILTER8TO1=$(BINDIR)/ras8to1
X
X#Sensible values of COMPILE_FLAGS are -g or -O
X#NB It must be called COMPILE_FLAGS here and not CFLAGS!
X#COMPILE_FLAGS=-g 
COMPILE_FLAGS=-O 
X
X##########################################################
X# You shouldn't need to modify anything below this point #
X# Type:                                                  #
X# 'make' to make tools standalone in place               #
X# 'make install' to make tools standalone and install    #
X##########################################################
X
WLIBS = support.o -lsuntool -lsunwindow -lpixrect -lm 
LIBS =  support.o -lpixrect -lm 
X
PROGS = convert dither rasthresh winlev dsp rasregion equalise ffill hist im2ras \
X	ras2im ras2lw invert rasval blend rasrange halftone box rasinfo scr2ras \
X	winlev8 rasscale transform convolve ras2array array2ras hough palettetool \
X	cst rasremap scrload ras8to1 fconvolve glass
X
CFLAGS=$(COMPILE_FLAGS) -DSTANDALONE
X
all: $(PROGS) 
X
glass: glass.o
X	cc $(CFLAGS) -o glass glass.o -lsuntool -lsunwindow -lpixrect -lm 
X
ras8to1: ras8to1.o support.o
X	cc $(CFLAGS) -o ras8to1 ras8to1.o $(LIBS)
X
scrload: scrload.o support.o
X	cc $(CFLAGS) -o scrload scrload.o $(LIBS)
X
cst: cst.o support.o
X	cc $(CFLAGS) -o cst cst.o $(WLIBS)
X
rasremap: rasremap.o support.o
X	cc $(CFLAGS) -o rasremap rasremap.o $(LIBS)
X
palettetool:  palettetool.o p_confirm.o p_init.o p_notif.o p_panel.o p_event.o support.o
X	cc $(CFLAGS) -o palettetool palettetool.o p_confirm.o p_init.o \
X	p_notif.o p_panel.o p_event.o $(WLIBS)
X
hough: hough.o support.o
X	cc $(CFLAGS) -o hough hough.o $(LIBS)
X
array2ras: array2ras.o support.o
X	cc $(CFLAGS) -o array2ras array2ras.o $(LIBS)
X
convert: convert.o support.o
X	cc $(CFLAGS) -o convert convert.o $(LIBS)
X
fconvolve.o: fconvolve.c defs.h support.c
X	cc $(CFLAGS) -DFILTERS_DIR=\"$(FILDIR)\" -c fconvolve.c
X
fconvolve: fconvolve.o support.o dynamem.o
X	cc $(CFLAGS) fconvolve.o dynamem.o -o fconvolve $(LIBS)
X
convolve.o: convolve.c defs.h support.c
X	cc $(CFLAGS) -DFILTERS_DIR=\"$(FILDIR)\" -c convolve.c
X
convolve: convolve.o support.o dynamem.o
X	cc $(CFLAGS) convolve.o dynamem.o -o convolve $(LIBS)
X
dither: dither.o support.o
X	cc $(CFLAGS) -o dither dither.o $(LIBS)
X
transform: transform.o matrix.o dynamem.o support.o
X	cc $(CFLAGS) -o transform transform.o dynamem.o matrix.o $(LIBS)
X
rasthresh: rasthresh.o support.o
X	cc $(CFLAGS) -o rasthresh rasthresh.o $(LIBS)
X
winlev: winlev.o support.o
X	cc $(CFLAGS) -o winlev winlev.o $(LIBS)
X
dsp: dsp.o support.o
X	cc $(CFLAGS) -o dsp dsp.o $(WLIBS)
X
dsp.o: dsp.c defs.h
X	cc $(CFLAGS) -DFILTER8TO1=\"$(FILTER8TO1)\" -c dsp.c 
X
rasregion: rasregion.o support.o
X	cc $(CFLAGS) -o rasregion rasregion.o $(LIBS)
X
equalise: equalise.o support.o
X	cc $(CFLAGS) -o equalise equalise.o $(LIBS)
X
ffill: ffill.o support.o
X	cc $(CFLAGS) -o ffill ffill.o $(LIBS)
X
hist: hist.o support.o
X	cc $(CFLAGS) -o hist hist.o $(WLIBS)
X
im2ras: im2ras.o support.o
X	cc $(CFLAGS) -o im2ras im2ras.o $(LIBS)
X
ras2im: ras2im.o support.o
X	cc $(CFLAGS) -o ras2im ras2im.o $(LIBS)
X
ras2lw: ras2lw.o support.o
X	cc $(CFLAGS) -o ras2lw ras2lw.o $(LIBS)
X
invert: invert.o support.o
X	cc $(CFLAGS) -o invert invert.o $(LIBS)
X
rasval: rasval.o support.o
X	cc $(CFLAGS) -o rasval rasval.o $(LIBS)
X
blend: blend.o support.o
X	cc $(CFLAGS) -o blend blend.o $(LIBS)
X
rasrange: rasrange.o support.o
X	cc $(CFLAGS) -o rasrange rasrange.o $(LIBS)
X
halftone: halftone.o support.o
X	cc $(CFLAGS) -o halftone halftone.o $(LIBS)
X
box: box.o support.o
X	cc $(CFLAGS) -o box box.o $(LIBS)
X
rasinfo: rasinfo.o support.o
X	cc $(CFLAGS) -o rasinfo rasinfo.o $(LIBS)
X
scr2ras: scr2ras.o
X	cc $(CFLAGS) -o scr2ras scr2ras.o $(WLIBS)
X
ras2array: ras2array.o
X	cc $(CFLAGS) -o ras2array ras2array.o $(LIBS)
X
winlev8: winlev8.o 
X	cc $(CFLAGS) -o winlev8 winlev8.o $(WLIBS)
X
rasscale double half quarter third triple quad: rasscale.o support.o
X	cc $(CFLAGS) -o rasscale rasscale.o $(LIBS)
X
clean:
X	rm -f *.o *~ core
X
spotless: clean
X	rm -f $(PROGS) double half quarter third triple quad MANIFEST alvtools
X
install: all
X	@for i in ${PROGS}; do \
X		(install -s $$i $(BINDIR)); \
X	done
X	@rm -f $(BINDIR)/double; ln -s $(BINDIR)/rasscale $(BINDIR)/double
X	@rm -f $(BINDIR)/half; ln -s $(BINDIR)/rasscale $(BINDIR)/half
X	@rm -f $(BINDIR)/quarter; ln -s $(BINDIR)/rasscale $(BINDIR)/quarter
X	@rm -f $(BINDIR)/third; ln -s $(BINDIR)/rasscale $(BINDIR)/third
X	@rm -f $(BINDIR)/triple; ln -s $(BINDIR)/rasscale $(BINDIR)/triple
X	@rm -f $(BINDIR)/quad; ln -s $(BINDIR)/rasscale $(BINDIR)/quad
X	@if test ! -d $(MANDIR)/man1; then mkdir $(MANDIR)/man1;fi
X	@for i in ../doc/man/man1/*; do \
X		(cp $$i $(MANDIR)/man1); \
X	done
X	@if test ! -d $(MANDIR)/man3; then mkdir $(MANDIR)/man3;fi
X	@for i in ../doc/man/man3/*; do \
X		(cp $$i $(MANDIR)/man3); \
X	done
X	@if test ! -d $(MANDIR)/man5; then mkdir $(MANDIR)/man5;fi
X	@for i in ../doc/man/man5/*; do \
X		(cp $$i $(MANDIR)/man5); \
X	done
X	@if test ! -d $(FILDIR); then mkdir $(FILDIR);fi
X	@for i in ../filters/*; do \
X		(cp $$i $(FILDIR)); \
X	done
X	@echo 'Programs, manual pages and filters installed'
X
END_OF_FILE
if test 5249 -ne `wc -c <'src/Makefile'`; then
    echo shar: \"'src/Makefile'\" unpacked with wrong size!
fi
# end of 'src/Makefile'
fi
if test -f 'src/convolve.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/convolve.c'\"
else
echo shar: Extracting \"'src/convolve.c'\" \(5296 characters\)
sed "s/^X//" >'src/convolve.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include "defs.h"
X
X#define DEFAULT		0
X#define ENHANCED	1
X#define MANUAL		2
X#define SYMMETRIC	3
X
typedef struct {
X	int   **image;
X	short   xsize, ysize;
X	int     nflag, spos, sneg;
X}       FILTER;
X
char   *progname;
char   *filename;
Pixrect *pr1, *pr2;
int     scale_method;
float   scale;
int     offset;
char   *filtername;
short   max_enhanced = -32768, min_enhanced = 32767;
int     mfx, mfy;
int     levels;
XFILTER *filter;
X
X#ifdef STANDALONE
main(argc, argv, envp)
X#else
convolve_main(argc, argv, envp)
X#endif
X	int     argc;
X	char  **argv;
X	char  **envp;
X{
X	register int i, j;
X	FILTER *loadfilter();
X
X	scale_method = DEFAULT;
X	scale = 1.;
X	offset = 0;
X	filtername = strsave("non-specified");
X	progname = strsave(argv[0]);
X	parse_profile(&argc, argv, envp);
X
X	while ((gc = getopt(argc, argv, "sef:lm:M:")) != EOF)
X		switch (gc) {
X		case 's':
X			scale_method = SYMMETRIC;
X			break;
X		case 'e':
X			scale_method = ENHANCED;
X			break;
X		case 'f':
X			filtername = strsave(optarg);
X			break;
X		case 'l':
X			execlp("ls", "ls", "-C", FILTERS_DIR, 0);
X			exit();
X			break;
X		case 'm':
X			scale_method = MANUAL;
X			scale = atof(optarg);
X			break;
X		case 'M':
X			scale_method = MANUAL;
X			offset = (int) atof(optarg);
X			break;
X		case '?':
X			errflag++;
X			break;
X		}
X
X	if (errflag)
X		error((char *) 0, "Usage: %s: [-e] [-s] [-f filter] [-l] [-m manual_scale] [-M manual_offset] [infile] [outfile]", progname);
X
X	for (stream = 0; optind < argc; stream++, optind++)
X		if (stream < 2 && strcmp(argv[optind], "-") != 0)
X			if (freopen(argv[optind], mode[stream], f[stream]) == NULL)
X				error("%s %s", PR_IO_ERR_INFILE, argv[optind]);
X
X	filter = loadfilter(filtername);
X
X	if ((pr1 = pr_load(stdin, NULL)) == NULL)
X		error(PR_IO_ERR_RASREAD);
X
X	if (bitrestrict)
X		levels = calc_max(pr1)+1;
X	else
X		levels = MAXLEVEL(pr1->pr_depth);
X
X	if ((pr2 = mem_create(pr1->pr_size.x, pr1->pr_size.y, pr1->pr_depth)) == NULL)
X		error("mem_create returned NULL");
X
X	mfx = filter->xsize / 2;
X	mfy = filter->ysize / 2;
X
X	switch (scale_method) {
X	case DEFAULT:
X		calc_default_scale();
X		one_pass();
X		break;
X	case ENHANCED:
X	case SYMMETRIC:
X		two_pass();
X		break;
X	case MANUAL:
X		one_pass();
X		break;
X	}
X
X	pr_dump(pr2, stdout, NULL, RT_STANDARD, 0);
X}
X
XFILTER *
loadfilter(name)
X	char   *name;
X{
X	char    buf[BUFSIZ];
X	FILE   *fp;
X	char   *ep;
X	FILTER *filter;
X	int     xsize, ysize, ival;
X	register int i, j;
X	char   *getenv();
X
X	if ((ep = getenv("FILTERS")) == NULL)
X		strcpy(buf, FILTERS_DIR);
X	else
X		strcpy(buf, ep);
X
X	strcat(buf, "/");
X	strcat(buf, name);
X
X	if (!(fp = fopen(buf, "r")))
X		error("Couldn't open filter %s", name);
X
X	fscanf(fp, "%d %d", &xsize, &ysize);
X	filter = (FILTER *) malloc(sizeof(FILTER));
X	filter->image = (int **) dynamem(&(filter->image), sizeof(int), 2, ysize, xsize);
X
X	filter->nflag = FALSE;
X	filter->xsize = xsize;
X	filter->ysize = ysize;
X
X	for (j = 0; j < ysize; j++)
X		for (i = 0; i < xsize; i++) {
X			fscanf(fp, "%d", &ival);
X			filter->image[j][i] = ival;
X			if (ival < 0) {
X				filter->nflag = TRUE;
X				filter->sneg += ival;
X			} else
X				filter->spos += ival;
X		}
X	filter->sneg = abs(filter->sneg);
X
X	return filter;
X}
calc_default_scale()
X{
X	if (filter->nflag) {
X		scale = (float) levels / (float) (MAX(filter->spos, filter->sneg) * 2);
X		offset = levels / 2;
X	} else {
X		scale = (float) levels / (float) (MAX(filter->spos, filter->sneg));
X		offset = 0;
X	}
X}
one_pass()
X{
X	register int total;
X	register int fj, fi;
X	register int i, j;
X
X	warning("scale = %g on input, offset = %d on output", scale, offset);
X
X	for (j = 0; j < pr1->pr_size.y - filter->ysize; j++)
X		for (i = 0; i < pr1->pr_size.x - filter->xsize; i++) {
X			total = 0;
X			for (fj = 0; fj < filter->ysize; fj++)
X				for (fi = 0; fi < filter->xsize; fi++)
X					total += (pr_get(pr1, i + fi, j + fj) * filter->image[fj][fi]);
X			pr_put(pr2, i + mfx, j + mfy, truncate((int) ((float) total * scale) + offset, levels, 0));
X		}
X}
two_pass()
X{
X	register int total;
X	register int least, most;
X	register int fj, fi;
X	register int i, j;
X	int     tmppix;
X	Pixrect *tmp;
X
X	if ((tmp = mem_create(pr1->pr_size.x, pr1->pr_size.y, 32)) == NULL)
X		error("mem_create returned NULL");
X
X	/* first pass */
X	least = 32768;
X	most -= 32767;
X	for (j = 0; j < pr1->pr_size.y - filter->ysize; j++)
X		for (i = 0; i < pr1->pr_size.x - filter->xsize; i++) {
X			total = 0;
X			for (fj = 0; fj < filter->ysize; fj++)
X				for (fi = 0; fi < filter->xsize; fi++)
X					total += (pr_get(pr1, i + fi, j + fj) * filter->image[fj][fi]);
X			pr_put(tmp, i + mfx, j + mfy, total);
X			least = MIN(total, least);
X			most = MAX(total, most);
X		}
X	least = abs(least);
X	
X	/* calculate scale and offset */
X	if (scale_method == SYMMETRIC) {
X		scale = (float) levels / (float) (MAX(least, most) * 2);
X		scale /= (filter->nflag) ? 2. : 1.;
X		offset = (filter->nflag) ? levels / 2 : 0;
X	} else {			    /* enhanced */
X		scale = (float) levels / (float) (least + most);
X		offset = (filter->nflag) ? least * scale : 0;
X	}
X
X	warning("scale = %g on filter, output offset = %d on output", scale, offset);
X
X	/* second pass */
X	for (j = 0; j < pr1->pr_size.y - filter->ysize; j++)
X		for (i = 0; i < pr1->pr_size.x - filter->xsize; i++) {
X			tmppix = truncate((int) ((float) pr_get(tmp, i, j) * scale + offset), levels, 0);
X			pr_put(pr2, i, j, tmppix);
X		}
X}
END_OF_FILE
if test 5296 -ne `wc -c <'src/convolve.c'`; then
    echo shar: \"'src/convolve.c'\" unpacked with wrong size!
fi
# end of 'src/convolve.c'
fi
if test -f 'src/dynamem.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/dynamem.c'\"
else
echo shar: Extracting \"'src/dynamem.c'\" \(4401 characters\)
sed "s/^X//" >'src/dynamem.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <varargs.h>
X
X/*
X * dynamem(p, s, d,  dn, dn ....) allocates a d dimensional array, whose 
X * dimensions are stored in a list starting at d1. Each array element is 
X * of size s. p is a pointer with d levels of indirection to the memory area 
X */
X
char *malloc();
X
char *
dynamem(va_alist)
va_dcl
X{
X		va_list ap;				/* varargs list traverser */
X        int max,                /* size of array to be declared */
X        *q;                     /* pointer to dimension list */
X        char **r,               /* pointer to begining of the array of the
X                                 * pointers for a dimension */
X        **s1, *t, *tree;        /* base pointer to begining of first array */
X        int i,                  /* loop counters */
X         j;
X        char **p;				/* pointer to memory area with d levels of indirection */
X		int s,					/* individual array element size */
X		d;						/* number of dimensions */
X		int *d1;				/* dimension list */
X
X		va_start(ap);
X		p = va_arg(ap, char**);
X		s = va_arg(ap,int);
X		d = va_arg(ap,int);
X		if ((d1 = (int *) malloc (sizeof(int) * d)) == NULL)
X			error("malloc returned NULL");
X
X		for(i=0;i<d;i++)
X			d1[i] = va_arg(ap,int);
X
X        r = &tree;
X        q = d1;                /* first dimension */
X        max = 1;
X        for (i = 0; i < d - 1; i++, q++) {      /* for each of the dimensions
X                                                 * but the last */
X                max *= (*q);
X                if ((r[0] = (char *) malloc((unsigned) max * sizeof (char **))) == NULL) {
X						free(d1);
X                        freeup(tree,i);
X                        return 0;
X                }
X                r = (char **) r[0];     /* step through to begining of next
X                                         * dimension array */
X        }
X        max *= s * (*q);        /* grab actual array memory */
X        if ((r[0] = (char *) malloc((unsigned) max)) == NULL) {
X				free(d1);
X                freeup(tree,d);
X                return 0;
X        }
X
X        /*
X         * r is now set to point to the begining of each array so that we can
X         * use it to scan down each array rather than having to go across and
X         * then down 
X         */
X        r = (char **) tree;     /* back to the begining of list of arrays */
X        q = d1;                 /* back to the first dimension */
X        max = 1;
X        for (i = 0; i < d - 2; i++, q++) {      /* we deal with the last
X                                                 * array of pointers later on */
X                max *= (*q);    /* number of elements in this dimension */
X                for (j = 1, s1 = r + 1, t = r[0]; j < max; j++) /* scans down array for
X                                                                 * first and subsequent
X                                                                 * elements */
X
X                        /*
X                         *  modify each of the pointers so that it points to
X                         * the correct position (sub-array) of the next
X                         * dimension array. s1 is the current position in the
X                         * current array. t is the current position in the
X                         * next array. t is incremented before s is, but it
X                         * starts off one behind. *(q+1) is the dimension of
X                         * the next array. 
X                         */
X                        *s1++ = (t += sizeof (char **) * *(q + 1));
X                r = (char **) r[0];     /* step through to begining of next
X                                         * dimension array */
X        }
X        max *= (*q);            /* max is total number of elements in the
X                                 * last pointer array */
X        for (j = 1, s1 = r + 1, t = r[0]; j < max; j++) /* same as previous
X                                                         * loop, but different
X                                                         * size factor */
X                *s1++ = (t += s * *(q + 1));
X		va_end(ap);
X		free(d1);
X        return tree;            /* return base pointer */
X}
X
X/*
X * freeup releases all memory that we have already declared analogous to
X * free() when using malloc() 
X */
freeup(r,d)
char **r;
int d;
X{
X        char **p;
X        int i;
X
X        for (p = r, i = 0; i < d; p = (char **) *p,i++)
X		if (p != NULL)
X		    free(p);
X}
END_OF_FILE
if test 4401 -ne `wc -c <'src/dynamem.c'`; then
    echo shar: \"'src/dynamem.c'\" unpacked with wrong size!
fi
# end of 'src/dynamem.c'
fi
if test -f 'src/hist.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/hist.c'\"
else
echo shar: Extracting \"'src/hist.c'\" \(5232 characters\)
sed "s/^X//" >'src/hist.c' <<'END_OF_FILE'
X#include <suntool/sunview.h>
X#include <suntool/canvas.h>
X#include "defs.h"
X
static short    histicon[] =
X{
X#include "../images/icons/hist.icon"
X};
DEFINE_ICON_FROM_IMAGE(icon, histicon);
X
X#define HSIZE	128
X#define HEADER	10
X#define BOTTOM	30
X#define BOXSIZE	3
X
XFrame           frame;
Canvas          canvas;
Menu            menu;
Pixwin         *pw;
char           *filename;
double          lhist[90000];
int             hist[90000], n = 0;
int             greylevels;
char           *progname;
int             max_val, min_val;
int             winxsiz, winysiz;
Pixrect        *pr, *dpr;
int             vertical, logarithmic;
int             maxh;
double          lmaxh;
X
X#ifdef STANDALONE
main(argc, argv, envp)
X#else
hist_main(argc, argv, envp)
X#endif
X	int             argc;
X	char          **argv;
X	char          **envp;
X{
X	register int    i, j;
X	int             len, dummy;
X	char           *itoa();
X	char            message[BUFSIZ];
X	char            buf1[BUFSIZ];
X	int             c;
X	colormap_t		colormap;
X
X	filename = strsave("stdin");
X	vertical = FALSE;
X	logarithmic = FALSE;
X	progname = strsave(argv[0]);
X	parse_profile(&argc, argv, envp);
X
X	while ((gc = getopt(argc, argv, "W:lvb")) != EOF)
X		switch (gc) {
X		case 'l':
X			logarithmic = TRUE;
X			break;
X		case 'v':
X			vertical = TRUE;
X			break;
X		case 'b':
X			bitrestrict = TRUE;
X			break;
X		case '?':
X			errflag++;
X			break;
X		}
X	if (errflag)
X		error((char *) 0, "Usage: %s: [-l] [-v] [-b] [infile]\n", progname);
X
X	for (stream = 0; optind < argc; stream++, optind++)
X		if (stream == 0 && strcmp(argv[optind], "-") != 0) {
X			filename = strsave(argv[optind]);
X			if (freopen(argv[optind], mode[stream], f[stream]) == NULL)
X				error("%s %s", PR_IO_ERR_INFILE, argv[optind]);
X		}
X
X	if ((pr = pr_load(stdin, &colormap)) == NULL)
X		error(PR_IO_ERR_RASREAD);
X
X	if (bitrestrict)
X		greylevels = calc_max(pr)+1;
X	else
X		greylevels = MAXLEVEL(pr->pr_depth);
X
X	statistics();
X
X	calc_winsize();
X
X	sprintf(message, "%s: %s", (logarithmic) ? "logarithmic histogram" : "histogram", filename);
X	frame = window_create(NULL, FRAME,
X			      FRAME_LABEL, message,
X			      WIN_HEIGHT, winxsiz,
X			      WIN_WIDTH, winysiz,
X			      FRAME_ICON, &icon,
X			      FRAME_ARGS, argc, argv,
X			      0);
X	canvas = window_create(frame, CANVAS,
X			       CANVAS_HEIGHT, HSIZE + HEADER + BOTTOM,
X			       CANVAS_WIDTH, greylevels * BOXSIZE + 10,
X			       CANVAS_AUTO_SHRINK, FALSE,
X			       WIN_HORIZONTAL_SCROLLBAR, scrollbar_create(0),
X			       0);
X
X	dpr = mem_create(window_get(canvas, CANVAS_HEIGHT),
X			 window_get(canvas, CANVAS_WIDTH),
X			 8);
X
X	pw = canvas_pixwin(canvas);
X
X	draw_histogram(pw);
X
X	pw_vector(pw, 0, HSIZE + HEADER, greylevels * BOXSIZE, HSIZE + HEADER, PIX_SET, 1);
X	for (i = 0; i < greylevels; i++) {
X		len = (i % 100 == 0) ? 10 :
X			(i % 50 == 0) ? 10 :
X			(i % 10 == 0) ? 6 :
X			(i % 2 == 0) ? 2 : 0;
X		if (len)
X			pw_vector(pw, i * BOXSIZE, HSIZE + HEADER, i * BOXSIZE, HSIZE + HEADER + len, PIX_SET, 1);
X		if (i % 10 == 0)
X			pw_text(pw, i * BOXSIZE, HSIZE + HEADER + 17, PIX_SRC, smallfont, itoa(i));
X	}
X
X	window_main_loop(frame);
X
X	exit(0);
X}
X
calc_winsize()
X{
X	winxsiz = HSIZE + 28 + HEADER + BOTTOM;
X	if ((greylevels * BOXSIZE + 10) > 500)
X		winysiz = 500;
X	else
X		winysiz = greylevels * BOXSIZE + 10;
X}
X
statistics()
X{
X	register int    i, j;
X	double          sumsq, stddev, mean;
X	int             cumulate, count, val, sum, median, mode;
X
X	sumsq = 0.;
X	sum = 0;
X	max_val = 0;
X	min_val = 10000;
X
X	for (j = 0; j < pr->pr_size.y; j++)
X		for (i = 0; i < pr->pr_size.x; i++) {
X			val = pr_get(pr, i, j);
X			max_val = MAX(max_val, val);
X			min_val = MIN(min_val, val);
X			hist[val]++;
X			sumsq += (val * val);
X			sum += val;
X		}
X	n = pr->pr_size.y * pr->pr_size.x;
X	mean = (double) sum / (double) n;
X	stddev = sqrt(sumsq / (double) n - mean * mean);
X
X	maxh = 0;
X	for (i = 0; i < greylevels; i++)
X		maxh = MAX(maxh, hist[i]);
X
X	i = count = 0;
X	while (count < n / 2)
X		count += hist[i++];
X	median = i - 1;
X
X
X	i = mode = cumulate = 0;
X
X	for (i = 0; i < greylevels; i++)
X		if (hist[i] > cumulate) {
X			cumulate = hist[i];
X			mode = i;
X		}
X	fprintf(stderr, "mean       = %3g\n", mean);
X	fprintf(stderr, "median     = %d\n", median);
X	fprintf(stderr, "mode       = %d\n", mode);
X	fprintf(stderr, "std. dev.  = %3g\n", stddev);
X	fprintf(stderr, "max pixel  = %d\n", max_val);
X	fprintf(stderr, "min pixel  = %d\n", min_val);
X}
X
draw_histogram(pw)
X	Pixwin         *pw;
X{
X	int             temp, count, i, npts, dx, dy;
X
X	npts = greylevels * 2 + 4;
X	dx = 0;
X	dy = HSIZE + HEADER;
X
X	pw_batch_on(pw);
X	pw_vector(pw, dx, dy, i * BOXSIZE, dy - hist[0] * HSIZE / maxh, PIX_SRC, 1);
X
X	if (logarithmic)
X		for (i = 0; i < greylevels; i++) {
X			lhist[i] = log((double) hist[i] + 1.0);	/* add 1 to avoid log(0) */
X			if (lmaxh < lhist[i])
X				lmaxh = lhist[i];
X		}
X
X	for (i = 0; i < greylevels; i++) {
X		if (logarithmic)
X			temp = (int) (lhist[i] * HSIZE / lmaxh);
X		else
X			temp = hist[i] * HSIZE / maxh;
X		pw_vector(pw, i * BOXSIZE, dy - temp, (i + 1) * BOXSIZE, dy - temp, PIX_SRC, 1);
X		if (vertical) {
X			pw_vector(pw, i * BOXSIZE, dy - temp, i * BOXSIZE, dy, PIX_SET, 1);
X			pw_vector(pw, (i + 1) * BOXSIZE, dy - temp, (i + 1) * BOXSIZE, dy, PIX_SET, 1);
X		}
X	}
X	pw_batch_off(pw);
X}
END_OF_FILE
if test 5232 -ne `wc -c <'src/hist.c'`; then
    echo shar: \"'src/hist.c'\" unpacked with wrong size!
fi
# end of 'src/hist.c'
fi
if test -f 'src/rasremap.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/rasremap.c'\"
else
echo shar: Extracting \"'src/rasremap.c'\" \(3647 characters\)
sed "s/^X//" >'src/rasremap.c' <<'END_OF_FILE'
X/**************************************************************************/
X/*  Based on the program blend.c by Phill Everson, from the ALV version   */
X/*  2.1 suite of public-domain image processing programs.                 */
X/*  Program to read a rasterfile and (optionally) a lookup table (LUT)    */
X/*  file produced by the program cst.  Using the values from either the   */
X/*  rasterfile's LUTs (=default) or the input LUTs, map pixel values to   */
X/*  their LUT equivalents, then substitute a 1:1 mapping LUT and write    */
X/*  out the file.  This allows interactively thresholded and contrast     */
X/*  stretched images to be used in programs which ignore LUTs.            */
X/*                                                                        */
X/*                              ras_remap.c                               */
X/*                                                                        */
X/*  Bryan Dawson, Keele University Geography Dept.                        */
X/*                                                        30/3/89         */
X/**************************************************************************/
X
X#include <stdio.h>
X#include "defs.h"
X
char * progname;
char * malloc();
int header[8];
unsigned char red[256],green[256],blue[256];
long filelen;
unsigned char * image;
X
X#ifdef STANDALONE
main(argc, argv, envp)
X#else
rasremap_main(argc, argv, envp)
X#endif
X    int   argc;
X    char  **argv;
X    char  **envp;
X{
X    register int x,y;
X    int   lutfile = 0;
X    FILE  *f1, *f2;
X
X    f1 = stdin;
X    f2 = stdin;
X    progname = strsave(argv[0]);
X    parse_profile(&argc, argv, envp);
X
X    while ((gc = getopt(argc, argv, "f:l:")) != EOF)
X        switch (gc) 
X        {
X        case 'f':
X            if ((f1 = fopen(optarg, "r")) == NULL)
X                error("Can't open %s\n", optarg);
X            break;
X        case 'l':
X            if ((f2 = fopen(optarg, "r")) == NULL) lutfile = 0 ; 
X                else lutfile = 1;
X            break;
X        case '?':
X            errflag++;
X            break;
X        } /* end switch */
X
if (errflag)
X    error((char *) 0, "Usage: %s: [-f imgfile] [-l LUTfile] [outfile] \n", progname);
X
X/* read rasterfile header */
x = fread(header,sizeof(int),8,f1);;
if (header[0] != 0x59a66a95) error("This isn't a Sun rasterfile !");
filelen = (long)header[4];
image = (u_char *)malloc(filelen); /* allocate space for image data */
X
X/* if there is a LUT on the file, and it's needed, read it, else skip it */
if ((lutfile == 0) && (header[7] == 768)) 
X    {
X    x = fread(red,1,256,f1);
X    x = fread(green,1,256,f1);
X    x = fread(blue,1,256,f1);
X    } else x = fseek(f1,header[7],1);
X
X/* read image data */
x = fread(image,1,filelen,f1);    
X
X/* if external LUTs are to be used, read them */
if (lutfile == 1)
X    {
X    x = fread(red,1,256,f2);
X    x = fread(green,1,256,f2);
X    x = fread(blue,1,256,f2);
X    }
X
X/* if there is still no LUT, create a dummy one */
if ((lutfile == 0) && (header[6] == RMT_NONE))
X    for (x=0;x<256;x++) red[x]=green[x]=blue[x] = x;
X    
remap();
for (x=0;x<256;x++) red[x]=green[x]=blue[x] = x;
writeit();
free(image);
exit();
X}
X
X/* routine to map pixel values to their LUT equivalents */
remap()
X{
register int temp;
register long p;
X
for (p = 0L ; p < filelen ; p++)
X    {
X    temp = red[(int)*(image+p)];
X    *(image+p) = temp;
X    }
X}
X
X/* routine to write out the three components of a rasterfile */
writeit()
X{
header[6] = 1;/* RMT_EQUAL_RGB */
header[7] = 768;
fwrite(header,4,8,stdout);
fwrite(red,1,256,stdout);/* greyscale image */
fwrite(red,1,256,stdout);
fwrite(red,1,256,stdout);
fwrite(image,1,filelen,stdout);
X}
X
X
END_OF_FILE
if test 3647 -ne `wc -c <'src/rasremap.c'`; then
    echo shar: \"'src/rasremap.c'\" unpacked with wrong size!
fi
# end of 'src/rasremap.c'
fi
if test -f 'src/scr2ras.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/scr2ras.c'\"
else
echo shar: Extracting \"'src/scr2ras.c'\" \(3964 characters\)
sed "s/^X//" >'src/scr2ras.c' <<'END_OF_FILE'
X/*
X * Modified and renamed src2ras, 1988 by Phill Everson for inclusion into ALV
X * toolkit.
X * 
X * dumpregion - dump a region of a sun screen in rasterfile format. Copyright
X * Richard Tobin 1987.  You may freely copy, modify and distribute this
X * program in source form provided this comment remains intact.
X * 
X * Richard Tobin,                    JANET: R.Tobin@uk.ac.ed           AI
X * Applications Institute,        ARPA:  R.Tobin%uk.ac.ed@nss.cs.ucl.ac.uk
X * Edinburgh University.             UUCP:  ...!ukc!ed.ac.uk!R.Tobin
X */
X
X#include "defs.h"
X#include <sys/file.h>
X#include <suntool/fullscreen.h>
X
char           *progname;
X
short           nwdata[] = {
X#include "../images/cursors/stretchNW.cursor"
X};
mpr_static(nwpixrect, 16, 16, 1, nwdata);
X
short           sedata[] = {
X#include "../images/cursors/stretchSE.cursor"
X};
mpr_static(sepixrect, 16, 16, 1, sedata);
X
Rect            rect = {0, 0, 0, 0};
X
colormap_t     *colormap = NULL;
X
X#ifdef STANDALONE
main(argc, argv, envp)
X#else
scr2ras_main(argc, argv, envp)
X#endif
X	int             argc;
X	char          **argv;
X	char          **envp;
X{
X	int             wfd;
X	struct fullscreen *fs;
X	Event           event;
X	Pixwin         *pw;
X	int             left, right, top, bottom, temp;
X	Window          win;
X	double          w;
X
X	progname = strsave(argv[0]);
X	parse_profile(&argc, argv, envp);
X
X	while ((gc = getopt(argc, argv, " ")) != EOF)
X		switch (gc) {
X		case '?':
X			errflag++;
X			break;
X		}
X
X	if (errflag)
X		error((char *) 0, "Usage: %s: [outfile]\n", progname);
X
X	for (stream = 0; optind < argc; stream++, optind++)
X		if (stream ==0 && strcmp(argv[optind], "-") != 0)
X			if (freopen(argv[optind],"w" ,stdout) == NULL)
X				error("%s %s", PR_IO_ERR_INFILE, argv[optind]);
X
X	win = window_create(0, FRAME,
X			    FRAME_OPEN_RECT, &rect,
X			    WIN_CONSUME_PICK_EVENTS,
X			    LOC_MOVE, WIN_MOUSE_BUTTONS, 0,
X			    0);
X
X	wfd = (int) window_get(win, WIN_FD);
X	fs = fullscreen_init(wfd);
X	pw = fs->fs_pixwin;
X
X	window_set(win,
X		   WIN_CURSOR, cursor_create(CURSOR_IMAGE, &nwpixrect,
X					     CURSOR_XHOT, 0, CURSOR_YHOT, 0,
X					     0),
X		   0);
X
X	while (window_read_event(win, &event) == -1 ||
X	       !event_is_down(&event) ||
X	       !event_is_button(&event));
X
X	right = left = event_x(&event);
X	bottom = top = event_y(&event);
X
X	window_set(win,
X		   WIN_CURSOR, cursor_create(CURSOR_IMAGE, &sepixrect,
X					   CURSOR_XHOT, 15, CURSOR_YHOT, 15,
X					     0),
X		   0);
X
X	drawbox(pw, left, top, right, bottom);
X
X	while (window_read_event(win, &event) == -1 ||
X	       !event_is_up(&event) ||
X	       !event_is_button(&event)) {
X		drawbox(pw, left, top, right, bottom);
X		right = event_x(&event);
X		bottom = event_y(&event);
X		drawbox(pw, left, top, right, bottom);
X	}
X
X	drawbox(pw, left, top, right, bottom);
X	fullscreen_destroy(fs);
X
X	window_set(win, FRAME_NO_CONFIRM, TRUE, 0);
X	window_destroy(win);
X
X	if (right < left) {
X		temp = right;
X		right = left;
X		left = temp;
X	}
X	if (bottom < top) {
X		temp = bottom;
X		bottom = top;
X		top = temp;
X	}
X	dumpregion(left, top, right, bottom);
X
X	return 0;
X}
X
drawbox(pw, left, top, right, bottom)
X	Pixwin         *pw;
X	int             left, top, right, bottom;
X{
X	fullscreen_pw_vector(pw, left, top, right, top, PIX_NOT(PIX_DST), 0);
X	fullscreen_pw_vector(pw, right, top, right, bottom, PIX_NOT(PIX_DST), 0);
X	fullscreen_pw_vector(pw, right, bottom, left, bottom, PIX_NOT(PIX_DST), 0);
X	fullscreen_pw_vector(pw, left, bottom, left, top, PIX_NOT(PIX_DST), 0);
X}
X
dumpregion(left, top, right, bottom)
X	int             left, top, right, bottom;
X{
X	Pixrect        *pr, *pr2, *pr3;
X	int             width, height;
X
X
X	pr = pr_open("/dev/fb");
X	if (pr == 0)
X		error("Can't open /dev/fb");
X
X	width = (((right - left + 1) / 8) * 8);
X	height = (((bottom - top + 1) / 4) * 4);
X	pr2 = pr_region(pr, left, top, width, height);
X	pr3 = pr_region(pr2, 0, 0, width, height);
X
X	if (pr_dump(pr3, stdout, colormap, RT_STANDARD, 1) != 0) {
X		perror("pr_dump");
X		exit(1);
X	}
X}
END_OF_FILE
if test 3964 -ne `wc -c <'src/scr2ras.c'`; then
    echo shar: \"'src/scr2ras.c'\" unpacked with wrong size!
fi
# end of 'src/scr2ras.c'
fi
if test -f 'src/transform.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/transform.c'\"
else
echo shar: Extracting \"'src/transform.c'\" \(5625 characters\)
sed "s/^X//" >'src/transform.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include "defs.h"
X#include "matrix.h"
X
char   *progname;
char   *filename;
Pixrect *pr1, *pr2;
X
X#ifdef STANDALONE
main(argc, argv, envp)
X#else
transform_main(argc, argv, envp)
X#endif
X	int     argc;
X	char  **argv;
X	char  **envp;
X{
X	register int i, j;
X	float   a, xs, ys;
X	int     x, y;
X	int     rotation, shearing;
X	int     levels;
X	int     max_xsize, min_xsize, max_ysize, min_ysize, tr_xsize, tr_ysize;
X	VECTOR  start, stop;
X	VECTOR  tr_start, tr_stop;
X	VECTOR  top_left, top_right, bottom_left, bottom_right;
X	VECTOR  tr_top_left, tr_top_right, tr_bottom_left, tr_bottom_right;
X	MATRIX  transform;
X	colormap_t	colormap;
X
X	warning("THIS CODE STILL UNDER DEVELOPMENT\nDO NOT TRUST");
X	a = M_PI / 2.;
X	xs = ys = 0.;
X	x = y = 0;
X	rotation = shearing = FALSE;
X	progname = strsave(argv[0]);
X	parse_profile(&argc, argv, envp);
X
X	while ((gc = getopt(argc, argv, "X:Y:a:x:y:")) != EOF)
X		switch (gc) {
X		case 'x':
X			if (!shearing) {
X				rotation = TRUE;
X				x = atoi(optarg);
X			} else
X				error("Cannot rotate and shear in same invocation");
X			break;
X		case 'y':
X			if (!shearing) {
X				rotation = TRUE;
X				y = atoi(optarg);
X			} else
X				error("Cannot rotate and shear in same invocation");
X			break;
X		case 'a':
X			if (!shearing) {
X				rotation = TRUE;
X				a = atof(optarg);
X			} else
X				error("Cannot rotate and shear in same invocation");
X			break;
X		case 'X':
X			if (!rotation) {
X				shearing = TRUE;
X				xs = atof(optarg);
X			} else
X				error("Cannot rotate and shear in same invocation");
X			break;
X		case 'Y':
X			if (!rotation) {
X				shearing = TRUE;
X				ys = atof(optarg);
X			} else
X				error("Cannot rotate and shear in same invocation");
X			break;
X		case '?':
X			errflag++;
X			break;
X		}
X
X	if (errflag)
X		error((char *) 0, "Usage: %s: [[-x xcoord] [-y ycoord] [-a angle]] | [[-X xshear] [-Y yshear]] [infile] [outfile]\n", progname);
X
X	for (stream = 0; optind < argc; stream++, optind++)
X		if (stream < 2 && strcmp(argv[optind], "-") != 0)
X			if (freopen(argv[optind], mode[stream], f[stream]) == NULL)
X				error("%s %s", PR_IO_ERR_INFILE, argv[optind]);
X
X	if ((pr1 = pr_load(stdin, &colormap)) == NULL)
X		error(PR_IO_ERR_RASREAD);
X
X	top_left = vinit(0., 0., 0., 1.);
X	top_right = vinit((double) pr1->pr_size.x, 0., 0., 1.);
X	bottom_right = vinit((double) pr1->pr_size.x, (double) pr1->pr_size.y, 0., 1.);
X	bottom_left = vinit(0., (double) pr1->pr_size.y, 0., 1.);
X
X	warning("top_left = ");
X	dbgvprint(top_left);
X	warning("top_right = ");
X	dbgvprint(top_right);
X	warning("bottom_right = ");
X	dbgvprint(bottom_right);
X	warning("bottom_left = ");
X	dbgvprint(bottom_left);
X
X	if (rotation)
X		transform = minit(cos(a), sin(a), 0., 0., -sin(a), cos(a), 0., 0., (1 - cos(a)) * x + y * sin(a), (1 - cos(a)) * y - x * sin(a), 1., 0., 0., 0., 0., 1.);
X	else
X		transform = minit(1., ys, 0., 0., xs, 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.);
X
X	dbgmprint(transform);
X	tr_top_left = vnil();
X	tr_top_right = vnil();
X	tr_bottom_left = vnil();
X	tr_bottom_right = vnil();
X
X	vmult(top_left, transform, tr_top_left);
X	vmult(top_right, transform, tr_top_right);
X	vmult(bottom_left, transform, tr_bottom_left);
X	vmult(bottom_right, transform, tr_bottom_right);
X
X	warning("tr_top_left = ");
X	dbgvprint(tr_top_left);
X
X	warning("tr_top_right = ");
X	dbgvprint(tr_top_right);
X
X	warning("tr_bottom_right = ");
X	dbgvprint(tr_bottom_right);
X
X	warning("tr_bottom_left = ");
X	dbgvprint(tr_bottom_left);
X
X	max_xsize = (int) MAX(tr_top_left[0], tr_top_right[0]);
X	max_xsize = (int) MAX(max_xsize, tr_bottom_left[0]);
X	max_xsize = (int) MAX(max_xsize, tr_bottom_right[0]);
X
X	min_xsize = (int) MIN(tr_top_left[0], tr_top_right[0]);
X	min_xsize = (int) MIN(min_xsize, tr_bottom_left[0]);
X	min_xsize = (int) MIN(min_xsize, tr_bottom_right[0]);
X
X	max_ysize = (int) MAX(tr_top_left[1], tr_top_right[1]);
X	max_ysize = (int) MAX(max_ysize, tr_bottom_left[1]);
X	max_ysize = (int) MAX(max_ysize, tr_bottom_right[1]);
X
X	min_ysize = (int) MIN(tr_top_left[1], tr_top_right[1]);
X	min_ysize = (int) MIN(min_ysize, tr_bottom_left[1]);
X	min_ysize = (int) MIN(min_ysize, tr_bottom_right[1]);
X
X	tr_xsize = abs(max_xsize - min_xsize);
X	tr_ysize = abs(max_ysize - min_xsize);
X
X	warning("xsize = %d, ysize = %d", tr_xsize, tr_ysize);
X	warning("minxsize = %d, min_ysize = %d", min_xsize, min_ysize);
X
X	if ((pr2 = mem_create(tr_xsize, tr_ysize, pr1->pr_depth)) == NULL)
X		error("mem_create returned NULL");
X
X	tr_start = vnil();
X	tr_stop = vnil();
X	for (j = 0; j < pr1->pr_size.y; j++) {
X		start = vinit(0., (double) j, 0., 1.);
X		stop = vinit((double) (pr1->pr_size.x), (double) j, 0., 1.);
X		vmult(start, transform, tr_start);
X		tr_start[0] += abs(min_xsize);
X		tr_start[1] += abs(min_ysize);
X		vmult(stop, transform, tr_stop);
X		tr_stop[0] += abs(min_xsize);
X		tr_stop[1] += abs(min_ysize);
X		bres_line((int) tr_start[0], (int) tr_start[1], (int) tr_stop[0], (int) tr_stop[1], j);
X	}
X
X	pr_dump(pr2, stdout, &colormap, RT_STANDARD, 0);
X}
X#define SIGN(a)	((a<0)?-1:((a>0)?1:0))
X
X/* line end pts are (x1, y1) & (x2, y2). Assumed not equal */
bres_line(x1, y1, x2, y2, iny)
X	int     x1, y1, x2, y2, iny;
X{
X	register int i;
X	int     temp;
X	int     x, y;
X	int     dx, dy, s1, s2, e, interchange;
X
X	x = x1;
X	y = y1;
X	dx = abs(x2 - x1);
X	dy = abs(y2 - y1);
X	s1 = SIGN(x2 - x1);
X	s2 = SIGN(y2 - y1);
X
X	if (dy > dx) {
X		temp = dx;
X		dx = dy;
X		dy = temp;
X		interchange = FALSE;
X	} else
X		interchange = TRUE;
X
X	e = 2 * dy - dx;
X
X	for (i = 0; i < dx; i++) {
X		pr_put(pr2, x, y, pr_get(pr1, i, iny));
X		while (e >= 0) {
X			if (interchange)
X				x += s1;
X			else
X				y += s2;
X			e -= 2 * dx;
X		}
X		if (interchange)
X			y += s2;
X		else
X			x += s1;
X		e += 2 * dy;
X	}
X}
END_OF_FILE
if test 5625 -ne `wc -c <'src/transform.c'`; then
    echo shar: \"'src/transform.c'\" unpacked with wrong size!
fi
# end of 'src/transform.c'
fi
echo shar: End of archive 5 \(of 10\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 10 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0