PBMPLUS, part 11 of 18

Jef Poskanzer pokey at well.UUCP
Thu Sep 14 21:25:32 AEST 1989


#! /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:
#	ppm/ppm.h
#	ppm/ppmcmap.h
#	ppm/ppmdraw.h
#	ppm/libppm.h
#	ppm/tga.h
#	ppm/mtvtoppm.c
#	ppm/mtvtoppm.1
#	ppm/giftoppm.c
#	ppm/giftoppm.1
#	ppm/ppmrotate.c
#	ppm/ppmrotate.1
# This archive created: Thu Sep 14 03:43:42 1989
# By:	Jef Poskanzer (Paratheo-Anametamystikhood Of Eris Esoteric, Ada Lovelace Cabal)
export PATH; PATH=/bin:$PATH
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppm.h'" '(2434 characters)'
if test -f 'ppm/ppm.h'
then
	echo shar: will not over-write existing file "'ppm/ppm.h'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppm.h'
X/* ppm.h - header file for libppm portable pixelmap library
X*/
X
X#ifndef _PPM_H_
X#define _PPM_H_
X
X#include "pgm.h"
X
Xtypedef gray pixval;
X
X#ifdef PPM_PACKCOLORS
X
X#define PPM_MAXMAXVAL 1023
Xtypedef unsigned long pixel;
X#define PPM_GETR(p) (((p) & 0x3ff00000) >> 20)
X#define PPM_GETG(p) (((p) & 0xffc00) >> 10)
X#define PPM_GETB(p) ((p) & 0x3ff)
X#define PPM_ASSIGN(p,red,grn,blu) (p) = ((pixel) (red) << 20) | ((pixel) (grn) << 10) | (pixel) (blu)
X#define PPM_EQUAL(p,q) ((p) == (q))
X
X#else PPM_PACKCOLORS
X
X#define PPM_MAXMAXVAL PGM_MAXMAXVAL
Xtypedef struct
X    {
X    pixval r, g, b;
X    } pixel;
X#define PPM_GETR(p) ((p).r)
X#define PPM_GETG(p) ((p).g)
X#define PPM_GETB(p) ((p).b)
X#define PPM_ASSIGN(p,red,grn,blu) do { (p).r = (red); (p).g = (grn); (p).b = (blu); } while ( 0 )
X#define PPM_EQUAL(p,q) ( (p).r == (q).r && (p).g == (q).g && (p).b == (q).b )
X
X#endif PPM_PACKCOLORS
X
X/* Declarations of routines. */
X
X#define ppm_allocarray( cols, rows ) ((pixel **) pm_allocarray( cols, rows, sizeof(pixel) ))
X#define ppm_allocrow( cols ) ((pixel *) pm_allocrow( cols, sizeof(pixel) ))
X#define ppm_freearray( pixelrow, rows ) pm_freearray( pixelrow, rows )
X#define ppm_freerow( pixelrow ) pm_freerow( pixelrow )
X
Xpixel **ppm_readppm( /* FILE *file, int *colsP, int *rowsP, pixval *maxvalP */ );
Xvoid ppm_readppminit( /* FILE *file, int *colsP, int *rowsP, pixval *maxvalP, int *formatP */ );
Xvoid ppm_readppmrow( /* FILE *file, pixel *pixelrow, int cols, pixval maxval, int format */ );
X
Xvoid ppm_writeppm( /* FILE *file, pixel **pixels, int cols, int rows, pixval maxval */ );
Xvoid ppm_writeppminit( /* FILE *file, int cols, int rows, pixval maxval */ );
Xvoid ppm_writeppmrow( /* FILE *file, pixel *pixelrow, int cols, pixval maxval */ );
X
Xpixel ppm_backgroundpixel( /* pixel **pixels, int cols, int rows */ );
X
Xextern pixval ppm_pbmmaxval;
X/* This is the maxval used when a PPM program reads a PBM file.  Normally
X** it is 1; however, for some programs, a larger value gives better results
X*/
X
X/* Color scaling macro -- to make writing ppmtowhatever easier. */
X
X#define PPM_CSCALE(newp,p,oldmaxval,newmaxval) \
X    PPM_ASSIGN( (newp), \
X	        (int) PPM_GETR(p) * (newmaxval) / (oldmaxval), \
X	        (int) PPM_GETG(p) * (newmaxval) / (oldmaxval), \
X	        (int) PPM_GETB(p) * (newmaxval) / (oldmaxval) )
X
X/* Luminance macro. */
X
X#define PPM_LUMIN(p) ( 0.299 * PPM_GETR(p) + 0.587 * PPM_GETG(p) + 0.114 * PPM_GETB(p) )
X
X#endif _PPM_H_
SHAR_EOF
if test 2434 -ne "`wc -c < 'ppm/ppm.h'`"
then
	echo shar: error transmitting "'ppm/ppm.h'" '(should have been 2434 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmcmap.h'" '(1328 characters)'
if test -f 'ppm/ppmcmap.h'
then
	echo shar: will not over-write existing file "'ppm/ppmcmap.h'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmcmap.h'
X/* ppmcmap.h - header file for colormap routines in libppm
X*/
X
X/* Color histogram stuff. */
X
Xtypedef struct colorhist_item *colorhist_vector;
Xstruct colorhist_item
X    {
X    pixel color;
X    int value;
X    };
X
Xtypedef struct colorhist_list_item *colorhist_list;
Xstruct colorhist_list_item
X    {
X    struct colorhist_item ch;
X    colorhist_list next;
X    };
X
Xcolorhist_vector ppm_computecolorhist( /* pixel **pixels, int cols, int rows, int maxcolors, int *colorsP */ );
X/* (Returns a colorhist *colorsP long (with space allocated for maxcolors). */
X
Xvoid ppm_addtocolorhist( /* colorhist_vector chv, int *colorsP, int maxcolors, pixel color, int value, int position */ );
X
Xvoid ppm_freecolorhist( /* colorhist_vector chv */ );
X
X
X/* Color hash table stuff. */
X
Xtypedef colorhist_list *colorhash_table;
X
Xcolorhash_table ppm_computecolorhash( /* pixel **pixels, int cols, int rows, int maxcolors, int *colorsP */ );
X
Xint
Xppm_lookupcolor( /* colorhash_table cht, pixel color */ );
X
Xcolorhist_vector ppm_colorhashtocolorhist( /* colorhash_table cht, int maxcolors */ );
Xcolorhash_table ppm_colorhisttocolorhash( /* colorhist_vector chv, int colors */ );
X
Xvoid ppm_addtocolorhash( /* colorhash_table cht, pixel color, int value */ );
X
Xcolorhash_table ppm_alloccolorhash( /* */ );
X
Xvoid ppm_freecolorhash( /* colorhash_table cht */ );
SHAR_EOF
if test 1328 -ne "`wc -c < 'ppm/ppmcmap.h'`"
then
	echo shar: error transmitting "'ppm/ppmcmap.h'" '(should have been 1328 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmdraw.h'" '(4534 characters)'
