Newsgroups: comp.sources.misc
From: jef@well.sf.ca.us (Jef Poskanzer)
Subject:  REPOST: v23i045:  pbmplus - Extended Portable Bitmap Toolkit, Part10/24
Message-ID: <1991Oct16.022741.5617@sparky.imd.sterling.com>
X-Md4-Signature: f1da1d0a7465b95abf5fa48dcc696286
Date: Wed, 16 Oct 1991 02:27:41 GMT
Approved: kent@sparky.imd.sterling.com

Submitted-by: jef@well.sf.ca.us (Jef Poskanzer)
Posting-number: Volume 23, Issue 45
Archive-name: pbmplus/part10
Environment: UNIX

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	pgm/pgmnorm.1
#	pgm/pgmramp.c
#	pgm/pgmramp.1
#	pgm/pgmmerge.c
#	pgm/pgmedge.c
#	pgm/pgmedge.1
#	pgm/pgmtofs.c
#	pgm/pgmtofs.1
#	pgm/pgmbentley.c
#	pgm/pgmbentley.1
#	pgm/pgmoil.c
#	pgm/pgmoil.1
#	pgm/pgmtexture.c
#	pgm/pgmtexture.1
# This archive created: Fri Sep 27 17:50:19 1991
# By:	Jef Poskanzer (Acme Software)
export PATH; PATH=/bin:$PATH
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmnorm.1'" '(1886 characters)'
if test -f 'pgm/pgmnorm.1'
then
	echo shar: will not over-write existing file "'pgm/pgmnorm.1'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmnorm.1'
X.TH pgmnorm 1 "28 February 1989"
X.IX pgmnorm
X.SH NAME
Xpgmnorm - normalize the contrast in a portable graymap
X.SH SYNOPSIS
X.B pgmnorm
X.RB [ -bpercent
X.I N
X|
X.B -bvalue
X.IR N ]
X.RB [ -wpercent
X.I N
X|
X.B -wvalue
X.IR N ]
X.RI [ pgmfile ]
X.SH DESCRIPTION
XReads a portable graymap as input.
XNormalizes the contrast by forcing the lightest pixels to white, the
X.IX "contrast normalization"
Xdarkest pixels to black, and linearly rescaling the ones in between;
Xand produces a portable graymap as output.
X.SH OPTIONS
X.PP
XBy default, the darkest 2 percent of all pixels are mapped to black, and
Xthe lightest 1 percent are mapped to white.
XYou can override these percentages by using the
X.B -bpercent
Xand
X.B -wpercent
Xflags,
Xor you can specify the exact pixel values to be mapped by using the
X.B -bvalue
Xand
X.B -wvalue
Xflags.
XAppropriate numbers for the flags can be gotten from the
X.I pgmhist
Xtool.
X.IX pgmhist
XIf you just want to enhance the contrast, then choose values at elbows in the
Xhistogram; e.g. if value 29 represents 3% of the image but value 30
Xrepresents 20%, choose 30 for
X.IR bvalue .
XIf you want to lighten the
Ximage, then set
X.I bvalue
Xto 0 and just fiddle with
X.IR wvalue ;
Xsimilarly, to darken the image, set
X.I wvalue
Xto maxval and play with
X.IR bvalue .
X.PP
XAll flags can be abbreviated to their shortest unique prefix.
X.SH "SEE ALSO"
Xpgmhist(1), pgm(5)
X.SH AUTHOR
XPartially based on the fbnorm filter in Michael Mauldin's "Fuzzy Pixmap"
Xpackage.
X
XCopyright (C) 1989 by Jef Poskanzer.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 1886 -ne "`wc -c < 'pgm/pgmnorm.1'`"
then
	echo shar: error transmitting "'pgm/pgmnorm.1'" '(should have been 1886 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmramp.c'" '(2325 characters)'
if test -f 'pgm/pgmramp.c'
then
	echo shar: will not over-write existing file "'pgm/pgmramp.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmramp.c'
