allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (11/27/89)
Posting-number: Volume 9, Issue 25 Submitted-by: jef@helios.ee.lbl.gov (Jef Poskanzer) Archive-name: pbmplus/part09 #! /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/pgmtopbm.c # pgm/pgmtopbm.1 # pgm/dithers.h # pgm/tiff.h # pgm/pgmtops.c # pgm/pgmtops.1 # pgm/psidtopgm.c # pgm/psidtopgm.1 # pgm/fitstopgm.c # pgm/fitstopgm.1 # This archive created: Wed Nov 22 21:13:49 1989 # By: Jef Poskanzer (Paratheo-Anametamystikhood Of Eris Esoteric, Ada Lovelace Cabal) export PATH; PATH=/bin:$PATH if test ! -d 'pgm' then echo shar: creating directory "'pgm'" mkdir 'pgm' fi echo shar: extracting "'pgm/pgmtopbm.c'" '(7022 characters)' if test -f 'pgm/pgmtopbm.c' then echo shar: will not over-write existing file "'pgm/pgmtopbm.c'" else sed 's/^X//' << \SHAR_EOF > 'pgm/pgmtopbm.c' X/* pgmtopbm.c - read a portable graymap and write a portable bitmap 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 "pgm.h" X#include "pbm.h" X#include "dithers.h" X#ifdef SYSV X#include <string.h> X#define srandom srand X#define random rand X#else /*SYSV*/ X#include <strings.h> X#endif /*SYSV*/ X X#define max(a,b) ((a) > (b) ? (a) : (b)) X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X FILE *ifd; X register gray *grayrow, *gP; X register bit *bitrow, *bP; X int argn, rows, cols, format, row, col, limitcol; X float fthreshval; X gray maxval; X char *usage = "[-floyd|-fs | -threshold | -dither8|-d8 |\n -cluster3|-c3|-cluster4|-c4|-cluster8|-c8] [-value <val>] [pgmfile]"; X int halftone; X#define QT_FS 1 X#define QT_THRESH 2 X#define QT_DITHER8 3 X#define QT_CLUSTER3 4 X#define QT_CLUSTER4 5 X#define QT_CLUSTER8 6 X long threshval, sum, *thiserr, *nexterr, *temperr; X#define FS_SCALE 1024 X#define HALF_FS_SCALE 512 X int fs_direction; X X pm_progname = argv[0]; X X argn = 1; X halftone = QT_FS; /* default quantization is Floyd-Steinberg */ X fthreshval = 0.5; X X while ( argn < argc && argv[argn][0] == '-' ) X { X if ( strncmp(argv[argn],"-fs",max(strlen(argv[argn]),2)) == 0 || X strncmp(argv[argn],"-floyd",max(strlen(argv[argn]),2)) == 0 ) X halftone = QT_FS; X else if ( strncmp(argv[argn],"-threshold",max(strlen(argv[argn]),2)) == 0 ) X halftone = QT_THRESH; X else if ( strncmp(argv[argn],"-dither8",max(strlen(argv[argn]),2)) == 0 || X strncmp(argv[argn],"-d8",max(strlen(argv[argn]),3)) == 0 ) X halftone = QT_DITHER8; X else if ( strncmp(argv[argn],"-cluster3",max(strlen(argv[argn]),9)) == 0 || X strncmp(argv[argn],"-c3",max(strlen(argv[argn]),3)) == 0 ) X halftone = QT_CLUSTER3; X else if ( strncmp(argv[argn],"-cluster4",max(strlen(argv[argn]),9)) == 0 || X strncmp(argv[argn],"-c4",max(strlen(argv[argn]),3)) == 0 ) X halftone = QT_CLUSTER4; X else if ( strncmp(argv[argn],"-cluster8",max(strlen(argv[argn]),9)) == 0 || X strncmp(argv[argn],"-c8",max(strlen(argv[argn]),3)) == 0 ) X halftone = QT_CLUSTER8; X else if ( strncmp(argv[argn],"-value",max(strlen(argv[argn]),2)) == 0 ) X { X argn++; X if ( argn == argc || sscanf( argv[argn], "%g", &fthreshval ) != 1 || X fthreshval < 0.0 || fthreshval > 1.0 ) X pm_usage( usage ); X } X else X pm_usage( usage ); X argn++; X } 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 pgm_readpgminit( ifd, &cols, &rows, &maxval, &format ); X grayrow = pgm_allocrow( cols ); X X pbm_writepbminit( stdout, cols, rows ); X bitrow = pbm_allocrow( cols ); X X /* Initialize. */ X switch ( halftone ) X { X case QT_FS: X /* Initialize Floyd-Steinberg error vectors. */ X thiserr = (long *) pm_allocrow( cols + 2, sizeof(long) ); X nexterr = (long *) pm_allocrow( cols + 2, sizeof(long) ); X srandom( (int) time( 0 ) ); X for ( col = 0; col < cols + 2; col++ ) X thiserr[col] = ( random( ) % FS_SCALE - HALF_FS_SCALE ) / 4; X /* (random errors in [-FS_SCALE/8 .. FS_SCALE/8]) */ X fs_direction = 1; X threshval = fthreshval * FS_SCALE; X break; X X case QT_THRESH: X threshval = fthreshval * maxval; X break; X X case QT_DITHER8: X /* Scale dither matrix. */ X for ( row = 0; row < 16; row++ ) X for ( col = 0; col < 16; col++ ) X dither8[row][col] = dither8[row][col] * ( maxval + 1 ) / 256; X break; X X case QT_CLUSTER3: X /* Scale order-3 clustered dither matrix. */ X for ( row = 0; row < 6; row++ ) X for ( col = 0; col < 6; col++ ) X cluster3[row][col] = cluster3[row][col] * ( maxval + 1 ) / 18; X break; X X case QT_CLUSTER4: X /* Scale order-4 clustered dither matrix. */ X for ( row = 0; row < 8; row++ ) X for ( col = 0; col < 8; col++ ) X cluster4[row][col] = cluster4[row][col] * ( maxval + 1 ) / 32; X break; X X case QT_CLUSTER8: X /* Scale order-8 clustered dither matrix. */ X for ( row = 0; row < 16; row++ ) X for ( col = 0; col < 16; col++ ) X cluster8[row][col] = cluster8[row][col] * ( maxval + 1 ) / 128; X break; X X default: X pm_error( "can't happen", 0,0,0,0,0 ); X exit( 1 ); X } X X for ( row = 0; row < rows; row++ ) X { X pgm_readpgmrow( ifd, grayrow, cols, maxval, format ); X X switch ( halftone ) X { X case QT_FS: X for ( col = 0; col < cols + 2; col++ ) X nexterr[col] = 0; X if ( fs_direction ) X { X col = 0; X limitcol = cols; X gP = grayrow; X bP = bitrow; X } X else X { X col = cols - 1; X limitcol = -1; X gP = &(grayrow[col]); X bP = &(bitrow[col]); X } X do X { X sum = ( (long) *gP * FS_SCALE ) / maxval + thiserr[col + 1]; X if ( sum >= threshval ) X { X *bP = PBM_WHITE; X sum = sum - threshval - HALF_FS_SCALE; X } X else X *bP = PBM_BLACK; X X if ( fs_direction ) X { X thiserr[col + 2] += ( sum * 7 ) / 16; X nexterr[col ] += ( sum * 3 ) / 16; X nexterr[col + 1] += ( sum * 5 ) / 16; X nexterr[col + 2] += ( sum ) / 16; X X col++; X gP++; X bP++; X } X else X { X thiserr[col ] += ( sum * 7 ) / 16; X nexterr[col + 2] += ( sum * 3 ) / 16; X nexterr[col + 1] += ( sum * 5 ) / 16; X nexterr[col ] += ( sum ) / 16; X X col--; X gP--; X bP--; X } X } X while ( col != limitcol ); X temperr = thiserr; X thiserr = nexterr; X nexterr = temperr; X fs_direction = ! fs_direction; X break; X X case QT_THRESH: X for ( col = 0, gP = grayrow, bP = bitrow; col < cols; col++, gP++, bP++ ) X if ( *gP >= threshval ) X *bP = PBM_WHITE; X else X *bP = PBM_BLACK; X break; X X case QT_DITHER8: X for ( col = 0, gP = grayrow, bP = bitrow; col < cols; col++, gP++, bP++ ) X if ( *gP >= dither8[row % 16][col % 16] ) X *bP = PBM_WHITE; X else X *bP = PBM_BLACK; X break; X X case QT_CLUSTER3: X for ( col = 0, gP = grayrow, bP = bitrow; col < cols; col++, gP++, bP++ ) X if ( *gP >= cluster3[row % 6][col % 6] ) X *bP = PBM_WHITE; X else X *bP = PBM_BLACK; X break; X X case QT_CLUSTER4: X for ( col = 0, gP = grayrow, bP = bitrow; col < cols; col++, gP++, bP++ ) X if ( *gP >= cluster4[row % 8][col % 8] ) X *bP = PBM_WHITE; X else X *bP = PBM_BLACK; X break; X X case QT_CLUSTER8: X for ( col = 0, gP = grayrow, bP = bitrow; col < cols; col++, gP++, bP++ ) X if ( *gP >= cluster8[row % 16][col % 16] ) X *bP = PBM_WHITE; X else X *bP = PBM_BLACK; X break; X X default: X pm_error( "can't happen", 0,0,0,0,0 ); X exit( 1 ); X } X X pbm_writepbmrow( stdout, bitrow, cols ); X } X X pm_close( ifd ); X X exit( 0 ); X } SHAR_EOF if test 7022 -ne "`wc -c < 'pgm/pgmtopbm.c'`" then echo shar: error transmitting "'pgm/pgmtopbm.c'" '(should have been 7022 characters)' fi fi # end of overwriting check if test ! -d 'pgm' then echo shar: creating directory "'pgm'" mkdir 'pgm' fi echo shar: extracting "'pgm/pgmtopbm.1'" '(1883 characters)' if test -f 'pgm/pgmtopbm.1' then echo shar: will not over-write existing file "'pgm/pgmtopbm.1'" else sed 's/^X//' << \SHAR_EOF > 'pgm/pgmtopbm.1' X.TH pgmtopbm 1 "26 July 1988" X.SH NAME Xpgmtopbm - convert a portable graymap into a portable bitmap X.SH SYNOPSIS Xpgmtopbm [-floyd|-fs | -threshold | -dither8|-d8 | X -cluster3|-c3|-cluster4|-c4|-cluster8|-c8] [-value <val>] [pgmfile] X.SH DESCRIPTION XReads a portable graymap as input. XProduces a portable bitmap as output. XThe default quantization method is boustrophedonic Floyd-Steinberg error Xdiffusion (-floyd). XAlso available are simple thresholding; XBayer's ordered dither (-dither8) with a 16x16 matrix; Xthree different sizes of 45-degree clustered-dot dither X(-cluster3, -cluster4, -cluster8); X.PP XFloyd-Steinberg will almost always give the best looking results; however, Xlooking good is not always what you want. XFor instance, thresholding can be used in a pipeline with the ppmconvol Xtool, for tasks like edge and peak detection. XAnd clustered-dot dithering gives a newspaper-ish look, a useful special effect. X.PP XThe -value flag alters the thresholding value for Floyd-Steinberg and Xsimple threshholding. XIt should be a real number between 0 and 1. XAbove 0.5 means darker images; below 0.5 means lighter. X.PP XAll flags can be abbreviated to their shortest unique prefix. X.PP XNote that there is no pbmtopgm converter, because any pgm program can Xread pbm files automagically. X.SH REFERENCES XThe only reference you need for this stuff is "Digital Halftoning" by XRobert Ulichney, MIT Press, ISBN 0-262-21009-6. X.SH "SEE ALSO" Xpbmreduce(1), pgm(5), pbm(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 1883 -ne "`wc -c < 'pgm/pgmtopbm.1'`" then echo shar: error transmitting "'pgm/pgmtopbm.1'" '(should have been 1883 characters)' fi fi # end of overwriting check if test ! -d 'pgm' then echo shar: creating directory "'pgm'" mkdir 'pgm' fi echo shar: extracting "'pgm/dithers.h'" '(3499 characters)' if test -f 'pgm/dithers.h' then echo shar: will not over-write existing file "'pgm/dithers.h'" else sed 's/^X//' << \SHAR_EOF > 'pgm/dithers.h' X/* X** dithers.h X** X** Here are some dithering matrices. They are all taken from "Digital X** Halftoning" by Robert Ulichney, MIT Press, ISBN 0-262-21009-6. X*/ X X/* X** Order-6 ordered dithering matrix. Note that smaller ordered dithers X** have no advantage over larger ones, so use dither8 instead. X*/ Xstatic int dither6[8][8] = { X 1, 59, 15, 55, 2, 56, 12, 52, X 33, 17, 47, 31, 34, 18, 44, 28, X 9, 49, 5, 63, 10, 50, 6, 60, X 41, 25, 37, 21, 42, 26, 38, 22, X 3, 57, 13, 53, 0, 58, 14, 54, X 35, 19, 45, 29, 32, 16, 46, 30, X 11, 51, 7, 61, 8, 48, 4, 62, X 43, 27, 39, 23, 40, 24, 36, 20 }; X X/* Order-8 ordered dithering matrix. */ Xstatic int dither8[16][16] = { X 1,235, 59,219, 15,231, 55,215, 2,232, 56,216, 12,228, 52,212, X 129, 65,187,123,143, 79,183,119,130, 66,184,120,140, 76,180,116, X 33,193, 17,251, 47,207, 31,247, 34,194, 18,248, 44,204, 28,244, X 161, 97,145, 81,175,111,159, 95,162, 98,146, 82,172,108,156, 92, X 9,225, 49,209, 5,239, 63,223, 10,226, 50,210, 6,236, 60,220, X 137, 73,177,113,133, 69,191,127,138, 74,178,114,134, 70,188,124, X 41,201, 25,241, 37,197, 21,255, 42,202, 26,242, 38,198, 22,252, X 169,105,153, 89,165,101,149, 85,170,106,154, 90,166,102,150, 86, X 3,233, 57,217, 13,229, 53,213, 0,234, 58,218, 14,230, 54,214, X 131, 67,185,121,141, 77,181,117,128, 64,186,122,142, 78,182,118, X 35,195, 19,249, 45,205, 29,245, 32,192, 16,250, 46,206, 30,246, X 163, 99,147, 83,173,109,157, 93,160, 96,144, 80,174,110,158, 94, X 11,227, 51,211, 7,237, 61,221, 8,224, 48,208, 4,238, 62,222, X 139, 75,179,115,135, 71,189,125,136, 72,176,112,132, 68,190,126, X 43,203, 27,243, 39,199, 23,253, 40,200, 24,240, 36,196, 20,254, X 171,107,155, 91,167,103,151, 87,168,104,152, 88,164,100,148, 84 }; X X/* Order-3 clustered dithering matrix. */ Xstatic int cluster3[6][6] = { X 9,11,10, 8, 6, 7, X 12,17,16, 5, 0, 1, X 13,14,15, 4, 3, 2, X 8, 6, 7, 9,11,10, X 5, 0, 1,12,17,16, X 4, 3, 2,13,14,15 }; X X/* Order-4 clustered dithering matrix. */ Xstatic int cluster4[8][8] = { X 18,20,19,16,13,11,12,15, X 27,28,29,22, 4, 3, 2, 9, X 26,31,30,21, 5, 0, 1,10, X 23,25,24,17, 8, 6, 7,14, X 13,11,12,15,18,20,19,16, X 4, 3, 2, 9,27,28,29,22, X 5, 0, 1,10,26,31,30,21, X 8, 6, 7,14,23,25,24,17 }; X X/* Order-8 clustered dithering matrix. */ Xstatic int cluster8[16][16] = { X 64, 69, 77, 87, 86, 76, 68, 67, 63, 58, 50, 40, 41, 51, 59, 60, X 70, 94,100,109,108, 99, 93, 75, 57, 33, 27, 18, 19, 28, 34, 52, X 78,101,114,116,115,112, 98, 83, 49, 26, 13, 11, 12, 15, 29, 44, X 88,110,123,124,125,118,107, 85, 39, 17, 4, 3, 2, 9, 20, 42, X 89,111,122,127,126,117,106, 84, 38, 16, 5, 0, 1, 10, 21, 43, X 79,102,119,121,120,113, 97, 82, 48, 25, 8, 6, 7, 14, 30, 45, X 71, 95,103,104,105, 96, 92, 74, 56, 32, 24, 23, 22, 31, 35, 53, X 65, 72, 80, 90, 91, 81, 73, 66, 62, 55, 47, 37, 36, 46, 54, 61, X 63, 58, 50, 40, 41, 51, 59, 60, 64, 69, 77, 87, 86, 76, 68, 67, X 57, 33, 27, 18, 19, 28, 34, 52, 70, 94,100,109,108, 99, 93, 75, X 49, 26, 13, 11, 12, 15, 29, 44, 78,101,114,116,115,112, 98, 83, X 39, 17, 4, 3, 2, 9, 20, 42, 88,110,123,124,125,118,107, 85, X 38, 16, 5, 0, 1, 10, 21, 43, 89,111,122,127,126,117,106, 84, X 48, 25, 8, 6, 7, 14, 30, 45, 79,102,119,121,120,113, 97, 82, X 56, 32, 24, 23, 22, 31, 35, 53, 71, 95,103,104,105, 96, 92, 74, X 62, 55, 47, 37, 36, 46, 54, 61, 65, 72, 80, 90, 91, 81, 73, 66 }; SHAR_EOF if test 3499 -ne "`wc -c < 'pgm/dithers.h'`" then echo shar: error transmitting "'pgm/dithers.h'" '(should have been 3499 characters)' fi fi # end of overwriting check if test ! -d 'pgm' then echo shar: creating directory "'pgm'" mkdir 'pgm' fi echo shar: extracting "'pgm/tiff.h'" '(2762 characters)' if test -f 'pgm/tiff.h' then echo shar: will not over-write existing file "'pgm/tiff.h'" else sed 's/^X//' << \SHAR_EOF > 'pgm/tiff.h' X/* X**--------------------------------------------------------------------- X** Tiff.h X**--------------------------------------------------------------------- X** Copyright 1988 by Paul J. Emerson X** X** Permission to use, copy, modify, and distribute this software X** and its documentation for any purpose and without fee is X** hereby granted, provided that the above copyright notice X** appear in all copies and that both that copyright notice and X** this permission notice appear in supporting documentation, and X** that the name of Paul J. Emerson not be used in advertising or X** publicity pertaining to distribution of the software without X** specific, written prior permission. Paul J. Emerson makes no X** representations about the suitability of this software for X** any purpose. It is provided "as is" without express or implied X** warranty. X** X** Version 1.0 X** Paul Emerson (ucf-cs!sdgsun!paul) December 1988 X** X**--------------------------------------------------------------------- X*/ X X/* Types as defined in the TIFF standard for SUN3 */ X Xtypedef unsigned char BYTE; /* 8-bits */ Xtypedef unsigned char ASCII; /* 8-bits */ Xtypedef unsigned short SHORT; /* 16 bits */ Xtypedef unsigned int LONG; /* 32 bits */ Xtypedef unsigned long RATIONAL; /* 2 LONG's numerator : denominator X X#define INFINITY 99999 X X/* X** Data Types X*/ X X#define TYPEBYTE 1 X#define TYPEASCII 2 X#define TYPESHORT 3 X#define TYPELONG 4 X#define TYPERATIONAL 5 X Xstruct TiffHeader X { X BYTE ByteOrder[2]; X SHORT Version; X LONG IdfOffset; X }; X Xstruct IDF X { X SHORT NumEntries; X struct IDF_Entry *idfptr; X }; X Xstruct IDF_Entry X { X SHORT Tag; X SHORT Type; X LONG Length; X LONG ValueOffset; X }; X Xstruct Tiffstruct X { X int SubFileType; X int ImageWidth; X int ImageLength; X int BitsPerSample; X int Compression; X int PhotoInterp; X int Threshold; X int CellWidth; X int CellLength; X int FillOrder; X char *DocName; X char *ImageDescript; X char *Make; X char *Model; X int StOffsetCnt; X LONG *StripOffset; X int Orientation; X int SamplesPixel; X int RowsStrip; X int StripByteCnt; X LONG *SBytesCntOffset; X int MinSampleValue; X int MaxSampleValue; X int Xres; X int Yres; X int PlanarConfig; X char *PageName; X int XPos; X int YPos; X int FreeOffsets; X int FreeByteCount; X int GrayResUnit; X int GrayResCurve; X int Group3Option; X int Group4Option; X int ResolutionUnit; X int PageNumber; X int ColorResUnit; X int ColorResCurv; X }; SHAR_EOF if test 2762 -ne "`wc -c < 'pgm/tiff.h'`" then echo shar: error transmitting "'pgm/tiff.h'" '(should have been 2762 characters)' fi fi # end of overwriting check if test ! -d 'pgm' then echo shar: creating directory "'pgm'" mkdir 'pgm' fi echo shar: extracting "'pgm/pgmtops.c'" '(9439 characters)' if test -f 'pgm/pgmtops.c' then echo shar: will not over-write existing file "'pgm/pgmtops.c'" else sed 's/^X//' << \SHAR_EOF > 'pgm/pgmtops.c' X/* pgmtops.c - read a portable graymap and produce a PostScript file 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 "pgm.h" X#ifdef SYSV X#include <string.h> X#define index strchr X#else /*SYSV*/ X#include <strings.h> X#endif /*SYSV*/ X X#define max(a,b) ((a) > (b) ? (a) : (b)) X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X FILE *ifd; X register gray *grayrow, *gP; X int argn, rleflag, rows, cols, format, bps, padright, row, col; X gray maxval; X float scale; X char name[100], *cp; X int maxvaltobps(); X char *usage = "[-rle] [-scale <x>] [pgmfile]"; X X pm_progname = argv[0]; X X argn = 1; X rleflag = 0; X scale = 1.0; X X /* Check for flags. */ X while ( argn < argc && argv[argn][0] == '-' ) X { X if ( strncmp(argv[argn],"-rle",max(strlen(argv[argn]),2)) == 0 || X strncmp(argv[argn],"-runlength",max(strlen(argv[argn]),2)) == 0 ) X rleflag = 1; X else if ( strncmp(argv[argn],"-scale",max(strlen(argv[argn]),2)) == 0 ) X { X argn++; X if ( argn == argc || sscanf( argv[argn], "%f", &scale ) != 1 ) X pm_usage( usage ); X } X else X pm_usage( usage ); X argn++; X } X X if ( argn < argc ) X { X ifd = pm_openr( argv[argn] ); X strcpy( name, argv[argn] ); X if ( strcmp( name, "-" ) == 0 ) X strcpy( name, "noname" ); X X if ( ( cp = index( name, '.' ) ) != 0 ) X *cp = '\0'; X argn++; X } X else X { X ifd = stdin; X strcpy( name, "noname" ); X } X X if ( argn != argc ) X pm_usage( usage ); X X pgm_readpgminit( ifd, &cols, &rows, &maxval, &format ); X grayrow = pgm_allocrow( cols ); X X /* Figure out bps. */ X bps = maxvaltobps( maxval ); 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 if ( rleflag ) X rleputinit( name, cols, rows, bps, scale ); X else X putinit( name, cols, rows, bps, scale ); X for ( row = 0; row < rows; row++ ) X { X pgm_readpgmrow( ifd, grayrow, cols, maxval, format ); X for ( col = 0, gP = grayrow; col < cols; col++, gP++ ) X if ( rleflag ) X rleputgray( *gP ); X else X putgray( *gP ); X for ( col = 0; col < padright; col++ ) X if ( rleflag ) X rleputgray( maxval ); X else X putgray( maxval ); X } X X pm_close( ifd ); X X if ( rleflag ) X rleputrest( ); X else X putrest( ); X X exit( 0 ); X } X Xint Xmaxvaltobps( maxval ) Xgray maxval; X { X switch ( maxval ) X { X case 1: X return 1; X X case 3: X return 2; X X case 15: X return 4; X X case 255: X return 8; X X#ifdef notdef X case 7: X return 3; X X case 31: X return 5; X X case 63: X return 6; X X case 127: X return 7; X#endif /*notdef*/ X X default: X pm_error( "maxval of %d is not supported", maxval, 0,0,0,0 ); X /* NOTREACHED */ X } X } X X Xint bitspersample, item, bitsperitem, bitshift, itemsperline, items; Xint rleitem, rlebitsperitem, rlebitshift; Xint repeat, itembuf[128], count, repeatitem, repeatcount; X#define HSBUFSIZ 256 X Xputinit( name, cols, rows, bps, scale ) Xchar *name; Xint cols, rows, bps; Xfloat scale; X { X float scols, srows, llx, lly; X X scols = scale * cols * 0.96 + 0.5; /* 0.96 is the multiple of */ X srows = scale * rows * 0.96 + 0.5; /* 72/300 that is closest to 1 */ X llx = ( 612.0 - scols ) / 2; X lly = ( 792.0 - srows ) / 2; X if ( llx < 0.0 || lly < 0.0 ) X pm_message( "warning, image too large for page", 0,0,0,0,0 ); X X printf( "%%!PS-Adobe-2.0 EPSF-2.0\n" ); X printf( "%%%%Creator: pgmtops\n" ); X printf( "%%%%Title: %s.ps\n", name ); X printf( "%%%%Pages: 1\n" ); X printf( X "%%%%BoundingBox: %d %d %d %d\n", X (int) llx, (int) lly, (int) ( llx + scols ), (int) ( lly + srows ) ); X printf( "%%%%EndComments\n" ); X printf( "%%%%EndProlog\n" ); X printf( "%%%%Page 1 1\n" ); X printf( "/picstr %d string def\n", HSBUFSIZ ); X printf( "gsave\n" ); X printf( "%g %g translate\n", llx, lly ); X printf( "%g %g scale\n", scols, srows ); X printf( "%d %d %d\n", cols, rows, bps ); X printf( "[ %d 0 0 -%d 0 %d ]\n", cols, rows, rows ); X printf( "{ currentfile picstr readhexstring pop }\n" ); X printf( "image\n" ); X X bitspersample = bps; X itemsperline = items = 0; X item = 0; X bitsperitem = 0; X bitshift = 8 - bitspersample; X } X 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 Xputgray( g ) Xgray g; X { X if ( bitsperitem == 8 ) X putitem( ); X item += g << bitshift; X bitsperitem += bitspersample; X bitshift -= bitspersample; X } X Xputrest( ) X { X if ( bitsperitem > 0 ) X putitem( ); X while ( items % HSBUFSIZ != 0 ) X putitem( ); X printf( "\n" ); X printf( "grestore\n" ); X printf( "showpage\n" ); X printf( "%%%%Trailer\n" ); X } X Xrleputinit( name, cols, rows, bps, scale ) Xchar *name; Xint cols, rows, bps; Xfloat scale; X { X float scols, srows, llx, lly; X X scols = scale * cols * 0.96 + 0.5; /* 0.96 is the multiple of */ X srows = scale * rows * 0.96 + 0.5; /* 72/300 that is closest to 1 */ X llx = ( 612.0 - scols ) / 2; X lly = ( 792.0 - srows ) / 2; X if ( llx < 0.0 || lly < 0.0 ) X pm_message( "warning, image too large for page", 0,0,0,0,0 ); X X printf( "%%!PS-Adobe-2.0 EPSF-2.0\n" ); X printf( "%%%%Creator: pgmtops\n" ); X printf( "%%%%Title: %s.ps\n", name ); X printf( "%%%%Pages: 1\n" ); X printf( X "%%%%BoundingBox: %d %d %d %d\n", X (int) llx, (int) lly, (int) ( llx + scols ), (int) ( lly + srows ) ); X printf( "%%%%EndComments\n" ); X printf( "%%%%EndProlog\n" ); X printf( "/rlestr1 1 string def\n" ); X printf( "/rlestr 128 string def\n" ); X printf( "/readrlestring {\n" ); X printf( " currentfile rlestr1 readhexstring pop 0 get\n" ); X printf( " dup 127 le {\n" ); X printf( " currentfile rlestr 0 4 3 roll 1 add getinterval\n" ); X printf( " readhexstring pop\n" ); X printf( " } {\n" ); X printf( " 256 exch sub dup\n" ); X printf( " currentfile rlestr1 readhexstring pop 0 get\n" ); X printf( " exch 0 exch 1 exch 1 sub { rlestr exch 2 index put } for\n" ); X printf( " pop rlestr exch 0 exch getinterval\n" ); X printf( " } ifelse\n" ); X printf( "} bind def\n" ); X printf( "%%%%EndProlog\n" ); X printf( "%%%%Page 1 1\n" ); X printf( "gsave\n" ); X printf( "%g %g translate\n", llx, lly ); X printf( "%g %g scale\n", scols, srows ); X printf( "%d %d %d\n", cols, rows, bps ); X printf( "[ %d 0 0 -%d 0 %d ]\n", cols, rows, rows ); X printf( "{ readrlestring }\n" ); X printf( "image\n" ); X X bitspersample = bps; X itemsperline = items = 0; X rleitem = 0; X rlebitsperitem = 0; X rlebitshift = 8 - bitspersample; X repeat = 1; X count = 0; X } X Xrleputbuffer( ) X { X int i; X X if ( repeat ) X { X item = 256 - count; X putitem( ); X item = repeatitem; X putitem( ); X } X else X { X item = count - 1; X putitem( ); X for ( i = 0; i < count; i++ ) X { X item = itembuf[i]; X putitem( ); X } X } X repeat = 1; X count = 0; X } X Xrleputitem( ) X { X int i; X X if ( count == 128 ) X rleputbuffer( ); X X if ( repeat && count == 0 ) X { /* Still initializing a repeat buf. */ X itembuf[count] = repeatitem = rleitem; X count++; X } X else if ( repeat ) X { /* Repeating - watch for end of run. */ X if ( rleitem == repeatitem ) X { /* Run continues. */ X itembuf[count] = rleitem; X count++; X } X else X { /* Run ended - is it long enough to dump? */ X if ( count > 2 ) X { /* Yes, dump a repeat-mode buffer and start a new one. */ X rleputbuffer( ); X itembuf[count] = repeatitem = rleitem; X count++; X } X else X { /* Not long enough - convert to non-repeat mode. */ X repeat = 0; X itembuf[count] = repeatitem = rleitem; X count++; X repeatcount = 1; X } X } X } X else X { /* Not repeating - watch for a run worth repeating. */ X if ( rleitem == repeatitem ) X { /* Possible run continues. */ X repeatcount++; X if ( repeatcount > 3 ) X { /* Long enough - dump non-repeat part and start repeat. */ X count = count - ( repeatcount - 1 ); X rleputbuffer( ); X count = repeatcount; X for ( i = 0; i < count; i++ ) X itembuf[i] = rleitem; X } X else X { /* Not long enough yet - continue as non-repeat buf. */ X itembuf[count] = rleitem; X count++; X } X } X else X { /* Broken run. */ X itembuf[count] = repeatitem = rleitem; X count++; X repeatcount = 1; X } X } X X rleitem = 0; X rlebitsperitem = 0; X rlebitshift = 8 - bitsperitem; X } X Xrleputgray( g ) Xgray g; X { X if ( rlebitsperitem == 8 ) X { X rleputitem( ); X } X rleitem += g << rlebitshift; X rlebitsperitem += bitsperitem; X rlebitshift -= bitsperitem; X } X Xrleputrest( ) X { X if ( rlebitsperitem > 0 ) X rleputitem( ); X if ( count > 0 ) X rleputbuffer( ); X printf( "\n" ); X printf( "grestore\n" ); X printf( "showpage\n" ); X printf( "%%%%Trailer\n" ); X } SHAR_EOF if test 9439 -ne "`wc -c < 'pgm/pgmtops.c'`" then echo shar: error transmitting "'pgm/pgmtops.c'" '(should have been 9439 characters)' fi fi # end of overwriting check if test ! -d 'pgm' then echo shar: creating directory "'pgm'" mkdir 'pgm' fi echo shar: extracting "'pgm/pgmtops.1'" '(1677 characters)' if test -f 'pgm/pgmtops.1' then echo shar: will not over-write existing file "'pgm/pgmtops.1'" else sed 's/^X//' << \SHAR_EOF > 'pgm/pgmtops.1' X.TH pgmtops 1 "04 March 1989" X.SH NAME Xpgmtops - convert a portable graymap into Encapsulated PostScript X.SH SYNOPSIS Xpgmtops [-rle] [-scale <x>] [<pgmfile>] X.SH DESCRIPTION XReads a portable graymap as input. XProduces Encapsulated PostScript as output. X.PP XThe -scale flag controls the scale of the result. The default scale is 1, Xwhich results in one pgm pixel producing a 3x3 square of PostScript Xpixels. On a 300 dpi printer such as the Apple LaserWriter, this makes Xthe output look about the same size as the input would if it was displayed Xon a typical 72 dpi screen. XTo get one pgm pixel per LaserWriter pixel, use "-s 0.333333". X.PP XThe -rle flag specifies run-length compression. This may save time Xif the host-to-printer link is slow; but normally the printer's processing Xtime dominates, so -rle makes things slower. X.PP XAll flags can be abbreviated to their shortest unique prefix. X.PP XNote that there is no pstopgm Xtool - this transformation is one-way, because a pstopgm tool would Xbe a full-fledged PostScript interpreter, which is beyond the scope Xof this package. XHowever, see the psidtopgm tool. X.SH "SEE ALSO" Xpsidtopgm(1), pgm(5), ppmtops(1) X.BUGS XOne NeXT user reported that, while the EPS image did load, it also Xlocked up his machine. 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 1677 -ne "`wc -c < 'pgm/pgmtops.1'`" then echo shar: error transmitting "'pgm/pgmtops.1'" '(should have been 1677 characters)' fi fi # end of overwriting check if test ! -d 'pgm' then echo shar: creating directory "'pgm'" mkdir 'pgm' fi echo shar: extracting "'pgm/psidtopgm.c'" '(2883 characters)' if test -f 'pgm/psidtopgm.c' then echo shar: will not over-write existing file "'pgm/psidtopgm.c'" else sed 's/^X//' << \SHAR_EOF > 'pgm/psidtopgm.c' X/* psidtopgm.c - convert PostScript "image" data into 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 <stdio.h> X#include "pgm.h" X#ifdef SYSV X#include <string.h> X#else /*SYSV*/ X#include <strings.h> X#endif /*SYSV*/ X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X FILE *ifd; X register gray *grayrow, *gP; X int argn, row; X register int col, val; X int maxval; X int rows, cols, bitspersample; X char *usage = "<width> <height> <bits/sample> [imagedata]"; X X pm_progname = argv[0]; X X argn = 1; X X if ( argn + 3 > argc ) X pm_usage( usage ); X X cols = atoi( argv[argn++] ); X rows = atoi( argv[argn++] ); X bitspersample = atoi( argv[argn++] ); X if ( cols <= 0 || rows <= 0 || bitspersample <= 0 ) X pm_usage( usage ); 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 maxval = ( 1 << bitspersample ) - 1; X if ( maxval > PGM_MAXMAXVAL ) X pm_error( "bits/sample is too large - try recompiling with a larger gray type" ); X X pgm_writepgminit( stdout, cols, rows, (gray) maxval ); X grayrow = pgm_allocrow( ( cols + 7 ) / 8 * 8 ); X for ( row = 0; row < rows; row++) X { X for ( col = 0, gP = grayrow; col < cols; ) X { X val = gethexit( ifd ) << 4; X val += gethexit( ifd ); X switch ( bitspersample ) X { X case 1: X *gP++ = val >> 7; X *gP++ = ( val >> 6 ) & 0x1; X *gP++ = ( val >> 5 ) & 0x1; X *gP++ = ( val >> 4 ) & 0x1; X *gP++ = ( val >> 3 ) & 0x1; X *gP++ = ( val >> 2 ) & 0x1; X *gP++ = ( val >> 1 ) & 0x1; X *gP++ = val & 0x1; X col += 8; X break; X X case 2: X *gP++ = val >> 6; X *gP++ = ( val >> 4 ) & 0x3; X *gP++ = ( val >> 2 ) & 0x3; X *gP++ = val & 0x3; X col += 4; X break; X X case 4: X *gP++ = val >> 4; X *gP++ = val & 0xf; X col += 2; X break; X X case 8: X *gP++ = val; X col++; X break; X X default: X pm_error( X "bitspersample of %d not supported", bitspersample, X 0,0,0,0 ); X } X } X pgm_writepgmrow( stdout, grayrow, cols, (gray) maxval ); X } X pm_close( ifd ); X X exit( 0 ); X } X Xint Xgethexit( ifd ) XFILE *ifd; X { X register int i; X register char c; X X for ( ; ; ) X { X i = getc( ifd ); X if ( i == EOF ) X pm_error( "premature EOF", 0,0,0,0,0 ); X c = (char) i; X if ( c >= '0' && c <= '9' ) X return c - '0'; X else if ( c >= 'A' && c <= 'F' ) X return c - 'A' + 10; X else if ( c >= 'a' && c <= 'f' ) X return c - 'a' + 10; X /* Else ignore - whitespace. */ X } X } SHAR_EOF if test 2883 -ne "`wc -c < 'pgm/psidtopgm.c'`" then echo shar: error transmitting "'pgm/psidtopgm.c'" '(should have been 2883 characters)' fi fi # end of overwriting check if test ! -d 'pgm' then echo shar: creating directory "'pgm'" mkdir 'pgm' fi echo shar: extracting "'pgm/psidtopgm.1'" '(1419 characters)' if test -f 'pgm/psidtopgm.1' then echo shar: will not over-write existing file "'pgm/psidtopgm.1'" else sed 's/^X//' << \SHAR_EOF > 'pgm/psidtopgm.1' X.TH psidtopgm 1 "02 August 89" X.SH NAME Xpsidtopgm - convert PostScript "image" data into a portable graymap X.SH SYNOPSIS Xpsidtopgm <width> <height> <bits/sample> [imagedata] X.SH DESCRIPTION XReads the "image" data from a PostScript file as input. XProduces a portable graymap as output. X.PP XThis is a very simple and limited program, and is here only because Xso many people have asked for it. XTo use it you have to X.I manually Xextract the readhexstring data portion from your PostScript file, and then Xgive the width, height, and bits/sample on the command line. XBefore you attempt this, you should X.I at least Xread the description of the "image" operator in the PostScript Language XReference Manual. X.PP XIt would probably not be too hard to write a script that uses this filter Xto read a specific variety of PostScript image, but the variation is too Xgreat to make a general-purpose reader. XUnless, of course, you want to write a full-fledged PostScript interpreter... X.SH "SEE ALSO" Xpgmtops(1), pgm(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 1419 -ne "`wc -c < 'pgm/psidtopgm.1'`" then echo shar: error transmitting "'pgm/psidtopgm.1'" '(should have been 1419 characters)' fi fi # end of overwriting check if test ! -d 'pgm' then echo shar: creating directory "'pgm'" mkdir 'pgm' fi echo shar: extracting "'pgm/fitstopgm.c'" '(4533 characters)' if test -f 'pgm/fitstopgm.c' then echo shar: will not over-write existing file "'pgm/fitstopgm.c'" else sed 's/^X//' << \SHAR_EOF > 'pgm/fitstopgm.c' X/* fitstopgm.c - read a FITS file and produce 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 <stdio.h> X#include "pgm.h" X#ifdef SYSV X#include <string.h> X#else /*SYSV*/ X#include <strings.h> X#endif /*SYSV*/ X X#define min(a,b) ((a) < (b) ? (a) : (b)) X Xstruct FITS_Header { X int simple; /* basic format or not */ X int bitpix; /* number of bits per pixel */ X int naxis; /* number of axes */ X int naxis1; /* number of points on axis 1 */ X int naxis2; /* number of points on axis 2 */ X double datamin; /* min # */ X double datamax; /* max # */ X double bzero; /* ??? */ X double bscale; /* ??? */ X }; X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X FILE *ifd; X register gray *grayrow, *gP; X int argn, row; X register int col; X gray maxval; X double fmaxval, scale; X int rows, cols; X struct FITS_Header h; X X pm_progname = argv[0]; X X argn = 1; 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( "[fitsfile]" ); X X read_fits_header( ifd, &h ); X X if ( ! h.simple ) X pm_error( "FITS file is not in simple format, can't read", 0,0,0,0,0 ); X switch ( h.bitpix ) X { X case 8: X fmaxval = 255.0; X break; X X case 16: X fmaxval = 65535.0; X break; X X case 32: X fmaxval = 4294967295.0; X break; X X default: X pm_error( "unusual bits per pixel (%d), can't read", h.bitpix, 0,0,0,0 ); X } X if ( h.naxis != 2 ) X pm_error( "FITS file has %d axes, can't read", h.naxis, 0,0,0,0 ); X cols = h.naxis1; X rows = h.naxis2; X maxval = min( fmaxval, PGM_MAXMAXVAL ); X scale = maxval / ( h.datamax - h.datamin ); X X pgm_writepgminit( stdout, cols, rows, maxval ); X grayrow = pgm_allocrow( cols ); X for ( row = 0; row < rows; row++) X { X for ( col = 0, gP = grayrow; col < cols; col++, gP++ ) X { X int ich; X double val; X X switch ( h.bitpix ) X { X case 8: X ich = getc( ifd ); X if ( ich == EOF ) X pm_error( "premature EOF", 0,0,0,0,0 ); X val = ich; X break; X X case 16: X ich = getc( ifd ); X if ( ich == EOF ) X pm_error( "premature EOF", 0,0,0,0,0 ); X val = ich << 8; X ich = getc( ifd ); X if ( ich == EOF ) X pm_error( "premature EOF", 0,0,0,0,0 ); X val += ich; X break; X X case 32: X ich = getc( ifd ); X if ( ich == EOF ) X pm_error( "premature EOF", 0,0,0,0,0 ); X val = ich << 24; X ich = getc( ifd ); X if ( ich == EOF ) X pm_error( "premature EOF", 0,0,0,0,0 ); X val += ich << 16; X ich = getc( ifd ); X if ( ich == EOF ) X pm_error( "premature EOF", 0,0,0,0,0 ); X val += ich << 8; X ich = getc( ifd ); X if ( ich == EOF ) X pm_error( "premature EOF", 0,0,0,0,0 ); X val += ich; X break; X X default: X pm_error( "can't happen", 0,0,0,0,0 ); X } X *gP = (gray) ( scale * ( val * h.bscale + h.bzero - h.datamin) ); X } X pgm_writepgmrow( stdout, grayrow, cols, maxval ); X } X pm_close( ifd ); X X exit( 0 ); X } X Xread_fits_header( fd, hP ) XFILE *fd; Xstruct FITS_Header *hP; X { X char buf[80]; X int seen_end; X int i; X char c; X X seen_end = 0; X hP->simple = 0; X hP->bzero = 0.0; X hP->bscale = 1.0; X hP->datamin = 0.0; X hP->datamax = 1.0; X X while ( ! seen_end ) X for ( i = 0; i < 36; i++ ) X { X read_card( fd, buf ); X X if ( sscanf( buf, "SIMPLE = %c", &c ) == 1 ) X { X if ( c == 'T' || c == 't' ) X hP->simple = 1; X } X else if ( sscanf( buf, "BITPIX = %d", &(hP->bitpix) ) == 1 ); X else if ( sscanf( buf, "NAXIS = %d", &(hP->naxis) ) == 1 ); X else if ( sscanf( buf, "NAXIS1 = %d", &(hP->naxis1) ) == 1 ); X else if ( sscanf( buf, "NAXIS2 = %d", &(hP->naxis2) ) == 1 ); X else if ( sscanf( buf, "DATAMIN = %lg", &(hP->datamin) ) == 1 ); X else if ( sscanf( buf, "DATAMAX = %lg", &(hP->datamax) ) == 1 ); X else if ( sscanf( buf, "BZERO = %lg", &(hP->bzero) ) == 1 ); X else if ( sscanf( buf, "BSCALE = %lg", &(hP->bscale) ) == 1 ); X else if ( strncmp( buf, "END ", 4 ) == 0 ) seen_end = 1; X } X } X Xread_card( fd, buf ) XFILE *fd; Xchar *buf; X { X if ( fread( buf, 1, 80, fd ) == 0 ) X pm_error( "error reading header", 0,0,0,0,0 ); X } SHAR_EOF if test 4533 -ne "`wc -c < 'pgm/fitstopgm.c'`" then echo shar: error transmitting "'pgm/fitstopgm.c'" '(should have been 4533 characters)' fi fi # end of overwriting check if test ! -d 'pgm' then echo shar: creating directory "'pgm'" mkdir 'pgm' fi echo shar: extracting "'pgm/fitstopgm.1'" '(922 characters)' if test -f 'pgm/fitstopgm.1' then echo shar: will not over-write existing file "'pgm/fitstopgm.1'" else sed 's/^X//' << \SHAR_EOF > 'pgm/fitstopgm.1' X.TH fitstopgm 1 "20 September 89" X.SH NAME Xfitstopgm - convert a FITS file into a portable graymap X.SH SYNOPSIS Xfitstopgm [fitsfile] X.SH DESCRIPTION XReads a FITS file as input. XProduces a portable graymap as output. XThe results may need to be flipped top for bottom; if so, just Xpipe the output through pnmflip -tb. X.PP XFITS stands for Flexible Image Transport System. A full description Xcan be found in Astronomy & Astrophysics Supplement Series 44 (1981), Xpage 363. X.SH "SEE ALSO" Xpgmtofits(1), pgm(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 922 -ne "`wc -c < 'pgm/fitstopgm.1'`" then echo shar: error transmitting "'pgm/fitstopgm.1'" '(should have been 922 characters)' fi fi # end of overwriting check # End of shell archive exit 0