if test -f 'ppm/ppmdraw.h'
then
	echo shar: will not over-write existing file "'ppm/ppmdraw.h'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmdraw.h'
X/* ppmdraw.h - header file for simple drawing routines in libppm
X**
X** Simple, yes, and also fairly slow if the truth be told; but also very
X** flexible and powerful.
X**
X** The two basic concepts are the drawproc and clientdata.  All the drawing
X** routines take a drawproc that does the actual drawing.  A drawproc draws
X** a single point, and it looks like this:
X*/
Xvoid ppmd_point_drawproc( /* pixel **pixels, int cols, int rows, pixval maxval, int x, int y, char *clientdata */ );
X/*
X** So, you call a drawing routine, e.g. ppmd_line(), and pass it a drawproc;
X** it calls the drawproc for each point it wants to draw.  Why so complicated?
X** Because you can define your own drawprocs to do more interesting things than
X** simply draw the point.  For example, you could make one that calls back into
X** another drawing routine, say ppmd_circle() to draw a circle at each point
X** of a line.
X**
X** Slow?  Well sure, we're talking results here, not realtime.  You can do
X** tricks with this arrangement that you couldn't even think of before.
X** Still, to speed things up for the 90% case you can use this:
X*/
X#define PPMD_NULLDRAWPROC (void (*)()) 0
X/*
X** Just like ppmd_point_drawproc it simply draws the point, but it's done
X** inline, and clipping is assumed to be handled at a higher level.
X**
X** Now, what about clientdata.  Well, it's an arbitrary pointer, and can
X** mean something different to each different drawproc.  For the above two
X** drawproc, clientdata should be a pointer to a pixel holding the color
X** to be drawn.  Other drawprocs can use it to point to something else,
X** e.g. some structure to be modified, or they can ignore it.
X*/
X
X
X/* Outline drawing routines.  Lines, splines, circles, etc.
X*/
X
Xint ppmd_setlinetype( /* int type */ );
X#define PPMD_LINETYPE_NORMAL 0
X#define PPMD_LINETYPE_NODIAGS 1
X/* If you set NODIAGS, all pixels drawn by ppmd_line() will be 4-connected
X** instead of 8-connected; in other words, no diagonals.  This is useful
X** for some applications, for example when you draw many parallel lines
X** and you want them to fit together without gaps.
X*/
X
Xint ppmd_setlineclipping( /* int clip */ );
X/* Normally, ppmd_line() clips to the edges of the pixmap.  You can use this
X** routine to disable the clipping, for example if you are using a drawproc
X** that wants to do its own clipping.
X*/
X
Xvoid ppmd_line( /* pixel **pixels, int cols, int rows, pixval maxval, int x0, int y0, int x1, int y1, void (*drawprocP)(), char *clientdata */ );
X/* Draws a line from (x0, y0) to (x1, y1).
X*/
X
Xvoid ppmd_spline3( /* pixel **pixels, int cols, int rows, pixval maxval, int x0, int y0, int x1, int y1, int x2, int y2, void (*drawprocP)(), char *clientdata */ );
X/* Draws a three-point spline from (x0, y0) to (x2, y2), with (x1, y1) as
X** the control point.  All drawing is done via ppmd_line(), so the routines
X** that control it control ppmd_spline3() as well.
X*/
X
Xvoid ppmd_polyspline( /* pixel **pixels, int cols, int rows, pixval maxval, int x0, int y0, int nc, int *xc, int *yc, int x1, int y1, void (*drawprocP)(), char *clientdata */ );
X/* Draws a bunch of splines end to end.  (x0, y0) and (x1, y1) are the initial
X** and final points, and the xc and yc are the intermediate control points.
X** nc is the number of these control points.
X*/
X
Xvoid ppmd_circle( /* pixel **pixels, int cols, int rows, pixval maxval, int cx, int cy, int radius, void (*drawprocP)(), char *clientdata */ );
X/* Draws a circle centered at (cx, cy) with the specified radius.
X*/
X
X
X/* Simple filling routines.  Ok, so there's only one.
X*/
X
Xvoid ppmd_filledrectangle( /* pixel **pixels, int cols, int rows, pixval maxval, int x, int y, int width, int height, void (*drawprocP)(), char *clientdata */ );
X/* Fills in the rectangle [x, y, width, height].
X*/
X
X
X/* Arbitrary filling routines.  With these you can fill any outline that
X** you can draw with the outline routines.
X*/
X
Xchar *ppmd_fill_init( );
X/* Returns a blank fillhandle.
X*/
X
Xvoid ppmd_fill_drawproc( /* pixel **pixels, int cols, int rows, pixval maxval, int col, int row, char *clientdata */ );
X/* Use this drawproc to trace the outline you want filled.  Be sure to use
X** the fillhandle as the clientdata.
X*/
X
Xvoid ppmd_fill( /* pixel **pixels, int cols, int rows, pixval maxval, char *fillhandle, void (*drawprocP)(), char *clientdata */ );
X/* Once you've traced the outline, give the fillhandle to this routine to
X** do the actual drawing.  As usual, it takes a drawproc and clientdata;
X** you could define drawprocs to do stipple fills and such.
X*/
SHAR_EOF
if test 4534 -ne "`wc -c < 'ppm/ppmdraw.h'`"
then
	echo shar: error transmitting "'ppm/ppmdraw.h'" '(should have been 4534 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/libppm.h'" '(479 characters)'