X/* pgmramp.c - generate a grayscale ramp
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include "pgm.h"
X
Xvoid
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X    {
X    gray *grayrow;
X    register gray *gP;
X    int rows, cols, rowso2, colso2, row;
X    register int col;
X    int ramptype;
X#define RT_LR 1
X#define RT_TB 2
X#define RT_RECT 3
X#define RT_ELLIP 4
X    char *usage = "-lr|-tb|-rectangle|-ellipse <width> <height>";
X
X    pgm_init( &argc, argv );
X
X    if ( argc != 4 )
X	pm_usage( usage );
X
X    if ( pm_keymatch( argv[1], "-lr", 2 ) )
X	ramptype = RT_LR;
X    else if ( pm_keymatch( argv[1], "-tb", 2 ) )
X	ramptype = RT_TB;
X    else if ( pm_keymatch( argv[1], "-rectangle", 2 ) )
X	ramptype = RT_RECT;
X    else if ( pm_keymatch( argv[1], "-ellipse", 2 ) )
X	ramptype = RT_ELLIP;
X    else
X	pm_usage( usage );
X    
X    if ( sscanf( argv[2], "%d", &cols ) != 1 )
X	pm_usage( usage );
X    if ( sscanf( argv[3], "%d", &rows ) != 1 )
X	pm_usage( usage );
X
X    colso2 = cols / 2;
X    rowso2 = rows / 2;
X
X    pgm_writepgminit( stdout, cols, rows, PGM_MAXMAXVAL, 0 );
X    grayrow = pgm_allocrow( cols );
X
X    for ( row = 0; row < rows; ++row )
X	{
X	for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
X	    {
X	    switch ( ramptype )
X		{
X		case RT_LR:
X		*gP = col * PGM_MAXMAXVAL / cols;
X		break;
X
X		case RT_TB:
X		*gP = row * PGM_MAXMAXVAL / rows;
X		break;
X
X		case RT_RECT:
X		{
X		float r, c;
X		r = abs( rowso2 - row ) / (float) rowso2;
X		c = abs( colso2 - col ) / (float) colso2;
X		*gP = PGM_MAXMAXVAL - ( r + c ) / 2.0 * PGM_MAXMAXVAL;
X		}
X		break;
X
X		case RT_ELLIP:
X		{
X		float r, c, v;
X		r = abs( rowso2 - row ) / (float) rowso2;
X		c = abs( colso2 - col ) / (float) colso2;
X		v = r * r + c * c;
X		if ( v < 0.0 ) v = 0.0;
X		else if ( v > 1.0 ) v = 1.0;
X		*gP = PGM_MAXMAXVAL - v * PGM_MAXMAXVAL;
X		}
X		break;
X
X		default:
X		pm_error( "can't happen" );
X		}
X	    }
X	pgm_writepgmrow( stdout, grayrow, cols, PGM_MAXMAXVAL, 0 );
X	}
X
X    exit( 0 );
X    }
SHAR_EOF
if test 2325 -ne "`wc -c < 'pgm/pgmramp.c'`"
then
	echo shar: error transmitting "'pgm/pgmramp.c'" '(should have been 2325 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmramp.1'" '(1082 characters)'
if test -f 'pgm/pgmramp.1'
then
	echo shar: will not over-write existing file "'pgm/pgmramp.1'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmramp.1'
X.TH pgmramp 1 "24 November 1989"
X.IX pgmramp
X.SH NAME
Xpgmramp - generate a grayscale ramp
X.SH SYNOPSIS
X.B pgmramp
X.BR -lr | -tb
X|
X.BR -rectangle | -ellipse
X.I width height
X.SH DESCRIPTION
XGenerates a graymap of the specified size containing a black-to-white ramp.
X.IX "generating graymaps"
XThese ramps are useful for multiplying with other images, using the
X.I pnmarith
Xtool.
X.IX pnmarith
X.SH OPTIONS
X.TP
X.B -lr
XA left to right ramp.
X.TP
X.B -tb
XA top to bottom ramp.
X.TP
X.B -rectangle
XA rectangular ramp.
X.TP
X.B -ellipse
XAn elliptical ramp.
X.PP
XAll flags can be abbreviated to their shortest unique prefix.
X.SH "SEE ALSO"
Xpnmarith(1), pgm(5)
X.SH AUTHOR
XCopyright (C) 1989 by Jef Poskanzer.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 1082 -ne "`wc -c < 'pgm/pgmramp.1'`"
then
	echo shar: error transmitting "'pgm/pgmramp.1'" '(should have been 1082 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmmerge.c'" '(1597 characters)'
if test -f 'pgm/pgmmerge.c'
then
	echo shar: will not over-write existing file "'pgm/pgmmerge.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmmerge.c'
X/* pgmmerge.c - wrapper program for PGM
X**
X** Copyright (C) 1991 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include "pgm.h"
X
Xvoid
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X    {
X    register char *cp;
X
Xagain:
X    if ( ( cp = rindex( argv[0], '/' ) ) != (char*) 0 )
X	++cp;
X    else
X	cp = argv[0];
X    if ( strcmp( cp, "pgmmerge" ) == 0 )
X	{
X	++argv;
X	--argc;
X	goto again;
X	}
X
X#define TRY(s,m) { if ( strcmp( cp, s ) == 0 ) m( argc, argv ); }
X
X    TRY("fitstopgm", fitstopgm_main);
X    TRY("fstopgm", fstopgm_main);
X    TRY("hipstopgm", hipstopgm_main);
X    TRY("lispmtopgm", lispmtopgm_main);
X    TRY("pgmbentley", pgmbentley_main);
X    TRY("pgmedge", pgmedge_main);
X    TRY("pgmenhance", pgmenhance_main);
X    TRY("pgmhist", pgmhist_main);
X    TRY("pgmnorm", pgmnorm_main);
X    TRY("pgmoil", pgmoil_main);
X    TRY("pgmramp", pgmramp_main);
X    TRY("pgmtexture", pgmtexture_main);
X    TRY("pgmtopbm", pgmtopbm_main);
X    TRY("pgmtofits", pgmtofits_main);
X    TRY("pgmtofs", pgmtofs_main);
X    TRY("pgmtolispm", pgmtolispm_main);
X    TRY("psidtopgm", psidtopgm_main);
X    TRY("rawtopgm", rawtopgm_main);
X
X    (void) fprintf(
X	stderr, "pgmmerge: \"%s\" is an unknown PGM program!\n", cp );
X    exit( 1 );
X    }
SHAR_EOF
if test 1597 -ne "`wc -c < 'pgm/pgmmerge.c'`"
then
	echo shar: error transmitting "'pgm/pgmmerge.c'" '(should have been 1597 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmedge.c'" '(2780 characters)'
if test -f 'pgm/pgmedge.c'
then
	echo shar: will not over-write existing file "'pgm/pgmedge.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmedge.c'
X/* pgmedge.c - edge-detect a portable graymap
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include "pgm.h"
X#include <math.h>
X
Xvoid
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X    {
X    FILE *ifp;
X    gray *row0, *row1, *row2, *tmprow, *orow;
X    int argn, rows, cols, format, row;
X    register int col;
X    gray maxval;
X    double sum1, sum2, sum;
X    char *usage = "[pgmfile]";
X
X    pgm_init( &argc, argv );
X
X    argn = 1;
X
X    if ( argn != argc )
X	{
X	ifp = pm_openr( argv[argn] );
X	argn++;
X	}
X    else
X	ifp = stdin;
X
X    if ( argn != argc )
X	pm_usage( usage );
X
X    pgm_pbmmaxval = 255;	/* use larger value for better results */
X
X    pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
X    if ( cols < 3 || rows < 3 )
X	pm_error( "the image is too small" );
X
X    row0 = pgm_allocrow( cols );
X    row1 = pgm_allocrow( cols );
X    row2 = pgm_allocrow( cols );
X    orow = pgm_allocrow( cols );
X
X    pgm_writepgminit( stdout, cols, rows, maxval, 0 );
X
X    /* Read in the first two rows. */
X    pgm_readpgmrow( ifp, row0, cols, maxval, format );
X    pgm_readpgmrow( ifp, row1, cols, maxval, format );
X
X    /* Write out the first row, all zeros. */
X    for ( col = 0; col < cols; ++col )
X	orow[col] = 0;
X    pgm_writepgmrow( stdout, orow, cols, maxval, 0 );
X
X    /* Now the rest of the image -- read in the next row, and write
X    ** write out the current row.
X    */
X    for ( row = 1; row < rows - 1; row++ )
X	{
X	pgm_readpgmrow( ifp, row2, cols, maxval, format );
X
X	for ( col = 1; col < cols - 1; col++ )
X	    {
X	    sum1 = (double) row0[col+1] - (double) row0[col-1] +
X		   2.0 * ( (double) row1[col+1] - (double) row1[col-1] ) +
X		   (double) row2[col+1] - (double) row2[col-1];
X	    sum2 = ( (double) row2[col-1] + 2.0 * (double) row2[col] +
X		     (double) row2[col+1] ) -
X		   ( (double) row0[col-1] + 2.0 * (double) row0[col] +
X		     (double) row0[col+1] );
X	    sum = sqrt( sum1 * sum1 + sum2 * sum2 );
X	    sum /= 1.8;		/* arbitrary scaling factor */
X	    if ( sum > maxval ) sum = maxval;
X	    orow[col] = sum;
X	    }
X
X	/* Write out a row. */
X	pgm_writepgmrow( stdout, orow, cols, maxval, 0 );
X
X	/* Rotate rows. */
X	tmprow = row0;
X	row0 = row1;
X	row1 = row2;
X	row2 = tmprow;
X	}
X    pm_close( ifp );
X
X    /* And write the last row, zeros again. */
X    for ( col = 0; col < cols; ++col )
X	orow[col] = 0;
X    pgm_writepgmrow( stdout, orow, cols, maxval, 0 );
X
X    exit( 0 );
X    }
SHAR_EOF
if test 2780 -ne "`wc -c < 'pgm/pgmedge.c'`"
then
	echo shar: error transmitting "'pgm/pgmedge.c'" '(should have been 2780 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmedge.1'" '(1114 characters)'
if test -f 'pgm/pgmedge.1'
then
	echo shar: will not over-write existing file "'pgm/pgmedge.1'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmedge.1'
X.TH pgmedge 1 "04 February 1990"
X.IX pgmedge
X.SH NAME
Xpgmedge - edge-detect a portable graymap
X.SH SYNOPSIS
X.B pgmedge
X.RI [ pgmfile ]
X.SH DESCRIPTION
XReads a portable graymap as input.
XOutlines the edges, and writes a portable graymap as output.
X.IX "edge detection"
XPiping the result through
X.B pgmtopbm -threshold
Xand playing with the
Xthreshold value will give a bitmap of the edges.
X.IX thresholding
X.PP
XThe edge detection technique used is to take the Pythagorean sum of
Xtwo Sobel gradient operators at 90 degrees to each other.
XFor more details see "Digital Image Processing" by Gonzalez and Wintz,
Xchapter 7.
X.SH "SEE ALSO"
Xpgmenhance(1), pgmtopbm(1), pgm(5), pbm(5)
X.SH AUTHOR
XCopyright (C) 1991 by Jef Poskanzer.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 1114 -ne "`wc -c < 'pgm/pgmedge.1'`"
then
	echo shar: error transmitting "'pgm/pgmedge.1'" '(should have been 1114 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmtofs.c'" '(3317 characters)'
if test -f 'pgm/pgmtofs.c'
then
	echo shar: will not over-write existing file "'pgm/pgmtofs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmtofs.c'