if test -f 'ppm/libppm.h'
then
	echo shar: will not over-write existing file "'ppm/libppm.h'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/libppm.h'
X/* libppm.h - internal header file for libppm portable pixmap library
X*/
X
X#ifndef _LIBPPM_H_
X#define _LIBPPM_H_
X
X/* Magic constants. */
X
X#define PPM_MAGIC1 'P'
X#define PPM_MAGIC2 '3'
X#define RPPM_MAGIC2 '6'
X#define PPM_FORMAT (PPM_MAGIC1 * 256 + PPM_MAGIC2)
X#define RPPM_FORMAT (PPM_MAGIC1 * 256 + RPPM_MAGIC2)
X
X
X/* And here are some routines internal to the ppm library. */
X
Xvoid ppm_readppminitrest( /* FILE *file, int *colsP, int *rowsP, int *maxvalP */ );
X
X#endif _LIBPPM_H_
SHAR_EOF
if test 479 -ne "`wc -c < 'ppm/libppm.h'`"
then
	echo shar: error transmitting "'ppm/libppm.h'" '(should have been 479 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/tga.h'" '(1424 characters)'
if test -f 'ppm/tga.h'
then
	echo shar: will not over-write existing file "'ppm/tga.h'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/tga.h'
X/* tga.h - header file for Targa files
X*/
X 
X/* Header definition. */
Xstruct ImageHeader {
X    unsigned char IDLength;		/* length of Identifier String */
X    unsigned char CoMapType;		/* 0 = no map */
X    unsigned char ImgType;		/* image type (see below for values) */
X    unsigned char Index_lo, Index_hi;	/* index of first color map entry */
X    unsigned char Length_lo, Length_hi;	/* number of entries in color map */
X    unsigned char CoSize;		/* size of color map entry (15,16,24,32) */
X    unsigned char X_org_lo, X_org_hi;	/* x origin of image */
X    unsigned char Y_org_lo, Y_org_hi;	/* y origin of image */
X    unsigned char Width_lo, Width_hi;	/* width of image */
X    unsigned char Height_lo, Height_hi;	/* height of image */
X    unsigned char PixelSize;		/* pixel size (8,16,24,32) */
X    unsigned char AttBits;		/* 4 bits, number of attribute bits per pixel */
X    unsigned char Rsrvd;		/* 1 bit, reserved */
X    unsigned char OrgBit;		/* 1 bit, origin: 0=lower left, 1=upper left */
X    unsigned char IntrLve;		/* 2 bits, interleaving flag */
X    };
X
Xtypedef char ImageIDField[256];
X
X/* Definitions for image types. */
X#define TGA_Null 0
X#define TGA_Map 1
X#define TGA_RGB 2
X#define TGA_Mono 3
X#define TGA_RLEMap 9
X#define TGA_RLERGB 10
X#define TGA_RLEMono 11
X#define TGA_CompMap 32
X#define TGA_CompMap4 33
X
X/* Definitions for interleave flag. */
X#define TGA_IL_None 0
X#define TGA_IL_Two 1
X#define TGA_IL_Four 2
SHAR_EOF
if test 1424 -ne "`wc -c < 'ppm/tga.h'`"
then
	echo shar: error transmitting "'ppm/tga.h'" '(should have been 1424 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/mtvtoppm.c'" '(1592 characters)'
if test -f 'ppm/mtvtoppm.c'
then
	echo shar: will not over-write existing file "'ppm/mtvtoppm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/mtvtoppm.c'
X/* mtvtoppm.c - read an MTV ray-tracer output file and produce a portable pixmap
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 <stdio.h>
X#include "ppm.h"
X
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X    {
X    FILE *ifd;
X    register pixel *pixelrow, *pP;
X    int rows, cols, row, col;
X    pixval maxval;
X    unsigned char buf[3];
X
X    pm_progname = argv[0];
X
X    if ( argc > 2 )
X	pm_usage( "[mtvfile]" );
X
X    if ( argc == 2 )
X	ifd = pm_openr( argv[1] );
X    else
X	ifd = stdin;
X
X    /* Read in the MTV file.  First the header. */
X    if ( fscanf( ifd, "%d%d\n", &cols, &rows ) != 2 )
X	pm_error( "unable to read MTV file header", 0,0,0,0,0 );
X
X    if ( cols <= 0 || rows <= 0 )
X	pm_error( "invalid size: %d %d", cols, rows, 0,0,0 );
X    maxval = 255;
X
X    ppm_writeppminit( stdout, cols, rows, maxval );
X    pixelrow = ppm_allocrow( cols );
X
X    for ( row = 0; row < rows; row++ )
X	{
X	for ( col = 0, pP = pixelrow; col < cols; col++, pP++ )
X	    {
X	    if ( fread( buf, sizeof(buf), 1, ifd ) != 1 )
X		pm_error( "premature EOF", 0,0,0,0,0 );
X	    PPM_ASSIGN( *pP, buf[0], buf[1], buf[2] );
X	    }
X	ppm_writeppmrow( stdout, pixelrow, cols, maxval );
X	}
X
X    pm_close( ifd );
X
X    exit( 0 );
X    }
SHAR_EOF
if test 1592 -ne "`wc -c < 'ppm/mtvtoppm.c'`"
then
	echo shar: error transmitting "'ppm/mtvtoppm.c'" '(should have been 1592 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/mtvtoppm.1'" '(683 characters)'
if test -f 'ppm/mtvtoppm.1'
then
	echo shar: will not over-write existing file "'ppm/mtvtoppm.1'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/mtvtoppm.1'
X.TH mtvtoppm 1 "02 February 1989"
X.SH NAME
Xmtvtoppm - convert output from Mark VanDeWettering's ray tracer into a portable pixmap
X.SH SYNOPSIS
Xmtvtoppm [mtvfile]
X.SH DESCRIPTION
XReads an mtv file as input.
XProduces a portable pixmap as output.
X.SH "SEE ALSO"
Xppm(5)
X.SH AUTHOR
XCopyright (C) 1989 by Jef Poskanzer.
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted, provided
Xthat the above copyright notice appear in all copies and that both that
Xcopyright notice and this permission notice appear in supporting
Xdocumentation.  This software is provided "as is" without express or
Ximplied warranty.
SHAR_EOF
if test 683 -ne "`wc -c < 'ppm/mtvtoppm.1'`"
then
	echo shar: error transmitting "'ppm/mtvtoppm.1'" '(should have been 683 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/giftoppm.c'" '(14842 characters)'
if test -f 'ppm/giftoppm.c'
then
	echo shar: will not over-write existing file "'ppm/giftoppm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/giftoppm.c'
X/*-
X * giftoppm.c - Converts from a Compuserve GIF (tm) image to a PPM file.
X *
X * Copyright (c) 1988, 1989 by Patrick J. Naughton
X *
X * Author: Patrick J. Naughton
X * naughton at wind.sun.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,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation.
X *
X * This file is provided AS IS with no warranties of any kind.  The author
X * shall have no liability with respect to the infringement of copyrights,
X * trade secrets or any patents by this file or any part thereof.  In no
X * event will the author be liable for any lost revenue or profits or
X * other special, indirect and consequential damages.
X *
X * Comments and additions should be sent to the author:
X *
X *                     Patrick J. Naughton
X *                     Sun Microsystems
X *                     2550 Garcia Ave, MS 14-40
X *                     Mountain View, CA 94043
X *                     (415) 336-1080
X *
X * Revision History:
X * 15-Apr-89: (JP) Changed to use pbm_ error routines.
X * 23-Feb-89: (JP) Changed from PBM to PPM.
X * 03-Feb-89: (JP) Changed u_char to unsigned char, and unincluded types.h.
X * 01-Jan-89: Added error checking and removed NEXTSHORT.
X * 07-Sep-88: Added BytesPerScanline fix.
X * 30-Aug-88: Allow stdin/stdout. Restructured argument parser.
X * 28-Aug-88: (JP) Modified to output PBM instead of Sun raster.
X * 27-Jul-88: Updated to use libpixrect to fix 386i byteswapping problems.
X * 11-Apr-88: Converted to C and changed to write Sun rasterfiles.
X * 19-Jan-88: GIFSLOW.PAS posted to comp.graphics by Jim Briebel,
X *            a Turbo Pascal 4.0 program to painfully slowly display
X *            GIF images on an EGA equipped IBM-PC.
X *
X * Description:
X *   This program takes a Compuserve "Graphics Interchange Format" or "GIF"
X * file as input and writes a PPM file.
X *
X * Portability:
X *   To make this program convert to some image format other than PPM
X * format simply seach for the tag "PPMS:" in the source and
X * replace these simple mechanisms with the appropriate ones for the
X * other output format.  I have marked all (six) PPM Specific pieces
X * of code with this comment.
X *
X * SS: compile with "cc -o giftoppm -O giftoppm.c -lpixrect"
X * PPMS: compile with "cc -o giftoppm -O giftoppm.c libppm.a
X */
X
X#include <stdio.h>
X#ifdef	SYSV
X#include <string.h>
X#else	SYSV
X#include <strings.h>
X#endif	SYSV
X#ifdef notdefSS
X#include <pixrect/pixrect_hs.h> /* SS: main Pixrect header file */
X#endif notdefSS
X#include "ppm.h"		/* PPMS: main PPM header file */
X
Xtypedef int boolean;
X#define True (1)
X#define False (0)
X
X#define NEXTBYTE (*ptr++)
X#define IMAGESEP 0x2c
X#define INTERLACEMASK 0x40
X#define COLORMAPMASK 0x80
X
XFILE *fp;
X
Xint BitOffset = 0,		/* Bit Offset of next code */
X    XC = 0, YC = 0,		/* Output X and Y coords of current pixel */
X    Pass = 0,			/* Used by output routine if interlaced pic */
X    OutCount = 0,		/* Decompressor output 'stack count' */
X    RWidth, RHeight,		/* screen dimensions */
X    Width, Height,		/* image dimensions */
X    LeftOfs, TopOfs,		/* image offset */
X    BitsPerPixel,		/* Bits per pixel, read from GIF header */
X    BytesPerScanline,		/* bytes per scanline in output raster */
X    ColorMapSize,		/* number of colors */
X    CodeSize,			/* Code size, read from GIF header */
X    InitCodeSize,		/* Starting code size, used during Clear */
X    Code,			/* Value returned by ReadCode */
X    MaxCode,			/* limiting value for current code size */
X    ClearCode,			/* GIF clear code */
X    EOFCode,			/* GIF end-of-information code */
X    CurCode, OldCode, InCode,	/* Decompressor variables */
X    FirstFree,			/* First free code, generated per GIF spec */
X    FreeCode,			/* Decompressor, next free slot in hash table */
X    FinChar,			/* Decompressor variable */
X    BitMask,			/* AND mask for data size */
X    ReadMask;			/* Code AND mask for current code size */
X
Xboolean Interlace, HasColormap;
Xboolean Verbose = False;
X
X#ifdef notdefSS
X/* SS: defined in pixrect/pixrect_hs.h */
XPixrect *Output;		/* The Sun Pixrect */
Xcolormap_t Colormap;		/* The Pixrect Colormap */
Xunsigned char *Image;			/* The result array */
X#endif notdefSS
X/* PPMS: defined in ppm.h */
Xpixel **pixels;			/* The PPM pixel array */
X
Xunsigned char *RawGIF;			/* The heap array to hold it, raw */
Xunsigned char *Raster;			/* The raster data stream, unblocked */
X
X    /* The hash table used by the decompressor */
Xint Prefix[4096];
Xint Suffix[4096];
X
X    /* An output array used by the decompressor */
Xint OutCode[1025];
X
X    /* The color map, read from the GIF header */
Xunsigned char Red[256], Green[256], Blue[256];
X
Xchar *id = "GIF87a";
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
Xchar *inf = NULL;
Xchar *outf = NULL;
Xint filesize;
Xregister unsigned char ch, ch1;
Xregister unsigned char *ptr, *ptr1;
Xregister int i;
Xchar *usage = "[-vq] [-|GIFfile] [ppmfile]";
X
X    pm_progname = argv[0];
X
X    setbuf(stderr, NULL);
X
X    while (--argc)
X	if ((++argv)[0][0] == '-')
X	    switch (argv[0][1]) {
X	    case 'v':
X		Verbose = True;
X		break;
X	    case 'q':
X		pm_usage(usage);
X	    case '\0':
X		if (inf == NULL)
X		    inf = "Standard Input";
X		else if (outf == NULL)
X		    outf = "Standard Output";
X		else
X		    pm_usage(usage);
X		break;
X	    default:
X		pm_usage(usage);
X	    }
X	else if (inf == NULL)
X	    inf = argv[0];
X	else if (outf == NULL)
X	    outf = argv[0];
X	else
X	    pm_usage(usage);
X
X    if (inf == NULL || strcmp(inf, "Standard Input") == 0 || strcmp(inf, "-") == 0) {
X	inf = "Standard Input";
X	fp = stdin;
X    } else if (!(fp = fopen(inf, "r")))
X	pm_error( "%s not found", inf, 0,0,0,0 );
X
X    /* find the size of the file */
X    fseek(fp, 0L, 2);
X    filesize = ftell(fp);
X    fseek(fp, 0L, 0);
X
X    if (!(ptr = RawGIF = (unsigned char *) malloc(filesize)))
X	pm_error( "not enough memory to read gif file", 0,0,0,0,0 );
X
X    if (!(Raster = (unsigned char *) malloc(filesize)))
X	pm_error( "not enough memory to read gif file", 0,0,0,0,0 );
X
X    if (fread(ptr, filesize, 1, fp) != 1)
X	pm_error( "GIF data read failed", 0,0,0,0,0 );
X
X    if (strncmp(ptr, id, 6))
X	pm_error( "%s is not a GIF file", inf, 0,0,0,0 );
X    ptr += 6;
X
X/* Get variables from the GIF screen descriptor */
X
X    ch = NEXTBYTE;
X    RWidth = ch + 0x100 * NEXTBYTE;	/* screen dimensions... not used. */
X    ch = NEXTBYTE;
X    RHeight = ch + 0x100 * NEXTBYTE;
X
X    if (Verbose)
X	fprintf(stderr, "screen dims: %dx%d.\n", RWidth, RHeight);
X
X    ch = NEXTBYTE;
X    HasColormap = ((ch & COLORMAPMASK) ? True : False);
X
X    BitsPerPixel = (ch & 7) + 1;
X    ColorMapSize = 1 << BitsPerPixel;
X    BitMask = ColorMapSize - 1;
X
X    ch = NEXTBYTE;		/* background color... not used. */
X
X    if (NEXTBYTE)		/* supposed to be NULL */
X	pm_error( "%s is a corrupt GIF file (nonull)", inf, 0,0,0,0 );
X
X/* Read in global colormap. */
X
X    if (HasColormap) {
X	if (Verbose)
X	    fprintf(stderr, "%s is %d bits per pixel, (%d colors).\n",
X		inf, BitsPerPixel, ColorMapSize);
X	for (i = 0; i < ColorMapSize; i++) {
X	    Red[i] = NEXTBYTE;
X	    Green[i] = NEXTBYTE;
X	    Blue[i] = NEXTBYTE;
X	}
X
X#ifdef notdefSS
X/* SS: Fill in the Pixrect colormap struct */
X	Colormap.type = RMT_EQUAL_RGB;
X	Colormap.length = ColorMapSize;
X	Colormap.map[0] = Red;
X	Colormap.map[1] = Green;
X	Colormap.map[2] = Blue;
X#endif notdefSS
X	/* PPMS: Don't have to do anything special here. */
X    }
X    else pm_error( "%s does not have a colormap", inf, 0,0,0,0 );
X
X
X/* Check for image seperator */
X
X    if (NEXTBYTE != IMAGESEP)
X	pm_error( "%s is a corrupt GIF file (nosep)", inf, 0,0,0,0 );
X
X/* Now read in values from the image descriptor */
X
X    ch = NEXTBYTE;
X    LeftOfs = ch + 0x100 * NEXTBYTE;
X    ch = NEXTBYTE;
X    TopOfs = ch + 0x100 * NEXTBYTE;
X    ch = NEXTBYTE;
X    Width = ch + 0x100 * NEXTBYTE;
X    ch = NEXTBYTE;
X    Height = ch + 0x100 * NEXTBYTE;
X    Interlace = ((NEXTBYTE & INTERLACEMASK) ? True : False);
X
X    if (Verbose)
X	fprintf(stderr, "Reading a %d by %d %sinterlaced image...",
X		Width, Height, (Interlace) ? "" : "non-");
X    
X
X/* Note that I ignore the possible existence of a local color map.
X * I'm told there aren't many files around that use them, and the spec
X * says it's defined for future use.  This could lead to an error
X * reading some files. 
X */
X
X/* Start reading the raster data. First we get the intial code size
X * and compute decompressor constant values, based on this code size.
X */
X
X    CodeSize = NEXTBYTE;
X    ClearCode = (1 << CodeSize);
X    EOFCode = ClearCode + 1;
X    FreeCode = FirstFree = ClearCode + 2;
X
X/* The GIF spec has it that the code size is the code size used to
X * compute the above values is the code size given in the file, but the
X * code size used in compression/decompression is the code size given in
X * the file plus one. (thus the ++).
X */
X
X    CodeSize++;
X    InitCodeSize = CodeSize;
X    MaxCode = (1 << CodeSize);
X    ReadMask = MaxCode - 1;
X
X/* Read the raster data.  Here we just transpose it from the GIF array
X * to the Raster array, turning it from a series of blocks into one long
X * data stream, which makes life much easier for ReadCode().
X */
X
X    ptr1 = Raster;
X    do {
X	ch = ch1 = NEXTBYTE;
X	while (ch--) *ptr1++ = NEXTBYTE;
X	if ((ptr1 - Raster) > filesize)
X	    pm_error( "%s is a corrupt GIF file (unblock)", inf, 0,0,0,0 );
X    } while(ch1);
X
X    free(RawGIF);		/* We're done with the raw data now... */
X
X    if (Verbose) {
X	fprintf(stderr, "done.\n");
X	fprintf(stderr, "Decompressing...");
X    }
X
X
X#ifdef notdefSS
X/* SS: Allocate the Sun Pixrect and make "Image" point to the image data. */
X    Output = mem_create(Width, Height, 8);
X    if (Output == (Pixrect *) NULL)
X	pm_error( "not enough memory for output data", 0,0,0,0,0 );
X    Image = (unsigned char *) mpr_d(Output)->md_image;
X    BytesPerScanline = mpr_d(Output)->md_linebytes;
X#endif notdefSS
X/* PPMS: Allocate the PPM pixel array. */
X    pixels = ppm_allocarray(Width, Height);
X
X
X/* Decompress the file, continuing until you see the GIF EOF code.
X * One obvious enhancement is to add checking for corrupt files here.
X */
X
X    Code = ReadCode();
X    while (Code != EOFCode) {
X
X/* Clear code sets everything back to its initial value, then reads the
X * immediately subsequent code as uncompressed data.
X */
X
X	if (Code == ClearCode) {
X	    CodeSize = InitCodeSize;
X	    MaxCode = (1 << CodeSize);
X	    ReadMask = MaxCode - 1;
X	    FreeCode = FirstFree;
X	    CurCode = OldCode = Code = ReadCode();
X	    FinChar = CurCode & BitMask;
X	    AddToPixel(FinChar);
X	}
X	else {
X
X/* If not a clear code, then must be data: save same as CurCode and InCode */
X
X	    CurCode = InCode = Code;
X
X/* If greater or equal to FreeCode, not in the hash table yet;
X * repeat the last character decoded
X */
X
X	    if (CurCode >= FreeCode) {
X		CurCode = OldCode;
X		OutCode[OutCount++] = FinChar;
X	    }
X
X/* Unless this code is raw data, pursue the chain pointed to by CurCode
X * through the hash table to its end; each code in the chain puts its
X * associated output code on the output queue.
X */
X
X	    while (CurCode > BitMask) {
X		if (OutCount > 1024)
X		    pm_error(
X			"%s is a corrupt GIF file (OutCount)", inf, 0,0,0,0 );
X		OutCode[OutCount++] = Suffix[CurCode];
X		CurCode = Prefix[CurCode];
X	    }
X
X/* The last code in the chain is treated as raw data. */
X
X	    FinChar = CurCode & BitMask;
X	    OutCode[OutCount++] = FinChar;
X
X/* Now we put the data out to the Output routine.
X * It's been stacked LIFO, so deal with it that way...
X */
X
X	    for (i = OutCount - 1; i >= 0; i--)
X		AddToPixel(OutCode[i]);
X	    OutCount = 0;
X
X/* Build the hash table on-the-fly. No table is stored in the file. */
X
X	    Prefix[FreeCode] = OldCode;
X	    Suffix[FreeCode] = FinChar;
X	    OldCode = InCode;
X
X/* Point to the next slot in the table.  If we exceed the current
X * MaxCode value, increment the code size unless it's already 12.  If it
X * is, do nothing: the next code decompressed better be CLEAR
X */
X
X	    FreeCode++;
X	    if (FreeCode >= MaxCode) {
X		if (CodeSize < 12) {
X		    CodeSize++;
X		    MaxCode *= 2;
X		    ReadMask = (1 << CodeSize) - 1;
X		}
X	    }
X	}
X	Code = ReadCode();
X    }
X
X    free(Raster);
X
X    if (Verbose)
X	fprintf(stderr, "done.\n");
X
X    if (fp != stdin)
X	fclose(fp);
X
X    if (outf == NULL || strcmp(outf, "Standard Output") == 0) {
X	outf = "Standard Output";
X	fp = stdout;
X    }
X    else {
X	if (!(fp = fopen(outf, "w")))
X	    pm_error( "%s couldn't be opened for writing", outf, 0,0,0,0 );
X    }
X
X    if (Verbose)
X	fprintf(stderr, "Writing rasterfile in %s...", outf);
X
X#ifdef notdefSS
X/* SS: Pixrect Rasterfile output code. */
X    if (pr_dump(Output, fp, &Colormap, RT_STANDARD, 0) == PIX_ERR)
X	pm_error( "error writing Sun Rasterfile: %s", outf, 0,0,0,0 );
X#endif notdefSS
X/* PPMS: PPM output code. */
X    ppm_writeppm(stdout, pixels, Width, Height, (pixval) 255);
X
X    if (Verbose)
X	fprintf(stderr, "done.\n");
X
X#ifdef notdefSS
X    pr_destroy(Output);
X#endif notdefSS
X
X    if (fp != stdout)
X	fclose(fp);
X
X    exit(0);
X}
X
X
X/* Fetch the next code from the raster data stream.  The codes can be
X * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
X * maintain our location in the Raster array as a BIT Offset.  We compute
X * the byte Offset into the raster array by dividing this by 8, pick up
X * three bytes, compute the bit Offset into our 24-bit chunk, shift to
X * bring the desired code to the bottom, then mask it off and return it. 
X */
XReadCode()
X{
Xint RawCode, ByteOffset;
X
X    ByteOffset = BitOffset / 8;
X    RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
X    if (CodeSize >= 8)
X	RawCode += (0x10000 * Raster[ByteOffset + 2]);
X    RawCode >>= (BitOffset % 8);
X    BitOffset += CodeSize;
X    return(RawCode & ReadMask);
X}
X
X
XAddToPixel(Index)
Xunsigned char Index;
X{
X#ifdef notdefSS
X    *(Image + YC * BytesPerScanline + XC) = Index;
X#endif notdefSS
X/* PPMS: Store a pixel. */
X    if (YC < Height)
X	PPM_ASSIGN(pixels[YC][XC], Red[Index], Green[Index], Blue[Index]);
X
X/* Update the X-coordinate, and if it overflows, update the Y-coordinate */
X
X    if (++XC == Width) {
X
X/* If a non-interlaced picture, just increment YC to the next scan line. 
X * If it's interlaced, deal with the interlace as described in the GIF
X * spec.  Put the decoded scan line out to the screen if we haven't gone
X * past the bottom of it
X */
X
X	XC = 0;
X	if (!Interlace) YC++;
X	else {
X	    switch (Pass) {
X		case 0:
X		    YC += 8;
X		    if (YC >= Height) {
X			Pass++;
X			YC = 4;
X		    }
X		break;
X		case 1:
X		    YC += 8;
X		    if (YC >= Height) {
X			Pass++;
X			YC = 2;
X		    }
X		break;
X		case 2:
X		    YC += 4;
X		    if (YC >= Height) {
X			Pass++;
X			YC = 1;
X		    }
X		break;
X		case 3:
X		    YC += 2;
X		break;
X		default:
X		pm_error( "can't happen", 0,0,0,0,0 );
X	    }
X	}
X    }
X}
SHAR_EOF
if test 14842 -ne "`wc -c < 'ppm/giftoppm.c'`"
then
	echo shar: error transmitting "'ppm/giftoppm.c'" '(should have been 14842 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/giftoppm.1'" '(685 characters)'