X/* pgmtofs.c - convert portable graymap to Usenix FaceSaver(tm) format
X**
X** Copyright (C) 1991 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include "pgm.h"
X
Xstatic void putinit ARGS(( int cols, int rows, int bps ));
Xstatic void putitem ARGS(( void ));
Xstatic void putgray ARGS(( gray g ));
Xstatic void putrest ARGS(( void ));
X
Xvoid
Xmain( argc, argv )
Xint argc;
Xchar* argv[];
X    {
X    FILE* ifp;
X    gray** grays;
X    register gray* gP;
X    int argn, rows, cols, bps, padright, row, col;
X    gray maxval, nmaxval;
X    char* usage = "[pgmfile]";
X
X    pgm_init( &argc, argv );
X
X    argn = 1;
X
X    if ( argn < argc )
X	{
X	ifp = pm_openr( argv[argn] );
X	++argn;
X	}
X    else
X	{
X	ifp = stdin;
X	}
X
X    if ( argn != argc )
X	pm_usage( usage );
X
X    grays = pgm_readpgm( ifp, &cols, &rows, &maxval );
X    pm_close( ifp );
X
X    /* Figure out bps. */
X    bps = pm_maxvaltobits( (int) maxval );
X    if ( bps > 2 && bps < 4 )
X	bps = 4;
X    else if ( bps > 4 && bps < 8 )
X	bps = 8;
X    else if ( bps > 8 )
X	pm_error(
X	    "maxval of %d is too large for FaceSaver(tm)", maxval );
X    nmaxval = pm_bitstomaxval( bps );
X    
X    /* Compute padding to round cols * bps up to the nearest multiple of 8. */
X    padright = ( ( cols * bps + 7 ) / 8 ) * 8 - cols * bps;
X
X    putinit( cols, rows, bps );
X    for ( row = rows - 1; row >= 0; --row )
X	{
X        for ( col = 0, gP = grays[row]; col < cols; ++col, ++gP )
X	    {
X	    if ( maxval != nmaxval )
X		*gP = (int) *gP * nmaxval / maxval;
X	    putgray( *gP );
X	    }
X	for ( col = 0; col < padright; ++col )
X	    putgray( 0 );
X        }
X
X    putrest( );
X
X    exit( 0 );
X    }
X
X
Xstatic int bitspersample, item, bitsperitem, bitshift, itemsperline, items;
X
Xstatic void
Xputinit( cols, rows, bps )
Xint cols, rows, bps;
X    {
X    printf( "FirstName: \n" );
X    printf( "LastName: \n" );
X    printf( "E-mail: \n" );
X    printf( "Telephone: \n" );
X    printf( "Company: \n" );
X    printf( "Address1: \n" );
X    printf( "Address2: \n" );
X    printf( "CityStateZip: \n" );
X    printf( "Date: \n" );
X    printf( "PicData: %d %d %d\n", cols, rows, bps );
X    printf( "Image: %d %d %d\n", cols, rows, bps );
X    printf( "\n" );
X
X    bitspersample = bps;
X    itemsperline = items = 0;
X    item = 0;
X    bitsperitem = 0;
X    bitshift = 8 - bitspersample;
X    }
X
Xstatic void
Xputitem( )
X    {
X    char* hexits = "0123456789abcdef";
X
X    if ( itemsperline == 30 )
X	{
X	putchar( '\n' );
X	itemsperline = 0;
X	}
X    putchar( hexits[item >> 4] );
X    putchar( hexits[item & 15] );
X    ++itemsperline;
X    ++items;
X    item = 0;
X    bitsperitem = 0;
X    bitshift = 8 - bitspersample;
X    }
X
X#if __STDC__
Xstatic void
Xputgray( gray g )
X#else /*__STDC__*/
Xstatic void
Xputgray( g )
Xgray g;
X#endif /*__STDC__*/
X    {
X    if ( bitsperitem == 8 )
X	putitem( );
X    item += g << bitshift;
X    bitsperitem += bitspersample;
X    bitshift -= bitspersample;
X    }
X
Xstatic void
Xputrest( )
X    {
X    if ( bitsperitem > 0 )
X	putitem( );
X    printf( "\n" );
X    }
SHAR_EOF
if test 3317 -ne "`wc -c < 'pgm/pgmtofs.c'`"
then
	echo shar: error transmitting "'pgm/pgmtofs.c'" '(should have been 3317 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmtofs.1'" '(826 characters)'
if test -f 'pgm/pgmtofs.1'
then
	echo shar: will not over-write existing file "'pgm/pgmtofs.1'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmtofs.1'
X.TH pgmtofs 1 "18 May 1990"
X.IX pgmtofs
X.SH NAME
Xpgmtofs - convert portable graymap to Usenix FaceSaver(tm) format
X.SH SYNOPSIS
X.B pgmtofs
X.RI [ pgmfile ]
X.SH DESCRIPTION
XReads a portable graymap as input.
XProduces Usenix FaceSaver(tm) format as output.
X.IX FaceSaver
X.PP
XFaceSaver is a registered trademark of Metron Computerware Ltd. of
XOakland, CA.
X.SH "SEE ALSO"
Xfstopgm(1), pgm(5)
X.SH AUTHOR
XCopyright (C) 1991 by Jef Poskanzer.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 826 -ne "`wc -c < 'pgm/pgmtofs.1'`"
then
	echo shar: error transmitting "'pgm/pgmtofs.1'" '(should have been 826 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmbentley.c'" '(1427 characters)'
if test -f 'pgm/pgmbentley.c'
then
	echo shar: will not over-write existing file "'pgm/pgmbentley.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmbentley.c'
X/* pgmbentley.c - read a portable graymap and smear it according to brightness
X**
X** Copyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com)
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include "pgm.h"
X
Xvoid
Xmain( argc, argv )
X    int argc;
X    char* argv[];
X    {
X    FILE* ifp;
X    gray maxval;
X    gray** gin;
X    gray** gout;
X    int argn, rows, cols, row;
X    register int brow, col;
X    char* usage = "[pgmfile]";
X
X    pgm_init( &argc, argv );
X
X    argn = 1;
X
X    if ( argn < argc )
X	{
X	ifp = pm_openr( argv[argn] );
X	++argn;
X	}
X    else
X	ifp = stdin;
X
X    if ( argn != argc )
X	pm_usage( usage );
X
X    gin = pgm_readpgm( ifp, &cols, &rows, &maxval );
X    pm_close( ifp );
X    gout = pgm_allocarray( cols, rows );
X
X#define N 4
X    for ( row = 0; row < rows; ++row )
X	for ( col = 0; col < cols; ++col )
X	    {
X	    brow = row + (int) (gin[row][col]) / N;
X	    if ( brow >= rows )
X		brow = rows - 1;
X	    gout[brow][col] = gin[row][col];
X	    }
X
X    pgm_writepgm( stdout, gout, cols, rows, maxval, 0 );
X    pgm_freearray( gout, rows );
X
X    exit( 0 );
X    }
SHAR_EOF
if test 1427 -ne "`wc -c < 'pgm/pgmbentley.c'`"
then
	echo shar: error transmitting "'pgm/pgmbentley.c'" '(should have been 1427 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmbentley.1'" '(930 characters)'
if test -f 'pgm/pgmbentley.1'
then
	echo shar: will not over-write existing file "'pgm/pgmbentley.1'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmbentley.1'
X.TH pgmbentley 1 "11 January 1991"
X.IX pgmbentley
X.SH NAME
Xpgmbentley - Bentleyize a portable graymap
X.SH SYNOPSIS
X.B pgmbentley
X.RI [ pgmfile ]
X.SH DESCRIPTION
XReads a portable graymap as input.
XPerforms The Bentley Effect, and writes a portable graymap as output.
X.IX "Bentley Effect"
X.PP
XThe Bentley Effect is described in "Beyond Photography" by Holzmann,
Xchapter 4, photo 4.
XIt's a vertical smearing based on brightness.
X.SH "SEE ALSO"
Xpgmoil(1), ppmrelief(1), pgm(5)
X.SH AUTHOR
XCopyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com)
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 930 -ne "`wc -c < 'pgm/pgmbentley.1'`"
then
	echo shar: error transmitting "'pgm/pgmbentley.1'" '(should have been 930 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmoil.c'" '(2038 characters)'
if test -f 'pgm/pgmoil.c'
then
	echo shar: will not over-write existing file "'pgm/pgmoil.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmoil.c'
X/* pgmoil.c - read a portable graymap and turn into an oil painting
X**
X** Copyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com)
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include "pgm.h"
X
Xstatic int hist[PGM_MAXMAXVAL+1];
X
Xvoid
Xmain( argc, argv )
Xint argc;
Xchar* argv[];
X    {
X    FILE* ifp;
X    gray midval, maxval;
X    gray** gin;
X    gray** gout;
X    int argn, rows, n, cols, row;
X    register int col, drow, dcol;
X    int i;
X    char* usage = "[-n <n>] [pgmfile]";
X
X    pgm_init( &argc, argv );
X
X    argn = 1;
X    n = 3;		/* DEFAULT VALUE */
X
X    /* Check for flags. */
X    if ( argn < argc && argv[argn][0] == '-' )
X	{
X	if ( argv[argn][1] == 'n' )
X	    {
X	    ++argn;
X	    if ( argn == argc || sscanf( argv[argn], "%d", &n ) != 1 )
X		pm_usage( usage );
X	    }
X	else
X	    pm_usage( usage );
X	++argn;
X	}
X
X    if ( argn < argc )
X	{
X	ifp = pm_openr( argv[argn] );
X	++argn;
X	}
X    else
X	ifp = stdin;
X
X    if ( argn != argc )
X	pm_usage( usage );
X
X    gin = pgm_readpgm( ifp, &cols, &rows, &maxval );
X    pm_close( ifp );
X    gout = pgm_allocarray( cols, rows );
X
X    /* Build histogram. */
X    for ( row = n; row < rows - n; ++row )
X	for ( col = n; col < cols - n; ++col )
X	    {
X	    for ( i = 0; i <= maxval; ++i )
X		hist[i] = 0;
X
X	    for ( drow = row - n; drow <= row + n; ++drow )
X		for ( dcol = col - n; dcol <= col + n; ++dcol )
X		    ++hist[ (int) (gin[drow][dcol]) ];
X
X	    for ( drow = dcol = 0; dcol < maxval; ++dcol )
X		if ( hist[dcol] > drow )
X		    {
X		    drow = hist[dcol];
X		    midval = dcol;
X		    }
X	    gout[row][col] = midval;
X	    }
X
X    pgm_writepgm( stdout, gout, cols, rows, maxval, 0 );
X    pgm_freearray( gout, rows );
X
X    exit( 0 );
X    }
SHAR_EOF
if test 2038 -ne "`wc -c < 'pgm/pgmoil.c'`"
then
	echo shar: error transmitting "'pgm/pgmoil.c'" '(should have been 2038 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmoil.1'" '(1069 characters)'