if test -f 'ppm/giftoppm.1'
then
	echo shar: will not over-write existing file "'ppm/giftoppm.1'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/giftoppm.1'
X.TH giftoppm 1 "23 February 1989"
X.SH NAME
Xgiftoppm - convert a GIF file into a portable pixmap
X.SH SYNOPSIS
Xgiftoppm giffile
X.SH DESCRIPTION
XReads a GIF file as input.
XProduces a portable pixmap as output.
X.SH "SEE ALSO"
Xppmtogif(1), ppm(5)
X.SH AUTHOR
XTrivial modifications to produce PPM by Jef Poskanzer.  Otherwise:
X
XCopyright (c) 1988 by Patrick J. Naughton
X(naughton at wind.sun.com)
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted,
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in
Xsupporting documentation. 
SHAR_EOF
if test 685 -ne "`wc -c < 'ppm/giftoppm.1'`"
then
	echo shar: error transmitting "'ppm/giftoppm.1'" '(should have been 685 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmrotate.c'" '(6471 characters)'
if test -f 'ppm/ppmrotate.c'
then
	echo shar: will not over-write existing file "'ppm/ppmrotate.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmrotate.c'
X/* ppmrotate.c - read a portable pixmap and rotate it by some angle
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 <stdio.h>
X#include <math.h>
X#define M_PI	3.14159265358979323846
X#include "ppm.h"
X
X#define SCALE 4096
X#define HALFSCALE 2048
X
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X    {
X    FILE *ifd;
X    pixel **pixels, **temp1pixels, **temp2pixels, *newpixelrow;
X    register pixel *pP, *npP;
X    pixel bgpixel, prevpixel, p;
X    int argn, rows, cols, newrows, tempcols, newcols, yshearjunk, x2shearjunk, row, col, new;
X    pixval maxval;
X    float fangle, xshearfac, yshearfac, new0;
X    int intnew0;
X    register long fracnew0, omfracnew0;
X    char *usage = "<angle> [ppmfile]";
X
X    pm_progname = argv[0];
X
X    argn = 1;
X
X    if ( argn == argc )
X	pm_usage( usage );
X    if ( sscanf( argv[argn], "%g", &fangle ) != 1 )
X	pm_usage( usage );
X    argn++;
X    if ( fangle < -90.0 || fangle > 90.0 )
X	pm_error( "angle must be between -90 and 90", 0,0,0,0,0 );
X    fangle = fangle * M_PI / 180.0;	/* convert to radians */
X
X    xshearfac = tan( fangle / 2.0 );
X    if ( xshearfac < 0.0 )
X	xshearfac = -xshearfac;
X    yshearfac = sin( fangle );
X    if ( yshearfac < 0.0 )
X	yshearfac = -yshearfac;
X
X    if ( argn != argc )
X	{
X	ifd = pm_openr( argv[argn] );
X	argn++;
X	}
X    else
X	ifd = stdin;
X
X    if ( argn != argc )
X	pm_usage( usage );
X
X    ppm_pbmmaxval = 255;	/* use larger value for better results */
X    pixels = ppm_readppm( ifd, &cols, &rows, &maxval );
X
X    pm_close( ifd );
X
X    tempcols = rows * xshearfac + cols + 0.999999;
X    yshearjunk = ( tempcols - cols ) * yshearfac;
X    newrows = tempcols * yshearfac + rows + 0.999999;
X    x2shearjunk = ( newrows - rows - yshearjunk ) * xshearfac;
X    newrows -= 2 * yshearjunk;
X    newcols = newrows * xshearfac + tempcols + 0.999999 - 2 * x2shearjunk;
X
X    bgpixel = ppm_backgroundpixel( pixels, cols, rows );
X
X    /* First shear X into temp1pixels. */
X    temp1pixels = ppm_allocarray( tempcols, rows );
X    for ( row = 0; row < rows; row++ )
X	{
X	for ( col = 0, npP = temp1pixels[row]; col < tempcols; col++, npP++ )
X	    *npP = bgpixel;
X
X	if ( fangle > 0 )
X	    new0 = row * xshearfac;
X	else
X	    new0 = ( rows - row ) * xshearfac;
X	intnew0 = (int) new0;
X	fracnew0 = ( new0 - intnew0 ) * SCALE;
X	omfracnew0 = SCALE - fracnew0;
X
X	prevpixel = bgpixel;
X
X	for ( col = 0, npP = &(temp1pixels[row][intnew0]), pP = pixels[row]; col < cols; col++, npP++, pP++ )
X	    {
X	    PPM_ASSIGN( *npP,
X		( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(*pP) + HALFSCALE ) / SCALE,
X		( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(*pP) + HALFSCALE ) / SCALE,
X		( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(*pP) + HALFSCALE ) / SCALE );
X	    prevpixel = *pP;
X	    }
X	if ( fracnew0 > 0 && intnew0 + cols < tempcols )
X	    {
X	    PPM_ASSIGN( *npP,
X		( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(bgpixel) + HALFSCALE ) / SCALE,
X		( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(bgpixel) + HALFSCALE ) / SCALE,
X		( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(bgpixel) + HALFSCALE ) / SCALE );
X	    }
X
X	}
X    ppm_freearray( pixels, rows );
X
X    /* Now inverse shear Y from temp1 into temp2. */
X    temp2pixels = ppm_allocarray( tempcols, newrows );
X    for ( col = 0; col < tempcols; col++ )
X	{
X	for ( row = 0; row < newrows; row++ )
X	    temp2pixels[row][col] = bgpixel;
X
X	if ( fangle > 0 )
X	    new0 = ( tempcols - col ) * yshearfac;
X	else
X	    new0 = col * yshearfac;
X	intnew0 = (int) new0;
X	fracnew0 = ( new0 - intnew0 ) * SCALE;
X	omfracnew0 = SCALE - fracnew0;
X	intnew0 -= yshearjunk;
X
X	prevpixel = bgpixel;
X
X	for ( row = 0; row < rows; row++ )
X	    {
X	    new = intnew0 + row;
X	    if ( new >= 0 && new < newrows )
X		{
X		npP = &(temp2pixels[new][col]);
X		p = temp1pixels[row][col];
X		PPM_ASSIGN( *npP,
X		    ( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(p) + HALFSCALE ) / SCALE,
X		    ( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(p) + HALFSCALE ) / SCALE,
X		    ( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(p) + HALFSCALE ) / SCALE );
X		prevpixel = p;
X		}
X	    }
X	if ( fracnew0 > 0 && intnew0 + rows < newrows )
X	    {
X	    npP = &(temp2pixels[intnew0 + rows][col]);
X	    PPM_ASSIGN( *npP,
X		( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(bgpixel) + HALFSCALE ) / SCALE,
X		( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(bgpixel) + HALFSCALE ) / SCALE,
X		( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(bgpixel) + HALFSCALE ) / SCALE );
X	    }
X	}
X    ppm_freearray( temp1pixels, rows );
X
X    /* Finally, shear X from temp2 into newpixelrow. */
X    ppm_writeppminit( stdout, newcols, newrows, maxval );
X    newpixelrow = ppm_allocrow( newcols );
X    for ( row = 0; row < newrows; row++ )
X	{
X	for ( col = 0, npP = newpixelrow; col < newcols; col++, npP++ )
X	    *npP = bgpixel;
X
X	if ( fangle > 0 )
X	    new0 = row * xshearfac;
X	else
X	    new0 = ( newrows - row ) * xshearfac;
X	intnew0 = (int) new0;
X	fracnew0 = ( new0 - intnew0 ) * SCALE;
X	omfracnew0 = SCALE - fracnew0;
X	intnew0 -= x2shearjunk;
X
X	prevpixel = bgpixel;
X
X	for ( col = 0, pP = temp2pixels[row]; col < tempcols; col++, pP++ )
X	    {
X	    new = intnew0 + col;
X	    if ( new >= 0 && new < newcols )
X		{
X		npP = &(newpixelrow[new]);
X		PPM_ASSIGN( *npP,
X		    ( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(*pP) + HALFSCALE ) / SCALE,
X		    ( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(*pP) + HALFSCALE ) / SCALE,
X		    ( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(*pP) + HALFSCALE ) / SCALE );
X		prevpixel = *pP;
X		}
X	    }
X	if ( fracnew0 > 0 && intnew0 + tempcols < newcols )
X	    {
X	    npP = &(newpixelrow[intnew0 + tempcols]);
X	    PPM_ASSIGN( *npP,
X		( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(bgpixel) + HALFSCALE ) / SCALE,
X		( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(bgpixel) + HALFSCALE ) / SCALE,
X		( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(bgpixel) + HALFSCALE ) / SCALE );
X	    }
X	ppm_writeppmrow( stdout, newpixelrow, newcols, maxval );
X	}
X
X    exit( 0 );
X    }
SHAR_EOF
if test 6471 -ne "`wc -c < 'ppm/ppmrotate.c'`"
then
	echo shar: error transmitting "'ppm/ppmrotate.c'" '(should have been 6471 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmrotate.1'" '(1148 characters)'