if test -f 'pgm/pgmoil.1'
then
	echo shar: will not over-write existing file "'pgm/pgmoil.1'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmoil.1'
X.TH pgmoil 1 "11 January 1991"
X.IX pgmoil
X.SH NAME
Xpgmoil - turn a portable graymap into an oil painting
X.SH SYNOPSIS
X.B pgmoil
X.RB [ -n
X.IR N ]
X.RI [ pgmfile ]
X.SH DESCRIPTION
XReads a portable graymap as input.
XDoes an "oil transfer", and writes a portable graymap as output.
X.IX "oil transfer"
X.PP
XThe oil transfer is described in "Beyond Photography" by Holzmann,
Xchapter 4, photo 7.
XIt's a sort of localized smearing.
X.SH OPTIONS
X.PP
XThe optional
X.B -n
Xflag controls the size of the area smeared.  The default value is 3.
X.SH BUGS
XTakes a long time to run.
X.SH "SEE ALSO"
Xpgmbentley(1), ppmrelief(1), pgm(5)
X.SH AUTHOR
XCopyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com)
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 1069 -ne "`wc -c < 'pgm/pgmoil.1'`"
then
	echo shar: error transmitting "'pgm/pgmoil.1'" '(should have been 1069 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmtexture.c'" '(23779 characters)'
if test -f 'pgm/pgmtexture.c'
then
	echo shar: will not over-write existing file "'pgm/pgmtexture.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmtexture.c'