if test -f 'ppm/ppmrotate.1'
then
	echo shar: will not over-write existing file "'ppm/ppmrotate.1'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmrotate.1'
X.TH ppmrotate 1 "15 February 1989"
X.SH NAME
Xppmrotate - rotate a portable pixmap by some angle
X.SH SYNOPSIS
Xppmrotate angle [ppmfile]
X.SH DESCRIPTION
XReads a portable pixmap as input.
XRotates it by the specified angle and produces a portable
Xpixmap as output.
XThe angle is in degrees (floating point), measured counter-clockwise.
XIt can be negative, but it should be between -90 and 90.
X.PP
XThe rotation algorithm is Alan Paeth's three-shear method.
XEach shear is implemented by looping over the source pixels and distributing
Xfractions to each of the destination pixels.
X.SH REFERENCES
X"A Fast Algorithm for General Raster Rotation" by Alan Paeth,
XGraphics Interface '86, pp. 77-81.
X.SH "SEE ALSO"
Xppmshear(1), pnmflip(1), ppm(5)
X.SH AUTHOR
XCopyright (C) 1989 by Jef Poskanzer.
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted, provided
Xthat the above copyright notice appear in all copies and that both that
Xcopyright notice and this permission notice appear in supporting
Xdocumentation.  This software is provided "as is" without express or
Ximplied warranty.
SHAR_EOF
if test 1148 -ne "`wc -c < 'ppm/ppmrotate.1'`"
then
	echo shar: error transmitting "'ppm/ppmrotate.1'" '(should have been 1148 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0



More information about the Alt.sources mailing list