X/* pgmtxtur.c - calculate textural features on a portable graymap
X**
X** Author: James Darrell McCauley
X**         Texas Agricultural Experiment Station
X**         Department of Agricultural Engineering
X**         Texas A&M University
X**         College Station, Texas 77843-2117 USA
X**
X** Code written partially taken from pgmtofs.c in the PBMPLUS package
X** by Jef Poskanzer.
X**
X** Algorithms for calculating features (and some explanatory comments) are
X** taken from:
X**
X**   Haralick, R.M., K. Shanmugam, and I. Dinstein. 1973. Textural features
X**   for image classification.  IEEE Transactions on Systems, Man, and
X**   Cybertinetics, SMC-3(6):610-621.
X**
X** Copyright (C) 1991 Texas Agricultural Experiment Station, employer for
X** hire of James Darrell McCauley
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X**
X** THE TEXAS AGRICULTURAL EXPERIMENT STATION (TAES) AND THE TEXAS A&M
X** UNIVERSITY SYSTEM (TAMUS) MAKE NO EXPRESS OR IMPLIED WARRANTIES
X** (INCLUDING BY WAY OF EXAMPLE, MERCHANTABILITY) WITH RESPECT TO ANY
X** ITEM, AND SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL
X** OR CONSEQUENTAL DAMAGES ARISING OUT OF THE POSESSION OR USE OF
X** ANY SUCH ITEM. LICENSEE AND/OR USER AGREES TO INDEMNIFY AND HOLD
X** TAES AND TAMUS HARMLESS FROM ANY CLAIMS ARISING OUT OF THE USE OR
X** POSSESSION OF SUCH ITEMS.
X** 
X** Modification History:
X** 24 Jun 91 - J. Michael Carstensen <jmc@imsor.dth.dk> supplied fix for 
X**             correlation function.
X*/
X
X#include "pgm.h"
X#include <math.h>
X
X#define RADIX 2.0
X#define EPSILON 0.000000001
X#define BL  "Angle                 "
X#define F1  "Angular Second Moment "
X#define F2  "Contrast              "
X#define F3  "Correlation           "
X#define F4  "Variance              "
X#define F5  "Inverse Diff Moment   "
X#define F6  "Sum Average           "
X#define F7  "Sum Variance          "
X#define F8  "Sum Entropy           "
X#define F9  "Entropy               "
X#define F10 "Difference Variance   "
X#define F11 "Difference Entropy    "
X#define F12 "Meas of Correlation-1 "
X#define F13 "Meas of Correlation-2 "
X#define F14 "Max Correlation Coeff "
X
X#define SIGN(x,y) ((y)<0 ? -fabs(x) : fabs(x))
X#define DOT fprintf(stderr,".")
X#define SWAP(a,b) {y=(a);(a)=(b);(b)=y;}
X
Xvoid results (), hessenberg (), mkbalanced (), reduction (), simplesrt ();
Xfloat f1_asm (), f2_contrast (), f3_corr (), f4_var (), f5_idm (),
X f6_savg (), f7_svar (), f8_sentropy (), f9_entropy (), f10_dvar (),
X f11_dentropy (), f12_icorr (), f13_icorr (), f14_maxcorr (), *vector (),
X **matrix ();
X
X
Xvoid main (argc, argv)
X  int argc;
X  char *argv[];
X{
X  FILE *ifp;
X  register gray **grays, *gP;
X  int tone[PGM_MAXMAXVAL], R0, R45, R90, angle, d = 1, x, y;
X  int argn, rows, cols, bps, padright, row, col;
X  int itone, jtone, tones;
X  float **P_matrix0, **P_matrix45, **P_matrix90, **P_matrix135;
X  float ASM[4], contrast[4], corr[4], var[4], idm[4], savg[4];
X  float sentropy[4], svar[4], entropy[4], dvar[4], dentropy[4];
X  float icorr[4], maxcorr[4];
X  gray maxval, nmaxval;
X  char *usage = "[-d <d>] [pgmfile]";
X
X    pgm_init( &argc, argv );
X
X    argn = 1;
X
X    /* Check for flags. */
X    if ( argn < argc && argv[argn][0] == '-' )
X	{
X	if ( argv[argn][1] == 'd' )
X	    {
X	    ++argn;
X	    if ( argn == argc || sscanf( argv[argn], "%d", &d ) != 1 )
X		pm_usage( usage );
X	    }
X	else
X	    pm_usage( usage );
X	++argn;
X	}
X
X    if ( argn < argc )
X	{
X	ifp = pm_openr( argv[argn] );
X	++argn;
X	}
X    else
X	ifp = stdin;
X
X    if ( argn != argc )
X	pm_usage( usage );
X
X  grays = pgm_readpgm (ifp, &cols, &rows, &maxval);
X  pm_close (ifp);
X
X  /* Determine the number of different gray scales (not maxval) */
X  for (row = PGM_MAXMAXVAL; row >= 0; --row)
X    tone[row] = -1;
X  for (row = rows - 1; row >= 0; --row)
X    for (col = 0; col < cols; ++col)
X      tone[grays[row][col]] = grays[row][col];
X  for (row = PGM_MAXMAXVAL, tones = 0; row >= 0; --row)
X    if (tone[row] != -1)
X      tones++;
X  fprintf (stderr, "(Image has %d graylevels.)\n", tones);
X
X  /* Collapse array, taking out all zero values */
X  for (row = 0, itone = 0; row <= PGM_MAXMAXVAL; row++)
X    if (tone[row] != -1)
X      tone[itone++] = tone[row];
X  /* Now array contains only the gray levels present (in ascending order) */
X
X  /* Allocate memory for gray-tone spatial dependence matrix */
X  P_matrix0 = matrix (0, tones, 0, tones);
X  P_matrix45 = matrix (0, tones, 0, tones);
X  P_matrix90 = matrix (0, tones, 0, tones);
X  P_matrix135 = matrix (0, tones, 0, tones);
X  for (row = 0; row < tones; ++row)
X    for (col = 0; col < tones; ++col)
X    {
X      P_matrix0[row][col] = P_matrix45[row][col] = 0;
X      P_matrix90[row][col] = P_matrix135[row][col] = 0;
X    }
X
X  /* Find gray-tone spatial dependence matrix */
X  fprintf (stderr, "(Computing spatial dependence matrix...");
X  for (row = 0; row < rows; ++row)
X    for (col = 0; col < cols; ++col)
X      for (x = 0, angle = 0; angle <= 135; angle += 45)
X      {
X	while (tone[x] != grays[row][col])
X	  x++;
X	if (angle == 0 && col + d < cols)
X	{
X	  y = 0;
X	  while (tone[y] != grays[row][col + d])
X	    y++;
X	  P_matrix0[x][y]++;
X	  P_matrix0[y][x]++;
X	}
X	if (angle == 90 && row + d < rows)
X	{
X	  y = 0;
X	  while (tone[y] != grays[row + d][col])
X	    y++;
X	  P_matrix90[x][y]++;
X	  P_matrix90[y][x]++;
X	}
X	if (angle == 45 && row + d < rows && col - d >= 0)
X	{
X	  y = 0;
X	  while (tone[y] != grays[row + d][col - d])
X	    y++;
X	  P_matrix45[x][y]++;
X	  P_matrix45[y][x]++;
X	}
X	if (angle == 135 && row + d < rows && col + d < cols)
X	{
X	  y = 0;
X	  while (tone[y] != grays[row + d][col + d])
X	    y++;
X	  P_matrix135[x][y]++;
X	  P_matrix135[y][x]++;
X	}
X      }
X  /* Gray-tone spatial dependence matrices are complete */
X
X  /* Find normalizing constants */
X  R0 = 2 * rows * (cols - 1);
X  R45 = 2 * (rows - 1) * (cols - 1);
X  R90 = 2 * (rows - 1) * cols;
X
X  /* Normalize gray-tone spatial dependence matrix */
X  for (itone = 0; itone < tones; ++itone)
X    for (jtone = 0; jtone < tones; ++jtone)
X    {
X      P_matrix0[itone][jtone] /= R0;
X      P_matrix45[itone][jtone] /= R45;
X      P_matrix90[itone][jtone] /= R90;
X      P_matrix135[itone][jtone] /= R45;
X    }
X
X  fprintf (stderr, " done.)\n");
X  fprintf (stderr, "(Computing textural features");
X  fprintf (stdout, "\n");
X  DOT;
X  fprintf (stdout,
X	   "%s         0         45         90        135        Avg\n",
X	   BL);
X
X  ASM[0] = f1_asm (P_matrix0, tones);
X  ASM[1] = f1_asm (P_matrix45, tones);
X  ASM[2] = f1_asm (P_matrix90, tones);
X  ASM[3] = f1_asm (P_matrix135, tones);
X  results (F1, ASM);
X
X  contrast[0] = f2_contrast (P_matrix0, tones);
X  contrast[1] = f2_contrast (P_matrix45, tones);
X  contrast[2] = f2_contrast (P_matrix90, tones);
X  contrast[3] = f2_contrast (P_matrix135, tones);
X  results (F2, contrast);
X
X
X  corr[0] = f3_corr (P_matrix0, tones);
X  corr[1] = f3_corr (P_matrix45, tones);
X  corr[2] = f3_corr (P_matrix90, tones);
X  corr[3] = f3_corr (P_matrix135, tones);
X  results (F3, corr);
X
X  var[0] = f4_var (P_matrix0, tones);
X  var[1] = f4_var (P_matrix45, tones);
X  var[2] = f4_var (P_matrix90, tones);
X  var[3] = f4_var (P_matrix135, tones);
X  results (F4, var);
X
X
X  idm[0] = f5_idm (P_matrix0, tones);
X  idm[1] = f5_idm (P_matrix45, tones);
X  idm[2] = f5_idm (P_matrix90, tones);
X  idm[3] = f5_idm (P_matrix135, tones);
X  results (F5, idm);
X
X  savg[0] = f6_savg (P_matrix0, tones);
X  savg[1] = f6_savg (P_matrix45, tones);
X  savg[2] = f6_savg (P_matrix90, tones);
X  savg[3] = f6_savg (P_matrix135, tones);
X  results (F6, savg);
X
X  sentropy[0] = f8_sentropy (P_matrix0, tones);
X  sentropy[1] = f8_sentropy (P_matrix45, tones);
X  sentropy[2] = f8_sentropy (P_matrix90, tones);
X  sentropy[3] = f8_sentropy (P_matrix135, tones);
X  svar[0] = f7_svar (P_matrix0, tones, sentropy[0]);
X  svar[1] = f7_svar (P_matrix45, tones, sentropy[1]);
X  svar[2] = f7_svar (P_matrix90, tones, sentropy[2]);
X  svar[3] = f7_svar (P_matrix135, tones, sentropy[3]);
X  results (F7, svar);
X  results (F8, sentropy);
X
X  entropy[0] = f9_entropy (P_matrix0, tones);
X  entropy[1] = f9_entropy (P_matrix45, tones);
X  entropy[2] = f9_entropy (P_matrix90, tones);
X  entropy[3] = f9_entropy (P_matrix135, tones);
X  results (F9, entropy);
X
X  dvar[0] = f10_dvar (P_matrix0, tones);
X  dvar[1] = f10_dvar (P_matrix45, tones);
X  dvar[2] = f10_dvar (P_matrix90, tones);
X  dvar[3] = f10_dvar (P_matrix135, tones);
X  results (F10, dvar);
X
X  dentropy[0] = f11_dentropy (P_matrix0, tones);
X  dentropy[1] = f11_dentropy (P_matrix45, tones);
X  dentropy[2] = f11_dentropy (P_matrix90, tones);
X  dentropy[3] = f11_dentropy (P_matrix135, tones);
X  results (F11, dentropy);
X
X  icorr[0] = f12_icorr (P_matrix0, tones);
X  icorr[1] = f12_icorr (P_matrix45, tones);
X  icorr[2] = f12_icorr (P_matrix90, tones);
X  icorr[3] = f12_icorr (P_matrix135, tones);
X  results (F12, icorr);
X
X  icorr[0] = f13_icorr (P_matrix0, tones);
X  icorr[1] = f13_icorr (P_matrix45, tones);
X  icorr[2] = f13_icorr (P_matrix90, tones);
X  icorr[3] = f13_icorr (P_matrix135, tones);
X  results (F13, icorr);
X
X  maxcorr[0] = f14_maxcorr (P_matrix0, tones);
X  maxcorr[1] = f14_maxcorr (P_matrix45, tones);
X  maxcorr[2] = f14_maxcorr (P_matrix90, tones);
X  maxcorr[3] = f14_maxcorr (P_matrix135, tones);
X  results (F14, maxcorr);
X
X
X  fprintf (stderr, " done.)\n");
X  exit (0);
X}
X
Xfloat f1_asm (P, Ng)
X  float **P;
X  int Ng;
X
X/* Angular Second Moment */
X{
X  int i, j;
X  float sum = 0;
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      sum += P[i][j] * P[i][j];
X
X  return sum;
X
X  /*
X   * The angular second-moment feature (ASM) f1 is a measure of homogeneity
X   * of the image. In a homogeneous image, there are very few dominant
X   * gray-tone transitions. Hence the P matrix for such an image will have
X   * fewer entries of large magnitude.
X   */
X}
X
X
Xfloat f2_contrast (P, Ng)
X  float **P;
X  int Ng;
X
X/* Contrast */
X{
X  int i, j, n;
X  float sum = 0, bigsum = 0;
X
X  for (n = 0; n < Ng; ++n)
X  {
X    for (i = 0; i < Ng; ++i)
X      for (j = 0; j < Ng; ++j)
X	if ((i - j) == n || (j - i) == n)
X	  sum += P[i][j];
X    bigsum += n * n * sum;
X
X    sum = 0;
X  }
X  return bigsum;
X
X  /*
X   * The contrast feature is a difference moment of the P matrix and is a
X   * measure of the contrast or the amount of local variations present in an
X   * image.
X   */
X}
X
Xfloat f3_corr (P, Ng)
X  float **P;
X  int Ng;
X
X/* Correlation */
X{
X  int i, j;
X  float sum_sqrx = 0, sum_sqry = 0, tmp, *px;
X  float meanx =0 , meany = 0 , stddevx, stddevy;
X
X  px = vector (0, Ng);
X  for (i = 0; i < Ng; ++i)
X    px[i] = 0;
X
X  /*
X   * px[i] is the (i-1)th entry in the marginal probability matrix obtained
X   * by summing the rows of p[i][j]
X   */
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      px[i] += P[i][j];
X
X
X  /* Now calculate the means and standard deviations of px and py */
X  /*- fix supplied by J. Michael Christensen, 21 Jun 1991 */
X  /*- further modified by James Darrell McCauley, 16 Aug 1991 
X   *     after realizing that meanx=meany and stddevx=stddevy
X   */
X  for (i = 0; i < Ng; ++i)
X  {
X    meanx += px[i]*i;
X    sum_sqrx += px[i]*i*i;
X  }
X  meany = meanx;
X  sum_sqry = sum_sqrx;
X  stddevx = sqrt (sum_sqrx - (meanx * meanx));
X  stddevy = stddevx;
X
X  /* Finally, the correlation ... */
X  for (tmp = 0, i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      tmp += i*j*P[i][j];
X
X  return (tmp - meanx * meany) / (stddevx * stddevy);
X  /*
X   * This correlation feature is a measure of gray-tone linear-dependencies
X   * in the image.
X   */
X}
X
X
Xfloat f4_var (P, Ng)
X  float **P;
X  int Ng;
X
X/* Sum of Squares: Variance */
X{
X  int i, j;
X  float mean = 0, var = 0;
X
X  /*- Corrected by James Darrell McCauley, 16 Aug 1991
X   *  calculates the mean intensity level instead of the mean of
X   *  cooccurrence matrix elements 
X   */
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      mean += i * P[i][j];
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      var += (i + 1 - mean) * (i + 1 - mean) * P[i][j];
X
X  return var;
X}
X
Xfloat f5_idm (P, Ng)
X  float **P;
X  int Ng;
X
X/* Inverse Difference Moment */
X{
X  int i, j;
X  float idm = 0;
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      idm += P[i][j] / (1 + (i - j) * (i - j));
X
X  return idm;
X}
X
Xfloat Pxpy[2 * PGM_MAXMAXVAL];
X
Xfloat f6_savg (P, Ng)
X  float **P;
X  int Ng;
X
X/* Sum Average */
X{
X  int i, j;
X  extern float Pxpy[2 * PGM_MAXMAXVAL];
X  float savg = 0;
X
X  for (i = 0; i <= 2 * Ng; ++i)
X    Pxpy[i] = 0;
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      Pxpy[i + j + 2] += P[i][j];
X  for (i = 2; i <= 2 * Ng; ++i)
X    savg += i * Pxpy[i];
X
X  return savg;
X}
X
X
Xfloat f7_svar (P, Ng, S)
X  float **P, S;
X  int Ng;
X
X/* Sum Variance */
X{
X  int i, j;
X  extern float Pxpy[2 * PGM_MAXMAXVAL];
X  float var = 0;
X
X  for (i = 0; i <= 2 * Ng; ++i)
X    Pxpy[i] = 0;
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      Pxpy[i + j + 2] += P[i][j];
X
X  for (i = 2; i <= 2 * Ng; ++i)
X    var += (i - S) * (i - S) * Pxpy[i];
X
X  return var;
X}
X
Xfloat f8_sentropy (P, Ng)
X  float **P;
X  int Ng;
X
X/* Sum Entropy */
X{
X  int i, j;
X  extern float Pxpy[2 * PGM_MAXMAXVAL];
X  float sentropy = 0;
X
X  for (i = 0; i <= 2 * Ng; ++i)
X    Pxpy[i] = 0;
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      Pxpy[i + j + 2] += P[i][j];
X
X  for (i = 2; i <= 2 * Ng; ++i)
X    sentropy -= Pxpy[i] * log10 (Pxpy[i] + EPSILON);
X
X  return sentropy;
X}
X
X
Xfloat f9_entropy (P, Ng)
X  float **P;
X  int Ng;
X
X/* Entropy */
X{
X  int i, j;
X  float entropy = 0;
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      entropy += P[i][j] * log10 (P[i][j] + EPSILON);
X
X  return -entropy;
X}
X
X
Xfloat f10_dvar (P, Ng)
X  float **P;
X  int Ng;
X
X/* Difference Variance */
X{
X  int i, j, tmp;
X  extern float Pxpy[2 * PGM_MAXMAXVAL];
X  float sum = 0, sum_sqr = 0, var = 0;
X
X  for (i = 0; i <= 2 * Ng; ++i)
X    Pxpy[i] = 0;
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      Pxpy[abs (i - j)] += P[i][j];
X
X  /* Now calculate the variance of Pxpy (Px-y) */
X  for (i = 0; i < Ng; ++i)
X  {
X    sum += Pxpy[i];
X    sum_sqr += Pxpy[i] * Pxpy[i];
X  }
X  tmp = Ng * Ng;
X  var = ((tmp * sum_sqr) - (sum * sum)) / (tmp * tmp);
X
X  return var;
X}
X
Xfloat f11_dentropy (P, Ng)
X  float **P;
X  int Ng;
X
X/* Difference Entropy */
X{
X  int i, j, tmp;
X  extern float Pxpy[2 * PGM_MAXMAXVAL];
X  float sum = 0, sum_sqr = 0, var = 0;
X
X  for (i = 0; i <= 2 * Ng; ++i)
X    Pxpy[i] = 0;
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X      Pxpy[abs (i - j)] += P[i][j];
X
X  for (i = 0; i < Ng; ++i)
X    sum += Pxpy[i] * log10 (Pxpy[i] + EPSILON);
X
X  return -sum;
X}
X
Xfloat f12_icorr (P, Ng)
X  float **P;
X  int Ng;
X
X/* Information Measures of Correlation */
X{
X  int i, j, tmp;
X  float *px, *py;
X  float hx = 0, hy = 0, hxy = 0, hxy1 = 0, hxy2 = 0;
X
X  px = vector (0, Ng);
X  py = vector (0, Ng);
X
X  /*
X   * px[i] is the (i-1)th entry in the marginal probability matrix obtained
X   * by summing the rows of p[i][j]
X   */
X  for (i = 0; i < Ng; ++i)
X  {
X    for (j = 0; j < Ng; ++j)
X    {
X      px[i] += P[i][j];
X      py[j] += P[i][j];
X    }
X  }
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X    {
X      hxy1 -= P[i][j] * log10 (px[i] * py[j] + EPSILON);
X      hxy2 -= px[i] * py[j] * log10 (px[i] * py[j] + EPSILON);
X      hxy -= P[i][j] * log10 (P[i][j] + EPSILON);
X    }
X
X  /* Calculate entropies of px and py - is this right? */
X  for (i = 0; i < Ng; ++i)
X  {
X    hx -= px[i] * log10 (px[i] + EPSILON);
X    hy -= py[i] * log10 (py[i] + EPSILON);
X  }
X/*  fprintf(stderr,"hxy1=%f\thxy=%f\thx=%f\thy=%f\n",hxy1,hxy,hx,hy); */
X  return ((hxy - hxy1) / (hx > hy ? hx : hy));
X}
X
Xfloat f13_icorr (P, Ng)
X  float **P;
X  int Ng;
X
X/* Information Measures of Correlation */
X{
X  int i, j;
X  float *px, *py;
X  float hx = 0, hy = 0, hxy = 0, hxy1 = 0, hxy2 = 0;
X
X  px = vector (0, Ng);
X  py = vector (0, Ng);
X
X  /*
X   * px[i] is the (i-1)th entry in the marginal probability matrix obtained
X   * by summing the rows of p[i][j]
X   */
X  for (i = 0; i < Ng; ++i)
X  {
X    for (j = 0; j < Ng; ++j)
X    {
X      px[i] += P[i][j];
X      py[j] += P[i][j];
X    }
X  }
X
X  for (i = 0; i < Ng; ++i)
X    for (j = 0; j < Ng; ++j)
X    {
X      hxy1 -= P[i][j] * log10 (px[i] * py[j] + EPSILON);
X      hxy2 -= px[i] * py[j] * log10 (px[i] * py[j] + EPSILON);
X      hxy -= P[i][j] * log10 (P[i][j] + EPSILON);
X    }
X
X  /* Calculate entropies of px and py */
X  for (i = 0; i < Ng; ++i)
X  {
X    hx -= px[i] * log10 (px[i] + EPSILON);
X    hy -= py[i] * log10 (py[i] + EPSILON);
X  }
X/*  fprintf(stderr,"hx=%f\thxy2=%f\n",hx,hxy2); */
X  return (sqrt (abs (1 - exp (-2.0 * (hxy2 - hxy)))));
X}
X
Xfloat f14_maxcorr (P, Ng)
X  float **P;
X  int Ng;
X
X/* Returns the Maximal Correlation Coefficient */
X{
X  int i, j, k;
X  float *px, *py, **Q;
X  float *x, *iy, tmp;
X
X  px = vector (0, Ng);
X  py = vector (0, Ng);
X  Q = matrix (1, Ng + 1, 1, Ng + 1);
X  x = vector (1, Ng);
X  iy = vector (1, Ng);
X
X  /*
X   * px[i] is the (i-1)th entry in the marginal probability matrix obtained
X   * by summing the rows of p[i][j]
X   */
X  for (i = 0; i < Ng; ++i)
X  {
X    for (j = 0; j < Ng; ++j)
X    {
X      px[i] += P[i][j];
X      py[j] += P[i][j];
X    }
X  }
X
X  /* Find the Q matrix */
X  for (i = 0; i < Ng; ++i)
X  {
X    for (j = 0; j < Ng; ++j)
X    {
X      Q[i + 1][j + 1] = 0;
X      for (k = 0; k < Ng; ++k)
X	Q[i + 1][j + 1] += P[i][k] * P[j][k] / px[i] / py[k];
X    }
X  }
X
X  /* Balance the matrix */
X  mkbalanced (Q, Ng);
X  /* Reduction to Hessenberg Form */
X  reduction (Q, Ng);
X  /* Finding eigenvalue for nonsymetric matrix using QR algorithm */
X  hessenberg (Q, Ng, x, iy);
X  /* simplesrt(Ng,x); */
X  /* Returns the sqrt of the second largest eigenvalue of Q */
X  for (i = 2, tmp = x[1]; i <= Ng; ++i)
X    tmp = (tmp > x[i]) ? tmp : x[i];
X  return sqrt (x[Ng - 1]);
X}
X
Xfloat *vector (nl, nh)
X  int nl, nh;
X{
X  float *v;
X
X  v = (float *) malloc ((unsigned) (nh - nl + 1) * sizeof (float));
X  if (!v)
X    fprintf (stderr, "memory allocation failure"), exit (1);
X  return v - nl;
X}
X
X
Xfloat **matrix (nrl, nrh, ncl, nch)
X  int nrl, nrh, ncl, nch;
X
X/* Allocates a float matrix with range [nrl..nrh][ncl..nch] */
X{
X  int i;
X  float **m;
X
X  /* allocate pointers to rows */
X  m = (float **) malloc ((unsigned) (nrh - nrl + 1) * sizeof (float *));
X  if (!m)
X    fprintf (stderr, "memory allocation failure"), exit (1);
X  m -= ncl;
X
X  /* allocate rows and set pointers to them */
X  for (i = nrl; i <= nrh; i++)
X  {
X    m[i] = (float *) malloc ((unsigned) (nch - ncl + 1) * sizeof (float));
X    if (!m[i])
X      fprintf (stderr, "memory allocation failure"), exit (2);
X    m[i] -= ncl;
X  }
X  /* return pointer to array of pointers to rows */
X  return m;
X}
X
Xvoid results (c, a)
X  char *c;
X  float *a;
X{
X  int i;
X
X  DOT;
X  fprintf (stdout, "%s", c);
X  for (i = 0; i < 4; ++i)
X    fprintf (stdout, "% 1.3e ", a[i]);
X  fprintf (stdout, "% 1.3e\n", (a[0] + a[1] + a[2] + a[3]) / 4);
X}
X
Xvoid simplesrt (n, arr)
X  int n;
X  float arr[];
X{
X  int i, j;
X  float a;
X
X  for (j = 2; j <= n; j++)
X  {
X    a = arr[j];
X    i = j - 1;
X    while (i > 0 && arr[i] > a)
X    {
X      arr[i + 1] = arr[i];
X      i--;
X    }
X    arr[i + 1] = a;
X  }
X}
X
Xvoid mkbalanced (a, n)
X  float **a;
X  int n;
X{
X  int last, j, i;
X  float s, r, g, f, c, sqrdx;
X
X  sqrdx = RADIX * RADIX;
X  last = 0;
X  while (last == 0)
X  {
X    last = 1;
X    for (i = 1; i <= n; i++)
X    {
X      r = c = 0.0;
X      for (j = 1; j <= n; j++)
X	if (j != i)
X	{
X	  c += fabs (a[j][i]);
X	  r += fabs (a[i][j]);
X	}
X      if (c && r)
X      {
X	g = r / RADIX;
X	f = 1.0;
X	s = c + r;
X	while (c < g)
X	{
X	  f *= RADIX;
X	  c *= sqrdx;
X	}
X	g = r * RADIX;
X	while (c > g)
X	{
X	  f /= RADIX;
X	  c /= sqrdx;
X	}
X	if ((c + r) / f < 0.95 * s)
X	{
X	  last = 0;
X	  g = 1.0 / f;
X	  for (j = 1; j <= n; j++)
X	    a[i][j] *= g;
X	  for (j = 1; j <= n; j++)
X	    a[j][i] *= f;
X	}
X      }
X    }
X  }
X}
X
X
Xvoid reduction (a, n)
X  float **a;
X  int n;
X{
X  int m, j, i;
X  float y, x;
X
X  for (m = 2; m < n; m++)
X  {
X    x = 0.0;
X    i = m;
X    for (j = m; j <= n; j++)
X    {
X      if (fabs (a[j][m - 1]) > fabs (x))
X      {
X	x = a[j][m - 1];
X	i = j;
X      }
X    }
X    if (i != m)
X    {
X      for (j = m - 1; j <= n; j++)
X	SWAP (a[i][j], a[m][j])  
X	for (j = 1; j <= n; j++)
X	  SWAP (a[j][i], a[j][m]) 
X	  a[j][i] = a[j][i];
X    }
X    if (x)
X    {
X      for (i = m + 1; i <= n; i++)
X      {
X	if (y = a[i][m - 1])
X	{
X	  y /= x;
X	  a[i][m - 1] = y;
X	  for (j = m; j <= n; j++)
X	    a[i][j] -= y * a[m][j];
X	  for (j = 1; j <= n; j++)
X	    a[j][m] += y * a[j][i];
X	}
X      }
X    }
X  }
X}
X
Xvoid hessenberg (a, n, wr, wi)
X  float **a, wr[], wi[];
X  int n;
X
X{
X  int nn, m, l, k, j, its, i, mmin;
X  float z, y, x, w, v, u, t, s, r, q, p, anorm;
X
X  anorm = fabs (a[1][1]);
X  for (i = 2; i <= n; i++)
X    for (j = (i - 1); j <= n; j++)
X      anorm += fabs (a[i][j]);
X  nn = n;
X  t = 0.0;
X  while (nn >= 1)
X  {
X    its = 0;
X    do
X    {
X      for (l = nn; l >= 2; l--)
X      {
X	s = fabs (a[l - 1][l - 1]) + fabs (a[l][l]);
X	if (s == 0.0)
X	  s = anorm;
X	if ((float) (fabs (a[l][l - 1]) + s) == s)
X	  break;
X      }
X      x = a[nn][nn];
X      if (l == nn)
X      {
X	wr[nn] = x + t;
X	wi[nn--] = 0.0;
X      }
X      else
X      {
X	y = a[nn - 1][nn - 1];
X	w = a[nn][nn - 1] * a[nn - 1][nn];
X	if (l == (nn - 1))
X	{
X	  p = 0.5 * (y - x);
X	  q = p * p + w;
X	  z = sqrt (fabs (q));
X	  x += t;
X	  if (q >= 0.0)
X	  {
X	    z = p + SIGN (z, p); 
X	    wr[nn - 1] = wr[nn] = x + z;
X	    if (z)
X	      wr[nn] = x - w / z;
X	    wi[nn - 1] = wi[nn] = 0.0;
X	  }
X	  else
X	  {
X	    wr[nn - 1] = wr[nn] = x + p;
X	    wi[nn - 1] = -(wi[nn] = z);
X	  }
X	  nn -= 2;
X	}
X	else
X	{
X	  if (its == 30)
X	    fprintf (stderr, 
X                    "Too many iterations to required to find %s\ngiving up\n", 
X                     F14), exit (1);
X	  if (its == 10 || its == 20)
X	  {
X	    t += x;
X	    for (i = 1; i <= nn; i++)
X	      a[i][i] -= x;
X	    s = fabs (a[nn][nn - 1]) + fabs (a[nn - 1][nn - 2]);
X	    y = x = 0.75 * s;
X	    w = -0.4375 * s * s;
X	  }
X	  ++its;
X	  for (m = (nn - 2); m >= l; m--)
X	  {
X	    z = a[m][m];
X	    r = x - z;
X	    s = y - z;
X	    p = (r * s - w) / a[m + 1][m] + a[m][m + 1];
X	    q = a[m + 1][m + 1] - z - r - s;
X	    r = a[m + 2][m + 1];
X	    s = fabs (p) + fabs (q) + fabs (r);
X	    p /= s;
X	    q /= s;
X	    r /= s;
X	    if (m == l)
X	      break;
X	    u = fabs (a[m][m - 1]) * (fabs (q) + fabs (r));
X	    v = fabs (p) * (fabs (a[m - 1][m - 1]) + fabs (z) + fabs (a[m + 1][m + 1]));
X	    if ((float) (u + v) == v)
X	      break;
X	  }
X	  for (i = m + 2; i <= nn; i++)
X	  {
X	    a[i][i - 2] = 0.0;
X	    if (i != (m + 2))
X	      a[i][i - 3] = 0.0;
X	  }
X	  for (k = m; k <= nn - 1; k++)
X	  {
X	    if (k != m)
X	    {
X	      p = a[k][k - 1];
X	      q = a[k + 1][k - 1];
X	      r = 0.0;
X	      if (k != (nn - 1))
X		r = a[k + 2][k - 1];
X	      if (x = fabs (p) + fabs (q) + fabs (r))
X	      {
X		p /= x;
X		q /= x;
X		r /= x;
X	      }
X	    }
X	    if (s = SIGN (sqrt (p * p + q * q + r * r), p)) 
X	    {
X	      if (k == m)
X	      {
X		if (l != m)
X		  a[k][k - 1] = -a[k][k - 1];
X	      }
X	      else
X		a[k][k - 1] = -s * x;
X	      p += s;
X	      x = p / s;
X	      y = q / s;
X	      z = r / s;
X	      q /= p;
X	      r /= p;
X	      for (j = k; j <= nn; j++)
X	      {
X		p = a[k][j] + q * a[k + 1][j];
X		if (k != (nn - 1))
X		{
X		  p += r * a[k + 2][j];
X		  a[k + 2][j] -= p * z;
X		}
X		a[k + 1][j] -= p * y;
X		a[k][j] -= p * x;
X	      }
X	      mmin = nn < k + 3 ? nn : k + 3;
X	      for (i = l; i <= mmin; i++)
X	      {
X		p = x * a[i][k] + y * a[i][k + 1];
X		if (k != (nn - 1))
X		{
X		  p += z * a[i][k + 2];
X		  a[i][k + 2] -= p * r;
X		}
X		a[i][k + 1] -= p * q;
X		a[i][k] -= p;
X	      }
X	    }
X	  }
X	}
X      }
X    } while (l < nn - 1);
X  }
X}
SHAR_EOF
if test 23779 -ne "`wc -c < 'pgm/pgmtexture.c'`"
then
	echo shar: error transmitting "'pgm/pgmtexture.c'" '(should have been 23779 characters)'
fi
fi # end of overwriting check
if test ! -d 'pgm'
then
	echo shar: creating directory "'pgm'"
	mkdir 'pgm'
fi
echo shar: extracting "'pgm/pgmtexture.1'" '(2407 characters)'
if test -f 'pgm/pgmtexture.1'
then
	echo shar: will not over-write existing file "'pgm/pgmtexture.1'"
else
sed 's/^X//' << \SHAR_EOF > 'pgm/pgmtexture.1'
X.TH pgmtexture 1 "22 Aug 1991"
X.IX pgmtexture
X.SH NAME
Xpgmtexture - calculate textural features on a portable graymap
X.SH SYNOPSIS
X.B pgmtexture
X.RB [ -d
X.IR d ]
X.RI [ pgmfile ]
X.SH DESCRIPTION
XReads a portable graymap as input.  Calculates textural features
Xbased on spatial dependence matrices at 0, 45, 90, and 135 degrees for
Xa distance 
X.IR d 
X(default = 1).
XTextural features include:
X.IP
X(1) Angular Second Moment,
X.br
X(2) Contrast,
X.br
X(3) Correlation,
X.br
X(4) Variance,          
X.br
X(5) Inverse Difference Moment,
X.br
X(6) Sum Average,
X.br
X(7) Sum Variance,
X.br
X(8) Sum Entropy,
X.br
X(9) Entropy,
X.br
X(10) Difference Variance,
X.br
X(11) Difference Entropy,
X.br
X(12, 13) Information Measures of Correlation, and
X.br
X(14) Maximal Correlation Coefficient.
X.PP
XAlgorithm taken from:
X.br
XHaralick, R.M., K. Shanmugam, and I. Dinstein. 1973. Textural features
Xfor image classification.  
X.I IEEE Transactions on Systems, Man, 
X.I and Cybertinetics,
XSMC-3(6):610-621.
X.SH BUGS
XThe program can run incredibly slow for large images (larger than 64 x 64)
Xand command line options are limited.
XThe method for finding (14) the maximal correlation coefficient, which
Xrequires finding the second largest eigenvalue of a matrix Q, does not
Xalways converge.
X.SH REFERENCES
X.I IEEE Transactions on Systems, Man, 
X.I and Cybertinetics,
XSMC-3(6):610-621.
X.SH "SEE ALSO"
Xpgm(5), pnmcut(1)
X.SH AUTHOR
XCopyright (C) 1991 by Texas Agricultural Experiment Station, employer for
Xhire of James Darrell McCauley. 
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
X.\"
X.\" THE TEXAS AGRICULTURAL EXPERIMENT STATION (TAES) AND THE TEXAS A&M
X.\" UNIVERSITY SYSTEM (TAMUS) MAKE NO EXPRESS OR IMPLIED WARRANTIES
X.\" (INCLUDING BY WAY OF EXAMPLE, MERCHANTABILITY) WITH RESPECT TO ANY
X.\" ITEM, AND SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL
X.\" OR CONSEQUENTAL DAMAGES ARISING OUT OF THE POSESSION OR USE OF
X.\" ANY SUCH ITEM. LICENSEE AND/OR USER AGREES TO INDEMNIFY AND HOLD
X.\" TAES AND TAMUS HARMLESS FROM ANY CLAIMS ARISING OUT OF THE USE OR
X.\" POSSESSION OF SUCH ITEMS.
SHAR_EOF
if test 2407 -ne "`wc -c < 'pgm/pgmtexture.1'`"
then
	echo shar: error transmitting "'pgm/pgmtexture.1'" '(should have been 2407 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.
