Category : UNIX Files
Archive   : PBMPLUS.ZIP
Filename : PBMPLUS.TA

 
Output of file : PBMPLUS.TA contained in archive : PBMPLUS.ZIP

pbmplus05oct91/ 755 3010 34 0 5073531647 6554 pbmplus05oct91/pbm/ 755 3010 34 0 5070750323 7321 pbmplus05oct91/pbm/pbm.5 444 3010 34 6177 5070505572 10267 .TH pbm 5 "27 September 1991"
.SH NAME
pbm - portable bitmap file format
.SH DESCRIPTION
The portable bitmap format is a lowest common denominator monochrome
file format.
.IX "PBM file format"
It was originally designed to make it reasonable to mail bitmaps
between different types of machines using the typical stupid network
mailers we have today.
Now it serves as the common language of a large family of bitmap
conversion filters.
The definition is as follows:
.IP - 2
A "magic number" for identifying the file type.
A pbm file's magic number is the two characters "P1".
.IX "magic numbers"
.IP - 2
Whitespace (blanks, TABs, CRs, LFs).
.IP - 2
A width, formatted as ASCII characters in decimal.
.IP - 2
Whitespace.
.IP - 2
A height, again in ASCII decimal.
.IP - 2
Whitespace.
.IP - 2
Width * height bits, each either '1' or '0', starting at the top-left
corner of the bitmap, proceeding in normal English reading order.
.IP - 2
The character '1' means black, '0' means white.
.IP - 2
Whitespace in the bits section is ignored.
.IP - 2
Characters from a "#" to the next end-of-line are ignored (comments).
.IP - 2
No line should be longer than 70 characters.
.PP
Here is an example of a small bitmap in this format:
.nf
P1
# feep.pbm
24 7
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0
0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0
0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0
0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
.fi
.PP
Programs that read this format should be as lenient as possible,
accepting anything that looks remotely like a bitmap.
.PP
There is also a variant on the format, available
by setting the RAWBITS option at compile time. This variant is
.IX RAWBITS
different in the following ways:
.IP - 2
The "magic number" is "P4" instead of "P1".
.IP - 2
The bits are stored eight per byte, high bit first low bit last.
.IP - 2
No whitespace is allowed in the bits section, and only a single character
of whitespace (typically a newline) is allowed after the height.
.IP - 2
The files are eight times smaller and many times faster to read and write.
.SH "SEE ALSO"
atktopbm(1), brushtopbm(1), cmuwmtopbm(1), g3topbm(1),
gemtopbm(1), icontopbm(1),
macptopbm(1), mgrtopbm(1), pi3topbm(1), xbmtopbm(1),
ybmtopbm(1),
pbmto10x(1), pnmtoascii(1), pbmtoatk(1), pbmtobbnbg(1),
pbmtocmuwm(1), pbmtoepson(1),
pbmtog3(1), pbmtogem(1), pbmtogo(1), pbmtoicon(1), pbmtolj(1),
pbmtomacp(1), pbmtomgr(1), pbmtopi3(1), pbmtoplot(1), pbmtoptx(1),
pbmtox10bm(1), pbmtoxbm(1), pbmtoybm(1),
pbmtozinc(1),
pbmlife(1), pbmmake(1), pbmmask(1), pbmreduce(1),
pbmtext(1), pbmupc(1),
pnm(5), pgm(5), ppm(5)
.SH AUTHOR
Copyright (C) 1989, 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
pbmplus05oct91/pbm/pbmtobbnbg.1 444 3010 34 2100 5022773777 11612 .TH pbmtobg 1 "16 May 1989"
.IX pbmtobbnbg
.SH NAME
pbmtobg - convert a portable bitmap into BitGraph graphics
.SH SYNOPSIS
.B pbmtobg
.RI [ rasterop ]
.RI [ x
.IR y ]
<
.I pbmfile
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces BBN BitGraph terminal Display Pixel Data (DPD) sequence as output.
.IX "BBN BitGraph"
.PP
The rasterop can be specified on the command line. If this is omitted, 3
(replace) will be used. A position in (x,y) coordinates can also be
specified. If both are given, the rasterop comes first. The portable bitmap
is always taken from the standard input.
.PP
Note that there is no bgtopbm tool.
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright 1989 by Mike Parker.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
bm.1¨ . 
pbmtogem.1 .¡ bitreverse.hms.¢macp.hf.£ pbmtolj.1
.¤ pbmmake.c.¥ pbmtocmuwm.1ip-.¦ pbmtomacp.1appl.§
pbmtomgr.1d.¨pbmupc.1 .©libpbm.h¾(.ª pbmlife.cpm.« pbmreduce.cZ•.¬mgr.h5.­
pbmto10x.ct.®
pbmtoxbm.c.¯pbmupc.c.°
xbmtopbm.c.± libpbm3.cc-.² libpbm1.cb.³ libpbm4.c
.´ pbmtoepson.1.µpbmplus05oct91/pbm/libpbm.3 444 3010 34 10473 4755037301 10765 .TH libpbm 3
.SH NAME
libpbm - functions to support portable bitmap programs
.SH SYNOPSIS
.de Ss
.sp
.ft CW
.nf
..
.de Se
.fi
.ft P
.sp
..
.Ss
#include
cc ... libpbm.a
.Se
.SH DESCRIPTION - PACKAGE-WIDE ROUTINES
.SS KEYWORD MATCHING
.Ss
int pm_keymatch( char* str, char* keyword, int minchars )
.Se
Does a case-insensitive match of
.BR str
against
.BR keyword .
.BR str
can be a leading sunstring of
.BR keyword ,
but at least
.BR minchars
must be present.
.SS LOG BASE TWO
.Ss
int pm_maxvaltobits( int maxval )
int pm_bitstomaxval( int bits )
.Se
Convert between a maxval and the minimum number of bits required
to hold it.
.SS MESSAGES AND ERRORS
.Ss
void pm_message( char* fmt, ... )
.Se
.BR printf()
style routine to write an informational message.
.Ss
void pm_error( char* fmt, ... )
.Se
.BR printf()
style routine to write an error message and abort.
.Ss
void pm_usage( char* usage )
.Se
Write a usage message.
The string should indicate what arguments are to be provided to the program.
.SS GENERIC FILE MANAGEMENT
.Ss
FILE* pm_openr( char* name )
.Se
Open the given file for reading, with appropriate error checking.
A filename of "-" is taken as equivalent to stdin.
.Ss
FILE* pm_openw( char* name )
.Se
Open the given file for writing, with appropriate error checking.
.Ss
void pm_close( FILE* fp )
.Se
Close the file descriptor, with appropriate error checking.
.SS ENDIAN I/O
.Ss
int pm_readbigshort( FILE* in, short* sP )
int pm_writebigshort( FILE* out, short s )
int pm_readbiglong( FILE* in, long* lP )
int pm_writebiglong( FILE* out, long l )
int pm_readlittleshort( FILE* in, short* sP )
int pm_writelittleshort( FILE* out, short s )
int pm_readlittlelong( FILE* in, long* lP )
int pm_writelittlelong( FILE* out, long l )
.Se
Routines to read and write short and long ints in either big- or
little-endian byte order.
.SH DESCRIPTION - PBM-SPECIFIC ROUTINES
.SS TYPES AND CONSTANTS
.Ss
typedef ... bit;
#define PBM_WHITE ...
#define PBM_BLACK ...
.Se
each
.BR bit
should contain only the values of
.BR PBM_WHITE
or
.BR PBM_BLACK .
.Ss
#define PBM_FORMAT ...
#define RPBM_FORMAT ...
#define PBM_TYPE PBM_FORMAT
#define PBM_FORMAT_TYPE(f) ...
.Se
For distinguishing different file formats and types.
.SS INITIALIZATION
.Ss
void pbm_init( int* argcP, char* argv[] )
.Se
All PBM programs must call this routine.
.SS MEMORY MANAGEMENT
.Ss
bit** pbm_allocarray( int cols, int rows )
.Se
Allocate an array of bits.
.Ss
bit* pbm_allocrow( int cols )
.Se
Allocate a row of the given number of bits.
.Ss
void pbm_freearray( bit** bits, int rows )
.Se
Free the array allocated with
.BR pbm_allocarray()
containing the given number
of rows.
.Ss
void pbm_freerow( bit* bitrow )
.Se
Free a row of bits.
.SS READING FILES
.Ss
void pbm_readpbminit( FILE* fp, int* colsP, int* rowsP, int* formatP )
.Se
Read the header from a PBM file, filling in the rows, cols and format
variables.
.Ss
void pbm_readpbmrow( FILE* fp, bit* bitrow, int cols, int format )
.Se
Read a row of bits into the bitrow array.
Format and cols were filled in by
.BR pbm_readpbminit() .
.Ss
bit** pbm_readpbm( FILE* fp, int* colsP, int* rowsP )
.Se
Read an entire bitmap file into memory, returning the allocated array and
filling in the rows and cols variables.
This function combines
.BR pbm_readpbminit() ,
.BR pbm_allocarray()
and
.BR pbm_readpbmrow() .
.SS WRITING FILES
.Ss
void pbm_writepbminit( FILE* fp, int cols, int rows, int forceplain )
.Se
Write the header for a portable bitmap file.
The forceplain flag forces a plain-format file to be written, as opposed
to a raw-format one.
.Ss
void pbm_writepbmrow( FILE* fp, bit* bitrow, int cols, int forceplain )
.Se
Write a row from a portable bitmap.
.Ss
void pbm_writepbm( FILE* fp, bit** bits, int cols, int rows, int forceplain )
.Se
Write the header and all data for a portable bitmap.
This function combines
.BR pbm_writepbminit()
and
.BR pbm_writepbmrow() .
.SH "SEE ALSO"
libpgm(3), libppm(3), libpnm(3)
.SH AUTHOR
Copyright (C) 1989, 1991 by Tony Hansen and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
pbmplus05oct91/pbm/pbmtog3.c 444 3010 34 7471 5032725022 11130 /* pbmtog3.c - read a portable bitmap and produce a Group 3 FAX file
**
** Copyright (C) 1989 by Paul Haeberli .
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "g3.h"

static void tofax ARGS(( bit* bitrow, int n ));
static void putwhitespan ARGS(( int c ));
static void putblackspan ARGS(( int c ));
static void putcode ARGS(( tableentry* te ));
static void puteol ARGS(( void ));
static void putinit ARGS(( void ));
static void putbit ARGS(( int d ));
static void flushbits ARGS(( void ));

static int reversebits;

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
int argn, rows, cols, bigcols, format, row, col, i;
char* usage = " [-reversebits] [pbmfile]";

pbm_init( &argc, argv );

argn = 1;
reversebits = 0;

if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-reversebits", 2 ) )
reversebits = 1;
else
pm_usage( usage );
++argn;
}

if ( argn == argc )
ifp = stdin;
else
{
ifp = pm_openr( argv[argn] );
++argn;
}

if ( argn != argc )
pm_usage( usage );

pbm_readpbminit( ifp, &cols, &rows, &format );
bigcols = max( 1728, cols );
bitrow = pbm_allocrow( bigcols );

/* Write out four extra rows to get things stabilized. */
putinit();
for ( col = 0; col < bigcols; ++col )
bitrow[col] = PBM_WHITE;
tofax( bitrow, bigcols );
tofax( bitrow, bigcols );
tofax( bitrow, bigcols );
tofax( bitrow, bigcols );

/* Write out bitmap. */
for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = cols; col < bigcols; ++col )
bitrow[col] = PBM_WHITE;
tofax( bitrow, cols );
}

/* And finish off. */
for( i = 0; i < 6; ++i )
puteol( );
flushbits( );

pm_close( ifp );

exit( 0 );
}

static void
tofax(bitrow,n)
bit* bitrow;
int n;
{
int c;

while(n>0) {
c = 0;
while(*bitrow == PBM_WHITE && n>0) {
++bitrow;
++c;
--n;
}
putwhitespan(c);
c = 0;
if(n==0)
break;
while(*bitrow == PBM_BLACK && n>0) {
++bitrow;
++c;
--n;
}
putblackspan(c);
}
puteol();
}

static void
putwhitespan(c)
int c;
{
int tpos;
tableentry* te;

if(c>=64) {
tpos = (c/64)-1;
te = mwtable+tpos;
c -= te->count;
putcode(te);
}
tpos = c;
te = twtable+tpos;
putcode(te);
}

static void
putblackspan(c)
int c;
{
int tpos;
tableentry* te;

if(c>=64) {
tpos = (c/64)-1;
te = mbtable+tpos;
c -= te->count;
putcode(te);
}
tpos = c;
te = tbtable+tpos;
putcode(te);
}

static void
putcode(te)
tableentry* te;
{
unsigned int mask;
int code;

mask = 1<<(te->length-1);
code = te->code;
while(mask) {
if(code&mask)
putbit(1);
else
putbit(0);
mask >>= 1;
}

}

static void
puteol()
{
int i;

for(i=0; i<11; ++i)
putbit(0);
putbit(1);
}

static int shdata;
static int shbit;

static void
putinit()
{
shdata = 0;
shbit = reversebits ? 0x01 : 0x80;
}

static void
putbit(d)
int d;
{
if(d)
shdata = shdata|shbit;
if ( reversebits )
shbit = shbit<<1;
else
shbit = shbit>>1;
if((shbit&0xff) == 0) {
putchar(shdata);
shdata = 0;
shbit = reversebits ? 0x01 : 0x80;
}
}

static void
flushbits( )
{
if ( ( reversebits && shbit != 0x01 ) ||
( ! reversebits && shbit != 0x80 ) ) {
putchar(shdata);
shdata = 0;
shbit = reversebits ? 0x01 : 0x80;
}
}
t notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** impliedpbmplus05oct91/pbm/pbmmerge.c 444 3010 34 4505 5070505625 11355 /* pbmmerge.c - wrapper program for PBM
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
register char* cp;

again:
if ( ( cp = rindex( argv[0], '/' ) ) != (char*) 0 )
++cp;
else
cp = argv[0];
if ( strcmp( cp, "pbmmerge" ) == 0 )
{
++argv;
--argc;
goto again;
}

#define TRY(s,m) { if ( strcmp( cp, s ) == 0 ) m( argc, argv ); }

TRY( "atktopbm", atktopbm_main );
TRY( "brushtopbm", brushtopbm_main );
TRY( "cmuwmtopbm", cmuwmtopbm_main );
TRY( "g3topbm", g3topbm_main );
TRY( "icontopbm", icontopbm_main );
TRY( "gemtopbm", gemtopbm_main );
TRY( "macptopbm", macptopbm_main );
TRY( "mgrtopbm", mgrtopbm_main );
TRY( "pbmlife", pbmlife_main );
TRY( "pbmmake", pbmmake_main );
TRY( "pbmmask", pbmmask_main );
TRY( "pbmreduce", pbmreduce_main );
TRY( "pbmtext", pbmtext_main );
TRY( "pbmto10x", pbmto10x_main );
TRY( "pbmtoascii", pbmtoascii_main );
TRY( "pbmtoatk", pbmtoatk_main );
TRY( "pbmtobbnbg", pbmtobbnbg_main );
TRY( "pbmtocmuwm", pbmtocmuwm_main );
TRY( "pbmtoepson", pbmtoepson_main );
TRY( "pbmtog3", pbmtog3_main );
TRY( "pbmtogem", pbmtogem_main );
TRY( "pbmtogo", pbmtogo_main );
TRY( "pbmtoicon", pbmtoicon_main );
TRY( "pbmtolj", pbmtolj_main );
TRY( "pbmtomacp", pbmtomacp_main );
TRY( "pbmtomgr", pbmtomgr_main );
TRY( "pbmtopi3", pbmtopi3_main );
TRY( "pbmtoplot", pbmtoplot_main );
TRY( "pbmtoptx", pbmtoptx_main );
TRY( "pbmtox10bm", pbmtox10bm_main );
TRY( "pbmtoxbm", pbmtoxbm_main );
TRY( "pbmtoybm", pbmtoybm_main );
TRY( "pbmtozinc", pbmtozinc_main );
TRY( "pbmupc", pbmupc_main );
TRY( "pi3topbm", pi3topbm_main );
TRY( "xbmtopbm", xbmtopbm_main );
TRY( "ybmtopbm", ybmtopbm_main );

(void) fprintf(
stderr, "pbmmerge: \"%s\" is an unknown PBM program!\n", cp );
exit( 1 );
}
>0) {
++bitrow;
++c;
--n;
}
putwhitespan(c);
c = 0;
if(n==0)
break;
while(*bitrow == PBM_BLACK && n>0) {
++bitrow;
++c;
--n;
}
putblackspan(c);
pbmplus05oct91/pbm/pbmmask.c 444 3010 34 12227 5032725005 11223 /* pbmmask.c - create a mask bitmap from a portable bitmap
**
** Copyright (C) 1989, 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

static void addflood ARGS(( int col, int row ));
static void flood ARGS(( void ));

static bit** bits;
static bit** mask;
static bit backcolor;
static int rows, cols;

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
int argn, expand, wcount;
register int row, col;
char* usage = "[-expand] [pbmfile]";

pbm_init( &argc, argv );

argn = 1;
expand = 0;

if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-expand", 2 ) )
expand = 1;
else if ( pm_keymatch( argv[argn], "-noexpand", 2 ) )
expand = 0;
else
pm_usage( usage );
++argn;
}

if ( argn == argc )
ifp = stdin;
else
{
ifp = pm_openr( argv[argn] );
++argn;
}

if ( argn != argc )
pm_usage( usage );

bits = pbm_readpbm( ifp, &cols, &rows );
pm_close( ifp );
mask = pbm_allocarray( cols, rows );

/* Clear out the mask. */
for ( row = 0; row < rows; ++row )
for ( col = 0; col < cols; ++col )
mask[row][col] = PBM_BLACK;

/* Figure out the background color, by counting along the edge. */
wcount = 0;
for ( row = 0; row < rows; ++row )
{
if ( bits[row][0] == PBM_WHITE )
++wcount;
if ( bits[row][cols - 1] == PBM_WHITE )
++wcount;
}
for ( col = 1; col < cols - 1; ++col )
{
if ( bits[0][col] == PBM_WHITE )
++wcount;
if ( bits[rows - 1][col] == PBM_WHITE )
++wcount;
}
if ( wcount >= rows + cols - 2 )
backcolor = PBM_WHITE;
else
backcolor = PBM_BLACK;

/* Flood the entire edge. Probably the first call will be enough, but
** might as well be sure. */
for ( col = cols - 3; col >= 2; col -= 2 )
{
addflood( col, rows - 1 );
addflood( col, 0 );
}
for ( row = rows - 1; row >= 0; row -= 2 )
{
addflood( cols - 1, row );
addflood( 0, row );
}
flood( );

if ( ! expand )
/* Done. */
pbm_writepbm( stdout, mask, cols, rows, 0 );
else
{ /* Expand by one pixel. */
register int srow, scol;
bit** emask;

emask = pbm_allocarray( cols, rows );

for ( row = 0; row < rows; ++row )
for ( col = 0; col < cols; ++col )
if ( mask[row][col] == PBM_BLACK )
emask[row][col] = PBM_BLACK;
else
{
emask[row][col] = PBM_WHITE;
for ( srow = row - 1; srow <= row + 1; ++srow )
for ( scol = col - 1; scol <= col + 1; ++scol )
if ( srow >= 0 && srow < rows &&
scol >= 0 && scol < cols &&
mask[srow][scol] == PBM_BLACK )
{
emask[row][col] = PBM_BLACK;
break;
}
}

/* Done. */
pbm_writepbm( stdout, emask, cols, rows, 0 );
}

exit( 0 );
}

static short* fcols;
static short* frows;
static int fstacksize = 0, fstackp = 0;

static void
addflood( col, row )
int col, row;
{
if ( bits[row][col] == backcolor && mask[row][col] == PBM_BLACK )
{
if ( fstackp >= fstacksize )
{
if ( fstacksize == 0 )
{
fstacksize = 1000;
fcols = (short*) malloc( fstacksize * sizeof(short) );
frows = (short*) malloc( fstacksize * sizeof(short) );
if ( fcols == (short*) 0 || frows == (short*) 0 )
pm_error( "out of memory" );
}
else
{
fstacksize *= 2;
fcols = (short*) realloc(
(char*) fcols, fstacksize * sizeof(short) );
frows = (short*) realloc(
(char*) frows, fstacksize * sizeof(short) );
if ( fcols == (short*) 0 || frows == (short*) 0 )
pm_error( "out of memory" );
}
}
fcols[fstackp] = col;
frows[fstackp] = row;
++fstackp;
}
}

static void
flood( )
{
register int col, row, c;

while ( fstackp > 0 )
{
--fstackp;
col = fcols[fstackp];
row = frows[fstackp];
if ( bits[row][col] == backcolor && mask[row][col] == PBM_BLACK )
{
mask[row][col] = PBM_WHITE;
if ( row - 1 >= 0 )
addflood( col, row - 1 );
if ( row + 1 < rows )
addflood( col, row + 1 );
for ( c = col + 1; c < cols; ++c )
{
if ( bits[row][c] == backcolor && mask[row][c] == PBM_BLACK )
{
mask[row][c] = PBM_WHITE;
if ( row - 1 >= 0 && ( bits[row - 1][c - 1] != backcolor || mask[row - 1][c - 1] != PBM_BLACK ) )
addflood( c, row - 1 );
if ( row + 1 < rows && ( bits[row + 1][c - 1] != backcolor || mask[row + 1][c - 1] != PBM_BLACK ) )
addflood( c, row + 1 );
}
else
break;
}
for ( c = col - 1; c >= 0; --c )
{
if ( bits[row][c] == backcolor && mask[row][c] == PBM_BLACK )
{
mask[row][c] = PBM_WHITE;
if ( row - 1 >= 0 && ( bits[row - 1][c + 1] != backcolor || mask[row - 1][c + 1] != PBM_BLACK ) )
addflood( c, row - 1 );
if ( row + 1 < rows && ( bits[row + 1][c + 1] != backcolor || mask[row + 1][c + 1] != PBM_BLACK ) )
addflood( c, row + 1 );
}
else
break;
}
}
}
}
}

if ( argn == argc )
ifp = stdin;
else
{
ifp = pm_openr( argv[argn] );
++argn;
}

if ( argn != argc )
pm_usage( usage );

bits = pbm_readpbm( ifp, &cols, &rows );
pm_close( ifp );
mask = pbm_allocarray( cols, rows );

/* Clear out the mask. */
for ( row = 0; row < rows; ++row )
for ( col = 0; col < cols; ++col pbmplus05oct91/pbm/gemtopbm.c 444 3010 34 13473 5032726457 11423 /*
* Convert a GEM .img file to a portable bitmap file.
*
* Author: Diomidis D. Spinellis
* (C) Copyright 1988 Diomidis D. Spinellis.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* This file is provided AS IS with no warranties of any kind. The author
* shall have no liability with respect to the infringement of copyrights,
* trade secrets or any patents by this file or any part thereof. In no
* event will the author be liable for any lost revenue or profits or
* other special, indirect and consequential damages.
*
* Comments and additions should be sent to the author:
*
* Diomidis D. Spinellis
* 1 Myrsinis Str.
* GR-145 62 Kifissia
* GREECE
*
*/

#include
#include "pbm.h"

/*
* Handle systems that do CR-LF translation on reading / writing and
* little endians (some guesswork is involved).
*/
#ifdef MSDOS
#define LITTLE_ENDIAN
#endif /*MSDOS*/
#ifdef xenix
#define LITTLE_ENDIAN
#endif /*xenix*/
#ifdef sun386
#define LITTLE_ENDIAN
#endif /*sun386*/
#ifdef vax
#define LITTLE_ENDIAN
#endif /*vax*/


/* Seek from current position */
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif /*SEEK_CUR*/

/*
* File header structure
*/
struct header {
short version;/* Image file version */
unsigned short hlen; /* Header length in bytes */
unsigned short planes; /* Number of planes */
unsigned short patlen; /* Pattern definition length (bytes) */
unsigned short pxlen; /* Pixel height (microns) */
unsigned short pxht; /* Pixel height (microns) */
unsigned short linewid;/* Scan line width (bytes) */
unsigned short nitems; /* Number of scan line items */
};

/*
* Scan item header
*/
struct line {
char d1, d2; /* Should be 0 */
char d3; /* Should be 0xff */
char count; /* Repetition count */
};

char pattern[256];


#ifdef LITTLE_ENDIAN
static void byteswap ARGS(( unsigned short* data, int n ));
#endif /*LITTLE_ENDIAN*/

void
main(argc, argv)
int argc;
char *argv[];
{
int debug = 0;
FILE *f;
struct header hd;
int x;
int i, j, k, l;
int c, cc, linerep;
int rows, cols;
bit *bitrow;

pbm_init( &argc, argv );

/* Check if the compiler alligns structures the way we want */
if ( sizeof( struct header ) != 16 )
pm_error( "sizeof( struct header ) != 16 ???" );

if (argc > 1 && !strcmp(argv[1], "-d")) {
argc--;
argv[1] = argv[0];
++argv;
++debug;
}

if (argc != 2)
pm_usage("[-d] ");

f = pm_openr( argv[1] );

if (fread(&hd, sizeof hd, 1, f) != 1)
pm_perror( "read" );

#ifdef LITTLE_ENDIAN
byteswap((unsigned short *) &hd, sizeof hd / 2);
#endif /*LITTLE_ENDIAN*/

for ( i = sizeof(struct header); i < hd.hlen; ++i )
(void) getc(f);

if (debug) {
pm_message(
"version %d, hlen %d, planes %d, patlen %d",
hd.version, hd.hlen, hd.planes, hd.patlen, 0);
pm_message(
"pxlen %d, pxht %d, linewid %d, nitems %d",
hd.pxlen, hd.pxht, hd.linewid, hd.nitems, 0);
}

cols = hd.linewid % 8 == 0 ? hd.linewid : hd.linewid + 8 - hd.linewid % 8;
rows = hd.nitems;
pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

for (i = 0; i < hd.nitems; ) {
x = 0;
linerep = 0;
while (x < hd.linewid) {
switch (c = getc(f)) {
case 0x80: /* Bit String */
c = getc(f); /* Byte count */
if (debug)
pm_message(
"bit string of %d bytes",
c );
for (j = 0; j < c; ++j) {
cc = getc(f);
for (k = 0x80; k; k >>= 1) {
bitrow[x] = (k & cc) ? PBM_BLACK : PBM_WHITE;
++x;
}
}
break;
case 0: /* Pattern run */
c = getc(f); /* Repeat count */
if (debug)
pm_message(
"pattern run of %d repetitions",
c );
/* line repeat */
if (c == 0) {
c = getc(f);
if (c != 0x00ff)
pm_error( "badly formed line repeat" );
linerep = getc(f);
break;
}
fread(pattern, 1, hd.patlen, f);
for (j = 0; j < c; ++j)
for (l = 0; l < hd.patlen; ++l)
for (k = 0x80; k; k >>= 1) {
bitrow[x] = (k & pattern[l]) ? PBM_BLACK : PBM_WHITE;
++x;
}
break;

default: /* Solid run */
if (debug)
pm_message(
"solid run of %d bytes %s",
c & 0x7f,
c & 0x80 ? "on" : "off" );
/* each byte had eight bits DSB */
l = (c & 0x80) ? PBM_BLACK : PBM_WHITE;
c = (c & 0x7f) * 8;
for (j = 0; j < c; ++j) {
bitrow[x] = l;
++x;
}
break;

case EOF: /* End of file */
pm_error( "end of file reached" );

}
}
if ( debug )
pm_message( "EOL" );
if ( x != hd.linewid )
pm_error( "EOL beyond edge" );
do {
pbm_writepbmrow( stdout, bitrow, cols, 0 );
++i;
} while (linerep--);
}
pm_close( f );
exit(0);
}

#ifdef LITTLE_ENDIAN
static void
byteswap(data, n)
unsigned short* data;
int n;
{
register i;
char *p, c;

for (i = 0, p = (char *) data; i < n; ++i, ++p) {
c = *p;
*p = *(p + 1);
*++p = c;
}
}
#endif /*LITTLE_ENDIAN*/
pbmplus05oct91/pbm/gemtopbm.1 444 3010 34 1522 5022773133 11301 .TH gemtopbm 1 "3 December 1988"
.IX gemtopbm
.SH NAME
gemtopbm - convert a GEM .img file into a portable bitmap
.SH SYNOPSIS
.B gemtopbm
.RB [ -d ]
.I gemfile
.SH DESCRIPTION
Reads a GEM .img file as input.
.IX GEM
Produces a portable bitmap as output.
.SH OPTIONS
.TP
.B -d
Produce output describing the contents of the .img file.
.SH BUGS
Does not support file containing more than one plane.
Can't read from standard input.
.SH "SEE ALSO"
pbmtogem(1), pbm(5)
.SH AUTHOR
Copyright (C) 1988 Diomidis D. Spinellis ([email protected]).
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted,
.\" provided that the above copyright notice appear in all copies and that
.\" both that copyright notice and this permission notice appear in
.\" supporting documentation.
.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmmask.1 444 3010 34 4406 5022773476 11137 .TH pbmmask 1 "08 August 1989"
.IX pbmmask
.SH NAME
pbmmask - create a mask bitmap from a regular bitmap
.SH SYNOPSIS
.B pbmmask
.RB [ -expand ]
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Creates a corresponding mask bitmap and writes it out.
.PP
The color to be interpreted as "background" is determined automatically.
Regardless of which color is background, the mask will be white where
the background is and black where the figure is.
.PP
This lets you do a masked paste like this, for objects with a black background:
.nf
pbmmask obj > objmask
pnmpaste < dest -and objmask | pnmpaste -or obj
.fi
.IX pnmpaste
For objects with a white background, you can either invert them or
add a step:
.nf
pbmmask obj > objmask
pnminvert objmask | pnmpaste -and obj 0 0 > blackback
pnmpaste < dest -and objmask | pnmpaste -or blackback
.fi
.IX pnminvert
Note that this three-step version works for objects with black backgrounds
too, if you don't care about the wasted time.
.PP
You can also use masks with graymaps and pixmaps, using the
.I pnmarith
tool. For instance:
.nf
ppmtopgm obj.ppm | pgmtopbm -threshold | pbmmask > objmask.pbm
pnmarith -multiply dest.ppm objmask.pbm > t1.ppm
pnminvert objmask.pbm | pnmarith -multiply obj.ppm - > t2.ppm
pnmarith -add t1.ppm t2.ppm
.fi
.IX pnmarith
An interesting variation on this is to pipe the mask through the
.I pnmsmooth
.IX pnmsmooth
script before using it. This makes the boundary between the two images less
sharp.
.OPTIONS
.TP
.B -expand
Expands the mask by one pixel out from the image.
This is useful if you want a little white border around your image.
(A better solution might be to turn the
.I pbmlife
tool into a general cellular automaton tool...)
.SH "SEE ALSO"
pnmpaste(1), pnminvert(1), pbm(5), pnmarith(1), pnmsmooth(1)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
int argc;
char *argv[];
{
int debug = 0;
FILE *f;
struct header hd;
int x;
int i, j, k, l;
int c, cc, linerep;
int rows, cols;
bit *bitrow;

pbm_init( &argpbmplus05oct91/pbm/brushtopbm.c 444 3010 34 4500 5032724762 11742 /* brushtopbm.c - read a doodle brush file and write a portable bitmap
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

static void getinit ARGS(( FILE* file, int* colsP, int* rowsP ));
static bit getbit ARGS(( FILE* file ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, padright, row, col;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[brushfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

getinit( ifp, &cols, &rows );

pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

/* Compute padding to round cols up to the next multiple of 16. */
padright = ( ( cols + 15 ) / 16 ) * 16 - cols;

for ( row = 0; row < rows; ++row )
{
/* Get data. */
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
*bP = getbit( ifp );
/* Discard line padding. */
for ( col = 0; col < padright; ++col )
(void) getbit( ifp );
/* Write row. */
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}

pm_close( ifp );

exit( 0 );
}


static int item, bitsperitem, bitshift;

static void
getinit( file, colsP, rowsP )
FILE* file;
int* colsP;
int* rowsP;
{
int i;

if ( getc( file ) != 1 )
pm_error( "bad magic number 1" );
if ( getc( file ) != 0 )
pm_error( "bad magic number 2" );
*colsP = getc( file ) << 8;
*colsP += getc( file );
*rowsP = getc( file ) << 8;
*rowsP += getc( file );
bitsperitem = 8;

/* Junk rest of header. */
for ( i = 0; i < 10; ++i ) /* 10 is just a guess at the header size */
(void) getc( file );
}

static bit
getbit( file )
FILE* file;
{
bit b;

if ( bitsperitem == 8 )
{
item = getc( file );
bitsperitem = 0;
bitshift = 7;
}
++bitsperitem;
b = ( ( item >> bitshift) & 1 ) ? PBM_WHITE : PBM_BLACK;
--bitshift;
return b;
}
debug = 0;
FILE *f;
struct header hd;
int x;
int i, j, k, l;
int c, cc, linerep;
int rows, cols;
bit *bitrow;

pbm_init( &argpbmplus05oct91/pbm/cmuwmtopbm.c 444 3010 34 5153 5032726454 11754 /* cmuwmtopbm.c - read a CMU window manager bitmap and produce a portable bitmap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "cmuwm.h"

static void getinit ARGS(( FILE* file, int* colsP, int* rowsP, short* depthP, int* padrightP ));
static bit getbit ARGS(( FILE* file ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, padright, row, col;
short depth;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[cmuwmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

getinit( ifp, &cols, &rows, &depth, &padright );
if ( depth != 1 )
pm_error(
"CMU window manager file has depth of %d, must be 1",
(int) depth );

pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

for ( row = 0; row < rows; ++row )
{
/* Get data. */
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
*bP = getbit( ifp );
/* Discard line padding */
for ( col = 0; col < padright; ++col )
(void) getbit( ifp );
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}

pm_close( ifp );

exit( 0 );
}

static int item, bitsperitem, bitshift;

static void
getinit( file, colsP, rowsP, depthP, padrightP )
FILE* file;
int* colsP;
int* rowsP;
short* depthP;
int* padrightP;
{
long l;

if ( pm_readbiglong( file, &l ) == -1 )
pm_error( "EOF / read error" );
if ( l != CMUWM_MAGIC )
pm_error( "bad magic number in CMU window manager file" );
if ( pm_readbiglong( file, &l ) == -1 )
pm_error( "EOF / read error" );
*colsP = (int) l;
if ( pm_readbiglong( file, &l ) == -1 )
pm_error( "EOF / read error" );
*rowsP = (int) l;
if ( pm_readbigshort( file, depthP ) == -1 )
pm_error( "EOF / read error" );
*padrightP = ( ( *colsP + 7 ) / 8 ) * 8 - *colsP;

bitsperitem = 0;
}

static bit
getbit( file )
FILE* file;
{
bit b;

if ( bitsperitem == 0 )
{
item = getc( file );
if ( item == EOF )
pm_error( "EOF / read error" );
bitsperitem = 8;
bitshift = 7;
}
b = ( ( item >> bitshift) & 1 ) ? PBM_WHITE : PBM_BLACK;
--bitsperitem;
--bitshift;
return b;
}
= 16 )
pm_error( "sizeof( struct header ) != 16 ???" );

if (argc > 1 && !strcmp(argv[1], "-d")) {
argc--;
argv[1] = argv[0];
++argv;
++debug;
}

if (argc != 2)
pm_usage("[-d] ");

f = pm_openr( argv[1] );

if (fread(&hd, sizeof hd, 1, f) != 1)
pm_perror( "read" );

#ifdef LITTLE_ENDIAN
byteswap((unsigned short *) &hd, sizeof hd / 2);
#endif /*LITTLE_ENDIAN*/

for ( i = sipbmplus05oct91/pbm/brushtopbm.1 444 3010 34 1452 5022773004 11653 .TH brushtopbm 1 "28 August 1988"
.IX brushtopbm
.SH NAME
brushtopbm - convert a doodle brush file into a portable bitmap
.SH SYNOPSIS
.B brushtopbm
.RI [ brushfile ]
.SH DESCRIPTION
Reads a Xerox doodle brush file as input.
.IX "Xerox doodle brush format"
Produces a portable bitmap as output.
.PP
Note that there is currently no pbmtobrush tool.
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
p.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/Imakefile 444 3010 34 4465 5070733135 11230 # Imakefile for pbm tools.
#
# Copyright (C) 1989, 1991 by Jef Poskanzer.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted, provided
# that the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation. This software is provided "as is" without express or
# implied warranty.

RGBDEF = -DRGB_DB=\"DefaultRGBDatabase\"
TIFFDEF = -DLIBTIFF
INCLUDE = -I..
ALLCFLAGS = $(CFLAGS) $(RGBDEF) $(TIFFDEF) $(INCLUDE)
LIBPBM = libpbm.a

BINARIES = atktopbm brushtopbm cmuwmtopbm g3topbm \
icontopbm gemtopbm macptopbm mgrtopbm \
pbmlife pbmmake pbmmask pbmreduce \
pbmtext pbmto10x pbmtoascii pbmtoatk \
pbmtobbnbg pbmtocmuwm pbmtoepson pbmtog3 \
pbmtogem pbmtogo pbmtoicon pbmtolj pbmtomacp \
pbmtomgr pbmtopi3 pbmtoplot pbmtoptx \
pbmtox10bm pbmtoxbm pbmtoybm pbmtozinc \
pbmupc pi3topbm xbmtopbm \
ybmtopbm

MANUALS1 = atktopbm.1 brushtopbm.1 cmuwmtopbm.1 g3topbm.1 \
icontopbm.1 gemtopbm.1 macptopbm.1 mgrtopbm.1 \
pbmlife.1 pbmmake.1 pbmmask.1 pbmreduce.1 \
pbmtext.1 pbmto10x.1 pbmtoascii.1 pbmtoatk.1 \
pbmtobbnbg.1 pbmtocmuwm.1 pbmtoepson.1 pbmtog3.1 \
pbmtogem.1 pbmtogo.1 pbmtoicon.1 pbmtolj.1 pbmtomacp.1 \
pbmtomgr.1 pbmtopi3.1 pbmtoplot.1 pbmtoptx.1 \
pbmtox10bm.1 pbmtoxbm.1 pbmtoybm.1 pbmtozinc.1 \
pbmupc.1 pi3topbm.1 xbmtopbm.1 \
ybmtopbm.1
MANUALS3 = libpbm.3
MANUALS5 = pbm.5

all: $(BINARIES)

install:: all
cp $(BINARIES) $(BINDIR)

install.man::
cp $(MANUALS1) $(MANUALS3) $(MANUALS5) $(MANDIR)

# Rule for plain programs.
$(BINARIES): pbm.h ../pbmplus.h $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] $(LIBPBM)

# And library.
$(LIBPBM): libpbm1.o libpbm2.o libpbm3.o libpbm4.o libpbm5.o
-rm $(LIBPBM)
$(AR) $(LIBPBM) libpbm1.o libpbm2.o libpbm3.o libpbm4.o libpbm5.o
-$(RANLIB) $(LIBPBM)

libpbm1.o: pbm.h ../pbmplus.h libpbm.h libpbm1.c
$(CC) $(ALLCFLAGS) -c libpbm1.c
libpbm2.o: pbm.h ../pbmplus.h libpbm.h libpbm2.c
$(CC) $(ALLCFLAGS) -c libpbm2.c
libpbm3.o: pbm.h ../pbmplus.h libpbm.h libpbm3.c
$(CC) $(ALLCFLAGS) -c libpbm3.c
libpbm4.o: pbm.h ../pbmplus.h libpbm.h libpbm4.c
$(CC) $(ALLCFLAGS) -c libpbm4.c
libpbm5.o: pbm.h ../pbmplus.h pbmfont.h libpbm5.c
$(CC) $(ALLCFLAGS) -c libpbm5.c

DependTarget()
etbit( file )
FILE* file;
{
bit b;

if ( bitsperitem == 0 )
{
item = getc( file );
if ( item == EOF )
pm_error( "EOF / read error" );
bitsperitem = 8;
bitshift = 7;
}
b = (pbmplus05oct91/pbm/g3topbm.c 444 3010 34 14610 5032727543 11153 /* g3topbm.c - read a Group 3 FAX file and produce a portable bitmap
**
** Copyright (C) 1989 by Paul Haeberli .
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "g3.h"

#define TABSIZE(tab) (sizeof(tab)/sizeof(struct tableentry))
#define MAXCOLS 1728
#define MAXROWS 4300 /* up to two pages long */

static int endoffile = 0;
static int eols;
static int rawzeros;
static int shdata;
static int kludge;
static int reversebits;
static int stretch;

#define WHASHA 3510
#define WHASHB 1178

#define BHASHA 293
#define BHASHB 2695

#define HASHSIZE 1021
static tableentry* whash[HASHSIZE];
static tableentry* bhash[HASHSIZE];

static void addtohash ARGS(( tableentry* hash[], tableentry* te, int n, int a, int b ));
static tableentry* hashfind ARGS(( tableentry* hash[], int length, int code, int a, int b ));
static int getfaxrow ARGS(( FILE* inf, int row, bit* bitrow ));
static void skiptoeol ARGS(( FILE* file ));
static int rawgetbit ARGS(( FILE* file ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
int argn, rows, cols, row, col, i;
bit* bits[MAXROWS];
char* usage = "[-kludge][-reversebits][-stretch] [g3file]";

pbm_init( &argc, argv );

argn = 1;
kludge = 0;
reversebits = 0;
stretch = 0;

/* Check for flags. */
while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-kludge", 2 ) )
kludge = 1;
else if ( pm_keymatch( argv[argn], "-reversebits", 2 ) )
reversebits = 1;
else if ( pm_keymatch( argv[argn], "-stretch", 2 ) )
stretch = 1;
else
pm_usage( usage );
argn++;
}

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
argn++;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

eols = 0;

if ( kludge )
{
/* Skip extra lines to get in sync. */
skiptoeol( ifp );
skiptoeol( ifp );
skiptoeol( ifp );
}
skiptoeol( ifp );
for ( i = 0; i < HASHSIZE; ++i )
whash[i] = bhash[i] = (tableentry*) 0;
addtohash( whash, twtable, TABSIZE(twtable), WHASHA, WHASHB );
addtohash( whash, mwtable, TABSIZE(mwtable), WHASHA, WHASHB );
addtohash( whash, extable, TABSIZE(extable), WHASHA, WHASHB );
addtohash( bhash, tbtable, TABSIZE(tbtable), BHASHA, BHASHB );
addtohash( bhash, mbtable, TABSIZE(mbtable), BHASHA, BHASHB );
addtohash( bhash, extable, TABSIZE(extable), BHASHA, BHASHB );

cols = 0;
for ( rows = 0; rows < MAXROWS; ++rows )
{
bits[rows] = pbm_allocrow( MAXCOLS );
col = getfaxrow( ifp, rows, bits[rows] );
if ( endoffile )
break;
if ( col > cols )
cols = col;
if ( stretch )
{
bits[rows + 1] = bits[rows];
++rows;
}
}

pm_close( ifp );

pbm_writepbminit( stdout, cols, rows, 0 );
for ( row = 0; row < rows; ++row )
pbm_writepbmrow( stdout, bits[row], cols, 0 );

exit(0);
}

static void
addtohash(hash, te, n, a, b)
tableentry* hash[];
tableentry* te;
int n, a, b;
{
unsigned int pos;

while (n--) {
pos = ((te->length+a)*(te->code+b))%HASHSIZE;
if (hash[pos] != 0)
pm_error( "internal error: addtohash fatal hash collision" );
hash[pos] = te;
te++;
}
}

static tableentry*
hashfind(hash, length, code, a, b)
tableentry* hash[];
int length, code;
int a, b;
{
unsigned int pos;
tableentry* te;

pos = ((length+a)*(code+b))%HASHSIZE;
if (pos < 0 || pos >= HASHSIZE)
pm_error(
"internal error: bad hash position, length %d code %d pos %d",
length, code, pos );
te = hash[pos];
return ((te && te->length == length && te->code == code) ? te : 0);
}

static int
getfaxrow( inf, row, bitrow )
FILE* inf;
int row;
bit* bitrow;
{
int col;
bit* bP;
int curlen, curcode, nextbit;
int count, color;
tableentry* te;

for ( col = 0, bP = bitrow; col < MAXCOLS; ++col, ++bP )
*bP = PBM_WHITE;
col = 0;
rawzeros = 0;
curlen = 0;
curcode = 0;
color = 1;
count = 0;
while (!endoffile) {
if (col >= MAXCOLS) {
skiptoeol(inf);
return (col);
}
do {
if (rawzeros >= 11) {
nextbit = rawgetbit(inf);
if (nextbit) {
if (col == 0)
/* XXX should be 6 */
endoffile = (++eols == 3);
else
eols = 0;
#ifdef notdef
if (col && col < 1728)
pm_message(
"warning, row %d short (len %d)",
row, col );
#endif /*notdef*/
return (col);
}
} else
nextbit = rawgetbit(inf);
curcode = (curcode<<1) + nextbit;
curlen++;
} while (curcode <= 0);
if (curlen > 13) {
pm_message(
"bad code word at row %d, col %d (len %d code 0x%x), skipping to EOL",
row, col, curlen, curcode, 0 );
skiptoeol(inf);
return (col);
}
if (color) {
if (curlen < 4)
continue;
te = hashfind(whash, curlen, curcode, WHASHA, WHASHB);
} else {
if (curlen < 2)
continue;
te = hashfind(bhash, curlen, curcode, BHASHA, BHASHB);
}
if (!te)
continue;
switch (te->tabid) {
case TWTABLE:
case TBTABLE:
count += te->count;
if (col+count > MAXCOLS)
count = MAXCOLS-col;
if (count > 0) {
if (color) {
col += count;
count = 0;
} else {
for ( ; count > 0; --count, ++col )
bitrow[col] = PBM_BLACK;
}
}
curcode = 0;
curlen = 0;
color = !color;
break;
case MWTABLE:
case MBTABLE:
count += te->count;
curcode = 0;
curlen = 0;
break;
case EXTABLE:
count += te->count;
curcode = 0;
curlen = 0;
break;
default:
pm_error( "internal bad poop" );
}
}
return (0);
}

static void
skiptoeol( file )
FILE* file;
{
while ( rawzeros < 11 )
(void) rawgetbit( file );
for ( ; ; )
{
if ( rawgetbit( file ) )
break;
}
}

static int shbit = 0;

static int
rawgetbit( file )
FILE* file;
{
int b;

if ( ( shbit & 0xff ) == 0 )
{
shdata = getc( file );
if ( shdata == EOF )
pm_error( "EOF / read error at line %d", eols );
shbit = reversebits ? 0x01 : 0x80;
}
if ( shdata & shbit )
{
rawzeros = 0;
b = 1;
}
else
{
rawzeros++;
b = 0;
}
if ( reversebits )
shbit <<= 1;
else
shbit >>= 1;
return b;
}
pbmplus05oct91/pbm/pbmtobbnbg.c 444 3010 34 5604 5032725016 11670 /* pbmtobg.c - read a portable bitmap and produce BitGraph graphics
**
** Copyright 1989 by Mike Parker.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

/*
** Changed to take advantage of negative Packed Pixed Data values and
** supply ANSI-standard string terminator. Paul Milazzo, 28 May 1990.
*/

#include "pbm.h"

static void write16 ARGS(( unsigned int ));

static int nco;

void
main(argc,argv)
int argc;
char **argv;
{
int rows;
int cols;
int format;
bit *bitrow;
int row;
unsigned int sixteen;
int i;
unsigned int mask;
int op;
int x;
int y;

pbm_init( &argc, argv );

op = 3;
switch (argc)
{ case 1:
break;
case 2:
op = atoi(argv[1]);
break;
case 3:
x = atoi(argv[1]);
y = atoi(argv[2]);
printf("\33:%d;%dm",x,y);
break;
case 4:
op = atoi(argv[1]);
x = atoi(argv[2]);
y = atoi(argv[3]);
printf("\33:%d;%dm",x,y);
break;
}
nco = 0;
pbm_readpbminit(stdin,&cols,&rows,&format);
printf("\33P:%d;%d;%ds\n",op,cols,rows);
bitrow = pbm_allocrow(cols);
for (row=0;row { pbm_readpbmrow(stdin,bitrow,cols,format);
sixteen = 0;
mask = 0x8000;
for (i=0;i { if (bitrow[i]==PBM_BLACK) sixteen |= mask;
mask >>= 1;
if (mask == 0)
{ mask = 0x8000;
write16(sixteen);
sixteen = 0;
}
}
if (mask != 0x8000)
{ write16(sixteen);
}
}
puts("\033\\");
exit(0);
}

#ifdef POSITIVE_VALUES_ONLY
static void
write16(sixteen)
unsigned int sixteen;
{
if (nco > 75)
{ putchar('\n');
nco = 0;
}
if (sixteen & 0xfc00)
{ putchar(0100+(sixteen>>10));
nco ++;
}
if (sixteen & 0xfff0)
{ putchar(0100+((sixteen>>4)&0x3f));
nco ++;
}
putchar(060+(sixteen&0xf));
nco ++;
}
#else
/*
* This version of "write16" uses negative Packed Pixel Data values to
* represent numbers in the range 0x7fff--0xffff; negative values will
* require fewer characters as they approach the upper end of that range.
*/
static void
write16 (word)
unsigned int word;
{
int high;
int mid;
int low;
int signChar;

if (nco > 75) {
putchar ('\n');
nco = 0;
}

if (word > 0x7fff) {
word = (unsigned int) (0x10000L - (long) word);
signChar = ' ';
}
else
signChar = '0';

high = (word >> 10) + '@';
mid = ((word & 0x3f0) >> 4) + '@';
low = (word & 0xf) + signChar;

if (high != '@') {
printf ("%c%c%c", high, mid, low);
nco += 3;
}
else if (mid != '@') {
printf ("%c%c", mid, low);
nco += 2;
}
else {
putchar (low);
nco++;
}
}
#endif
ii.cma.È
pbmtoatk.c.É
atktopbm.1.Ê
pbmtoatk.1tage( usage );
argn++;
}

if ( argn < argc )
{
ifpbmplus05oct91/pbm/pbmtolj.c 444 3010 34 7013 5032725030 11213 /* pbmtolj.c - read a portable bitmap and produce a LaserJet bitmap file
**
** based on pbmtops.c
**
** Michael Haberler HP Vienna [email protected]
** mcvax!tuvie!mah
** misfeatures:
** no positioning
**
** Bug fix Dec 12, 1988 :
** lines in putbit() reshuffled
** now runs OK on HP-UX 6.0 with X10R4 and HP Laserjet II
** Bo Thide', Swedish Institute of Space Physics, Uppsala
**
** Copyright (C) 1988 by Jef Poskanzer and Michael Haberler.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

static int dpi = 75;

static void putinit ARGS(( void ));
static void putbit ARGS(( bit b ));
static void putrest ARGS(( void ));
static void putitem ARGS(( void ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int argn, rows, cols, format, rucols, padright, row;
register int nzcol, col;
char* usage = "[-resolution N] [pbmfile]\n\tresolution = [75|100|150|300] (dpi)";

pbm_init( &argc, argv );

argn = 1;

/* Check for flags. */
if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-resolution", 2 ) )
{
++argn;
if ( argn == argc || sscanf( argv[argn], "%d", &dpi ) != 1 )
pm_usage( usage );
}
else
pm_usage( usage );
++argn;
}

if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pbm_readpbminit( ifp, &cols, &rows, &format );
bitrow = pbm_allocrow( cols );

putinit( );
for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );

/* Find rightmost black pixel. */
for ( nzcol = cols - 1; nzcol >= 0 && bitrow[nzcol] == PBM_WHITE; --nzcol )
continue;

/* Round up to the nearest multiple of 8. */
rucols = ( nzcol + 8 ) / 8;
rucols = rucols * 8;
padright = rucols - (nzcol + 1);

/* Transfer raster graphics */
printf("\033*b%dW",rucols/8);
for ( col = 0, bP = bitrow; col <= nzcol; ++col, ++bP )
putbit( *bP );
for ( col = 0; col < padright; ++col )
putbit( 0 );
}

pm_close( ifp );

putrest( );

exit( 0 );
}

static int item, bitsperitem, bitshift, itemsperline, firstitem;

static void
putinit( )
{
/* Printer reset. */
printf("\033E");

/* Ensure top margin is zero */
printf("\033&l0E");

/* Set raster graphics resolution */
printf("\033*t%dR",dpi);

/* Start raster graphics, relative adressing */
printf("\033*r1A");

itemsperline = 0;
bitsperitem = 1;
item = 0;
bitshift = 7;
firstitem = 1;
}

#if __STDC__
static void
putbit( bit b )
#else /*__STDC__*/
static void
putbit( b )
bit b;
#endif /*__STDC__*/
{
if ( b == PBM_BLACK )
item += 1 << bitshift;
bitshift--;
if ( bitsperitem == 8 ) {
putitem( );
bitshift = 7;
}
bitsperitem++;
}

static void
putrest( )
{
if ( bitsperitem > 1 )
putitem( );

/* end raster graphics */
printf( "\033*rB" );

/* Printer reset. */
printf("\033E");
}

static void
putitem( )
{
putchar( item );
bitsperitem = 0;
item = 0;
}
ength, code, a, b)
tableentry* hash[];
int length, code;
int a, b;
{
unsigned int pos;
tableentry* te;

pos = ((length+a)*(code+b))%HASHSIZE;
if (pos < 0 || pos >= HASHSIZE)
pm_error(
"internal error: bad hash position, length %d code %d pos %d",
length, code, pos );
te = hash[pos];
return ((te && te->length == length && te->code == code) ? te : 0);
}

static int
getfaxrow( inf, row, bitrow )
FILE* inf;
int row;
bit* bitrow;
{
inpbmplus05oct91/pbm/mgrtopbm.c 444 3010 34 6232 5032726461 11406 /* mgrtopbm.c - read a MGR bitmap and produce a portable bitmap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "mgr.h"

static void getinit ARGS(( FILE* file, int* colsP, int* rowsP, int* depthP, int* padrightP ));
static bit getbit ARGS(( FILE* file ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, depth, padright, row, col;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[mgrfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

getinit( ifp, &cols, &rows, &depth, &padright );
if ( depth != 1 )
pm_error( "MGR file has depth of %d, must be 1", depth );

pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

for ( row = 0; row < rows; row++ )
{
/* Get data, bit-reversed within each byte. */
for ( col = 0, bP = bitrow; col < cols; col++, bP++ )
*bP = getbit( ifp );
/* Discard line padding */
for ( col = 0; col < padright; col ++ )
(void) getbit( ifp );
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}

pm_close( ifp );

exit( 0 );
}


static unsigned char item;
static int bitsperitem, bitshift;

static void
getinit( file, colsP, rowsP, depthP, padrightP )
FILE* file;
int* colsP;
int* rowsP;
int* depthP;
int* padrightP;
{
struct b_header head;
int pad;

if ( fread( &head, sizeof(struct old_b_header), 1, file ) != 1 )
pm_perror( "reading header" );
if ( head.magic[0] == 'y' && head.magic[1] == 'z' )
{ /* new style bitmap */
if ( fread( &head.depth, sizeof(head) - sizeof(struct old_b_header), 1, file ) != 1 )
pm_perror( "reading rest of header" );
*depthP = (int) head.depth - ' ';
pad = 8;
}
else if ( head.magic[0] == 'x' && head.magic[1] == 'z' )
{ /* old style bitmap with 32-bit padding */
*depthP = 1;
pad = 32;
}
else if ( head.magic[0] == 'z' && head.magic[1] == 'z' )
{ /* old style bitmap with 16-bit padding */
*depthP = 1;
pad = 16;
}
else if ( head.magic[0] == 'z' && head.magic[1] == 'y' )
{ /* old style 8-bit pixmap with 16-bit padding */
*depthP = 8;
pad = 16;
}
else
pm_error(
"bad magic chars in MGR file: '%c%c'",
head.magic[0], head.magic[1] );
*colsP = ( ( (int) head.h_wide - ' ' ) << 6 ) + ( (int) head.l_wide - ' ' );
*rowsP = ( ( (int) head.h_high - ' ' ) << 6 ) + ( (int) head.l_high - ' ' );
*padrightP = ( ( *colsP + pad - 1 ) / pad ) * pad - *colsP;

bitsperitem = 8;
}

static bit
getbit( file )
FILE* file;
{
bit b;

if ( bitsperitem == 8 )
{
item = getc( file );
bitsperitem = 0;
bitshift = 7;
}
bitsperitem++;
b = ( ( item >> bitshift) & 1 ) ? PBM_BLACK : PBM_WHITE;
bitshift--;
return b;
}
nearest multiple of 8. */
rucols = ( nzcol + 8 ) / 8;
rucols = rucols * 8;
padright = rucols - (nzcol + 1);

/* Transfer raster graphics */
printf("\033*b%dW",rucols/8);
for ( col = 0, bP = bitrow; col <= nzcol; ++col, ++bP )
putbit( *bP );
for ( col = 0; col < padright; ++col )
putbit( 0 );
}

pm_close( ifp );

pupbmplus05oct91/pbm/pbmtocmuwm.c 444 3010 34 4752 5032725017 11752 /* pbmtocmuwm.c - read a portable bitmap and produce a CMU window manager bitmap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "cmuwm.h"

static void putinit ARGS(( int rows, int cols ));
static void putbit ARGS(( bit b ));
static void putrest ARGS(( void ));
static void putitem ARGS(( void ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, format, padright, row, col;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pbm_readpbminit( ifp, &cols, &rows, &format );
bitrow = pbm_allocrow( cols );

/* Round cols up to the nearest multiple of 8. */
padright = ( ( cols + 7 ) / 8 ) * 8 - cols;

putinit( rows, cols );
for ( row = 0; row < rows; row++ )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0, bP = bitrow; col < cols; col++, bP++ )
putbit( *bP );
for ( col = 0; col < padright; col++ )
putbit( 0 );
}

pm_close( ifp );

putrest( );

exit( 0 );
}

static unsigned char item;
static int bitsperitem, bitshift;

static void
putinit( rows, cols )
int rows, cols;
{
if ( pm_writebiglong( stdout, CMUWM_MAGIC ) == -1 )
pm_error( "write error" );
if ( pm_writebiglong( stdout, cols ) == -1 )
pm_error( "write error" );
if ( pm_writebiglong( stdout, rows ) == -1 )
pm_error( "write error" );
if ( pm_writebigshort( stdout, (short) 1 ) == -1 )
pm_error( "write error" );

item = 0;
bitsperitem = 0;
bitshift = 7;
}

#if __STDC__
static void
putbit( bit b )
#else /*__STDC__*/
static void
putbit( b )
bit b;
#endif /*__STDC__*/
{
if ( bitsperitem == 8 )
putitem( );
if ( b == PBM_WHITE )
item += 1 << bitshift;
bitsperitem++;
bitshift--;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
}

static void
putitem( )
{
if ( putc( item, stdout ) == EOF )
pm_error( "write error" );
item = 0;
bitsperitem = 0;
bitshift = 7;
}
_close( ifp );

pupbmplus05oct91/pbm/pbmtogo.1 444 3010 34 1761 5022774260 11145 .TH pbmtogo 1 "24 November 1989"
.IX pbmtogo
.SH NAME
pbmtogo - convert a portable bitmap into compressed GraphOn graphics
.SH SYNOPSIS
.B pbmtogo
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces 2D compressed GraphOn graphics as output.
.IX GraphOn
Be sure to set up your GraphOn with the following modes: 8 bits / no parity;
obeys no XON/XOFF; NULs are accepted. These are all on the Comm menu.
Also, remember to turn off tty post processing.
Note that there is no gotopbm tool.
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1988, 1989 by Jef Poskanzer, Michael Haberler, and Bo Thide'.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
.œ
pbmto10xpbmplus05oct91/pbm/pbmtoicon.c 444 3010 34 5405 5032725027 11547 /* pbmtoicon.c - read a portable bitmap and produce a Sun icon file
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

static void putinit ARGS(( void ));
static void putbit ARGS(( bit b ));
static void putrest ARGS(( void ));
static void putitem ARGS(( void ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, format, pad, padleft, padright, row, col;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pbm_readpbminit( ifp, &cols, &rows, &format );
bitrow = pbm_allocrow( cols );

/* Round cols up to the nearest multiple of 16. */
pad = ( ( cols + 15 ) / 16 ) * 16 - cols;
padleft = pad / 2;
padright = pad - padleft;

printf( "/* Format_version=1, Width=%d, Height=%d", cols + pad, rows );
printf( ", Depth=1, Valid_bits_per_item=16\n */\n" );

putinit( );
for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0; col < padleft; ++col )
putbit( 0 );
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
putbit( *bP );
for ( col = 0; col < padright; ++col )
putbit( 0 );
}

pm_close( ifp );

putrest( );

exit( 0 );
}

static int item, bitsperitem, bitshift, itemsperline, firstitem;

static void
putinit( )
{
itemsperline = 0;
bitsperitem = 0;
item = 0;
bitshift = 15;
firstitem = 1;
}

#if __STDC__
static void
putbit( bit b )
#else /*__STDC__*/
static void
putbit( b )
bit b;
#endif /*__STDC__*/
{
if ( bitsperitem == 16 )
putitem( );
++bitsperitem;
if ( b == PBM_BLACK )
item += 1 << bitshift;
--bitshift;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
putchar( '\n' );
}

static void
putitem( )
{
char* hexits = "0123456789abcdef";

if ( firstitem )
firstitem = 0;
else
putchar( ',' );
if ( itemsperline == 8 )
{
putchar( '\n' );
itemsperline = 0;
}
if ( itemsperline == 0 )
putchar( '\t' );
putchar( '0' );
putchar( 'x' );
putchar( hexits[item >> 12] );
putchar( hexits[( item >> 8 ) & 15] );
putchar( hexits[( item >> 4 ) & 15] );
putchar( hexits[item & 15] );
++itemsperline;
bitsperitem = 0;
item = 0;
bitshift = 15;
}
atic void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
}

static void
putitem( )
{
if ( putc( item, stdout ) == EOF )
pm_error( "write error" );
item = 0;
bitsperitem = 0;
bitshift = 7;
}
_close( ifp );

pupbmplus05oct91/pbm/cmuwmtopbm.1 444 3010 34 1415 5022773011 11655 .TH cmuwmtopbm 1 "15 April 1989"
.IX cmuwmtopbm
.SH NAME
cmuwmtopbm - convert a CMU window manager bitmap into a portable bitmap
.SH SYNOPSIS
.B cmuwmtopbm
.RI [ cmuwmfile ]
.SH DESCRIPTION
Reads a CMU window manager bitmap as input.
.IX "CMU window manager bitmap"
Produces a portable bitmap as output.
.SH "SEE ALSO"
pbmtocmuwm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
bmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/g3topbm.1 444 3010 34 3002 5022773106 11035 .TH g3topbm 1 "02 October 1989"
.IX g3topbm
.SH NAME
g3topbm - convert a Group 3 fax file into a portable bitmap
.SH SYNOPSIS
.B g3topbm
.RB [ -kludge ]
.RB [ -reversebits ]
.RB [ -stretch ]
.RI [ g3file ]
.SH DESCRIPTION
Reads a Group 3 fax file as input.
.IX "Group 3 fax"
.IX fax
Produces a portable bitmap as output.
.SH OPTIONS
.TP
.B -kludge
Tells
.I g3topbm
to ignore the first few lines of the file;
sometimes fax files have some junk at the beginning.
.TP
.B -reversebits
Tells
.I g3topbm
to interpret bits least-significant
first, instead of the default most-significant first.
Apparently some fax modems do it one way and others do it the other way.
If you get a whole bunch of "bad code word" messages, try using this
flag.
.TP
.B -stretch
Tells
.I g3topbm
to stretch the image vertically by
duplicating each row.
This is for the low-quality transmission mode.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH REFERENCES
The standard for Group 3 fax is defined in CCITT Recommendation T.4.
.SH BUGS
Probably.
.SH "SEE ALSO"
pbmtog3(1), pbm(5)
.SH AUTHOR
Copyright (C) 1989 by Paul Haeberli .
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
uwm.hkip.¶
pbmtopi3.1c.·pbm.hle.¸
pbmtoybm.1s.¹
pbmtoybm.cn.º
pbmtogem.cc.»
ybmtopbm.1
.¼
ybmtopbm.c
.½ pbmtoplot.1Vù.¾
pbmtopi3.cD.¿ pbmtozinc.1¾9.À pbmtoplot.cUq.Á
pi3topbm.1
.Â
pi3topbm.c.Ã pbmtoepson.c31.Ä pbmtozinc.cUv.Å
atktopbm.cw.Æ pbmtoascii.1.Ç pbmtoascii.cma.È
pbmtoatk.c.É
atktopbm.1.Ê
pbmtoatk.1tf ( itemsperline == 0 )
putchar( '\t' );
putchar( 'pbmplus05oct91/pbm/icontopbm.1 444 3010 34 1344 5023002413 11446 .TH icontopbm 1 "31 August 1988"
.IX icontopbm
.SH NAME
icontopbm - convert a Sun icon into a portable bitmap
.SH SYNOPSIS
.B icontopbm
.RI [ iconfile ]
.SH DESCRIPTION
Reads a Sun icon as input.
.IX Sun
.IX "Sun icon format"
Produces a portable bitmap as output.
.SH "SEE ALSO"
pbmtoicon(1), pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
pbmtext.1. pbmtext.css.‘ pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/macptopbm.1 444 3010 34 3364 5023104037 11447 .TH macptopbm 1 "29 March 1989"
.IX macptopbm
.SH NAME
macptopbm - convert a MacPaint file into a portable bitmap
.SH SYNOPSIS
.B macptopbm
.RB [ -extraskip
.IR N ]
.RI [ macpfile ]
.SH DESCRIPTION
Reads a MacPaint file as input.
.IX MacPaint
.IX Macintosh
Produces a portable bitmap as output.
.SH OPTIONS
.TP
.B -extraskip
This flag is to get around a problem with some methods
of transferring files from the Mac world to the Unix world.
Most of these methods leave the Mac files alone, but a few of
them add the "finderinfo" data onto the front of the Unix file.
This means an extra 128 bytes to skip over when reading the file.
The symptom to watch for is that the resulting PBM file looks shifted
to one side.
If you get this, try
.B -extraskip
128, and if that still doesn't look right try another value.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH "SEE ALSO"
picttoppm(1), pbmtomacp(1), pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
The MacPaint-reading code is copyright (c) 1987 by Patrick J. Naughton
([email protected]).
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted,
.\" provided that the above copyright notice appear in all copies and that
.\" both that copyright notice and this permission notice appear in
.\" supporting documentation.

pi3topbm.1
.Â
pi3topbm.c.Ã pbmtoepson.c31.Ä pbmtozinc.cUv.Å
atktopbm.cw.Æ pbmtoascii.1.Ç pbmtoascii.cma.È
pbmtoatk.c.É
atktopbm.1.Ê
pbmtoatk.1tf ( itemsperline == 0 )
putchar( '\t' );
putchar( 'pbmplus05oct91/pbm/mgrtopbm.1 444 3010 34 1315 5022773276 11326 .TH mgrtopbm 1 "24 January 1989"
.IX mgrtopbm
.SH NAME
mgrtopbm - convert a MGR bitmap into a portable bitmap
.SH SYNOPSIS
.B mgrtopbm
.RI [ mgrfile ]
.SH DESCRIPTION
Reads a MGR bitmap as input.
.IX MGR
Produces a portable bitmap as output.
.SH "SEE ALSO"
pbmtomgr(1), pbm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
 pbmtogo.c˜. pbmtext.1. pbmtext.css.‘ pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtomgr.c 444 3010 34 4761 5032725032 11404 /* pbmtomgr.c - read a portable bitmap and produce a MGR bitmap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "mgr.h"

static void putinit ARGS(( int rows, int cols ));
static void putbit ARGS(( bit b ));
static void putrest ARGS(( void ));
static void putitem ARGS(( void ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, format, padright, row, col;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pbm_readpbminit( ifp, &cols, &rows, &format );
bitrow = pbm_allocrow( cols );

/* Round cols up to the nearest multiple of 8. */
padright = ( ( cols + 7 ) / 8 ) * 8 - cols;

putinit( rows, cols );
for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
putbit( *bP );
for ( col = 0; col < padright; ++col )
putbit( 0 );
}

pm_close( ifp );

putrest( );

exit( 0 );
}

static unsigned char item;
static int bitsperitem, bitshift;

static void
putinit( rows, cols )
int rows, cols;
{
struct b_header head;

head.magic[0] = 'y';
head.magic[1] = 'z';
head.h_wide = ( ( cols >> 6 ) & 0x3f ) + ' ';
head.l_wide = ( cols & 0x3f ) + ' ';
head.h_high = ( ( rows >> 6 ) & 0x3f ) + ' ';
head.l_high = ( rows & 0x3f ) + ' ';
head.depth = ( 1 & 0x3f ) + ' ';
head._reserved = ' ';
fwrite( &head, sizeof(head), 1, stdout );

item = 0;
bitsperitem = 0;
bitshift = 7;
}

#if __STDC__
static void
putbit( bit b )
#else /*__STDC__*/
static void
putbit( b )
bit b;
#endif /*__STDC__*/
{
if ( bitsperitem == 8 )
putitem( );
++bitsperitem;
if ( b == PBM_BLACK )
item += 1 << bitshift;
--bitshift;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
}

static void
putitem( )
{
fwrite( &item, sizeof(item), 1, stdout );
item = 0;
bitsperitem = 0;
bitshift = 7;
}
ifp );

pupbmplus05oct91/pbm/pbmlife.1 444 3010 34 1555 5022773321 11112 .TH pbmlife 1 "21 February 1991"
.IX pbmlife
.SH NAME
pbmlife - apply Conway's rules of Life to a portable bitmap
.SH SYNOPSIS
.B pbmlife
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Applies the rules of Life to it for one generation,
.IX Life
and produces a portable bitmap as output.
.PP
A white pixel in the image is interpreted as a live beastie, and a
black pixel as an empty space.
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1988, 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
astie, and a
black pixel as an empty space.
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1988, 1991 by Jef Poskanzer.
.\" Permission to use, copypbmplus05oct91/pbm/pbmtoptx.c 444 3010 34 3637 5032725037 11440 /* pbmtoptx.c - read a portable bitmap and produce a Printronix printer file
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

static void putinit ARGS(( void ));
static void putbit ARGS(( bit b ));
static void putrest ARGS(( void ));
static void putitem ARGS(( void ));

void main( argc, argv )
int argc;
char *argv[];
{
FILE *ifp;
register bit *bitrow, *bP;
int rows, cols, format, row, col;
char *usage = "[pbmfile]";

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( usage );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pbm_readpbminit( ifp, &cols, &rows, &format );
bitrow = pbm_allocrow( cols );

putinit( );
for ( row = 0; row < rows; row++ )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0, bP = bitrow; col < cols; col++, bP++ )
putbit( *bP );
putrest( );
putchar( 5 );
putchar( '\n' );
}

pm_close( ifp );

exit( 0 );
}

static char item;
static int bitsperitem, bitshift;

static void
putinit( )
{
bitsperitem = 0;
item = 64;
bitshift = 0;
}

#if __STDC__
static void
putbit( bit b )
#else /*__STDC__*/
static void
putbit( b )
bit b;
#endif /*__STDC__*/
{
if ( bitsperitem == 6 )
putitem( );
if ( b == PBM_BLACK )
item += 1 << bitshift;
bitsperitem++;
bitshift++;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
}

static void
putitem( )
{
putchar( item );
bitsperitem = 0;
item = 64;
bitshift = 0;
}
.É
atktopbm.1.Ê
pbmtoatk.1t sizeof(head), 1, stdout );

item = 0;
bitsperitpbmplus05oct91/pbm/libpbm5.c 444 3010 34 32511 5032725570 11130 /* libpbm5.c - pbm utility library part 5
**
** Font routines.
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "pbmfont.h"

/* The default font, packed in hex so this source file doesn't get huge.
** You can replace this with your own font using pbm_dumpfont().
*/
#define DEFAULTFONT_ROWS 155
#define DEFAULTFONT_COLS 112
static unsigned long defaultfont_bits[DEFAULTFONT_ROWS][(DEFAULTFONT_COLS+31)/32] = {
{0x00000000L,0x20000c00L,0x10000000L,0x00000000L},
{0xc600a000L,0x42000810L,0x00000002L,0x00000063L},
{0x6c00a000L,0x45000810L,0x00000002L,0x00000036L},
{0x6c00a000L,0x88800808L,0xf2e1dee2L,0x00000036L},
{0x54000000L,0x80000800L,0x11122442L,0x0000002aL},
{0x54000001L,0x00000800L,0x11122442L,0x0000002aL},
{0x54000001L,0x00000800L,0x11122282L,0x0000002aL},
{0x44000102L,0x00000800L,0x11122382L,0x00000022L},
{0xee000102L,0x00000800L,0x11e1e102L,0x00000077L},
{0x00000204L,0x00000800L,0x11002102L,0x00000000L},
{0x00000000L,0x00000c00L,0x11002102L,0x00000000L},
{0x00000000L,0x003f8000L,0xe3807600L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x02000080L,0x00040000L,0x00120000L,0x00000001L},
{0x04000082L,0x828e1838L,0x20210100L,0x00000002L},
{0x04000082L,0x82912448L,0x20210100L,0x00000002L},
{0x08000082L,0x8fd01940L,0x404087c2L,0x00000004L},
{0x08000080L,0x050c0622L,0x00408102L,0x00000004L},
{0x10000080L,0x05061874L,0x0040828fL,0x00008008L},
{0x10000080L,0x1f912688L,0x00408002L,0x00000008L},
{0x20000000L,0x0a11098cL,0x00408002L,0x00000010L},
{0x20000080L,0x0a0e0672L,0x00210000L,0x00000010L},
{0x40000000L,0x00040000L,0x00210000L,0x00000020L},
{0x00000000L,0x00000000L,0x00120000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x004e0838L,0x7023e1cfL,0x00008000L},
{0x00000000L,0x00913844L,0x88620208L,0x00008000L},
{0x08000000L,0x00910844L,0x08a20401L,0x00000004L},
{0x10000000L,0x01110844L,0x08a20401L,0x00000008L},
{0x20000000L,0x01110808L,0x3123c781L,0x00000010L},
{0x400003e0L,0x02110810L,0x0a202441L,0x00000020L},
{0x20000000L,0x02110820L,0x0bf02442L,0x00000010L},
{0x10008000L,0x04110844L,0x88242442L,0x00000008L},
{0x08008002L,0x040e3e7cL,0x7073c382L,0x00000004L},
{0x00010000L,0x08000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x0000e1c0L,0x00000000L,0x00000000L,0x00000000L},
{0x00011220L,0x00000000L,0x70e38f87L,0x00000000L},
{0x20011220L,0x00020020L,0x89108448L,0x00008010L},
{0x10011220L,0x00040010L,0x09314448L,0x00008008L},
{0x0800e221L,0x02083e08L,0x11514788L,0x00000004L},
{0x040111e0L,0x00100004L,0x2153e448L,0x00000002L},
{0x08011020L,0x00083e08L,0x213a2448L,0x00008004L},
{0x10011040L,0x02040010L,0x01022448L,0x00008008L},
{0x2000e381L,0x02020020L,0x20e77f87L,0x00000010L},
{0x00000000L,0x04000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x3803e7efL,0xc73bbe3dL,0xdb863ce7L,0x0000001cL},
{0x44011224L,0x48910808L,0x91036648L,0x00008022L},
{0x4c011285L,0x48910808L,0xa1036648L,0x00008026L},
{0x54011387L,0x081f0808L,0xc102a548L,0x0000802aL},
{0x54011285L,0x09910808L,0xe102a548L,0x0000802aL},
{0x4e011204L,0x08910848L,0x9112a4c8L,0x00008027L},
{0x40011224L,0x08910848L,0x891224c8L,0x00008020L},
{0x3803e7efL,0x073bbe31L,0xcff77e47L,0x0000001cL},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000003L,0x00000000L},
{0x0003e1cfL,0x87bff7efL,0xdfbf77c2L,0x00000000L},
{0x00013224L,0x48a4a244L,0x89122442L,0x00000000L},
{0x00011224L,0x4824a244L,0xa8a14482L,0x00000000L},
{0x00013227L,0x8e04226cL,0xa8414102L,0x00000000L},
{0x0001e224L,0x83842228L,0xa8a08102L,0x00000000L},
{0x00010224L,0x40842228L,0xd8a08242L,0x00000000L},
{0x00010224L,0x48843638L,0x51108442L,0x00000000L},
{0x0003c1ceL,0x6f1f1c10L,0x53b9c7c2L,0x00000000L},
{0x00000060L,0x00000000L,0x00000002L,0x00000000L},
{0x00000000L,0x00000000L,0x00000003L,0x00000000L},
{0xfe000000L,0x00000000L,0x00000000L,0x0000007fL},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00010180L,0x000000c0L,0x003001c0L,0x00000000L},
{0x08008081L,0x00040040L,0x00100200L,0x00000004L},
{0x10008082L,0x80040040L,0x00100200L,0x00000008L},
{0x10004084L,0x40023c78L,0x70f1c7c7L,0x00004008L},
{0x10004080L,0x00000244L,0x89122208L,0x00008008L},
{0x20002080L,0x00001e44L,0x8113e208L,0x00008010L},
{0x10002080L,0x00002244L,0x81120208L,0x00008008L},
{0x10001080L,0x00002244L,0x89122208L,0x00008008L},
{0x10001080L,0x00001db8L,0x70e9c787L,0x00008008L},
{0x10000880L,0x00000000L,0x00000000L,0x00008008L},
{0x08000180L,0x00000000L,0x00000000L,0x00008004L},
{0x00000000L,0x1fc00000L,0x00000007L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00030080L,0x981c0000L,0x00000000L,0x00000000L},
{0x20010000L,0x08040000L,0x00000000L,0x00000010L},
{0x10010000L,0x08040000L,0x00000000L,0x00000008L},
{0x10016387L,0x898474b8L,0x72e1d5c7L,0x00000008L},
{0x10019080L,0x8a042a64L,0x89122208L,0x00008008L},
{0x08011080L,0x8c042a44L,0x89122207L,0x00000004L},
{0x10011080L,0x8a042a44L,0x89122200L,0x00008008L},
{0x10011080L,0x89042a44L,0x89122208L,0x00008008L},
{0x1003bbe0L,0x98dfebe6L,0x71e1e787L,0x00000008L},
{0x10000000L,0x80000000L,0x01002000L,0x00000008L},
{0x20000000L,0x80000000L,0x01002000L,0x00000010L},
{0x00000007L,0x00000000L,0x03807000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00008000L,0x00000000L,0x10410000L,0x00000000L},
{0x00008000L,0x00000000L,0x20408000L,0x00000000L},
{0x0001f66eL,0xfdfbf77cL,0x20408000L,0x00000000L},
{0x24008224L,0x488a2248L,0x20408240L,0x00000012L},
{0x54008224L,0x4a842210L,0x40404540L,0x0000002aL},
{0x48008222L,0x8a8a1420L,0x20408480L,0x00000024L},
{0x00008a23L,0x85111c44L,0x20408000L,0x00000000L},
{0x000071d1L,0x0531887cL,0x20408000L,0x00000000L},
{0x00000000L,0x00000800L,0x20408000L,0x00000000L},
{0x00000000L,0x00000800L,0x10410000L,0x00000000L},
{0x00000000L,0x00003000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x00000000L,0x00000000L,0x00000000L},
{0x00000000L,0x20000c00L,0x10000000L,0x00000000L},
{0xc600a000L,0x42000810L,0x00000002L,0x00000063L},
{0x6c00a000L,0x45000810L,0x00000002L,0x00000036L},
{0x6c00a000L,0x88800808L,0xf2e1dee2L,0x00000036L},
{0x54000000L,0x80000800L,0x11122442L,0x0000002aL},
{0x54000001L,0x00000800L,0x11122442L,0x0000002aL},
{0x54000001L,0x00000800L,0x11122282L,0x0000002aL},
{0x44000102L,0x00000800L,0x11122382L,0x00000022L},
{0xee000102L,0x00000800L,0x11e1e102L,0x00000077L},
{0x00000204L,0x00000800L,0x11002102L,0x00000000L},
{0x00000000L,0x00000c00L,0x11002102L,0x00000000L},
{0x00000000L,0x003f8000L,0xe3807600L,0x00000000L}
};

bit**
pbm_defaultfont( fcolsP, frowsP )
int* fcolsP;
int* frowsP;
{
bit** defaultfont;
int row, col, scol;
unsigned long l;

defaultfont = pbm_allocarray( DEFAULTFONT_COLS, DEFAULTFONT_ROWS );
for ( row = 0; row < DEFAULTFONT_ROWS; ++row )
{
for ( col = 0; col < DEFAULTFONT_COLS; col += 32 )
{
l = defaultfont_bits[row][col / 32];
for ( scol = min( col + 32, DEFAULTFONT_COLS ) - 1;
scol >= col; --scol )
{
if ( l & 1 )
defaultfont[row][scol] = 1;
else
defaultfont[row][scol] = 0;
l >>= 1;
}
}
}

*fcolsP = DEFAULTFONT_COLS;
*frowsP = DEFAULTFONT_ROWS;
return defaultfont;
}

void
pbm_dissectfont( font, frows, fcols, char_heightP, char_widthP, char_aheightP, char_awidthP, char_row0, char_col0 )
bit** font;
int frows;
int fcols;
int* char_heightP;
int* char_widthP;
int* char_aheightP;
int* char_awidthP;
int char_row0[95];
int char_col0[95];
{
/*
** This routine expects a font bitmap representing the following text:
**
** (0,0)
** M ",/^_[`jpqy| M
**
** / !"#$%&'()*+ /
** < ,-./01234567 <
** > 89:;<=>[email protected] >
** @ DEFGHIJKLMNO @
** _ PQRSTUVWXYZ[ _
** { \]^_`abcdefg {
** } hijklmnopqrs }
** ~ tuvwxyz{|}~ ~
**
** M ",/^_[`jpqy| M
**
** The bitmap must be cropped exactly to the edges.
**
** The dissection works by finding the first blank row and column; that
** gives the height and width of the maximum-sized character, which is
** not too useful. But the distance from there to the opposite side is
** an integral multiple of the cell size, and that's what we need. Then
** it's just a matter of filling in all the coordinates.
**
** The difference between char_height, char_width and char_aheight,
** char_awidth is that the first is the size of the cell including
** spacing, while the second is just the actual maximum-size character.
*/
int brow, bcol, row, col, d, ch;
bit b;

/* Find first blank row. */
for ( brow = 0; brow < frows / 6; ++brow )
{
b = font[brow][0];
for ( col = 1; col < fcols; ++col )
if ( font[brow][col] != b )
goto nextrow;
goto gotblankrow;
nextrow: ;
}
pm_error( "couldn't find blank row in font" );

gotblankrow:
/* Find first blank col. */
for ( bcol = 0; bcol < fcols / 8; ++bcol )
{
b = font[0][bcol];
for ( row = 1; row < frows; ++row )
if ( font[row][bcol] != b )
goto nextcol;
goto gotblankcol;
nextcol: ;
}
pm_error( "couldn't find blank col in font" );

gotblankcol:
/* Now compute character cell size. */
d = frows - brow;
*char_heightP = d / 11;
if ( *char_heightP * 11 != d )
pm_error( "problem computing character cell height" );
d = fcols - bcol;
*char_widthP = d / 15;
if ( *char_widthP * 15 != d )
pm_error( "problem computing character cell width" );
*char_aheightP = brow;
*char_awidthP = bcol;

/* Now fill in the 0,0 coords. */
row = *char_heightP * 2;
col = *char_widthP * 2;
for ( ch = 0; ch < 95; ++ch )
{
char_row0[ch] = row;
char_col0[ch] = col;
col += *char_widthP;
if ( col >= *char_widthP * 14 )
{
col = *char_widthP * 2;
row += *char_heightP;
}
}
}

void
pbm_dumpfont( font, fcols, frows )
bit** font;
int fcols;
int frows;
{
/* Dump out font as C source code. */
int row, col, scol, lperrow;
unsigned long l;

printf( "#define DEFAULTFONT_ROWS %d\n", frows );
printf( "#define DEFAULTFONT_COLS %d\n", fcols );
printf( "static unsigned long defaultfont_bits[DEFAULTFONT_ROWS][(DEFAULTFONT_COLS+31)/32] = {\n" );
for ( row = 0; row < frows; ++row )
{
lperrow = 0;
for ( col = 0; col < fcols; col += 32 )
{
if ( lperrow == 0 )
printf( " {" );
else if ( lperrow % 6 == 0 )
{
printf( ",\n " );
lperrow = 0;
}
else
printf( "," );
l = 0;
for ( scol = col; scol < min( col + 32, fcols ); ++scol )
{
l <<= 1;
if ( font[row][scol] )
l |= 1;
}
printf( "0x%08lxL", l );
++lperrow;
}
printf( "}%s\n", row == frows - 1 ? "" : "," );
}
printf( " };\n" );
}
x00010224L,0x40842228L,0xd8a08242L,0x00000000L},
{0x00010224L,0x48843638L,0x51108442L,0x00000000L},
{0x0003c1ceL,0x6f1f1c10L,0x53b9c7c2L,0x00000000L},
{0x00000060L,0x00000pbmplus05oct91/pbm/pbmfont.h 444 3010 34 544 4763120662 11212 /* pbmfont.h - header file for font routines in libpbm
*/

bit** pbm_defaultfont ARGS(( int* fcolsP, int* frowsP ));

void pbm_dissectfont ARGS(( bit** font, int frows, int fcols, int* char_heightP, int* char_widthP, int* char_aheightP, int* char_awidthP, int char_row0[], int char_col0[] ));

void pbm_dumpfont ARGS(( bit** font, int fcols, int frows ));
pbmtobbnbg.cnmp.m pbmtolj.c8.
mgrtopbm.c.€ pbmtocmuwm.citr. pbmtogo.1xt.‚ pbmtoicon.c.ƒ cmuwmtopbm.1.„ pbmplus05oct91/pbm/libpbm2.c 444 3010 34 5233 5032724774 11113 /* libpbm2.c - pbm utility library part 2
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "libpbm.h"

static bit
pbm_getbit( file )
FILE* file;
{
register char ch;

do
{
ch = pbm_getc( file );
}
while ( ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' );

if ( ch != '0' && ch != '1' )
pm_error( "junk in file where bits should be" );

return ( ch == '1' ) ? 1 : 0;
}

int
pbm_readmagicnumber( file )
FILE* file;
{
int ich1, ich2;

ich1 = getc( file );
if ( ich1 == EOF )
pm_error( "EOF / read error reading magic number" );
ich2 = getc( file );
if ( ich2 == EOF )
pm_error( "EOF / read error reading magic number" );
return ich1 * 256 + ich2;
}

void
pbm_readpbminitrest( file, colsP, rowsP )
FILE* file;
int* colsP;
int* rowsP;
{
/* Read size. */
*colsP = pbm_getint( file );
*rowsP = pbm_getint( file );
}

void
pbm_readpbminit( file, colsP, rowsP, formatP )
FILE* file;
int* colsP;
int* rowsP;
int* formatP;
{
/* Check magic number. */
*formatP = pbm_readmagicnumber( file );
switch ( PBM_FORMAT_TYPE(*formatP) )
{
case PBM_TYPE:
pbm_readpbminitrest( file, colsP, rowsP );
break;

default:
pm_error( "bad magic number - not a pbm file" );
}
}

void
pbm_readpbmrow( file, bitrow, cols, format )
FILE* file;
bit* bitrow;
int cols, format;
{
register int col, bitshift;
register unsigned char item;
register bit* bP;

switch ( format )
{
case PBM_FORMAT:
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
*bP = pbm_getbit( file );
break;

case RPBM_FORMAT:
bitshift = -1;
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
{
if ( bitshift == -1 )
{
item = pbm_getrawbyte( file );
bitshift = 7;
}
*bP = ( item >> bitshift ) & 1;
--bitshift;
}
break;

default:
pm_error( "can't happen" );
}
}

bit**
pbm_readpbm( file, colsP, rowsP )
FILE* file;
int* colsP;
int* rowsP;
{
register bit** bits;
int format, row;

pbm_readpbminit( file, colsP, rowsP, &format );

bits = pbm_allocarray( *colsP, *rowsP );

for ( row = 0; row < *rowsP; ++row )
pbm_readpbmrow( file, bits[row], *colsP, format );

return bits;
}
08000L,0x00000000L,0x10410000L,0x00000000L},
{0x00008000L,0x00000000L,0x20408000L,0x00000000L},
{0x0001f66eL,0xfdfbf77cL,0x20408000L,0x00000000L},
{0x24008224L,0x488a2248L,0x20408240L,0x00000012L},
{0x54008224L,0x4a842210L,0x40404540L,0x0000002aL},
{0x48008222L,0x8a8a1420L,0x20408480L,0x00000024L},
{0x00008a23L,0x85111c44L,0x204080pbmplus05oct91/pbm/pbmtogo.c 444 3010 34 17165 5032725025 11250 /* pbmtogo.c - read a portable bitmap and produce a GraphOn terminal raster file
**
** Rev 1.1 was based on pbmtolj.c
**
** Bo Thide', Swedish Institute of Space Physics, [email protected]
**
**
** $Log: pbmtogo.c,v $
* Revision 1.5 89/11/25 00:24:12 00:24:12 root (Bo Thide)
* Bug found: The byte after 64 repeated bytes sometimes lost. Fixed.
*
* Revision 1.4 89/11/24 14:56:04 14:56:04 root (Bo Thide)
* Fixed the command line parsing since pbmtogo now always uses 2D
* compression. Added a few comments to the source.
*
* Revision 1.3 89/11/24 13:43:43 13:43:43 root (Bo Thide)
* Added support for > 63 repeated bytes and > 62 repeated lines in
* the 2D compression scheme.
*
* Revision 1.2 89/11/15 01:04:47 01:04:47 root (Bo Thide)
* First version that works reasonably well with GraphOn 2D runlength
* encoding/compression.
*
* Revision 1.1 89/11/02 23:25:25 23:25:25 root (Bo Thide)
* Initial revision
*
**
** Copyright (C) 1988, 1989 by Jef Poskanzer, Michael Haberler, and Bo Thide'.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

#define TRUE 1
#define BUFSIZE 132 /* GraphOn has 132 byte/1056 bit wide raster lines */
#define REPEAT_CURRENT_LINE_MASK 0x00
#define SKIP_AND_PLOT_MASK 0x40
#define REPEAT_PLOT_MASK 0x80
#define PLOT_ARBITRARY_DATA_MASK 0xc0
#define MAX_REPEAT 64

static unsigned char *scanlineptr; /* Pointer to current scan line byte */

static void putinit ARGS(( void ));
static void putbit ARGS(( bit b ));
static void putrest ARGS(( void ));
static void putitem ARGS(( void ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int argn, rows, cols, format, rucols, padright, row, col;
int nbyte, bytesperrow, ecount, ucount, nout, i, linerepeat;
int olditem;
unsigned char oldscanline[BUFSIZE];
unsigned char newscanline[BUFSIZE];
unsigned char diff[BUFSIZE];
unsigned char buffer[BUFSIZE];
unsigned char outbuffer[2*(BUFSIZE+1)]; /* Worst case. Should malloc */
char* usage = "[-c] [pbmfile]";

pbm_init( &argc, argv );

argn = 2;

/* Check for flags. */
if (argc > argn + 1)
pm_usage(usage);

if (argc == argn)
ifp = pm_openr( argv[argn-1] );
else
ifp = stdin;

pbm_readpbminit(ifp, &cols, &rows, &format);
bitrow = pbm_allocrow(cols);

/* Round cols up to the nearest multiple of 8. */
rucols = ( cols + 7 ) / 8;
bytesperrow = rucols; /* GraphOn uses bytes */
rucols = rucols * 8;
padright = rucols - cols;

for (i = 0; i < BUFSIZE; ++i )
buffer[i] = 0;
putinit();

/* Start donwloading screen raster */
printf("\033P0;1;0;4;1;%d;%d;1!R1/", rows, rucols);

linerepeat = 63; /* 63 means "Start new picture" */
for (row = 0; row < rows; row++)
{
/* Store scan line data in the new scan line vector */
scanlineptr = newscanline;
pbm_readpbmrow(ifp, bitrow, cols, format);
/* Transfer raster graphics */
for (col = 0, bP = bitrow; col < cols; col++, bP++)
putbit(*bP);
for (col = 0; col < padright; col++)
putbit(0);

/* XOR data from the new scan line with data from the old scan line */
for (i = 0; i < bytesperrow; i++)
diff[i] = oldscanline[i]^newscanline[i];

/*
** If the difference map is different from the current internal buffer,
** encode the difference and put it in the output buffer.
** Else, increase the counter for the current buffer by one.
*/

if ((bcmp(buffer, diff, bytesperrow) != 0) || (row == 0))
{
/*
** Since the data in the buffer has changed, send the scan line
** repeat count to cause the old line(s) to be plotted on the screen,
** copy the new data into the internal buffer, and reset the counters.
*/
putchar(linerepeat);
for (i = 0; i < bytesperrow; ++i)
buffer[i] = diff[i];
nbyte = 0; /* Internal buffer byte counter */
nout = 0; /* Output buffer byte counter */

/* Run length encode the new internal buffer (= difference map) */
while (TRUE)
{
ucount = 0; /* Unique items counter */
do /* Find unique patterns */
{
olditem = buffer[nbyte++];
ucount++;
} while ((olditem != buffer[nbyte])
&& (ucount < min(bytesperrow, MAX_REPEAT)));

if ((ucount != MAX_REPEAT) && (nbyte != bytesperrow))
{
/* Back up to the last truly unique pattern */
ucount--;
nbyte--;
}

if (ucount > 0) /* Output the unique patterns */
{
outbuffer[nout++] = (ucount-1) | PLOT_ARBITRARY_DATA_MASK;
for (i = nbyte-ucount; i < nbyte; i++)
outbuffer[nout++] = buffer[i];
}

/*
** If we already are at the end of the current scan line, skip the
** rest of the encoding and start with a new scan line.
*/
if (nbyte >= bytesperrow)
goto nextrow;

ecount = 0; /* Equal items counter */
do /* Find equal patterns */
{
olditem = buffer[nbyte++];
ecount++;
} while ((olditem == buffer[nbyte])
&& (ecount < min(bytesperrow, MAX_REPEAT)));

if (ecount > 1) /* More than 1 equal pattern */
{
if (olditem == '\0') /* White patterns */
{
if (nbyte >= bytesperrow-1) /* No more valid data ahead */
{
outbuffer[nout++] = (ecount-2) | SKIP_AND_PLOT_MASK;
outbuffer[nout++] = buffer[nbyte-1];
}
else /* More valid data ahead */
{
outbuffer[nout++] = (ecount-1) | SKIP_AND_PLOT_MASK;
outbuffer[nout++] = buffer[nbyte++];
}
}
else /* Non-white patterns */
{
outbuffer[nout++] = (ecount-1) | REPEAT_PLOT_MASK;
outbuffer[nout++] = olditem;
} /* if (olditem == '\0') */
} /* if (ecount > 1) */
else
nbyte--; /* No equal items found */

if (nbyte >= bytesperrow)
goto nextrow;
} /* while (TRUE) */

nextrow: printf("%d/", nout+1); /* Total bytes to transfer = nout+1 */
fflush(stdout);

/* Output the plot data */
write(1, outbuffer, nout);

/* Reset the counters */
linerepeat = 0;
}
else
{
linerepeat++;
if (linerepeat == 62) /* 62 lines max, then restart */
{
putchar(linerepeat);
printf("%d/", nout+1);
fflush(stdout);
write(1, outbuffer, nout);
linerepeat = 0;
}
}

/* Now we are ready for a new scan line */
for (i = 0; i < bytesperrow; ++i)
oldscanline[i] = newscanline[i];
}
putchar(linerepeat); /* For the last line(s) to be plotted */
pm_close(ifp);
putrest();
exit(0);
}

static int item, bitsperitem, bitshift;

static void
putinit()
{
/* Enter graphics window */
printf("\0331");

/* Erase graphics window */
printf("\033\014");

/* Set graphics window in raster mode */
printf("\033r");

/* Select standard Tek coding **/
printf("\033[=11l");

bitsperitem = 1;
item = 0;
bitshift = 7;
}

#if __STDC__
static void
putbit(bit b)
#else /*__STDC__*/
static void
putbit(b)
bit b;
#endif /*__STDC__*/
{
if (b == PBM_BLACK)
item += 1 << bitshift;
bitshift--;
if (bitsperitem == 8)
{
putitem();
bitshift = 7;
}
bitsperitem++;
}

static void
putrest()
{
if (bitsperitem > 1)
putitem();

/* end raster downloading */
printf("\033\134");

/* Exit raster mode */
printf("\033t");

/* Exit graphics window
printf("\0332"); */
}

static void
putitem()
{
*scanlineptr++ = item;
bitsperitem = 0;
item = 0;
}
s routine expects a font bitmap representing the following text:
**
** (0,0)
** M ",/^_[`jpqy| M
**
** / !"#$%&'()*+ /
** < ,-./01234567 <
** > 89:;<=>[email protected] >
** @ DEFGHIJKLMNO @
** _ PQRSTUVWXYZ[ _
** { \]^_`abcdefg {
** } hijklmnopqrs }
** ~ tuvwxyz{|}~ ~
**
** M ",/^_[`jpqy| M
**
** The bitmap mpbmplus05oct91/pbm/pbmtext.1 444 3010 34 3212 5022773705 11155 .TH pbmtext 1 "5 January 1991"
.IX pbmtext
.SH NAME
pbmtext - render text into a bitmap
.SH SYNOPSIS
.B pbmtext
.RB [ -font
.IR fontfile ]
.RI [ text ]
.SH DESCRIPTION
.PP
Takes the specified text, either a single line from the command
line or multiple lines from standard input, and renders it
into a bitmap.
.IX text
.SH OPTIONS
.PP
By default, pbmtext uses a built-in font.
You can also specify your own font with the
.B -font
flag.
The
.I fontfile
is a pbm file, created in a very specific way.
In your window system of choice, display the following text
in the desired (fixed-width) font:
.nf

M ",/^_[`jpqy| M

/ !"#$%&'()*+ /
< ,-./01234567 <
> 89:;<=>[email protected] >
@ DEFGHIJKLMNO @
_ PQRSTUVWXYZ[ _
{ \\]^_`abcdefg {
} hijklmnopqrs }
~ tuvwxyz{|}~ ~

M ",/^_[`jpqy| M

.fi
Do a screen grab or window dump of that text, using for instance
.IR xwd ,
.IR xgrabsc ,
or
.IR screendump .
Convert the result into a pbm file.
If necessary, use
.I pnmcut
to remove everything except the text.
Finally, run it through
.I pnmcrop
.IX pnmcrop
to make sure the edges are right up against the text.
.I pbmtext
can figure out the sizes and spacings from that.
.SH "SEE ALSO"
pbm(5), pnmcut(1), pnmcrop(1)
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.

.RI [ text ]
.SH DESCRIPTION
.PP
Takes the specified text, either a single line from the command
line or multiple lines from standard input, and renders it
into a bitmap.
.IX text
.SH OPTIONS
.PP
By default, pbmtext uses a built-in font.
You can also specify your own font with the
.B -font
flag.
The
.I fontfile
is a pbm file, created in a very specific way.
In your windopbmplus05oct91/pbm/pbmtext.c 444 3010 34 12164 5032725013 11253 /* pbmtext.c - render text into a bitmap
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "pbmfont.h"

static void fix_control_chars ARGS(( char* buf ));
static void fill_rect ARGS(( bit** bits, int row0, int col0, int height, int width, bit color ));
static void copy_rect ARGS(( bit** fbits, int frow0, int fcol0, int height, int width, bit** tbits, int trow0, int tcol0 ));

void
main( argc, argv )
int argc;
char* argv[];
{
bit** bits;
int argn, rows, cols, row, col;
bit** font;
int frows, fcols;
FILE* ifp;
int dump;
int char_width, char_height, char_awidth, char_aheight, vmargin, hmargin;
int char_row0[95];
int char_col0[95];
char buf[5000];
char** lp;
int lines, maxlines, maxchars, line;
char* cp;
char* usage = "[-font ] [text]";

pbm_init( &argc, argv );

/* Set up default parameters. */
argn = 1;
font = pbm_defaultfont( &fcols, &frows );
dump = 0;

/* Check for flags. */
while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-font", 2 ) )
{
++argn;
if ( argn == argc )
pm_usage( usage );
ifp = pm_openr( argv[argn] );
pbm_freearray( font, frows );
font = pbm_readpbm( ifp, &fcols, &frows );
pm_close( ifp );
}
else if ( pm_keymatch( argv[argn], "-dump", 2 ) )
/* Undocumented dump flag for installing a new built-in font. */
dump = 1;
else
pm_usage( usage );
++argn;
}

if ( dump )
{
pbm_dumpfont( font, fcols, frows );
exit( 0 );
}

maxlines = 50;
lp = (char**) malloc( maxlines * sizeof(char*) );
if ( lp == (char**) 0 )
pm_error( "out of memory" );

if ( argn < argc )
{ /* Get text from the command line. */
(void) strcpy( buf, argv[argn] );
++argn;
while ( argn < argc )
{
(void) strcat( buf, " " );
(void) strcat( buf, argv[argn] );
++argn;
}
fix_control_chars( buf );
maxchars = strlen( buf );
lp[0] = buf;
lines = 1;
}
else
{ /* Read text from stdin. */
lines = 0;
maxchars = 0;
while ( gets( buf ) != NULL )
{
int l;

fix_control_chars( buf );
l = strlen( buf );
maxchars = max( maxchars, l );
if ( lines >= maxlines )
{
maxlines *= 2;
lp = (char**) realloc( (char*) lp, maxlines * sizeof(char*) );
if ( lp == (char**) 0 )
pm_error( "out of memory" );
}
lp[lines] = (char*) malloc( l + 1 );
if ( lp[lines] == 0 )
pm_error( "out of memory" );
(void) strcpy( lp[lines], buf );
++lines;
}
}

pbm_dissectfont( font, frows, fcols, &char_height, &char_width,
&char_aheight, &char_awidth, char_row0, char_col0 );
if ( lines == 1 )
{
vmargin = char_height / 2;
hmargin = char_width;
}
else
{
vmargin = char_height;
hmargin = 2 * char_width;
}
rows = 2 * vmargin + lines * char_height;
cols = 2 * hmargin + maxchars * char_width;
bits = pbm_allocarray( cols, rows );

/* Fill background with the color of ' '. */
fill_rect( bits, 0, 0, rows, cols, font[char_row0[0]][char_col0[0]] );

/* Render characters. */
for ( line = 0; line < lines; ++line )
{
row = vmargin + line * char_height;
col = hmargin;

for ( cp = lp[line]; *cp != '\0'; ++cp )
{
copy_rect( font, char_row0[*cp - ' '], char_col0[*cp - ' '],
char_height, char_width, bits, row, col );
col += char_width;
}
}

/* All done. */
pbm_writepbm( stdout, bits, cols, rows, 0 );

exit( 0 );
}

static void
fix_control_chars( buf )
char* buf;
{
int i, j, n, l;

for ( i = 0; buf[i] != '\0'; ++i )
{
if ( buf[i] == '\t' )
{ /* Turn tabs into the right number of spaces. */
n = ( i + 8 ) / 8 * 8;
l = strlen( buf );
for ( j = l; j > i; --j )
buf[j + n - i - 1] = buf[j];
for ( ; i < n; ++i )
buf[i] = ' ';
--i;
}
else if ( buf[i] < ' ' || buf[i] > '~' )
/* Turn other control chars into a single space. */
buf[i] = ' ';
}
}

#if __STDC__
static void
fill_rect( bit** bits, int row0, int col0, int height, int width, bit color )
#else /*__STDC__*/
static void
fill_rect( bits, row0, col0, height, width, color )
bit** bits;
int row0, col0, height, width;
bit color;
#endif /*__STDC__*/
{
int row, col;

for ( row = row0; row < row0 + height; ++row )
for ( col = col0; col < col0 + width; ++col )
bits[row][col] = color;
}

static void
copy_rect( fbits, frow0, fcol0, height, width, tbits, trow0, tcol0 )
bit** fbits;
int frow0, fcol0, height, width;
bit** tbits;
int trow0, tcol0;
{
int row, col;

for ( row = 0; row < height; ++row )
for ( col = 0; col < width; ++col )
tbits[trow0 + row][tcol0 + col] = fbits[frow0 + row][fcol0 + col];
}
/*__STDC__*/
static void
putbit(b)
bit b;
#endif /*__STDC__*/
{
if (b == PBM_BLACK)
item += 1 << bitshift;
bitshift--;
if (bitsperitem == 8)
{
putitem();
bitshift = 7;
}
bitsperitem++;
}

static void
putrest()
{
if (bitsperitem > 1)
putitem();

/* end raster downloading */
printf("\033\134");

/* Exit raster mode */
printf("\033t");

/* Exit graphics wpbmplus05oct91/pbm/pbmtomacp.c 444 3010 34 14277 5032725031 11561 /* pbmtomacp.c - read a portable bitmap and produce a MacPaint bitmap file
**
** Copyright (C) 1988 by Douwe vand der Schaaf.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "macp.h"

#define TRUE 1
#define FALSE 0
#define EQUAL 1
#define UNEQUAL 0

static void fillbits ARGS(( bit **bits, bit **bitsr, int top, int left, int bottom, int right ));
static void writemacp ARGS(( bit **bits ));
static int packit ARGS(( bit *pb, bit *bits ));
static void filltemp ARGS(( bit *dest, bit *src ));
static void sendbytes ARGS(( bit *pb, register int npb ));
static void header ARGS(( void ));

static FILE *fdout;

void main(argc, argv)
int argc;
char *argv[];
{ FILE *ifp;
register bit **bits, **bitsr;
int argn, rows, cols;
int left,bottom,right,top;
int lflg, rflg, tflg, bflg;
char name[100];
char *usage = "[-l left] [-r right] [-b bottom] [-t top] [pbmfile]";

pbm_init( &argc, argv );

argn = 1;
fdout = stdout;
lflg = rflg = tflg = bflg = 0;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{ switch ( argv[argn][1] )
{ case 'l':
lflg++;
argn++;
left = atoi( argv[argn] );
break;

case 'r':
rflg++;
argn++;
right = atoi( argv[argn] );
break;

case 't':
tflg++;
argn++;
top = atoi( argv[argn] );
break;

case 'b':
bflg++;
argn++;
bottom = atoi( argv[argn] );
break;

case '?':
default:
pm_usage( usage );
}
++argn;
}

if ( argn == argc )
{ ifp = stdin;
strcpy( name, "noname" );
}
else
{ ifp = pm_openr( argv[argn] );
strcpy( name, argv[argn] );
++argn;
}

if ( argn != argc )
pm_usage( usage );

bitsr = pbm_readpbm( ifp, &cols, &rows );

pm_close( ifp );

bits = pbm_allocarray( MAX_COLS, MAX_LINES );

if( !lflg )
left = 0;

if( rflg )
{ if( right - left >= MAX_COLS )
right = left + MAX_COLS - 1;
}
else
right = ( left + MAX_COLS > cols ) ? ( cols - 1 ) : ( left + MAX_COLS - 1 );

if( !tflg )
top = 0;

if( bflg )
{ if( bottom - top >= MAX_LINES )
bottom = top + MAX_LINES - 1;
}
else
bottom = ( top + MAX_LINES > rows ) ?
( rows - 1 ) : ( top + MAX_LINES - 1 );

if( right <= left || left < 0 || right - left + 1 > MAX_COLS )
pm_error("error in right (= %d) and/or left (=%d)",right,left );
if( bottom <= top || top < 0 || bottom - top + 1 > MAX_LINES )
pm_error("error in bottom (= %d) and/or top (=%d)",bottom,top );

fillbits( bits, bitsr, top, left, bottom, right );

writemacp( bits );

exit( 0 );

}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - */

/* centreer het over te zenden plaatje in het MacPaint document
*
* Het plaatje wordt vanaf al of niet opgegeven (left, bottom)
* in een pbm bitmap van de juist macpaint afmetingen gezet,
* en eventueel afgekapt.
*/
static void
fillbits( bits, bitsr, top, left, bottom, right )
bit **bits, **bitsr;
int top, left, bottom, right;
{ register bit *bi, *bir;
register int i, j;
register int bottomr, leftr, topr, rightr;
int width, height;

width = right - left + 1;
leftr = (MAX_COLS - width) / 2;
rightr = leftr + width - 1;

height = bottom - top + 1;
topr = ( MAX_LINES - height ) / 2;
bottomr = topr + height - 1;

for( i = 0; i < topr; i++ )
{ bi = bits[i];
for( j = 0; j < MAX_COLS; j++ )
*bi++ = 0;
}

for( i = topr; i <= bottomr; i++ )
{ bi = bits[i];
{ for( j = 0; j < leftr; j++ )
*bi++ = 0;
bir = bitsr[ i - topr + top ];
for( j = leftr; j <= rightr; j++ )
*bi++ = bir[j - leftr + left];
for( j = rightr + 1; j < MAX_COLS; j++ )
*bi++ = 0;
} }

for( i = bottomr + 1; i < MAX_LINES; i++ )
{ bi = bits[i];
for( j = 0; j < MAX_COLS; j++ )
*bi++ = 0;
}
} /* fillbits */

/* - - - - - - - - - - - - - - - - - - - - - - - - - - */

static void
writemacp( bits )
bit **bits;
{ register int i;
bit pb[MAX_COLS * 2];
int npb;

header();
for( i=0; i < MAX_LINES; i++ )
{ npb = packit( pb, bits[i] );
sendbytes( pb, npb );
}
} /* writemacp */

/* - - - - - - - - - - - - - - - - - - - - - - - - - - */

/* pack regel van MacPaint doc in Apple's format
* return value = # of bytes in pb
*/
static int
packit( pb, bits )
bit *pb, *bits;
{ register int charcount, npb, newcount, flg;
bit temp[72];
bit *count, *srcb, *destb, save;

srcb = bits; destb = temp;
filltemp( destb, srcb );
srcb = temp;
destb = pb;
npb = 0;
charcount = BYTES_WIDE;
flg = EQUAL;
while( charcount )
{ save = *srcb++;
charcount--;
newcount = 1;
while( (*srcb == save) && charcount )
{ srcb++;
newcount++;
charcount--;
}
if( newcount > 2 )
{ count = destb++;
*count = 257 - newcount;
*destb++ = save;
npb += 2;
flg = EQUAL;
}
else
{ if( flg == EQUAL )
{ count = destb++;
*count = newcount - 1;
npb++;
}
else
*count += newcount;
while( newcount-- )
{ *destb++ = save;
npb++;
}
flg = UNEQUAL;
} }
return npb;
} /* packit */

/* - - - - - - - - - - - - - - - - - - - - - - - - - - */

static void
filltemp( dest, src )
bit *dest, *src;
{ register unsigned char ch, zero, acht;
register int i, j;

zero = '\0';
acht = 8;
i = BYTES_WIDE;
while( i-- )
{ ch = zero;
j = acht;
while( j-- )
{ ch <<= 1;
if( *src++ )
ch++;
}
*dest++ = ch;
}
} /* filltemp */

/* - - - - - - - - - - - - - - - - - - - - - - - - - - */

static void
sendbytes( pb, npb )
bit *pb;
register int npb;
{ register bit *b;

b = pb;
while( npb-- )
putc( *b++, fdout );
} /* sendbytes */

/* - - - - - - - - - - - - - - - - - - - - - - - - - - */

static void
header()
{ register int i;
register char ch;

/* header contains nothing ... */
ch = '\0';
for(i = 0; i < HEADER_LENGTH; i++ )
putc( ch, fdout );
} /* header */
PBM_BLACK)
item += 1 << bitshift;
bitshift--;
if (bitsperitem == 8)
{
putitem();
bitshift = 7;
}
bitsperitem++;
}

static void
putrest()
{
if (bitsperitem > 1)
putitem();

/* end raster downloading */
printf("\033\134");

/* Exit raster mode */
printf("\033t");

/* Exit graphics wpbmplus05oct91/pbm/g3.h 444 3010 34 14633 4550530160 10112 /* g3.h - header file for group 3 FAX compression filters
*/

#ifndef _G3_H_
#define _G3_H_

typedef struct tableentry {
int tabid;
int code;
int length;
int count;
} tableentry;

#define TWTABLE 23
#define MWTABLE 24
#define TBTABLE 25
#define MBTABLE 26
#define EXTABLE 27
#define VRTABLE 28

static struct tableentry twtable[] = {
{ TWTABLE, 0x35, 8, 0 },
{ TWTABLE, 0x7, 6, 1 },
{ TWTABLE, 0x7, 4, 2 },
{ TWTABLE, 0x8, 4, 3 },
{ TWTABLE, 0xb, 4, 4 },
{ TWTABLE, 0xc, 4, 5 },
{ TWTABLE, 0xe, 4, 6 },
{ TWTABLE, 0xf, 4, 7 },
{ TWTABLE, 0x13, 5, 8 },
{ TWTABLE, 0x14, 5, 9 },
{ TWTABLE, 0x7, 5, 10 },
{ TWTABLE, 0x8, 5, 11 },
{ TWTABLE, 0x8, 6, 12 },
{ TWTABLE, 0x3, 6, 13 },
{ TWTABLE, 0x34, 6, 14 },
{ TWTABLE, 0x35, 6, 15 },
{ TWTABLE, 0x2a, 6, 16 },
{ TWTABLE, 0x2b, 6, 17 },
{ TWTABLE, 0x27, 7, 18 },
{ TWTABLE, 0xc, 7, 19 },
{ TWTABLE, 0x8, 7, 20 },
{ TWTABLE, 0x17, 7, 21 },
{ TWTABLE, 0x3, 7, 22 },
{ TWTABLE, 0x4, 7, 23 },
{ TWTABLE, 0x28, 7, 24 },
{ TWTABLE, 0x2b, 7, 25 },
{ TWTABLE, 0x13, 7, 26 },
{ TWTABLE, 0x24, 7, 27 },
{ TWTABLE, 0x18, 7, 28 },
{ TWTABLE, 0x2, 8, 29 },
{ TWTABLE, 0x3, 8, 30 },
{ TWTABLE, 0x1a, 8, 31 },
{ TWTABLE, 0x1b, 8, 32 },
{ TWTABLE, 0x12, 8, 33 },
{ TWTABLE, 0x13, 8, 34 },
{ TWTABLE, 0x14, 8, 35 },
{ TWTABLE, 0x15, 8, 36 },
{ TWTABLE, 0x16, 8, 37 },
{ TWTABLE, 0x17, 8, 38 },
{ TWTABLE, 0x28, 8, 39 },
{ TWTABLE, 0x29, 8, 40 },
{ TWTABLE, 0x2a, 8, 41 },
{ TWTABLE, 0x2b, 8, 42 },
{ TWTABLE, 0x2c, 8, 43 },
{ TWTABLE, 0x2d, 8, 44 },
{ TWTABLE, 0x4, 8, 45 },
{ TWTABLE, 0x5, 8, 46 },
{ TWTABLE, 0xa, 8, 47 },
{ TWTABLE, 0xb, 8, 48 },
{ TWTABLE, 0x52, 8, 49 },
{ TWTABLE, 0x53, 8, 50 },
{ TWTABLE, 0x54, 8, 51 },
{ TWTABLE, 0x55, 8, 52 },
{ TWTABLE, 0x24, 8, 53 },
{ TWTABLE, 0x25, 8, 54 },
{ TWTABLE, 0x58, 8, 55 },
{ TWTABLE, 0x59, 8, 56 },
{ TWTABLE, 0x5a, 8, 57 },
{ TWTABLE, 0x5b, 8, 58 },
{ TWTABLE, 0x4a, 8, 59 },
{ TWTABLE, 0x4b, 8, 60 },
{ TWTABLE, 0x32, 8, 61 },
{ TWTABLE, 0x33, 8, 62 },
{ TWTABLE, 0x34, 8, 63 },
};

static struct tableentry mwtable[] = {
{ MWTABLE, 0x1b, 5, 64 },
{ MWTABLE, 0x12, 5, 128 },
{ MWTABLE, 0x17, 6, 192 },
{ MWTABLE, 0x37, 7, 256 },
{ MWTABLE, 0x36, 8, 320 },
{ MWTABLE, 0x37, 8, 384 },
{ MWTABLE, 0x64, 8, 448 },
{ MWTABLE, 0x65, 8, 512 },
{ MWTABLE, 0x68, 8, 576 },
{ MWTABLE, 0x67, 8, 640 },
{ MWTABLE, 0xcc, 9, 704 },
{ MWTABLE, 0xcd, 9, 768 },
{ MWTABLE, 0xd2, 9, 832 },
{ MWTABLE, 0xd3, 9, 896 },
{ MWTABLE, 0xd4, 9, 960 },
{ MWTABLE, 0xd5, 9, 1024 },
{ MWTABLE, 0xd6, 9, 1088 },
{ MWTABLE, 0xd7, 9, 1152 },
{ MWTABLE, 0xd8, 9, 1216 },
{ MWTABLE, 0xd9, 9, 1280 },
{ MWTABLE, 0xda, 9, 1344 },
{ MWTABLE, 0xdb, 9, 1408 },
{ MWTABLE, 0x98, 9, 1472 },
{ MWTABLE, 0x99, 9, 1536 },
{ MWTABLE, 0x9a, 9, 1600 },
{ MWTABLE, 0x18, 6, 1664 },
{ MWTABLE, 0x9b, 9, 1728 },
};

static struct tableentry tbtable[] = {
{ TBTABLE, 0x37, 10, 0 },
{ TBTABLE, 0x2, 3, 1 },
{ TBTABLE, 0x3, 2, 2 },
{ TBTABLE, 0x2, 2, 3 },
{ TBTABLE, 0x3, 3, 4 },
{ TBTABLE, 0x3, 4, 5 },
{ TBTABLE, 0x2, 4, 6 },
{ TBTABLE, 0x3, 5, 7 },
{ TBTABLE, 0x5, 6, 8 },
{ TBTABLE, 0x4, 6, 9 },
{ TBTABLE, 0x4, 7, 10 },
{ TBTABLE, 0x5, 7, 11 },
{ TBTABLE, 0x7, 7, 12 },
{ TBTABLE, 0x4, 8, 13 },
{ TBTABLE, 0x7, 8, 14 },
{ TBTABLE, 0x18, 9, 15 },
{ TBTABLE, 0x17, 10, 16 },
{ TBTABLE, 0x18, 10, 17 },
{ TBTABLE, 0x8, 10, 18 },
{ TBTABLE, 0x67, 11, 19 },
{ TBTABLE, 0x68, 11, 20 },
{ TBTABLE, 0x6c, 11, 21 },
{ TBTABLE, 0x37, 11, 22 },
{ TBTABLE, 0x28, 11, 23 },
{ TBTABLE, 0x17, 11, 24 },
{ TBTABLE, 0x18, 11, 25 },
{ TBTABLE, 0xca, 12, 26 },
{ TBTABLE, 0xcb, 12, 27 },
{ TBTABLE, 0xcc, 12, 28 },
{ TBTABLE, 0xcd, 12, 29 },
{ TBTABLE, 0x68, 12, 30 },
{ TBTABLE, 0x69, 12, 31 },
{ TBTABLE, 0x6a, 12, 32 },
{ TBTABLE, 0x6b, 12, 33 },
{ TBTABLE, 0xd2, 12, 34 },
{ TBTABLE, 0xd3, 12, 35 },
{ TBTABLE, 0xd4, 12, 36 },
{ TBTABLE, 0xd5, 12, 37 },
{ TBTABLE, 0xd6, 12, 38 },
{ TBTABLE, 0xd7, 12, 39 },
{ TBTABLE, 0x6c, 12, 40 },
{ TBTABLE, 0x6d, 12, 41 },
{ TBTABLE, 0xda, 12, 42 },
{ TBTABLE, 0xdb, 12, 43 },
{ TBTABLE, 0x54, 12, 44 },
{ TBTABLE, 0x55, 12, 45 },
{ TBTABLE, 0x56, 12, 46 },
{ TBTABLE, 0x57, 12, 47 },
{ TBTABLE, 0x64, 12, 48 },
{ TBTABLE, 0x65, 12, 49 },
{ TBTABLE, 0x52, 12, 50 },
{ TBTABLE, 0x53, 12, 51 },
{ TBTABLE, 0x24, 12, 52 },
{ TBTABLE, 0x37, 12, 53 },
{ TBTABLE, 0x38, 12, 54 },
{ TBTABLE, 0x27, 12, 55 },
{ TBTABLE, 0x28, 12, 56 },
{ TBTABLE, 0x58, 12, 57 },
{ TBTABLE, 0x59, 12, 58 },
{ TBTABLE, 0x2b, 12, 59 },
{ TBTABLE, 0x2c, 12, 60 },
{ TBTABLE, 0x5a, 12, 61 },
{ TBTABLE, 0x66, 12, 62 },
{ TBTABLE, 0x67, 12, 63 },
};

static struct tableentry mbtable[] = {
{ MBTABLE, 0xf, 10, 64 },
{ MBTABLE, 0xc8, 12, 128 },
{ MBTABLE, 0xc9, 12, 192 },
{ MBTABLE, 0x5b, 12, 256 },
{ MBTABLE, 0x33, 12, 320 },
{ MBTABLE, 0x34, 12, 384 },
{ MBTABLE, 0x35, 12, 448 },
{ MBTABLE, 0x6c, 13, 512 },
{ MBTABLE, 0x6d, 13, 576 },
{ MBTABLE, 0x4a, 13, 640 },
{ MBTABLE, 0x4b, 13, 704 },
{ MBTABLE, 0x4c, 13, 768 },
{ MBTABLE, 0x4d, 13, 832 },
{ MBTABLE, 0x72, 13, 896 },
{ MBTABLE, 0x73, 13, 960 },
{ MBTABLE, 0x74, 13, 1024 },
{ MBTABLE, 0x75, 13, 1088 },
{ MBTABLE, 0x76, 13, 1152 },
{ MBTABLE, 0x77, 13, 1216 },
{ MBTABLE, 0x52, 13, 1280 },
{ MBTABLE, 0x53, 13, 1344 },
{ MBTABLE, 0x54, 13, 1408 },
{ MBTABLE, 0x55, 13, 1472 },
{ MBTABLE, 0x5a, 13, 1536 },
{ MBTABLE, 0x5b, 13, 1600 },
{ MBTABLE, 0x64, 13, 1664 },
{ MBTABLE, 0x65, 13, 1728 },
};

static struct tableentry extable[] = {
{ EXTABLE, 0x8, 11, 1792 },
{ EXTABLE, 0xc, 11, 1856 },
{ EXTABLE, 0xd, 11, 1920 },
{ EXTABLE, 0x12, 12, 1984 },
{ EXTABLE, 0x13, 12, 2048 },
{ EXTABLE, 0x14, 12, 2112 },
{ EXTABLE, 0x15, 12, 2176 },
{ EXTABLE, 0x16, 12, 2240 },
{ EXTABLE, 0x17, 12, 2304 },
{ EXTABLE, 0x1c, 12, 2368 },
{ EXTABLE, 0x1d, 12, 2432 },
{ EXTABLE, 0x1e, 12, 2496 },
{ EXTABLE, 0x1f, 12, 2560 },
};

#endif /*_G3_H_*/
- - - - - - - - - - - - - - - - - - */

static void
filltemp( dest, src )
bit *dest, *src;
{ registepbmplus05oct91/pbm/pbmtog3.1 444 3010 34 1543 5022774205 11046 .TH pbmtog3 1 "02 October 1989"
.IX pbmtog3
.SH NAME
pbmtog3 - convert a portable bitmap into a Group 3 fax file
.SH SYNOPSIS
.B pbmtog3
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as output.
Produces a Group 3 fax file as input.
.IX "Group 3 fax"
.IX fax
.SH REFERENCES
The standard for Group 3 fax is defined in CCITT Recommendation T.4.
.SH BUGS
Probably.
.SH "SEE ALSO"
g3topbm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1989 by Paul Haeberli .
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
bm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/Makefile 444 3010 34 12055 5070703537 11074 # Makefile for pbm tools.
#
# Copyright (C) 1989, 1991 by Jef Poskanzer.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted, provided
# that the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation. This software is provided "as is" without express or
# implied warranty.

# Default values, usually overridden by top-level Makefile.
#CC = cc
CC = gcc -ansi -pedantic -fcombine-regs -fpcc-struct-return
#CFLAGS = -O
CFLAGS = -g
#CFLAGS = -g -O
RGBDEF = -DRGB_DB=\"/usr/lib/X11/rgb.txt\"
TIFFDEF = -DLIBTIFF
#LDFLAGS = -s
LDFLAGS =
INSTALLBINARIES = /usr/new/pbm
INSTALLMANUALS1 = /usr/man/man1
SUFFIXMANUALS1 = 1
INSTALLMANUALS3 = /usr/man/man3
SUFFIXMANUALS3 = 3
INSTALLMANUALS5 = /usr/man/man5
SUFFIXMANUALS5 = 5
MANCP = cp

SHELL = /bin/sh
INCLUDE = -I..
ALLCFLAGS = $(CFLAGS) $(RGBDEF) $(TIFFDEF) $(INCLUDE)
LIBPBM = libpbm.a
DEFPBM = pbm.h ../pbmplus.h

BINARIES = atktopbm brushtopbm cmuwmtopbm g3topbm \
icontopbm gemtopbm macptopbm mgrtopbm \
pbmlife pbmmake pbmmask pbmreduce \
pbmtext pbmto10x pbmtoascii pbmtoatk \
pbmtobbnbg pbmtocmuwm pbmtoepson pbmtog3 \
pbmtogem pbmtogo pbmtoicon pbmtolj pbmtomacp \
pbmtomgr pbmtopi3 pbmtoplot pbmtoptx \
pbmtox10bm pbmtoxbm pbmtoybm pbmtozinc \
pbmupc pi3topbm xbmtopbm \
ybmtopbm

OBJECTS = atktopbm.o brushtopbm.o cmuwmtopbm.o g3topbm.o \
icontopbm.o gemtopbm.o macptopbm.o mgrtopbm.o \
pbmlife.o pbmmake.o pbmmask.o pbmreduce.o \
pbmtext.o pbmto10x.o pbmtoascii.o pbmtoatk.o \
pbmtobbnbg.o pbmtocmuwm.o pbmtoepson.o pbmtog3.o \
pbmtogem.o pbmtogo.o pbmtoicon.o pbmtolj.o pbmtomacp.o \
pbmtomgr.o pbmtopi3.o pbmtoplot.o pbmtoptx.o \
pbmtox10bm.o pbmtoxbm.o pbmtoybm.o pbmtozinc.o \
pbmupc.o pi3topbm.o xbmtopbm.o \
ybmtopbm.o

MANUALS1 = $(BINARIES)
MANUALS3 = libpbm
MANUALS5 = pbm


#all: binaries
all: merge
#install: install.bin
install: install.merge


binaries: $(BINARIES)

install.bin: binaries
cd $(INSTALLBINARIES) ; rm -f $(BINARIES)
cp $(BINARIES) $(INSTALLBINARIES)


merge: pbmmerge
pbmmerge: pbmmerge.c $(OBJECTS) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] $(OBJECTS) $(LIBPBM)

install.merge: install.pbmmerge
install.pbmmerge: pbmmerge
cd $(INSTALLBINARIES) ; rm -f $(BINARIES)
cp pbmmerge $(INSTALLBINARIES)
cd $(INSTALLBINARIES) ; for i in $(BINARIES) ; do ln pbmmerge $$i ; done
rm $(INSTALLBINARIES)/pbmmerge


install.man:
for i in $(MANUALS1) ; do \
rm -f $(INSTALLMANUALS1)/$$i.$(SUFFIXMANUALS1) ; \
$(MANCP) $$i.1 $(INSTALLMANUALS1)/$$i.$(SUFFIXMANUALS1) ; \
done
for i in $(MANUALS3) ; do \
rm -f $(INSTALLMANUALS3)/$$i.$(SUFFIXMANUALS3) ; \
$(MANCP) $$i.3 $(INSTALLMANUALS3)/$$i.$(SUFFIXMANUALS3) ; \
done
for i in $(MANUALS5) ; do \
rm -f $(INSTALLMANUALS5)/$$i.$(SUFFIXMANUALS5) ; \
$(MANCP) $$i.5 $(INSTALLMANUALS5)/$$i.$(SUFFIXMANUALS5) ; \
done


# Rules for plain programs.
$(BINARIES): $(DEFPBM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] $(LIBPBM)
$(OBJECTS): $(DEFPBM)
$(CC) $(ALLCFLAGS) "-Dmain=$*_main" -c $*.c

# And library.
lib: $(LIBPBM)
$(LIBPBM): libpbm1.o libpbm2.o libpbm3.o libpbm4.o libpbm5.o
-rm $(LIBPBM)
ar rc $(LIBPBM) libpbm1.o libpbm2.o libpbm3.o libpbm4.o libpbm5.o
-ranlib $(LIBPBM)

libpbm1.o: $(DEFPBM) ../version.h libpbm.h libpbm1.c
$(CC) $(ALLCFLAGS) -c libpbm1.c
libpbm2.o: $(DEFPBM) libpbm.h libpbm2.c
$(CC) $(ALLCFLAGS) -c libpbm2.c
libpbm3.o: $(DEFPBM) libpbm.h libpbm3.c
$(CC) $(ALLCFLAGS) -c libpbm3.c
libpbm4.o: $(DEFPBM) libpbm.h libpbm4.c
$(CC) $(ALLCFLAGS) -c libpbm4.c
libpbm5.o: $(DEFPBM) pbmfont.h libpbm5.c
$(CC) $(ALLCFLAGS) -c libpbm5.c

# Other dependencies.
atktopbm atktopbm.o: atktopbm.c
brushtopbm brushtopbm.o: brushtopbm.c
cmuwmtopbm cmuwmtopbm.o: cmuwmtopbm.c cmuwm.h
g3topbm g3topbm.o: g3topbm.c g3.h
icontopbm icontopbm.o: icontopbm.c
gemtopbm gemtopbm.o: gemtopbm.c
macptopbm macptopbm.o: macptopbm.c macp.h
mgrtopbm mgrtopbm.o: mgrtopbm.c mgr.h
pbmlife pbmlife.o: pbmlife.c
pbmmake pbmmake.o: pbmmake.c
pbmmask pbmmask.o: pbmmask.c
pbmreduce pbmreduce.o: pbmreduce.c
pbmtext pbmtext.o: pbmtext.c pbmfont.h
pbmto10x pbmto10x.o: pbmto10x.c
pbmtoascii pbmtoascii.o: pbmtoascii.c
pbmtoatk pbmtoatk.o: pbmtoatk.c
pbmtobbnbg pbmtobbnbg.o: pbmtobbnbg.c
pbmtocmuwm pbmtocmuwm.o: pbmtocmuwm.c cmuwm.h
pbmtoepson pbmtoepson.o: pbmtoepson.c
pbmtog3 pbmtog3.o: pbmtog3.c g3.h
pbmtogem pbmtogem.o: pbmtogem.c
pbmtogo pbmtogo.o: pbmtogo.c
pbmtoicon pbmtoicon.o: pbmtoicon.c
pbmtolj pbmtolj.o: pbmtolj.c
pbmtomacp pbmtomacp.o: pbmtomacp.c macp.h
pbmtomgr pbmtomgr.o: pbmtomgr.c mgr.h
pbmtopi3 pbmtopi3.o: pbmtopi3.c
pbmtoplot pbmtoplot.o: pbmtoplot.c
pbmtoptx pbmtoptx.o: pbmtoptx.c
pbmtox10bm pbmtox10bm.o: pbmtox10bm.c
pbmtoxbm pbmtoxbm.o: pbmtoxbm.c
pbmtoybm pbmtoybm.o: pbmtoybm.c
pbmtozinc pbmtozinc.o: pbmtozinc.c
pbmupc pbmupc.o: pbmupc.c
pi3topbm pi3topbm.o: pi3topbm.c
xbmtopbm xbmtopbm.o: xbmtopbm.c
ybmtopbm ybmtopbm.o: ybmtopbm.c

clean:
-rm -f *.o *.a *.cat core $(BINARIES) pbmmerge
74, 13, 1024 },
{ MBTABLE, 0x75, 13, 1088 },
{ MBTABLE, 0x76, 13, 1152 },
{ MBTABLE, 0x77, 13, 1216 },
{ MBTABLE, 0x52, 13, 1280 },
{ MBTABLE, 0x53, 13, 1344 },
{ MBTABLE, 0x54, 13, 1408 },
{ MBTABLE, 0x55, 13, 1472 },
{ MBTABLE, 0x5a, 13, 1536 },
{ MBTABLE, 0x5b, 13, 1600 },
{ MBTABLE, 0x64, 13, 1664 },
{ MBTABLE, 0x65, 13, 1728 },
};

static struct tableentry extable[] = {
{ EXTABLE, 0x8, 11, 1792 },
{ EXTpbmplus05oct91/pbm/icontopbm.c 444 3010 34 6645 5032724771 11563 /* icontopbm.c - read a Sun icon file and produce a portable bitmap
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

static void ReadIconFile ARGS(( FILE* file, int* width, int* height, short** data ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, row, col, shortcount, mask;
short* data;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[iconfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

ReadIconFile( ifp, &cols, &rows, &data );

pm_close( ifp );

pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

for ( row = 0; row < rows; row++ )
{
shortcount = 0;
mask = 0x8000;
for ( col = 0, bP = bitrow; col < cols; col++, bP++ )
{
if ( shortcount >= 16 )
{
data++;
shortcount = 0;
mask = 0x8000;
}
*bP = ( *data & mask ) ? PBM_BLACK : PBM_WHITE;
shortcount++;
mask = mask >> 1;
}
data++;
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}

exit( 0 );
}

/* size in bytes of a bitmap */
#define BitmapSize(width, height) (((((width) + 15) >> 3) &~ 1) * (height))

static void
ReadIconFile( file, width, height, data )
FILE* file;
int* width;
int* height;
short** data;
{
char variable[81], ch;
int status, value, i, data_length, gotsome;

gotsome = 0;
*width = *height = -1;
for ( ; ; )
{
while ( ( ch = getc( file ) ) == ',' || ch == '\n' || ch == '\t' ||
ch == ' ' )
;
for ( i = 0;
ch != '=' && ch != ',' && ch != '\n' && ch != '\t' && ch != ' ';
i++ )
{
variable[i] = ch;
ch = getc( file );
}
variable[i] = '\0';

if ( strcmp( variable, "*/" ) == 0 && gotsome )
break;

if ( fscanf( file, "%d", &value ) != 1 )
continue;

if ( strcmp( variable, "Width" ) == 0 )
{
*width = value;
gotsome = 1;
}
else if ( strcmp( variable, "Height" ) == 0 )
{
*height = value;
gotsome = 1;
}
else if ( strcmp( variable, "Depth" ) == 0 )
{
if ( value != 1 )
pm_error( "invalid depth" );
gotsome = 1;
}
else if ( strcmp( variable, "Format_version" ) == 0 )
{
if ( value != 1 )
pm_error( "invalid Format_version" );
gotsome = 1;
}
else if ( strcmp( variable, "Valid_bits_per_item" ) == 0 )
{
if ( value != 16 )
pm_error( "invalid Valid_bits_per_item" );
gotsome = 1;
}
}

if ( *width <= 0 )
pm_error( "invalid width: %d", *width );
if ( *height <= 0 )
pm_error( "invalid height: %d", *height );

data_length = BitmapSize( *width, *height );
*data = (short*) malloc( data_length );
if ( *data == NULL )
pm_error( "out of memory" );
data_length /= sizeof( short );

for ( i = 0 ; i < data_length; i++ )
{
if ( i == 0 )
status = fscanf( file, " 0x%4hx", *data );
else
status = fscanf( file, ", 0x%4hx", *data + i );
if ( status != 1 )
pm_error( "error 4 scanning bits item" );
}
}
: pi3topbm.c
xbmtopbm xbmtopbm.o: xbmtopbm.c
ybmtopbm ybmtopbm.o: ybmtopbm.c

clean:
-rpbmplus05oct91/pbm/pbmmake.1 444 3010 34 2001 5022776765 11112 .TH pbmmake 1 "22 February 1989"
.IX pbmmake
.SH NAME
pbmmake - create a blank bitmap of a specified size
.SH SYNOPSIS
.B pbmmake
.RB [ -white | -black | -gray
.RB ]
.I width height
.SH DESCRIPTION
Produces a portable bitmap of the specified width and height.
.IX "generating bitmaps"
The color defaults to white.
.SH OPTIONS
.PP
In addition to the usual
.B -white
and
.BR -black ,
this program implements
.BR -gray .
This gives a simple 50% gray pattern with 1's and 0's alternating.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH "SEE ALSO"
pbm(5), ppmmake(1)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
1e.
pbmtoxbm.1.ž pbmtox10bm.cNSt.Ÿ pbmtox10bm.1¨ . 
pbmtogem.1 .¡ bitreverse.hms.¢macp.hf.£ pbmtolj.1
.¤ pbmmake.c.¥ pbmtocmuwm.1ip-.¦ pbmtomacp.1appl.§
pbmtomgr.1d.¨pbmupc.1 .©libpbm.h¾(.ª pbmlife.cpm.« pbmreduce.cZ•.¬mgr.h5.­
pbmto10x.ct.®
pbmtoxbm.c.¯pbmupc.c.°
xbmtopbm.c.± libpbm3.cc-.² libpbm1.cb.³ libpbm4.c
.´ pbmtoepson.1.µpbmplus05oct91/pbm/macptopbm.c 444 3010 34 6557 5032725001 11540 /* macptopbm.c - read a MacPaint file and produce a portable bitmap
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "macp.h"

static void ReadMacPaintFile ARGS(( FILE* file, int extraskip, int* scanLineP, unsigned char Pic[MAX_LINES][BYTES_WIDE] ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
unsigned char Pic[MAX_LINES][BYTES_WIDE];
bit* bitrow;
int argn, extraskip, scanLine, rows, cols, row, bcol, i;
char* usage = "[-extraskip N] [macpfile]";

pbm_init( &argc, argv );

argn = 1;
extraskip = 0;

/* Check for flags. */
if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-extraskip", 2 ) )
{
argn++;
if ( argn == argc || sscanf( argv[argn], "%d", &extraskip ) != 1 )
pm_usage( usage );
}
else
pm_usage( usage );
argn++;
}

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
argn++;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

ReadMacPaintFile( ifp, extraskip, &scanLine, Pic );

pm_close( ifp );

cols = BYTES_WIDE * 8;
rows = scanLine;
pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

for ( row = 0; row < rows; row++ )
{
for ( bcol = 0; bcol < BYTES_WIDE; bcol++ )
for ( i = 0; i < 8; i++ )
bitrow[bcol * 8 + i] =
( (Pic[row][bcol] >> (7 - i)) & 1 ) ? PBM_BLACK : PBM_WHITE;
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}

exit( 0 );
}

/*
** Some of the following routine is:
**
** Copyright 1987 by Patrick J. Naughton
** All Rights Reserved
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation.
*/

static void
ReadMacPaintFile( file, extraskip, scanLineP, Pic )
FILE* file;
int extraskip;
int* scanLineP;
unsigned char Pic[MAX_LINES][BYTES_WIDE];
{
unsigned int i, j, k;
unsigned char ch;

/* Skip over the header. */
for ( i = 0; i < extraskip; i++ )
getc( file );
for ( i = 0; i < HEADER_LENGTH; i++ )
getc( file );

*scanLineP = 0;
k = 0;

while ( *scanLineP < MAX_LINES )
{
ch = (unsigned char) getc( file ); /* Count byte */
i = (unsigned int) ch;
if ( ch < 0x80 )
{ /* Unpack next (I+1) chars as is */
for ( j = 0; j <= i; j++ )
if ( *scanLineP < MAX_LINES )
{
Pic[*scanLineP][k++] = (unsigned char) getc( file );
if ( ! (k %= BYTES_WIDE) )
*scanLineP += 1;
}
}
else
{ /* Repeat next char (2's comp I) times */
ch = getc( file );
for ( j = 0; j <= 256 - i; j++ )
if ( *scanLineP < MAX_LINES )
{
Pic[*scanLineP][k++] = (unsigned char) ch;
if ( ! (k %= BYTES_WIDE) )
*scanLineP += 1;
}
}
}
}
m_error( "error 4 scanning bits item" );
}
}
: pi3topbm.c
xbmtopbm xbmtopbm.o: xbmtopbm.c
ybmtopbm ybmtopbm.o: ybmtopbm.c

clean:
-rpbmplus05oct91/pbm/pbmreduce.1 444 3010 34 4023 5023045325 11430 .TH pbmreduce 1 "02 August 1989"
.IX pbmreduce
.SH NAME
pbmreduce - read a portable bitmap and reduce it N times
.SH SYNOPSIS
.B pbmreduce
.RB [ -floyd | -fs | -threshold
.RB ]
.RB [ -value
.IR val ]
.I N
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Reduces it by a factor of
.IR N ,
and produces a portable bitmap as output.
.IX shrinking
.PP
.I pbmreduce
duplicates a lot of the functionality of
.I pgmtopbm;
.IX pgmtopbm
you could do something like
.B pnmscale | pgmtopbm,
.IX pnmscale
but
.I pbmreduce
is a lot faster.
.PP
.I pbmreduce
can be used to "re-halftone" an image.
.IX halftoning
Let's say you have a scanner that only produces black&white, not
grayscale, and it does a terrible job of halftoning (most b&w scanners
fit this description).
One way to fix the halftoning is to scan at the highest possible
resolution, say 300 dpi, and then reduce by a factor of three or
so using
.IR pbmreduce .
You can even correct the brightness of an image, by using the
.B -value
flag.
.SH OPTIONS
.PP
By default, the halftoning after the reduction is done via
boustrophedonic Floyd-Steinberg error diffusion; however, the
.IX Floyd-Steinberg
.IX "error diffusion"
.B -threshold
flag can be used to specify simple thresholding. This gives better
.IX thresholding
results when reducing line drawings.
.PP
The
.B -value
flag alters the thresholding value for all quantizations.
It should be a real number between 0 and 1.
Above 0.5 means darker images; below 0.5 means lighter.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH "SEE ALSO"
pnmenlarge(1), pnmscale(1), pgmtopbm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
lot faster.
.PP
.I pbmreduce
can be used to "re-halftone" an image.
.IX halftoning
Let's say you have a scanner that only produces black&white, not
grayscale, and it does a terrible job of halftoning (most b&w scanners
fit this description).
One way to fix the halftoning is to scan at the highest possible
resolution, say 300 dpi, and then reduce by a factor of three or
so using
.IR pbmreduce .
You can even correct the brightness of an image, by using the
.B -value
flag.
.SH OPTIONS
.PP
Bpbmplus05oct91/pbm/xbmtopbm.1 444 3010 34 1413 5022774742 11325 .TH xbmtopbm 1 "31 August 1988"
.IX xbmtopbm
.SH NAME
xbmtopbm - convert an X11 or X10 bitmap into a portable bitmap
.SH SYNOPSIS
.B xbmtopbm
.RI [ bitmapfile ]
.SH DESCRIPTION
Reads an X11 or X10 bitmap as input.
Produces a portable bitmap as output.
.IX "X bitmap"
.IX "X window system"
.SH "SEE ALSO"
pbmtoxbm(1), pbmtox10bm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtoicon.1 444 3010 34 1343 5023002421 11444 .TH pbmtoicon 1 "31 August 1988"
.IX pbmtoicon
.SH NAME
pbmtoicon - convert a portable bitmap into a Sun icon
.SH SYNOPSIS
.B pbmtoicon
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a Sun icon as output.
.IX Sun
.IX "Sun icon format"
.SH "SEE ALSO"
icontopbm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
pbmtext.1. pbmtext.css.‘ pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtoptx.1 444 3010 34 1470 5022774456 11357 .TH pbmtoptx 1 "31 August 1988"
.IX pbmtoptx
.SH NAME
pbmtoptx - convert a portable bitmap into Printronix printer graphics
.SH SYNOPSIS
.B pbmtoptx
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a file of Printronix printer graphics as output.
.IX Printronix
.PP
Note that there is no ptxtopbm tool - this transformation is one way.
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
og3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmto10x.1 444 3010 34 2125 5022773740 11145 .TH pbmto10x 1 "1 January 1990"
.IX pbmto10x
.SH NAME
pbmto10x - convert a portable bitmap into Gemini 10X printer graphics
.SH SYNOPSIS
.B pbmto10x
.RB [ -h ]
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a file of Gemini 10X printer graphics as output.
.IX "Gemini 10X printer graphics"
The 10x's printer codes are alleged to be similar to the Epson codes.
.IX Epson
.PP
Note that there is no 10xtopbm tool - this transformation is one way.
.SH OPTIONS
.PP
The resolution is normally 60H by 72V.
If the
.B -h
flag is specified, resolution is 120H by 144V.
You may find it useful to rotate landscape images before printing.
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1990 by Ken Yap
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
gem.1 .¡ bitreverse.hms.¢macp.hf.£ pbmtolj.1
.¤ pbmmake.c.¥ pbmtocmuwm.1ip-.¦ pbmtomacp.1appl.§
pbmtomgr.1d.¨pbmupc.1 .©libpbm.h¾(.ª pbmlife.cpm.« pbmreduce.cZ•.¬mgr.h5.­
pbmto10x.ct.®
pbmtoxbm.c.¯pbmupc.c.°
xbmtopbm.c.± libpbm3.cc-.² libpbm1.cb.³ libpbm4.c
.´ pbmtoepson.1.µpbmplus05oct91/pbm/pbmtoxbm.1 444 3010 34 1372 5022774576 11336 .TH pbmtoxbm 1 "31 August 1988"
.IX pbmtoxbm
.SH NAME
pbmtoxbm - convert a portable bitmap into an X11 bitmap
.SH SYNOPSIS
.B pbmtoxbm
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces an X11 bitmap as output.
.IX "X bitmap"
.IX "X window system"
.SH "SEE ALSO"
pbmtox10bm(1), xbmtopbm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
mtext.css.‘ pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtox10bm.c 444 3010 34 5135 5032725040 11541 /* pbmtox10bm.c - read a portable bitmap and produce an X10 bitmap file
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, format, padright, row;
register int col;
char name[100];
char* cp;
int itemsperline;
register int bitsperitem;
register int item;
int firstitem;
char* hexchar = "0123456789abcdef";

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
{
ifp = pm_openr( argv[1] );
strcpy( name, argv[1] );
if ( strcmp( name, "-" ) == 0 )
strcpy( name, "noname" );

if ( ( cp = index( name, '.' ) ) != 0 )
*cp = '\0';
}
else
{
ifp = stdin;
strcpy( name, "noname" );
}

pbm_readpbminit( ifp, &cols, &rows, &format );
bitrow = pbm_allocrow( cols );

/* Compute padding to round cols up to the nearest multiple of 16. */
padright = ( ( cols + 15 ) / 16 ) * 16 - cols;

printf( "#define %s_width %d\n", name, cols );
printf( "#define %s_height %d\n", name, rows );
printf( "static short %s_bits[] = {\n", name );

itemsperline = 0;
bitsperitem = 0;
item = 0;
firstitem = 1;

#define PUTITEM \
{ \
if ( firstitem ) \
firstitem = 0; \
else \
putchar( ',' ); \
if ( itemsperline == 11 ) \
{ \
putchar( '\n' ); \
itemsperline = 0; \
} \
if ( itemsperline == 0 ) \
putchar( ' ' ); \
++itemsperline; \
putchar('0'); \
putchar('x'); \
putchar(hexchar[item >> 12]); \
putchar(hexchar[(item >> 8) & 15]); \
putchar(hexchar[(item >> 4) & 15]); \
putchar(hexchar[item & 15]); \
bitsperitem = 0; \
item = 0; \
}

#define PUTBIT(b) \
{ \
if ( bitsperitem == 16 ) \
PUTITEM; \
if ( (b) == PBM_BLACK ) \
item += 1 << bitsperitem; \
++bitsperitem; \
}

for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
PUTBIT(*bP);
for ( col = 0; col < padright; ++col )
PUTBIT(0);
}

pm_close( ifp );

if ( bitsperitem > 0 )
PUTITEM;
printf( "};\n" );

exit( 0 );
}
i < extraskip; i++ )
getc( file );
for ( i = 0; i < HEADER_LENGTH; i++ )
getc( file );

*scanLineP = 0;
k = 0;

while ( *scanLineP < MAX_LINES )
{
ch = (unsigned char) getc( file ); /* Count byte */
i = (unsigned int) ch;
if ( ch < 0x80 )
{ /* Unpack next (I+1) chars as is */
for ( j = 0; j <= i; j++ )
if ( *scanLineP < MAX_LINES )
{
Pic[*scanLineP][k++] = (unsigned charpbmplus05oct91/pbm/pbmtox10bm.1 444 3010 34 1625 5022774550 11470 .TH pbmtox10bm 1 "31 August 1988"
.IX pbmtox10bm
.SH NAME
pbmtox10bm - convert a portable bitmap into an X10 bitmap
.SH SYNOPSIS
.B pbmtox10bm
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces an X10 bitmap as output.
This older format is maintained for compatibility.
.IX "X bitmap"
.IX "X window system"
.PP
Note that there is no x10bmtopbm tool, because
.I xbmtopbm
can read both X11 and X10 bitmaps.
.SH "SEE ALSO"
pbmtoxbm(1), xbmtopbm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
ip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtogem.1 444 3010 34 1334 5022774246 11310 .TH pbmtogem 1 "11 March 1990"
.IX pbmtogem
.SH NAME
pbmtogem - convert a portable bitmap into a GEM .img file
.SH SYNOPSIS
.B pbmtogem
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a GEM .img file as output.
.IX GEM
.SH BUGS
It does not support compression of the data.
.SH "SEE ALSO"
gemtopbm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1988 by David Beckemeyer (bdt!david) and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted,
.\" provided that the above copyright notice appear in all copies and that
.\" both that copyright notice and this permission notice appear in
.\" supporting documentation.
. pbmtext.1. pbmtext.css.‘ pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/bitreverse.h 444 3010 34 4353 4523200264 11730 /*
** bitreverse.h
**
** This particular array seems to be useful in a lot of bitmap
** conversion programs. It's not used in pbm because bits are
** stored one per byte, for easier manipulation. But if you wanted
** to write, for example, a program to directly convert Sun raster
** format into X bitmaps, you could use this.
**
** Of course, you could also use this fairly slick chunk of code:
**
** c = ((c >> 1) & 0x55) | ((c << 1) & 0xaa);
** c = ((c >> 2) & 0x33) | ((c << 2) & 0xcc);
** c = ((c >> 4) & 0x0f) | ((c << 4) & 0xf0);
*/

#ifndef _BITR_H_
#define _BITR_H_

static unsigned char bitreverse[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
0x3f, 0xbf, 0x7f, 0xff};

#endif /*_BITR_H_*/
++bitsperitem; \
}

for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
PUTBIT(*bP);
for ( col = 0; col < padright; ++col )
PUTBIT(0);
}

pm_close( pbmplus05oct91/pbm/macp.h 444 3010 34 331 4523200361 10444 /* macp.h - header file for MacPaint files
*/

#ifndef _MACP_H_
#define _MACP_H_

#define HEADER_LENGTH 512
#define MAX_LINES 720
#define BYTES_WIDE 72
#define MAX_COLS 576 /* = BYTES_WIDE * 8 */

#endif /*_MACP_H_*/
.x pbmmask.1¾c.y brushtopbm.c
.z cmuwmtopbm.cODO.{ brushtopbm.1TEM.| ImakefileS.} g3topbm.cil.~ pbmtobbnbg.cmp.m pbmtolj.c8.
mgrtopbm.c.€ pbmtocmuwm.citr. pbmtogo.1xt.‚ pbmtoicon.c.ƒ cmuwmtopbm.1.„ pbmplus05oct91/pbm/pbmtolj.1 444 3010 34 1767 5022774326 11156 .TH pbmtolj 1 "29 August 1988"
.IX pbmtolj
.SH NAME
pbmtolj - convert a portable bitmap into HP LaserJet format
.SH SYNOPSIS
.B pbmtolj
.RB [ -resolution
.IR N ]
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces HP LaserJet data as output.
.IX "HP LaserJet"
.PP
Note that there is no ljtopbm tool.
.SH OPTIONS
.TP
.B -resolution
Specifies the resolution of the output device, in dpi.
Typical values are 75, 100, 150, 300.
The default is 75.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer and Michael Haberler.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.

pbmto10xpbmplus05oct91/pbm/pbmmake.c 444 3010 34 3752 5032725004 11167 /* pbmmake.c - create a blank bitmap of a specified size
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
register bit color, gray, rowcolor;
bit* bitrow;
register bit* bP;
int argn, rows, cols, row, col;
char* usage = "[-white|-black|-gray] ";

pbm_init( &argc, argv );

argn = 1;
color = PBM_WHITE;
gray = 0;

/* Check for flags. */
if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-white", 2 ) )
color = PBM_WHITE;
else if ( pm_keymatch( argv[argn], "-black", 2 ) )
color = PBM_BLACK;
else if ( pm_keymatch( argv[argn], "-gray", 2 ) ||
pm_keymatch( argv[argn], "-grey", 2 ) )
gray = 1;
else
pm_usage( usage );
++argn;
}

if ( argn == argc )
pm_usage( usage );
if ( sscanf( argv[argn], "%d", &cols ) != 1 )
pm_usage( usage );
++argn;
if ( argn == argc )
pm_usage( usage );
if ( sscanf( argv[argn], "%d", &rows ) != 1 )
pm_usage( usage );
++argn;

if ( argn != argc )
pm_usage( usage );

pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

if ( gray )
rowcolor = PBM_WHITE; /* arbitrarily make the corner white */
for ( row = 0; row < rows; ++row )
{
if ( gray )
{
color = rowcolor;
rowcolor = 1 - rowcolor;
}
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
{
*bP = color;
if ( gray )
color = 1 - color;
}
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}

exit( 0 );
}
0xdb, 0x3b, 0xbb, 0x7pbmplus05oct91/pbm/pbmtocmuwm.1 444 3010 34 1413 5022774110 11654 .TH pbmtocmuwm 1 "15 April 1989"
.IX pbmtocmuwm
.SH NAME
pbmtocmuwm - convert a portable bitmap into a CMU window manager bitmap
.SH SYNOPSIS
.B pbmtocmuwm
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a CMU window manager bitmap as output.
.IX "CMU window manager bitmap"
.SH "SEE ALSO"
cmuwmtopbm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtomacp.1 444 3010 34 2702 5023104042 11436 .TH pbmtomacp 1 "31 August 1988"
.IX pbmtomacp
.SH NAME
pbmtomacp - convert a portable bitmap into a MacPaint file
.SH SYNOPSIS
.B pbmtomacp
.RB [ -l
.IR left ]
.RB [ -r
.IR right ]
.RB [ -b
.IR bottom ]
.RB [ -t
.IR top ]
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
If no input-file is given, standard input is assumed.
Produces a MacPaint file as output.
.IX MacPaint
.IX Macintosh
.PP
The generated file is only the data fork of a picture.
You will need a program such as
.I mcvert
to generate a Macbinary or a BinHex file that contains the necessary
information to identify the file as a PNTG file to MacOS.
.SH OPTIONS
.PP
Left, right, bottom & top let you define a square into the pbm file,
that must be converted.
Default is the whole file.
If the file is too large for a MacPaint-file, the bitmap is cut to fit
from ( left, top ).
.SH BUGS
The source code contains comments in a language other than English.
.SH "SEE ALSO"
ppmtopict(1), macptopbm(1), pbm(5), mcvert(1)
.SH AUTHOR
Copyright (C) 1988 by Douwe van der Schaaf (...!mcvax!uvapsy!vdschaaf).
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
bpbm1.cb.³ libpbm4.c
.´ pbmtoepson.1.µpbmplus05oct91/pbm/pbmtomgr.1 444 3010 34 1315 5022774364 11325 .TH pbmtomgr 1 "24 January 1989"
.IX pbmtomgr
.SH NAME
pbmtomgr - convert a portable bitmap into a MGR bitmap
.SH SYNOPSIS
.B pbmtomgr
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a MGR bitmap as output.
.IX MGR
.SH "SEE ALSO"
mgrtopbm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
 pbmtogo.c˜. pbmtext.1. pbmtext.css.‘ pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmupc.1 444 3010 34 3037 5022774662 10770 .TH pbmupc 1 "14 March 1989"
.IX pbmupc
.SH NAME
pbmupc - create a Universal Product Code bitmap
.SH SYNOPSIS
.B pbmupc
.RB [ -s1 | -s2 ]
.I type manufac product
.SH DESCRIPTION
Generates a Universal Product Code symbol.
.IX "Universal Product Code"
The three arguments are: a one digit product type, a five digit
manufacturer code, and a five digit product code.
For example, "0 72890 00011" is the code for Heineken.
.IX Heineken
.PP
As presently configured,
.I pbmupc
produces a bitmap 230 bits wide and 175 bits high.
The size can be altered by changing the defines at the beginning of
the program, or by running the output through
.I pnmenlarge
or
.IR pnmscale .
.SH OPTIONS
.PP
The
.B -s1
and
.B -s2
flags select the style of UPC to generate.
The default,
.BR -s1 ,
looks more or less like this:
.nf
||||||||||||||||
||||||||||||||||
||||||||||||||||
||||||||||||||||
0||12345||67890||5
.fi
The other style,
.BR -s2 ,
puts the product type digit higher up, and
doesn't display the checksum digit:
.nf
||||||||||||||||
||||||||||||||||
0||||||||||||||||
||||||||||||||||
||12345||67890||
.fi
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
c.·pbm.hle.¸
pbmtoybm.1s.¹
pbmtoybm.cn.º
pbmtogem.cc.»
ybmtopbm.1
.¼
ybmtopbm.c
.½ pbmtoplot.1Vù.¾
pbmtopi3.cD.¿ pbmtozinc.1¾9.À pbmtoplot.cUq.Á
pi3topbm.1
.Â
pi3topbm.c.Ã pbmtoepson.c31.Ä pbmtozinc.cUv.Å
atktopbm.cw.Æ pbmtoascii.1.Ç pbmtoascii.cma.È
pbmtoatk.c.É
atktopbm.1.Ê
pbmtoatk.1tls, 0 );
}

exit( 0 );
}
0xdb, 0x3b, 0xbb, 0x7pbmplus05oct91/pbm/libpbm.h 444 3010 34 666 4742167733 11026 /* libpbm.h - internal header file for libpbm portable bitmap library
*/

#ifndef _LIBPBM_H_
#define _LIBPBM_H_

/* Here are some routines internal to the pbm library. */

char pbm_getc ARGS(( FILE* file ));
unsigned char pbm_getrawbyte ARGS(( FILE* file ));
int pbm_getint ARGS(( FILE* file ));

int pbm_readmagicnumber ARGS(( FILE* file ));

void pbm_readpbminitrest ARGS(( FILE* file, int* colsP, int* rowsP ));

#endif /*_LIBPBM_H_*/
. pbmtogo.1xt.‚ pbmtoicon.c.ƒ cmuwmtopbm.1.„ pbmplus05oct91/pbm/pbmlife.c 444 3010 34 5133 5032725003 11163 /* pbmlife.c - read a portable bitmap and apply Conway's rules of Life to it
**
** Copyright (C) 1988,1 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* prevrow;
bit* thisrow;
bit* nextrow;
bit* temprow;
register bit* newrow;
int rows, cols, row;
register int col, count;
int format;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pbm_readpbminit( ifp, &cols, &rows, &format );
prevrow = pbm_allocrow( cols );
thisrow = pbm_allocrow( cols );
nextrow = pbm_allocrow( cols );

pbm_writepbminit( stdout, cols, rows, 0 );
newrow = pbm_allocrow( cols );

pbm_readpbmrow( ifp, nextrow, cols, format );

for ( row = 0; row < rows; ++row )
{
temprow = prevrow;
prevrow = thisrow;
thisrow = nextrow;
nextrow = temprow;
if ( row < rows - 1 )
pbm_readpbmrow( ifp, nextrow, cols, format );

for ( col = 0; col < cols; ++col )
{
/* Check the neighborhood, with an unrolled double loop. */
count = 0;
if ( row > 0 )
{
/* upper left */
if ( col > 0 && prevrow[col - 1] == PBM_WHITE )
++count;
/* upper center */
if ( prevrow[col] == PBM_WHITE )
++count;
/* upper right */
if ( col < cols - 1 && prevrow[col + 1] == PBM_WHITE )
++count;
}
/* left */
if ( col > 0 && thisrow[col - 1] == PBM_WHITE )
++count;
/* right */
if ( col < cols - 1 && thisrow[col + 1] == PBM_WHITE )
++count;
if ( row < rows - 1 )
{
/* lower left */
if ( col > 0 && nextrow[col - 1] == PBM_WHITE )
++count;
/* lower center */
if ( nextrow[col] == PBM_WHITE )
++count;
/* lower right */
if ( col < cols - 1 && nextrow[col + 1] == PBM_WHITE )
++count;
}

/* And compute the new value. */
if ( thisrow[col] == PBM_WHITE )
if ( count == 2 || count == 3 )
newrow[col] = PBM_WHITE;
else
newrow[col] = PBM_BLACK;
else
if ( count == 3 )
newrow[col] = PBM_WHITE;
else
newrow[col] = PBM_BLACK;
}
pbm_writepbmrow( stdout, newrow, cols, 0 );
}

pm_close( ifp );

exit( 0 );
}
}
i < extraskip; i++ )
getc( file );
for ( i = 0; i < HEADER_LENGTH; i++ )
getc( file );

*scanLineP = 0;
k = 0;

while ( *scanLineP < MAX_LINES )
{
ch = (unsigned char) getc( file ); /* Count byte */
i = (unsigned int) ch;
if ( ch < 0x80 )
{ /* Unpack next (I+1) chars as is */
for ( j = 0; j <= i; j++ )
if ( *scanLineP < MAX_LINES )
{
Pic[*scanLineP][k++] = (unsigned charpbmplus05oct91/pbm/pbmreduce.c 444 3010 34 10640 5035730717 11545 /* pbmreduce.c - read a portable bitmap and reduce it N times
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
register bit** bitslice;
register bit* newbitrow;
register bit* nbP;
int argn, n, rows, cols, format, newrows, newcols;
int row, col, limitcol, subrow, subcol, count, direction;
char* usage = "[-floyd|-fs | -threshold] [-value ] N [pbmfile]";
int halftone;
#define QT_FS 1
#define QT_THRESH 2
#define SCALE 1024
#define HALFSCALE 512
long threshval, sum;
long* thiserr;
long* nexterr;
long* temperr;

pbm_init( &argc, argv );

argn = 1;
halftone = QT_FS;
threshval = HALFSCALE;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-fs", 2 ) ||
pm_keymatch( argv[argn], "-floyd", 2 ) )
halftone = QT_FS;
else if ( pm_keymatch( argv[argn], "-threshold", 2 ) )
halftone = QT_THRESH;
else if ( pm_keymatch( argv[argn], "-value", 2 ) )
{
float f;

++argn;
if ( argn == argc || sscanf( argv[argn], "%f", &f ) != 1 ||
f < 0.0 || f > 1.0 )
pm_usage( usage );
threshval = f * SCALE;
}
else
pm_usage( usage );
++argn;
}

if ( argn == argc )
pm_usage( usage );
if ( sscanf( argv[argn], "%d", &n ) != 1 )
pm_usage( usage );
if ( n < 2 )
pm_error( "N must be greater than 1" );
++argn;

if ( argn == argc )
ifp = stdin;
else
{
ifp = pm_openr( argv[argn] );
++argn;
}

if ( argn != argc )
pm_usage( usage );

pbm_readpbminit( ifp, &cols, &rows, &format );
bitslice = pbm_allocarray( cols, n );

newrows = rows / n;
newcols = cols / n;
pbm_writepbminit( stdout, newcols, newrows, 0 );
newbitrow = pbm_allocrow( newcols );

if ( halftone == QT_FS )
{
/* Initialize Floyd-Steinberg. */
thiserr = (long*) malloc( ( newcols + 2 ) * sizeof(long) );
nexterr = (long*) malloc( ( newcols + 2 ) * sizeof(long) );
if ( thiserr == 0 || nexterr == 0 )
pm_error( "out of memory" );

srandom( (int) ( time( 0 ) ^ getpid( ) ) );
for ( col = 0; col < newcols + 2; ++col )
thiserr[col] = ( random( ) % SCALE - HALFSCALE ) / 4;
/* (random errors in [-SCALE/8 .. SCALE/8]) */
}
direction = 1;

for ( row = 0; row < newrows; ++row )
{
for ( subrow = 0; subrow < n; ++subrow )
pbm_readpbmrow( ifp, bitslice[subrow], cols, format );

if ( halftone == QT_FS )
for ( col = 0; col < newcols + 2; ++col )
nexterr[col] = 0;
if ( direction )
{
col = 0;
limitcol = newcols;
nbP = newbitrow;
}
else
{
col = newcols - 1;
limitcol = -1;
nbP = &(newbitrow[col]);
}

do
{
sum = 0;
count = 0;
for ( subrow = 0; subrow < n; ++subrow )
for ( subcol = 0; subcol < n; ++subcol )
if ( row * n + subrow < rows && col * n + subcol < cols )
{
count += 1;
if ( bitslice[subrow][col * n + subcol] == PBM_WHITE )
sum += 1;
}
sum = ( sum * SCALE ) / count;

if ( halftone == QT_FS )
sum += thiserr[col + 1];

if ( sum >= threshval )
{
*nbP = PBM_WHITE;
if ( halftone == QT_FS )
sum = sum - threshval - HALFSCALE;
}
else
*nbP = PBM_BLACK;

if ( halftone == QT_FS )
{
if ( direction )
{
thiserr[col + 2] += ( sum * 7 ) / 16;
nexterr[col ] += ( sum * 3 ) / 16;
nexterr[col + 1] += ( sum * 5 ) / 16;
nexterr[col + 2] += ( sum ) / 16;
}
else
{
thiserr[col ] += ( sum * 7 ) / 16;
nexterr[col + 2] += ( sum * 3 ) / 16;
nexterr[col + 1] += ( sum * 5 ) / 16;
nexterr[col ] += ( sum ) / 16;
}
}
if ( direction )
{
++col;
++nbP;
}
else
{
--col;
--nbP;
}
}
while ( col != limitcol );

pbm_writepbmrow( stdout, newbitrow, newcols, 0 );

if ( halftone == QT_FS )
{
temperr = thiserr;
thiserr = nexterr;
nexterr = temperr;
direction = ! direction;
}
}

pm_close( ifp );

exit( 0 );
}
n. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.pbmplus05oct91/pbm/mgr.h 444 3010 34 600 4523200364 10313 /* mgr.h - the following defs are taken from the MGR header file lib/dump.h
*/

#ifndef _MGR_H_
#define _MGR_H_

struct old_b_header {
char magic[2];
char h_wide;
char l_wide;
char h_high;
char l_high;
};

struct b_header {
char magic[2];
char h_wide;
char l_wide;
char h_high;
char l_high;
char depth;
char _reserved;
};

#endif /*_MGR_H_*/
olj.c8.
mgrtopbm.c.€ pbmtocmuwm.citr. pbmtogo.1xt.‚ pbmtoicon.c.ƒ cmuwmtopbm.1.„ pbmplus05oct91/pbm/pbmto10x.c 444 3010 34 5703 5032725015 11225 /* pbmto10x.c - read a portable bitmap and produce a Gemini 10X printer file
**
** Copyright (C) 1990 by Ken Yap
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

#define LOW_RES_ROWS 8 /* printed per pass */
#define HIGH_RES_ROWS 16 /* printed per pass */

static void res_60x72 ARGS(( void ));
static void res_120x144 ARGS(( void ));

static int highres = 0;
static FILE *ifp;
static int rows, cols, format;

void
main(argc, argv)
int argc;
char *argv[];
{
pbm_init( &argc, argv );
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'h')
{
highres = 1;
--argc;
++argv;
}
if (argc > 2)
pm_usage("[pbmfile]");
if (argc == 2)
ifp = pm_openr(argv[1]);
else
ifp = stdin;

pbm_readpbminit(ifp, &cols, &rows, &format);
if (highres)
res_120x144();
else
res_60x72();

pm_close(ifp);
exit(0);
}

static void
res_60x72()
{
register int i, item, npins, row, col;
bit *bitrows[LOW_RES_ROWS], *bP[LOW_RES_ROWS];

for (i = 0; i < LOW_RES_ROWS; ++i)
bitrows[i] = pbm_allocrow(cols);
printf("\033A\010"); /* '\n' = 8/72 */
for (row = 0; row < rows; row += LOW_RES_ROWS)
{
if (row + LOW_RES_ROWS <= rows)
npins = LOW_RES_ROWS;
else
npins = rows - row;
for (i = 0; i < npins; ++i)
pbm_readpbmrow(ifp, bP[i] = bitrows[i], cols, format);
printf("\033K%c%c", cols % 256, cols / 256);
for (col = 0; col < cols; ++col)
{
item = 0;
for (i = 0; i < npins; ++i)
if (*(bP[i]++) == PBM_BLACK)
item |= 1 << (7 - i);
putchar(item);
}
putchar('\n');
}
}

static void
res_120x144()
{
register int i, pin, item, npins, row, col;
bit *bitrows[HIGH_RES_ROWS], *bP[HIGH_RES_ROWS];

for (i = 0; i < HIGH_RES_ROWS; ++i)
bitrows[i] = pbm_allocrow(cols);
putchar('\033'); putchar('3'); putchar('\0');
for (row = 0; row < rows; row += HIGH_RES_ROWS)
{
if (row + HIGH_RES_ROWS <= rows)
npins = HIGH_RES_ROWS;
else
npins = rows - row;
for (i = 0; i < npins; ++i)
pbm_readpbmrow(ifp, bP[i] = bitrows[i], cols, format);
printf("\033L%c%c", cols % 256, cols / 256);
for (col = 0; col < cols; ++col)
{
item = 0;
/* even rows */
for (pin = i = 0; i < npins; i += 2, ++pin)
if (*(bP[i]++) == PBM_BLACK)
item |= 1 << (7 - pin);
putchar(item);
}
putchar('\n'); /* flush buffer */
printf("\033J\001"); /* 1/144 down */
printf("\033L%c%c", cols % 256, cols / 256);
for (col = 0; col < cols; ++col)
{
item = 0;
/* odd rows */
for (i = 1, pin = 0; i < npins; i += 2, ++pin)
if (*(bP[i]++) == PBM_BLACK)
item |= 1 << (7 - pin);
putchar(item);
}
putchar('\n'); /* flush buffer */
printf("\033J\017"); /* 15/144 down */
}
}
limitcol = newcols;
nbP = newbitrow;
}
else
pbmplus05oct91/pbm/pbmtoxbm.c 444 3010 34 5023 5032725041 11375 /* pbmtoxbm.c - read a portable bitmap and produce an X11 bitmap file
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, format, padright, row;
register int col;
char name[100];
char* cp;
int itemsperline;
register int bitsperitem;
register int item;
int firstitem;
char* hexchar = "0123456789abcdef";

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
{
ifp = pm_openr( argv[1] );
strcpy( name, argv[1] );
if ( strcmp( name, "-" ) == 0 )
strcpy( name, "noname" );

if ( ( cp = index( name, '.' ) ) != 0 )
*cp = '\0';
}
else
{
ifp = stdin;
strcpy( name, "noname" );
}

pbm_readpbminit( ifp, &cols, &rows, &format );
bitrow = pbm_allocrow( cols );

/* Compute padding to round cols up to the nearest multiple of 8. */
padright = ( ( cols + 7 ) / 8 ) * 8 - cols;

printf( "#define %s_width %d\n", name, cols );
printf( "#define %s_height %d\n", name, rows );
printf( "static char %s_bits[] = {\n", name );

itemsperline = 0;
bitsperitem = 0;
item = 0;
firstitem = 1;

#define PUTITEM \
{ \
if ( firstitem ) \
firstitem = 0; \
else \
putchar( ',' ); \
if ( itemsperline == 15 ) \
{ \
putchar( '\n' ); \
itemsperline = 0; \
} \
if ( itemsperline == 0 ) \
putchar( ' ' ); \
++itemsperline; \
putchar('0'); \
putchar('x'); \
putchar(hexchar[item >> 4]); \
putchar(hexchar[item & 15]); \
bitsperitem = 0; \
item = 0; \
}

#define PUTBIT(b) \
{ \
if ( bitsperitem == 8 ) \
PUTITEM; \
if ( (b) == PBM_BLACK ) \
item += 1 << bitsperitem; \
++bitsperitem; \
}

for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
PUTBIT(*bP);
for ( col = 0; col < padright; ++col )
PUTBIT(0);
}

if ( ifp != stdin )
fclose( ifp );

if ( bitsperitem > 0 )
PUTITEM;
printf( "};\n" );

exit( 0 );
}
d a portable bitmap and produce an X11 bitmap file
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#inclupbmplus05oct91/pbm/pbmupc.c 444 3010 34 40260 5032726223 11060 /* pbmupc.c - create a Universal Product Code bitmap
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

#define MARGIN 20
#define DIGIT_WIDTH 14
#define DIGIT_HEIGHT 23
#define LINE1_WIDTH 2

#define LINE2_WIDTH ( 2 * LINE1_WIDTH )
#define LINE3_WIDTH ( 3 * LINE1_WIDTH )
#define LINE4_WIDTH ( 4 * LINE1_WIDTH )
#define LINES_WIDTH ( 7 * LINE1_WIDTH )
#define SHORT_HEIGHT ( 8 * LINES_WIDTH )
#define TALL_HEIGHT ( SHORT_HEIGHT + DIGIT_HEIGHT / 2 )

static int alldig ARGS(( char* cp ));
static void putdigit ARGS(( int d, bit** bits, int row0, int col0 ));
static int addlines ARGS(( int d, bit** bits, int row0, int col0, int height, bit color ));
static int rect ARGS(( bit** bits, int row0, int col0, int height, int width, bit color ));

void
main( argc, argv )
int argc;
char* argv[];
{
register bit** bits;
int argn, style, rows, cols, row, digrow, col, digcolofs;
char* typecode;
char* manufcode;
char* prodcode;
int sum, p, lc0, lc1, lc2, lc3, lc4, rc0, rc1, rc2, rc3, rc4;
void putdigit( );
char* usage = "[-s1|-s2] ";

pbm_init( &argc, argv );

argn = 1;
style = 1;

/* Check for flags. */
while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-s1", 3 ) )
style = 1;
else if ( pm_keymatch( argv[argn], "-s2", 3 ) )
style = 2;
else
pm_usage( usage );
argn++;
}

if ( argn + 3 < argc )
pm_usage( usage );
typecode = argv[argn];
manufcode = argv[argn + 1];
prodcode = argv[argn + 2];
argn += 3;

if ( argn != argc )
pm_usage( usage );

if ( strlen( typecode ) != 1 || ( ! alldig( typecode ) ) ||
strlen( manufcode ) != 5 || ( ! alldig ( manufcode ) ) ||
strlen( prodcode ) != 5 || ( ! alldig ( prodcode ) ) )
pm_error(
"type code must be one digit, and\n manufacturer and product codes must be five digits" );
p = typecode[0] - '0';
lc0 = manufcode[0] - '0';
lc1 = manufcode[1] - '0';
lc2 = manufcode[2] - '0';
lc3 = manufcode[3] - '0';
lc4 = manufcode[4] - '0';
rc0 = prodcode[0] - '0';
rc1 = prodcode[1] - '0';
rc2 = prodcode[2] - '0';
rc3 = prodcode[3] - '0';
rc4 = prodcode[4] - '0';
sum = ( 10 - ( ( ( p + lc1 + lc3 + rc0 + rc2 + rc4 ) * 3 + lc0 + lc2 + lc4 + rc1 + rc3 ) % 10 ) ) % 10;

rows = 2 * MARGIN + SHORT_HEIGHT + DIGIT_HEIGHT;
cols = 2 * MARGIN + 12 * LINES_WIDTH + 11 * LINE1_WIDTH;
bits = pbm_allocarray( cols, rows );

(void) rect( bits, 0, 0, rows, cols, PBM_WHITE );

row = MARGIN;
digrow = row + SHORT_HEIGHT;
col = MARGIN;
digcolofs = ( LINES_WIDTH - DIGIT_WIDTH ) / 2;

if ( style == 1 )
putdigit( p, bits, digrow, col - DIGIT_WIDTH - LINE1_WIDTH );
else if ( style == 2 )
putdigit(
p, bits, row + SHORT_HEIGHT / 2, col - DIGIT_WIDTH - LINE1_WIDTH );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_BLACK );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_WHITE );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_BLACK );
col = addlines( p, bits, row, col, TALL_HEIGHT, PBM_WHITE );
putdigit( lc0, bits, digrow, col + digcolofs );
col = addlines( lc0, bits, row, col, SHORT_HEIGHT, PBM_WHITE );
putdigit( lc1, bits, digrow, col + digcolofs );
col = addlines( lc1, bits, row, col, SHORT_HEIGHT, PBM_WHITE );
putdigit( lc2, bits, digrow, col + digcolofs );
col = addlines( lc2, bits, row, col, SHORT_HEIGHT, PBM_WHITE );
putdigit( lc3, bits, digrow, col + digcolofs );
col = addlines( lc3, bits, row, col, SHORT_HEIGHT, PBM_WHITE );
putdigit( lc4, bits, digrow, col + digcolofs );
col = addlines( lc4, bits, row, col, SHORT_HEIGHT, PBM_WHITE );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_WHITE );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_BLACK );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_WHITE );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_BLACK );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_WHITE );
putdigit( rc0, bits, digrow, col + digcolofs );
col = addlines( rc0, bits, row, col, SHORT_HEIGHT, PBM_BLACK );
putdigit( rc1, bits, digrow, col + digcolofs );
col = addlines( rc1, bits, row, col, SHORT_HEIGHT, PBM_BLACK );
putdigit( rc2, bits, digrow, col + digcolofs );
col = addlines( rc2, bits, row, col, SHORT_HEIGHT, PBM_BLACK );
putdigit( rc3, bits, digrow, col + digcolofs );
col = addlines( rc3, bits, row, col, SHORT_HEIGHT, PBM_BLACK );
putdigit( rc4, bits, digrow, col + digcolofs );
col = addlines( rc4, bits, row, col, SHORT_HEIGHT, PBM_BLACK );
col = addlines( sum, bits, row, col, TALL_HEIGHT, PBM_BLACK );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_BLACK );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_WHITE );
col = rect( bits, row, col, TALL_HEIGHT, LINE1_WIDTH, PBM_BLACK );
if ( style == 1 )
putdigit( sum, bits, digrow, col + LINE1_WIDTH );

pbm_writepbm( stdout, bits, cols, rows, 0 );

exit( 0 );
}

static int
alldig( cp )
char* cp;
{
for ( ; *cp != '\0'; cp++ )
if ( *cp < '0' || *cp > '9' )
return 0;
return 1;
}

static void
putdigit( d, bits, row0, col0 )
int d;
bit** bits;
int row0, col0;
{
int row, col;
static bit digits[10][DIGIT_HEIGHT][DIGIT_WIDTH] = {
/* 0 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,1,1,1,1,1,1,0,0,0,0,
0,0,0,1,1,1,1,1,1,1,1,0,0,0,
0,0,1,1,1,0,0,0,0,1,1,1,0,0,
0,0,1,1,0,0,0,0,0,0,1,1,0,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,0,1,1,0,0,0,0,0,0,1,1,0,0,
0,0,1,1,1,0,0,0,0,1,1,1,0,0,
0,0,0,1,1,1,1,1,1,1,1,0,0,0,
0,0,0,0,1,1,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,

/* 1 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,1,1,1,0,0,0,0,0,0,
0,0,0,0,1,1,1,1,0,0,0,0,0,0,
0,0,0,1,1,1,1,1,0,0,0,0,0,0,
0,0,1,1,1,0,1,1,0,0,0,0,0,0,
0,0,1,1,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,

/* 2 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,1,1,1,1,0,0,0,0,0,
0,0,0,1,1,1,1,1,1,1,1,0,0,0,
0,0,1,1,1,1,0,0,1,1,1,1,0,0,
0,1,1,1,0,0,0,0,0,0,1,1,0,0,
0,1,1,0,0,0,0,0,0,0,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,1,1,0,
0,0,0,0,0,0,0,0,0,0,1,1,1,0,
0,0,0,0,0,0,0,0,0,1,1,1,0,0,
0,0,0,0,0,0,0,0,1,1,1,0,0,0,
0,0,0,0,0,0,0,1,1,1,0,0,0,0,
0,0,0,0,0,0,1,1,1,0,0,0,0,0,
0,0,0,0,0,1,1,1,0,0,0,0,0,0,
0,0,0,0,1,1,1,0,0,0,0,0,0,0,
0,0,0,1,1,1,0,0,0,0,0,0,0,0,
0,0,1,1,1,0,0,0,0,0,0,0,0,0,
0,1,1,1,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,

/* 3 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,1,1,1,0,
0,0,0,0,0,0,0,0,0,1,1,1,0,0,
0,0,0,0,0,0,0,0,1,1,1,0,0,0,
0,0,0,0,0,0,0,1,1,1,0,0,0,0,
0,0,0,0,0,0,1,1,1,0,0,0,0,0,
0,0,0,0,0,1,1,1,1,0,0,0,0,0,
0,0,0,0,0,1,1,1,1,1,1,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,0,1,1,0,0,
0,0,0,0,0,0,0,0,0,0,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,1,1,1,0,
0,1,1,1,0,0,0,0,0,0,1,1,0,0,
0,0,1,1,1,1,0,0,1,1,1,1,0,0,
0,0,0,1,1,1,1,1,1,1,1,0,0,0,
0,0,0,0,0,1,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,

/* 4 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,1,1,1,0,0,0,0,0,0,
0,0,0,0,0,1,1,0,0,0,0,0,0,0,
0,0,0,0,1,1,1,0,0,0,0,0,0,0,
0,0,0,0,1,1,0,0,0,0,0,0,0,0,
0,0,0,1,1,1,0,0,0,0,0,0,0,0,
0,0,0,1,1,0,0,0,1,1,0,0,0,0,
0,0,1,1,1,0,0,0,1,1,0,0,0,0,
0,0,1,1,0,0,0,0,1,1,0,0,0,0,
0,1,1,1,0,0,0,0,1,1,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,

/* 5 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,0,1,1,0,0,
0,0,0,0,0,0,0,0,0,0,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,1,1,1,0,
0,1,1,1,0,0,0,0,0,0,1,1,0,0,
0,0,1,1,1,1,0,0,1,1,1,1,0,0,
0,0,0,1,1,1,1,1,1,1,1,0,0,0,
0,0,0,0,0,1,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,

/* 6 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,1,0,0,0,0,0,
0,0,0,0,0,0,1,1,1,0,0,0,0,0,
0,0,0,0,0,1,1,1,0,0,0,0,0,0,
0,0,0,0,1,1,1,0,0,0,0,0,0,0,
0,0,0,1,1,1,0,0,0,0,0,0,0,0,
0,0,0,1,1,0,0,0,0,0,0,0,0,0,
0,0,1,1,1,0,0,0,0,0,0,0,0,0,
0,0,1,1,0,1,1,1,1,0,0,0,0,0,
0,0,1,1,1,1,1,1,1,1,1,0,0,0,
0,1,1,1,1,1,0,0,1,1,1,1,0,0,
0,1,1,1,0,0,0,0,0,0,1,1,0,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,0,1,1,0,0,0,0,0,0,1,1,0,0,
0,0,1,1,1,1,0,0,1,1,1,1,0,0,
0,0,0,1,1,1,1,1,1,1,1,0,0,0,
0,0,0,0,0,1,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,

/* 7 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,1,1,0,0,
0,0,0,0,0,0,0,0,0,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,1,1,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,0,0,0,
0,0,0,0,0,0,0,0,1,1,0,0,0,0,
0,0,0,0,0,0,0,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,1,1,0,0,0,0,0,
0,0,0,0,0,0,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,1,1,1,0,0,0,0,0,0,
0,0,0,0,0,1,1,0,0,0,0,0,0,0,
0,0,0,0,0,1,1,0,0,0,0,0,0,0,
0,0,0,0,1,1,1,0,0,0,0,0,0,0,
0,0,0,0,1,1,0,0,0,0,0,0,0,0,
0,0,0,0,1,1,0,0,0,0,0,0,0,0,
0,0,0,0,1,1,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,

/* 8 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,1,1,1,1,1,1,1,1,0,0,0,
0,0,1,1,1,1,1,1,1,1,1,1,0,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,0,1,1,1,0,0,0,0,1,1,1,0,0,
0,0,0,1,1,1,0,0,1,1,1,0,0,0,
0,0,0,0,1,1,1,1,1,1,0,0,0,0,
0,0,0,0,1,1,1,1,1,1,0,0,0,0,
0,0,0,1,1,1,0,0,1,1,1,0,0,0,
0,0,1,1,1,0,0,0,0,1,1,1,0,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,0,1,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,1,1,1,1,1,1,1,1,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,

/* 9 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,1,1,1,1,0,0,0,0,0,
0,0,0,1,1,1,1,1,1,1,1,0,0,0,
0,0,1,1,1,1,0,0,1,1,1,1,0,0,
0,0,1,1,0,0,0,0,0,0,1,1,0,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,0,1,1,0,0,0,0,0,0,1,1,1,0,
0,0,1,1,1,1,0,0,1,1,1,1,1,0,
0,0,0,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,1,1,1,1,0,1,1,0,0,
0,0,0,0,0,0,0,0,0,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,1,1,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,0,0,0,
0,0,0,0,0,0,0,1,1,1,0,0,0,0,
0,0,0,0,0,0,1,1,1,0,0,0,0,0,
0,0,0,0,0,1,1,1,0,0,0,0,0,0,
0,0,0,0,0,1,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};

for ( row = 0; row < DIGIT_HEIGHT; row++ )
for ( col = 0; col < DIGIT_WIDTH; col++ )
bits[row0 + row][col0 + col] = digits[d][row][col];
}

#if __STDC__
static int
addlines( int d, bit** bits, int row0, int col0, int height, bit color )
#else /*__STDC__*/
static int
addlines( d, bits, row0, col0, height, color )
int d;
bit** bits;
int row0, col0, height;
bit color;
#endif /*__STDC__*/
{
switch ( d )
{
case 0:
col0 = rect( bits, row0, col0, height, LINE3_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, 1 - color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, 1 - color );
break;

case 1:
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, 1 - color );
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, 1 - color );
break;

case 2:
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, 1 - color );
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, 1 - color );
break;

case 3:
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE4_WIDTH, 1 - color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, 1 - color );
break;

case 4:
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, 1 - color );
col0 = rect( bits, row0, col0, height, LINE3_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, 1 - color );
break;

case 5:
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, 1 - color );
col0 = rect( bits, row0, col0, height, LINE3_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, 1 - color );
break;

case 6:
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, 1 - color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE4_WIDTH, 1 - color );
break;

case 7:
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE3_WIDTH, 1 - color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, 1 - color );
break;

case 8:
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, 1 - color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE3_WIDTH, 1 - color );
break;

case 9:
col0 = rect( bits, row0, col0, height, LINE3_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, 1 - color );
col0 = rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE2_WIDTH, 1 - color );
break;

default:
pm_error( "can't happen" );
}

return col0;
}

#if __STDC__
static int
rect( bit** bits, int row0, int col0, int height, int width, bit color )
#else /*__STDC__*/
static int
rect( bits, row0, col0, height, width, color )
bit** bits;
int row0, col0, height, width;
bit color;
#endif /*__STDC__*/
{
int row, col;

for ( row = row0; row < row0 + height; row++ )
for ( col = col0; col < col0 + width; col++ )
bits[row][col] = color;
return col0 + width;
}
0,0,0,0,0,0,0,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,0,0,0,0,0,0,0,1,1,1,0,
0,1,1,1,0,0,0,0,0,0,1,1,0,0,
0,0,1,1,1,1,0,0,1,1,1,1,0,0,
0,0,0,1,1,1,1,1,1,1,1,0,0,0,
0,0,0,0,0,1,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,

/* 4 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,pbmplus05oct91/pbm/xbmtopbm.c 444 3010 34 12217 5032725046 11425 /* xbmtopbm.c - read an X bitmap file and produce a portable bitmap
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

static void ReadBitmapFile ARGS(( FILE* stream, int* widthP, int* heightP, char** dataP ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, row, col, charcount;
char* data;
char mask;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[bitmapfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

ReadBitmapFile( ifp, &cols, &rows, &data );

pm_close( ifp );

pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

for ( row = 0; row < rows; ++row )
{
charcount = 0;
mask = 1;
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
{
if ( charcount >= 8 )
{
++data;
charcount = 0;
mask = 1;
}
*bP = ( *data & mask ) ? PBM_BLACK : PBM_WHITE;
++charcount;
mask = mask << 1;
}
++data;
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}

exit( 0 );
}

#define MAX_LINE 500

static void
ReadBitmapFile( stream, widthP, heightP, dataP )
FILE* stream;
int* widthP;
int* heightP;
char** dataP;
{
char line[MAX_LINE], name_and_type[MAX_LINE];
char* ptr;
char* t;
int version10, raster_length, v;
register int bytes, bytes_per_line, padding;
register int c1, c2, value1, value2;
int hex_table[256];

*widthP = *heightP = -1;

for ( ; ; )
{
if ( fgets( line, MAX_LINE, stream ) == NULL )
pm_error( "EOF / read error" );
if ( strlen( line ) == MAX_LINE - 1 )
pm_error( "line too long" );

if ( sscanf( line, "#define %s %d", name_and_type, &v ) == 2 )
{
if ( ( t = rindex( name_and_type, '_' ) ) == NULL )
t = name_and_type;
else
++t;
if ( ! strcmp( "width", t ) )
*widthP = v;
else if ( ! strcmp( "height", t ) )
*heightP = v;
continue;
}

if ( sscanf( line, "static short %s = {", name_and_type ) == 1 ) /* } */
{
version10 = 1;
break;
}
if ( sscanf( line, "static char %s = {", name_and_type ) == 1 ) /* } */
{
version10 = 0;
break;
}
}

if ( *widthP == -1 )
pm_error( "invalid width" );
if ( *heightP == -1 )
pm_error( "invalid height" );

padding = 0;
if ( ((*widthP % 16) >= 1) && ((*widthP % 16) <= 8) && version10 )
padding = 1;

bytes_per_line = (*widthP+7)/8 + padding;

raster_length = bytes_per_line * *heightP;
*dataP = (char*) malloc( raster_length );
if ( *dataP == (char*) 0 )
pm_error( "out of memory" );

/* Initialize hex_table. */
for ( c1 = 0; c1 < 256; ++c1 )
hex_table[c1] = 256;
hex_table['0'] = 0;
hex_table['1'] = 1;
hex_table['2'] = 2;
hex_table['3'] = 3;
hex_table['4'] = 4;
hex_table['5'] = 5;
hex_table['6'] = 6;
hex_table['7'] = 7;
hex_table['8'] = 8;
hex_table['9'] = 9;
hex_table['A'] = 10;
hex_table['B'] = 11;
hex_table['C'] = 12;
hex_table['D'] = 13;
hex_table['E'] = 14;
hex_table['F'] = 15;
hex_table['a'] = 10;
hex_table['b'] = 11;
hex_table['c'] = 12;
hex_table['d'] = 13;
hex_table['e'] = 14;
hex_table['f'] = 15;

if ( version10 )
for ( bytes = 0, ptr = *dataP; bytes < raster_length; bytes += 2 )
{
while ( ( c1 = getc( stream ) ) != 'x' )
if ( c1 == EOF )
pm_error( "EOF / read error" );
c1 = getc( stream );
c2 = getc( stream );
if ( c1 == EOF || c2 == EOF )
pm_error( "EOF / read error" );
value1 = ( hex_table[c1] << 4 ) + hex_table[c2];
if ( value1 >= 256 )
pm_error( "syntax error" );
c1 = getc( stream );
c2 = getc( stream );
if ( c1 == EOF || c2 == EOF )
pm_error( "EOF / read error" );
value2 = ( hex_table[c1] << 4 ) + hex_table[c2];
if ( value2 >= 256 )
pm_error( "syntax error" );
*ptr++ = value2;
if ( ( ! padding ) || ( ( bytes + 2 ) % bytes_per_line ) )
*ptr++ = value1;
}
else
for ( bytes = 0, ptr = *dataP; bytes < raster_length; ++bytes )
{
/*
** Skip until digit is found.
*/
for ( ; ; )
{
c1 = getc( stream );
if ( c1 == EOF )
pm_error( "EOF / read error" );
value1 = hex_table[c1];
if ( value1 != 256 )
break;
}
/*
** Loop on digits.
*/
for ( ; ; )
{
c2 = getc( stream );
if ( c2 == EOF )
pm_error( "EOF / read error" );
value2 = hex_table[c2];
if ( value2 != 256 )
{
value1 = (value1 << 4) | value2;
if ( value1 >= 256 )
pm_error( "syntax error" );
}
else if ( c2 == 'x' || c2 == 'X' )
if ( value1 == 0 )
continue;
else pm_error( "syntax error" );
else break;
}
*ptr++ = value1;
}
}
,0,1,1,0,
0,1,1,1,0,0,0,0,0,0,1,1,1,0,
0,0,1,1,0,0,0,0,0,0,1,1,1,0,
0,0,1,1,1,1,0,0,1,1,1,1,1,0,
0,0,0,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,1,1,1,1,0,1,1,0,0,
0,0,0,0,0,0,0,0,0,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,1,1,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,0,0,0,
0,0,0,0,0,0,0,1,1,1,0,0,0,0,
0,0,0,0,0,0,1,1,1,0,0,0,0,0,
0,0,0,0,0,1,1,1,0,0,0,0,0,0,
0,0,0,0,0,1,1,0,0,0,0,0,0,0,pbmplus05oct91/pbm/libpbm3.c 444 3010 34 5374 5032724775 11123 /* libpbm3.c - pbm utility library part 3
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "libpbm.h"

void
pbm_writepbminit( file, cols, rows, forceplain )
FILE* file;
int cols, rows;
int forceplain;
{
#ifdef PBMPLUS_RAWBITS
if ( ! forceplain )
fprintf( file, "%c%c\n%d %d\n", PBM_MAGIC1, RPBM_MAGIC2, cols, rows );
else
fprintf( file, "%c%c\n%d %d\n", PBM_MAGIC1, PBM_MAGIC2, cols, rows );
#else /*PBMPLUS_RAWBITS*/
fprintf( file, "%c%c\n%d %d\n", PBM_MAGIC1, PBM_MAGIC2, cols, rows );
#endif /*PBMPLUS_RAWBITS*/
}

#ifdef PBMPLUS_RAWBITS
static void
pbm_writepbmrowraw( file, bitrow, cols )
FILE* file;
bit* bitrow;
int cols;
{
register int col, bitshift;
register unsigned char item;
register bit* bP;

bitshift = 7;
item = 0;
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
{
if ( *bP )
item += 1 << bitshift;
--bitshift;
if ( bitshift == -1 )
{
if ( putc( item, file ) == EOF )
pm_error( "write error" );
bitshift = 7;
item = 0;
}
}
if ( bitshift != 7 )
if ( putc( item, file ) == EOF )
pm_error( "write error" );
}
#endif /*PBMPLUS_RAWBITS*/

static void
pbm_writepbmrowplain( file, bitrow, cols )
FILE* file;
bit* bitrow;
int cols;
{
register int col, charcount;
register bit* bP;

charcount = 0;
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
{
if ( charcount >= 70 )
{
if ( putc( '\n', file ) == EOF )
pm_error( "write error" );
charcount = 0;
}
if ( putc( *bP ? '1' : '0', file ) == EOF )
pm_error( "write error" );
++charcount;
}
if ( putc( '\n', file ) == EOF )
pm_error( "write error" );
}

void
pbm_writepbmrow( file, bitrow, cols, forceplain )
FILE* file;
bit* bitrow;
int cols;
int forceplain;
{
#ifdef PBMPLUS_RAWBITS
if ( ! forceplain )
pbm_writepbmrowraw( file, bitrow, cols );
else
pbm_writepbmrowplain( file, bitrow, cols );
#else /*PBMPLUS_RAWBITS*/
pbm_writepbmrowplain( file, bitrow, cols );
#endif /*PBMPLUS_RAWBITS*/
}

void
pbm_writepbm( file, bits, cols, rows, forceplain )
FILE* file;
bit** bits;
int cols, rows;
int forceplain;
{
int row;

pbm_writepbminit( file, cols, rows, forceplain );

for ( row = 0; row < rows; ++row )
pbm_writepbmrow( file, bits[row], cols, forceplain );
}
P % 16) <= 8) && version10 )
padding = 1;

bytes_per_line = (*widthP+7)/8 + padding;

raster_length = bytes_per_line * *heightP;
*dataP = (char*) malloc( raster_length );
if ( *dataP == (char*) 0 )
pm_error( "out of memory" );

/* Inpbmplus05oct91/pbm/libpbm1.c 444 3010 34 30612 5034427251 11121 /* libpbm1.c - pbm utility library part 1
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "version.h"
#include "libpbm.h"
#if __STDC__
#include
#else /*__STDC__*/
#include
#endif /*__STDC__*/


/* Forward routines. */

#if defined(NEED_VFPRINTF1) || defined(NEED_VFPRINTF2)
int vfprintf ARGS(( FILE* stream, char* format, va_list args ));
#endif /*NEED_VFPRINTF*/


/* Variable-sized arrays. */

char*
pm_allocrow( cols, size )
int cols;
int size;
{
register char* itrow;

itrow = (char*) malloc( cols * size );
if ( itrow == (char*) 0 )
pm_error( "out of memory allocating a row" );
return itrow;
}

void
pm_freerow( itrow )
char* itrow;
{
free( itrow );
}


char**
pm_allocarray( cols, rows, size )
int cols, rows;
int size;
{
char** its;
int i;

its = (char**) malloc( rows * sizeof(char*) );
if ( its == (char**) 0 )
pm_error( "out of memory allocating an array" );
its[0] = (char*) malloc( rows * cols * size );
if ( its[0] == (char*) 0 )
pm_error( "out of memory allocating an array" );
for ( i = 1; i < rows; ++i )
its[i] = &(its[0][i * cols * size]);
return its;
}

void
pm_freearray( its, rows )
char** its;
int rows;
{
free( its[0] );
free( its );
}


/* Case-insensitive keyword matcher. */

int
pm_keymatch( str, keyword, minchars )
char* str;
char* keyword;
int minchars;
{
register int len;

len = strlen( str );
if ( len < minchars )
return 0;
while ( --len >= 0 )
{
register char c1, c2;

c1 = *str++;
c2 = *keyword++;
if ( c2 == '\0' )
return 0;
if ( isupper( c1 ) )
c1 = tolower( c1 );
if ( isupper( c2 ) )
c1 = tolower( c2 );
if ( c1 != c2 )
return 0;
}
return 1;
}


/* Log base two hacks. */

int
pm_maxvaltobits( maxval )
int maxval;
{
if ( maxval <= 1 )
return 1;
else if ( maxval <= 3 )
return 2;
else if ( maxval <= 7 )
return 3;
else if ( maxval <= 15 )
return 4;
else if ( maxval <= 31 )
return 5;
else if ( maxval <= 63 )
return 6;
else if ( maxval <= 127 )
return 7;
else if ( maxval <= 255 )
return 8;
else if ( maxval <= 511 )
return 9;
else if ( maxval <= 1023 )
return 10;
else if ( maxval <= 2047 )
return 11;
else if ( maxval <= 4095 )
return 12;
else if ( maxval <= 8191 )
return 13;
else if ( maxval <= 16383 )
return 14;
else if ( maxval <= 32767 )
return 15;
else if ( (long) maxval <= 65535L )
return 16;
else
pm_error( "maxval of %d is too large!", maxval );
}

int
pm_bitstomaxval( bits )
int bits;
{
return ( 1 << bits ) - 1;
}


/* Initialization. */

static char* progname;
static int showmessages;

void
pm_init( argcP, argv )
int* argcP;
char* argv[];
{
int argn, i;

/* Extract program name. */
progname = rindex( argv[0], '/');
if ( progname == NULL )
progname = argv[0];
else
++progname;

/* Check for any global args. */
showmessages = 1;
for ( argn = 1; argn < *argcP; ++argn )
{
if ( pm_keymatch( argv[argn], "-quiet", 6 ) )
{
showmessages = 0;
}
else if ( pm_keymatch( argv[argn], "-version", 7 ) )
{
pm_message( "Version of %s", PBMPLUS_VERSION );
#ifdef BSD
pm_message( "BSD defined" );
#endif /*BSD*/
#ifdef SYSV
pm_message( "SYSV defined" );
#endif /*SYSV*/
#ifdef MSDOS
pm_message( "MSDOS defined" );
#endif /*MSDOS*/
#ifdef PBMPLUS_RAWBITS
pm_message( "PBMPLUS_RAWBITS defined" );
#endif /*PBMPLUS_RAWBITS*/
#ifdef PBMPLUS_BROKENPUTC1
pm_message( "PBMPLUS_BROKENPUTC1 defined" );
#endif /*PBMPLUS_BROKENPUTC1*/
#ifdef PBMPLUS_BROKENPUTC2
pm_message( "PBMPLUS_BROKENPUTC2 defined" );
#endif /*PBMPLUS_BROKENPUTC2*/
#ifdef PGM_BIGGRAYS
pm_message( "PGM_BIGGRAYS defined" );
#endif /*PGM_BIGGRAYS*/
#ifdef PPM_PACKCOLORS
pm_message( "PPM_PACKCOLORS defined" );
#endif /*PPM_PACKCOLORS*/
#ifdef DEBUG
pm_message( "DEBUG defined" );
#endif /*DEBUG*/
#ifdef NEED_VFPRINTF1
pm_message( "NEED_VFPRINTF1 defined" );
#endif /*NEED_VFPRINTF1*/
#ifdef NEED_VFPRINTF2
pm_message( "NEED_VFPRINTF2 defined" );
#endif /*NEED_VFPRINTF2*/
#ifdef RGB_DB
pm_message( "RGB_DB=\"%s\"", RGB_DB );
#endif /*RGB_DB*/
#ifdef LIBTIFF
pm_message( "LIBTIFF defined" );
#endif /*LIBTIFF*/
exit( 0 );
}
else
continue;
for ( i = argn + 1; i <= *argcP; ++i )
argv[i - 1] = argv[i];
--(*argcP);
}
}

void
pbm_init( argcP, argv )
int* argcP;
char* argv[];
{
pm_init( argcP, argv );
}


/* Error handling. */

void
pm_usage( usage )
char* usage;
{
fprintf( stderr, "usage: %s %s\n", progname, usage );
exit( 1 );
}

void
pm_perror( reason )
char* reason;
{
extern char* sys_errlist[];
extern int errno;
char* e;

e = sys_errlist[errno];

if ( reason != 0 && reason[0] != '\0' )
pm_error( "%s - %s", reason, e );
else
pm_error( "%s", e );
}

#if __STDC__
void
pm_message( char* format, ... )
{
va_list args;

va_start( args, format );
#else /*__STDC__*/
/*VARARGS1*/
void
pm_message( va_alist )
va_dcl
{ /*}*/
va_list args;
char* format;

va_start( args );
format = va_arg( args, char* );
#endif /*__STDC__*/

if ( showmessages )
{
fprintf( stderr, "%s: ", progname );
(void) vfprintf( stderr, format, args );
fputc( '\n', stderr );
}
va_end( args );
}

#if __STDC__
void
pm_error( char* format, ... )
{
va_list args;

va_start( args, format );
#else /*__STDC__*/
/*VARARGS1*/
void
pm_error( va_alist )
va_dcl
{ /*}*/
va_list args;
char* format;

va_start( args );
format = va_arg( args, char* );
#endif /*__STDC__*/

fprintf( stderr, "%s: ", progname );
(void) vfprintf( stderr, format, args );
fputc( '\n', stderr );
va_end( args );
exit( 1 );
}

#ifdef NEED_VFPRINTF1

/* Micro-vfprintf, for systems that don't have vfprintf but do have _doprnt.
*/

int
vfprintf( stream, format, args )
FILE* stream;
char* format;
va_list args;
{
return _doprnt( format, args, stream );
}
#endif /*NEED_VFPRINTF1*/

#ifdef NEED_VFPRINTF2

/* Portable mini-vfprintf, for systems that don't have either vfprintf or
** _doprnt. This depends only on fprintf. If you don't have fprintf,
** you might consider getting a new stdio library.
*/

int
vfprintf( stream, format, args )
FILE* stream;
char* format;
va_list args;
{
int n;
char* ep;
char fchar;
char tformat[512];
int do_long;
int i;
long l;
unsigned u;
unsigned long ul;
char* s;
double d;

n = 0;
while ( *format != '\0' )
{
if ( *format != '%' )
{ /* Not special, just write out the char. */
putc( *format, stream );
++n;
++format;
}
else
{
do_long = 0;
ep = format + 1;

/* Skip over all the field width and precision junk. */
if ( *ep == '-' )
++ep;
if ( *ep == '0' )
++ep;
while ( isdigit( *ep ) )
++ep;
if ( *ep == '.' )
{
++ep;
while ( isdigit( *ep ) )
++ep;
}
if ( *ep == '#' )
++ep;
if ( *ep == 'l' )
{
do_long = 1;
++ep;
}

/* Here's the field type. Extract it, and copy this format
** specifier to a temp string so we can add an end-of-string.
*/
fchar = *ep;
(void) strncpy( tformat, format, ep - format + 1 );
tformat[ep - format + 1] = '\0';

/* Now do a one-argument fprintf with the format string we have
** isolated.
*/
switch ( fchar )
{
case 'd':
if ( do_long )
{
l = va_arg( args, long );
n += fprintf( stream, tformat, l );
}
else
{
i = va_arg( args, int );
n += fprintf( stream, tformat, i );
}
break;

case 'o':
case 'x':
case 'X':
case 'u':
if ( do_long )
{
ul = va_arg( args, unsigned long );
n += fprintf( stream, tformat, ul );
}
else
{
u = va_arg( args, unsigned );
n += fprintf( stream, tformat, u );
}
break;

case 'c':
i = (char) va_arg( args, int );
n += fprintf( stream, tformat, i );
break;

case 's':
s = va_arg( args, char* );
n += fprintf( stream, tformat, s );
break;

case 'e':
case 'E':
case 'f':
case 'g':
case 'G':
d = va_arg( args, double );
n += fprintf( stream, tformat, d );
break;

case '%':
putc( '%', stream );
++n;
break;

default:
return -1;
}

/* Resume formatting on the next character. */
format = ep + 1;
}
}
return nc;
}
#endif /*NEED_VFPRINTF2*/


/* File open/close that handles "-" as stdin and checks errors. */

FILE*
pm_openr( name )
char* name;
{
FILE* f;

if ( strcmp( name, "-" ) == 0 )
f = stdin;
else
{
#ifdef MSDOS
f = fopen( name, "rb" );
#else /*MSDOS*/
f = fopen( name, "r" );
#endif /*MSDOS*/
if ( f == NULL )
{
pm_perror( name );
exit( 1 );
}
}
return f;
}

FILE*
pm_openw( name )
char* name;
{
FILE* f;

#ifdef MSDOS
f = fopen( name, "wb" );
#else /*MSDOS*/
f = fopen( name, "w" );
#endif /*MSDOS*/
if ( f == NULL )
{
pm_perror( name );
exit( 1 );
}
return f;
}

void
pm_close( f )
FILE* f;
{
if ( f != stdin )
if ( fclose( f ) != 0 )
pm_perror( "fclose" );
}

/* Broken putc() fix. */

#ifdef PBMPLUS_BROKENPUTC2
int
putc( c, stream )
char c;
FILE* stream;
{
return fwrite( &c, 1, 1, stream ) == 1 ? c : EOF;
}
#endif /*PBMPLUS_BROKENPUTC2*/

/* Endian I/O.
*/

int
pm_readbigshort( in, sP )
FILE* in;
short* sP;
{
int c;

if ( (c = getc( in )) == EOF )
return -1;
*sP = ( c & 0xff ) << 8;
if ( (c = getc( in )) == EOF )
return -1;
*sP |= c & 0xff;
return 0;
}

#if __STDC__
int
pm_writebigshort( FILE* out, short s )
#else /*__STDC__*/
int
pm_writebigshort( out, s )
FILE* out;
short s;
#endif /*__STDC__*/
{
if ( putc( ( s >> 8 ) & 0xff, out ) == EOF )
return -1;
if ( putc( s & 0xff, out ) == EOF )
return -1;
return 0;
}

int
pm_readbiglong( in, lP )
FILE* in;
long* lP;
{
int c;

if ( (c = getc( in )) == EOF )
return -1;
*lP = ( c & 0xff ) << 24;
if ( (c = getc( in )) == EOF )
return -1;
*lP |= ( c & 0xff ) << 16;
if ( (c = getc( in )) == EOF )
return -1;
*lP |= ( c & 0xff ) << 8;
if ( (c = getc( in )) == EOF )
return -1;
*lP |= c & 0xff;
return 0;
}

int
pm_writebiglong( out, l )
FILE* out;
long l;
{
if ( putc( ( l >> 24 ) & 0xff, out ) == EOF )
return -1;
if ( putc( ( l >> 16 ) & 0xff, out ) == EOF )
return -1;
if ( putc( ( l >> 8 ) & 0xff, out ) == EOF )
return -1;
if ( putc( l & 0xff, out ) == EOF )
return -1;
return 0;
}

int
pm_readlittleshort( in, sP )
FILE* in;
short* sP;
{
int c;

if ( (c = getc( in )) == EOF )
return -1;
*sP = c & 0xff;
if ( (c = getc( in )) == EOF )
return -1;
*sP |= ( c & 0xff ) << 8;
return 0;
}

#if __STDC__
int
pm_writelittleshort( FILE* out, short s )
#else /*__STDC__*/
int
pm_writelittleshort( out, s )
FILE* out;
short s;
#endif /*__STDC__*/
{
if ( putc( s & 0xff, out ) == EOF )
return -1;
if ( putc( ( s >> 8 ) & 0xff, out ) == EOF )
return -1;
return 0;
}

int
pm_readlittlelong( in, lP )
FILE* in;
long* lP;
{
int c;

if ( (c = getc( in )) == EOF )
return -1;
*lP = c & 0xff;
if ( (c = getc( in )) == EOF )
return -1;
*lP |= ( c & 0xff ) << 8;
if ( (c = getc( in )) == EOF )
return -1;
*lP |= ( c & 0xff ) << 16;
if ( (c = getc( in )) == EOF )
return -1;
*lP |= ( c & 0xff ) << 24;
return 0;
}

int
pm_writelittlelong( out, l )
FILE* out;
long l;
{
if ( putc( l & 0xff, out ) == EOF )
return -1;
if ( putc( ( l >> 8 ) & 0xff, out ) == EOF )
return -1;
if ( putc( ( l >> 16 ) & 0xff, out ) == EOF )
return -1;
if ( putc( ( l >> 24 ) & 0xff, out ) == EOF )
return -1;
return 0;
}
= rect( bits, row0, col0, height, LINE1_WIDTH, color );
col0 = rect( bits, row0, col0, height, LINE3_WIDTH, 1 - colopbmplus05oct91/pbm/libpbm4.c 444 3010 34 2747 5032724777 11127 /* libpbm4.c - pbm utility library part 4
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"
#include "libpbm.h"

char
pbm_getc( file )
FILE* file;
{
register int ich;
register char ch;

ich = getc( file );
if ( ich == EOF )
pm_error( "EOF / read error" );
ch = (char) ich;

if ( ch == '#' )
{
do
{
ich = getc( file );
if ( ich == EOF )
pm_error( "EOF / read error" );
ch = (char) ich;
}
while ( ch != '\n' );
}

return ch;
}

unsigned char
pbm_getrawbyte( file )
FILE* file;
{
register int iby;

iby = getc( file );
if ( iby == EOF )
pm_error( "EOF / read error" );
return (unsigned char) iby;
}

int
pbm_getint( file )
FILE* file;
{
register char ch;
register int i;

do
{
ch = pbm_getc( file );
}
while ( ch == ' ' || ch == '\t' || ch == '\n' );

if ( ch < '0' || ch > '9' )
pm_error( "junk in file where an integer should be" );

i = 0;
do
{
i = i * 10 + ch - '0';
ch = pbm_getc( file );
}
while ( ch >= '0' && ch <= '9' );

return i;
}
pbmtoepson.1.µpbmplus05oct91/pbm/pbmtoepson.1 444 3010 34 1541 5022774150 11656 .TH pbmtoepson 1 "4 January 1991"
.IX pbmtoepson
.SH NAME
pbmtoepson - convert a portable bitmap into Epson printer graphics
.SH SYNOPSIS
.B pbmtoepson
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a file of Epson printer graphics as output.
.IX Epson
.PP
Note that there is no epsontopbm tool - this transformation is one way.
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1991 by John Tiller ([email protected]) and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
opbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/cmuwm.h 444 3010 34 376 4760652121 10675 /* cmuwm.h - definitions for the CMU window manager format
*/

#ifndef _CMUWM_H_
#define _CMUWM_H_

struct cmuwm_header
{
long magic;
long width;
long height;
short depth;
};

#define CMUWM_MAGIC 0xf10040bbL

#endif /*_CMUWM_H_*/
.c
.z cmuwmtopbm.cODO.{ brushtopbm.1TEM.| ImakefileS.} g3topbm.cil.~ pbmtobbnbg.cmp.m pbmtolj.c8.
mgrtopbm.c.€ pbmtocmuwm.citr. pbmtogo.1xt.‚ pbmtoicon.c.ƒ cmuwmtopbm.1.„ pbmplus05oct91/pbm/pbmtopi3.1 444 3010 34 1346 5023000303 11207 .TH pbmtopi3 1 "11 March 1990"
.IX pbmtopi3
.SH NAME
pbmtopi3 - convert a portable bitmap into an Atari Degas .pi3 file
.SH SYNOPSIS
.B pbmtopi3
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces an Atari Degas .pi3 file as output.
.IX Atari
.IX "Degas .pi3"
.SH "SEE ALSO"
pi3topbm(1), pbm(5), ppmtopi1(1), pi1toppm(1)
.SH AUTHOR
Copyright (C) 1988 by David Beckemeyer (bdt!david) and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted,
.\" provided that the above copyright notice appear in all copies and that
.\" both that copyright notice and this permission notice appear in
.\" supporting documentation.
mtext.1. pbmtext.css.‘ pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbm.h 444 3010 34 2626 4755321450 10345 /* pbm.h - header file for libpbm portable bitmap library
*/

#ifndef _PBM_H_
#define _PBM_H_

#include "pbmplus.h"

typedef unsigned char bit;
#define PBM_WHITE 0
#define PBM_BLACK 1


/* Magic constants. */

#define PBM_MAGIC1 'P'
#define PBM_MAGIC2 '1'
#define RPBM_MAGIC2 '4'
#define PBM_FORMAT (PBM_MAGIC1 * 256 + PBM_MAGIC2)
#define RPBM_FORMAT (PBM_MAGIC1 * 256 + RPBM_MAGIC2)
#define PBM_TYPE PBM_FORMAT


/* Macro for turning a format number into a type number. */

#define PBM_FORMAT_TYPE(f) ((f) == PBM_FORMAT || (f) == RPBM_FORMAT ? PBM_TYPE : -1)


/* Declarations of routines. */

void pbm_init ARGS(( int* argcP, char* argv[] ));

#define pbm_allocarray( cols, rows ) ((bit**) pm_allocarray( cols, rows, sizeof(bit) ))
#define pbm_allocrow( cols ) ((bit*) pm_allocrow( cols, sizeof(bit) ))
#define pbm_freearray( bits, rows ) pm_freearray( (char**) bits, rows )
#define pbm_freerow( bitrow ) pm_freerow( (char*) bitrow )

bit** pbm_readpbm ARGS(( FILE* file, int* colsP, int* rowsP ));
void pbm_readpbminit ARGS(( FILE* file, int* colsP, int* rowsP, int* formatP ));
void pbm_readpbmrow ARGS(( FILE* file, bit* bitrow, int cols, int format ));

void pbm_writepbm ARGS(( FILE* file, bit** bits, int cols, int rows, int forceplain ));
void pbm_writepbminit ARGS(( FILE* file, int cols, int rows, int forceplain ));
void pbm_writepbmrow ARGS(( FILE* file, bit* bitrow, int cols, int forceplain ));

#endif /*_PBM_H_*/

xbmtopbm.c.± libpbm3.cc-.² libpbm1.cb.³ libpbm4.c
.´ pbmtoepson.1.µpbmplus05oct91/pbm/pbmtoybm.1 444 3010 34 1515 5022774613 11326 .TH pbmtoybm 1 "06 March 1990"
.IX pbmtoybm
.SH NAME
pgmtoybm - convert a portable bitmap into a Bennet Yee "face" file
.SH SYNOPSIS
.B pbmtoybm
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces as output a file acceptable to the
.I face
and
.I xbm
programs by Bennet Yee ([email protected]).
.IX face
.SH "SEE ALSO"
ybmtopbm(1), pbm(5), face(1), face(5), xbm(1)
.SH AUTHOR
Copyright (C) 1991 by Jamie Zawinski and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
ile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtoybm.c 444 3010 34 4566 5032725042 11412 /* pbmtoybm.c - read a pbm and write a file for Bennet Yee's 'xbm' and 'face'
** programs.
**
** Written by Jamie Zawinski based on code (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

#define YBM_MAGIC ( ( '!' << 8 ) | '!' )

static void putinit ARGS(( int cols, int rows ));
static void putbit ARGS(( bit b ));
static void putrest ARGS(( void ));
static void putitem ARGS(( void ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, format, padright, row, col;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );
if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pbm_readpbminit( ifp, &cols, &rows, &format );
bitrow = pbm_allocrow( cols );

/* Compute padding to round cols up to the nearest multiple of 16. */
padright = ( ( cols + 15 ) / 16 ) * 16 - cols;

putinit( cols, rows );
for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
putbit( *bP );
for ( col = 0; col < padright; ++col )
putbit( 0 );
}

if ( ifp != stdin )
fclose( ifp );

putrest( );

exit( 0 );
}

static long item;
static int bitsperitem, bitshift;

static void
putinit( cols, rows )
int cols, rows;
{
pm_writebigshort( stdout, YBM_MAGIC );
pm_writebigshort( stdout, cols );
pm_writebigshort( stdout, rows );
item = 0;
bitsperitem = 0;
bitshift = 0;
}

#if __STDC__
static void
putbit( bit b )
#else /*__STDC__*/
static void
putbit( b )
bit b;
#endif /*__STDC__*/
{
if ( bitsperitem == 16 )
putitem( );
++bitsperitem;
if ( b == PBM_BLACK )
item += 1 << bitshift;
++bitshift;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
}

static void
putitem( )
{
pm_writebigshort( stdout, item );
item = 0;
bitsperitem = 0;
bitshift = 0;
}
[512];
int do_long;
int i;
long l;
unsigned u;
unsigned long ul;
char* s;
double d;

n = 0;
while ( *fpbmplus05oct91/pbm/pbmtogem.c 444 3010 34 7337 5032725023 11371 /* pbmtogem.c - read a portable bitmap and produce a GEM .img file
**
** Author: David Beckemeyer (bdt!david)
**
** Much of the code for this program was taken from other
** pbmto* programs. I just modified the code to produce
** a .img header and generate .img "Bit Strings".
**
** Thanks to Diomidis D. Spinellis for the .img header format.
**
** Copyright (C) 1988 by David Beckemeyer (bdt!david) and Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

/*
* File header structure
*/
struct header {
short version;/* Image file version */
unsigned short hlen; /* Header length in bytes */
unsigned short planes; /* Number of planes */
unsigned short patlen; /* Pattern definition length (bytes) */
unsigned short pxlen; /* Pixel height (microns) */
unsigned short pxht; /* Pixel height (microns) */
unsigned short linewid;/* Scan line width (pixels) */
unsigned short nitems; /* Number of scan line items */
};

#define MAXCOL 60
static unsigned short outrow[MAXCOL];

static void putinit ARGS(( struct header* hdr ));
static void putbit ARGS(( bit b ));
static void putrest ARGS(( void ));
static void putitem ARGS(( void ));
static void putrow ARGS(( void ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, format, row, col, pad;
struct header hd;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pbm_readpbminit( ifp, &cols, &rows, &format );

if (cols > MAXCOL * 16)
cols = MAXCOL * 16;

bitrow = pbm_allocrow( cols );

hd.version = 1; /* Image file version */
hd.hlen = 16; /* Header length in bytes */
hd.planes = 1; /* Number of planes */
hd.patlen = 2; /* Pattern definition length (bytes) */
hd.pxlen = 372; /* Pixel height (microns) */
hd.pxht = 372; /* Pixel height (microns) */
hd.linewid = ((cols + 15) / 16) * 16; /* Scan line width (pixels) */
hd.nitems = rows; /* Number of scan line items */

pad = hd.linewid - cols;

putinit( &hd );
for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
putbit( *bP );
for ( col = 0; col < pad; ++col )
putbit( 0 );
}

pm_close( ifp );

putrest( );

exit( 0 );
}

static short item, outcol, outmax;
static short bitsperitem, bitshift;

static void
putinit( hdr )
struct header* hdr;
{
fwrite( hdr, 32, 1, stdout );
item = 0;
bitsperitem = 0;
bitshift = 15;
outcol = 0;
outmax = hdr->linewid / 16;
}

#if __STDC__
static void
putbit( bit b )
#else /*__STDC__*/
static void
putbit( b )
bit b;
#endif /*__STDC__*/
{
if ( bitsperitem == 16 )
putitem( );
++bitsperitem;
if ( b == PBM_BLACK )
item += 1 << bitshift;
--bitshift;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
if ( outcol > 0 )
putrow( );
}

static void
putitem( )
{
outrow[outcol++] = item;
if (outcol >= outmax)
putrow( );
item = 0;
bitsperitem = 0;
bitshift = 15;
}

static void
putrow( )
{
putc(0x80, stdout); /* a Bit string */
putc(outcol*2, stdout); /* count */
fwrite( outrow, outcol*2, 1, stdout );
outcol = 0;
}
This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

/*
* File header structure
*/
struct header {
short version;/* Image file version */
unsigned short hlen; /* Header length in bytes */
unsigned short planes;pbmplus05oct91/pbm/ybmtopbm.1 444 3010 34 1503 5022774752 11327 .TH ybmtopbm 1 "06 March 1990"
.IX ybmtopbm
.SH NAME
ybmtopbm - convert a Bennet Yee "face" file into a portable bitmap
.SH SYNOPSIS
.B ybmtopbm
.RI [ facefile ]
.SH DESCRIPTION
Reads a file acceptable to the
.I face
and
.I xbm
programs by Bennet Yee ([email protected]).
.IX face
Writes a portable bitmap as output.
.SH "SEE ALSO"
pbmtoybm(1), pbm(5), face(1), face(5), xbm(1)
.SH AUTHOR
Copyright (C) 1991 by Jamie Zawinski and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/ybmtopbm.c 444 3010 34 5144 5032726462 11412 /* ybmtopbm.c - read a file from Bennet Yee's 'xbm' program and write a pbm.
**
** Written by Jamie Zawinski based on code (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

static void getinit ARGS(( FILE* file, short* colsP, short* rowsP, short* depthP, short* padrightP ));
static bit getbit ARGS(( FILE* file ));

#define YBM_MAGIC ( ( '!' << 8 ) | '!' )

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
short rows, cols, padright, row, col;
short depth;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[ybmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

getinit( ifp, &cols, &rows, &depth, &padright );
if ( depth != 1 )
pm_error(
"YBM file has depth of %d, must be 1",
(int) depth );

pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

for ( row = 0; row < rows; ++row )
{
/* Get data. */
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
*bP = getbit( ifp );
/* Discard line padding */
for ( col = 0; col < padright; ++col )
(void) getbit( ifp );
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}

pm_close( ifp );

exit( 0 );
}

static int item;
static int bitsperitem, bitshift;

static void
getinit( file, colsP, rowsP, depthP, padrightP )
FILE* file;
short* colsP;
short* rowsP;
short* depthP;
short* padrightP;
{
short magic;

if ( pm_readbigshort( file, &magic ) == -1 )
pm_error( "EOF / read error" );
if ( magic != YBM_MAGIC )
pm_error( "bad magic number in YBM file" );
if ( pm_readbigshort( file, colsP ) == -1 )
pm_error( "EOF / read error" );
if ( pm_readbigshort( file, rowsP ) == -1 )
pm_error( "EOF / read error" );

*depthP = 1;
*padrightP = ( ( *colsP + 15 ) / 16 ) * 16 - *colsP;
bitsperitem = 0;
}

static bit
getbit( file )
FILE* file;
{
bit b;

if ( bitsperitem == 0 )
{
item = getc(file) | getc(file)<<8;
if ( item == EOF )
pm_error( "EOF / read error" );
bitsperitem = 16;
bitshift = 0;
}
b = ( ( item >> bitshift) & 1 ) ? PBM_BLACK : PBM_WHITE;
--bitsperitem;
++bitshift;
return b;
}
< cols; ++col, ++bP )
putbit( *bP );
for ( col = 0; col < pad; ++col )
putbit( 0 );
}

pm_close( ifp );

putrest( );

exit( 0 );
}

static short item, outcol, outmax;
static short bitsperitem, bitshift;

static void
putinit( hdr )
struct header* hdr;
{
fwrite( hdr, 32, 1, stdout );
item = 0;
bitsperitem = 0;
bitshift = 15;
outcol = 0;
opbmplus05oct91/pbm/pbmtoplot.1 444 3010 34 1443 5022774445 11520 .TH pbmtoplot 1 "1 September 1990"
.IX pbmtoplot
.SH NAME
pbmtoplot - convert a portable bitmap into a Unix plot(5) file
.SH SYNOPSIS
.B pbmtoplot
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a Unix
.I plot
file.
.IX plot
.PP
Note that there is no plottopbm tool - this transformation is one-way.
.SH "SEE ALSO"
pbm(5), plot(5)
.SH AUTHOR
Copyright (C) 1990 by Arthur David Olson.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtopi3.c 444 3010 34 4714 5032725034 11312 /* pbmtopi3.c - read a portable bitmap and produce a Atari Degas .pi3 file
**
** Module created from other pbmplus tools by David Beckemeyer.
**
** Copyright (C) 1988 by David Beckemeyer and Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

static void putinit ARGS(( void ));
static void putbit ARGS(( bit b ));
static void putrest ARGS(( void ));
static void putitem ARGS(( void ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, format, padright, row, col;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pbm_readpbminit( ifp, &cols, &rows, &format );
if (cols > 640)
cols = 640;
if (rows > 400)
rows = 400;
bitrow = pbm_allocrow( cols );

/* Compute padding to round cols up to 640 */
padright = 640 - cols;

putinit( );
for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
putbit( *bP );
for ( col = 0; col < padright; ++col )
putbit( 0 );
}
while (row++ < 400)
for ( col = 0; col < 640; ++col)
putbit( 0 );

pm_close( ifp );

putrest( );

exit( 0 );
}

static short item;
static short bitsperitem, bitshift;

static void
putinit( )
{
struct degasHDR {
short res;
short pal[16];
} hdr;

hdr.res = 2;
hdr.pal[0] = 0x0777;
hdr.pal[1] = 0x0700;
fwrite( &hdr, sizeof(hdr), 1, stdout );
item = 0;
bitsperitem = 0;
bitshift = 15;
}

#if __STDC__
static void
putbit( bit b )
#else /*__STDC__*/
static void
putbit( b )
bit b;
#endif /*__STDC__*/
{
if ( bitsperitem == 16 )
putitem( );
++bitsperitem;
if ( b == PBM_BLACK )
item += 1 << bitshift;
--bitshift;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
}

static void
putitem( )
{
fwrite( &item, sizeof(item), 1, stdout );
item = 0;
bitsperitem = 0;
bitshift = 15;
}
bitsperitem = 16;
bitshift = 0;
}
b = ( ( itempbmplus05oct91/pbm/pbmtozinc.1 444 3010 34 1670 5022774630 11503 .TH pbmtozinc l "02 November 1990"
.IX pbmtozinc
.SH NAME
pbmtozinc - convert a portable bitmap into a Zinc bitmap
.SH SYNOPSIS
.B pbmtozinc
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a bitmap in the format used by the Zinc Interface Library
(ZIL) Version 1.0 as output.
.IX "Zinc Interface Library"
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1988 by James Darrell McCauley ([email protected]) and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
.\"
.\" Zinc and Zinc Interface Library are trademarks of
.\" Zinc Software Inc., Pleasant Grove, Utah.
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtoplot.c 444 3010 34 3056 5032725036 11575 /* pbmtoplot.c - read a portable bitmap and produce a UNIX-format plot file.
**
** Copyright (C) 1990 by Arthur David Olson.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

static void
puttwo( i )
int i;
{
(void) putchar(i);
(void) putchar(i >> 8);
}

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
register bit** bits;
register int row, col, scol;
int rows, cols;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

ifp = (argc == 2) ? pm_openr( argv[1] ) : stdin;

bits = pbm_readpbm( ifp, &cols, &rows );

pm_close( ifp );

(void) putchar( 's' );
puttwo( 0 );
puttwo( 0 );
puttwo( rows - 1 );
puttwo( cols - 1 );
for ( row = 0; row < rows; ++row )
{
for ( col = 0; col < cols; ++col )
{
if ( bits[row][col] == PBM_WHITE )
continue;
scol = col;
while ( ++col < cols && bits[row][col] == PBM_BLACK )
; /* nothing */
--col;
if ( col == scol )
(void) putchar( 'p' );
else
{
(void) putchar( 'l' );
puttwo( scol );
puttwo( rows - 1 - row );
}
puttwo( col );
puttwo( rows - 1 - row );
}
}

exit( 0 );
}
le.¸
pbmtoybm.1s.¹
pbmtoybm.cn.º
pbmtogem.cc.»
ybmtopbm.1
.¼
ybmtopbm.c
.½ pbmtoplot.1Vù.¾
pbmtopi3.cD.¿ pbmtozinc.1¾9.À pbmtoplot.cUq.Á
pi3topbm.1
.Â
pi3topbm.c.Ã pbmtoepson.c31.Ä pbmtozinc.cUv.Å
atktopbm.cw.Æ pbmtoascii.1.Ç pbmtoascii.cma.È
pbmtoatk.c.É
atktopbm.1.Ê
pbmtoatk.1t0;
bitsperitem = 0;
bitshift = 15;
}

#if __pbmplus05oct91/pbm/pi3topbm.1 444 3010 34 1355 5023000312 11207 .TH pi3topbm 1 "11 March 1990"
.IX pi3topbm
.SH NAME
pi3topbm - convert an Atari Degas .pi3 file into a portable bitmap
.SH SYNOPSIS
.B pi3topbm
.RI [ pi3file ]
.SH DESCRIPTION
Reads an Atari Degas .pi3 file as input.
.IX Atari
.IX "Degas .pi3"
Produces a portable bitmap as output.
.SH "SEE ALSO"
pbmtopi3(1), pbm(5), pi1toppm(1), ppmtopi1(1)
.SH AUTHOR
Copyright (C) 1988 by David Beckemeyer (bdt!david) and Diomidis D. Spinellis.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted,
.\" provided that the above copyright notice appear in all copies and that
.\" both that copyright notice and this permission notice appear in
.\" supporting documentation.
. pbmtext.css.‘ pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pi3topbm.c 444 3010 34 4210 5032725045 11303 /*
* Convert a ATARI Degas .pi3 file to a portable bitmap file.
*
* Author: David Beckemeyer
*
* This code was derived from the original gemtopbm program written
* by Diomidis D. Spinellis.
*
* (C) Copyright 1988 David Beckemeyer and Diomidis D. Spinellis.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* This file is provided AS IS with no warranties of any kind. The author
* shall have no liability with respect to the infringement of copyrights,
* trade secrets or any patents by this file or any part thereof. In no
* event will the author be liable for any lost revenue or profits or
* other special, indirect and consequential damages.
*/

#include
#include "pbm.h"

/*
* File header structure
*/
struct header {
short res; /* resolution */
short pal[16]; /* palette */
};

void
main(argc, argv)
int argc;
char *argv[];
{
int debug = 0;
FILE *f;
struct header hd;
int x;
int i, k;
int c;
int rows, cols;
bit *bitrow;

pbm_init( &argc, argv );

if (argc > 1 && !strcmp(argv[1], "-d")) {
--argc;
argv[1] = argv[0];
++argv;
debug = 1;
}

if (argc == 1)
f = stdin;
else if (argc == 2)
f = pm_openr( argv[1] );
else
pm_usage("[-d] [pi3file]");

if (fread(&hd, sizeof hd, 1, f) != 1)
pm_perror( "read" );

if (debug)
pm_message( "resolution is %d", hd.res );

/* only handles hi-rez 640x400 */
if (hd.res != 2)
pm_error( "bad resolution" );

cols = 640;
rows = 400;
pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

for (i = 0; i < rows; ++i) {
x = 0;
while (x < cols) {
if ((c = getc(f)) == EOF)
pm_error( "end of file reached" );
for (k = 0x80; k; k >>= 1) {
bitrow[x] = (k & c) ? PBM_BLACK : PBM_WHITE;
++x;
}
}
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}
pm_close( f );
exit(0);
}
== 16 )
putitem( );
++bitsperitem;
if ( b == PBM_BLACK )
item += 1 << bitshift;
--bitshift;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
}

static void
putitem( )
{
fwrite( &item, sizeof(item), 1, stdout );
item = 0;
bitsperitem = 0;
bitshift = 15;
}
bitsperitem = 16;
bitshift = 0;
}
b = ( ( itempbmplus05oct91/pbm/pbmtoepson.c 444 3010 34 4026 5032725021 11733 /* pbmtoeps.c - read a portable bitmap and produce Epson graphics
**
** Copyright (C) 1990 by John Tiller ([email protected])
** and Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

static int mask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit** bits;
bit* bP[8];
int rows, cols, row, col, lastcol;
int idx;
int val;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

bits = pbm_readpbm( ifp, &cols, &rows );

pm_close( ifp );

/* Change line spacing to 8/72 inches. */
printf("\033A\010");
/* Write out rows by eights. */
for ( row = 0; row < rows; row += 8 )
{
/* Find end of lines. */
for ( lastcol = cols-1; lastcol >= 0; --lastcol )
{
for ( idx = 0; idx < 8 && row+idx < rows; ++idx )
if ( bits[row+idx][lastcol] == PBM_BLACK )
break;
if ( idx < 8 && row+idx < rows )
break;
}
for ( idx = 0; idx < 8 && row+idx < rows; ++idx )
bP[idx] = bits[row+idx];
/* Put in plotter (1:1) graphics. */
if ( lastcol >= 0 )
printf("\033*\005%c%c", (lastcol+1)%256, (lastcol+1)/256);
for ( col = 0; col <= lastcol; ++col )
{
val = 0;
for ( idx = 0; idx < 8 && row+idx < rows; ++idx )
if ( *bP[idx] == PBM_BLACK )
val |= mask[idx];
putchar( val );
for ( idx = 0; idx < 8 && row+idx < rows; ++idx )
++bP[idx];
}
putchar( '\n' );
}
putchar( '\f' );
/* Restore normal line spacing. */
printf("\[email protected]");
exit( 0 );
}
BLACK : PBM_WHITE;
++x;
}
}
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}
pm_close( f );
exit(0);
}
== 16 )
putitem( );
++bitsperitem;
if ( b == PBM_BLACK )
item += 1 << bitshift;
--bitshift;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
}

static void
putitem( )
{
fwrite( &item, sizeof(item), 1, stdout );
item = 0;
bitsperitem = 0;
bitshift = 15;
}
bitsperitem = 16;
bitshift = 0;
}
b = ( ( itempbmplus05oct91/pbm/pbmtozinc.c 444 3010 34 5624 5032725043 11563 /* pbmtozinc.c - read a portable bitmap and produce an bitmap file
** in the format used by the Zinc Interface Library (v1.0)
** November 1990.
**
** Author: James Darrell McCauley
** Department of Agricultural Engineering
** Texas A&M University
** College Station, Texas 77843-2117 USA
**
** Copyright (C) 1988 by James Darrell McCauley ([email protected])
** and Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit* bitrow;
register bit* bP;
int rows, cols, format, padright, row;
register int col;
char name[100];
char* cp;
int itemsperline;
register int bitsperitem;
register int item;
int firstitem;
char* hexchar = "084c2a6e195d3b7f";

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
{
ifp = pm_openr( argv[1] );
strcpy( name, argv[1] );
if ( strcmp( name, "-" ) == 0 )
strcpy( name, "noname" );

if ( ( cp = index( name, '.' ) ) != 0 )
*cp = '\0';
}
else
{
ifp = stdin;
strcpy( name, "noname" );
}

pbm_readpbminit( ifp, &cols, &rows, &format );
bitrow = pbm_allocrow( cols );

/* Compute padding to round cols up to the nearest multiple of 16. */
padright = ( ( cols + 15 ) / 16 ) * 16 - cols;

printf( "USHORT %s[] = {\n",name);
printf( " %d\n", cols );
printf( " %d\n", rows );

itemsperline = 0;
bitsperitem = 0;
item = 0;
firstitem = 1;

#define PUTITEM \
{ \
if ( firstitem ) \
firstitem = 0; \
else \
putchar( ',' ); \
if ( itemsperline == 11 ) \
{ \
putchar( '\n' ); \
itemsperline = 0; \
} \
if ( itemsperline == 0 ) \
putchar( ' ' ); \
++itemsperline; \
putchar('0'); \
putchar('x'); \
putchar(hexchar[item & 15]); \
putchar(hexchar[(item >> 4) & 15]); \
putchar(hexchar[(item >> 8) & 15]); \
putchar(hexchar[item >> 12]); \
bitsperitem = 0; \
item = 0; \
}

#define PUTBIT(b) \
{ \
if ( bitsperitem == 16 ) \
PUTITEM; \
if ( (b) == PBM_BLACK ) \
item += 1 << bitsperitem; \
++bitsperitem; \
}

for ( row = 0; row < rows; ++row )
{
pbm_readpbmrow( ifp, bitrow, cols, format );
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
PUTBIT( *bP );
for ( col = 0; col < padright; ++col )
PUTBIT( 0 );
}

pm_close( ifp );

if ( bitsperitem > 0 )
PUTITEM;
printf( "};\n" );

exit( 0 );
}
strcpy( name, "noname" );

if ( ( cp = index( name, '.' ) ) != 0 )
*cp = '\0';
}
else
{
ifppbmplus05oct91/pbm/atktopbm.c 444 3010 34 21742 5070507644 11425 /* atktopbm.c - convert Andrew Toolkit raster object to portable bitmap
**
** Copyright (C) 1991 by Bill Janssen
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include
#include "pbm.h"

void ReadATKRaster();

void
main( argc, argv )
int argc;
char *argv[];
{
FILE *ifd;
register bit *bitrow, *bP;
int rows, cols, row, col, charcount;
unsigned char *data, mask;

pbm_init ( &argc, argv );

if ( argc > 2 )
pm_usage( "[raster obj]" );

if ( argc == 2 )
ifd = pm_openr( argv[1] );
else
ifd = stdin;

ReadATKRaster( ifd, &cols, &rows, &data );

pm_close( ifd );

pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

for ( row = 0; row < rows; ++row )
{
charcount = 0;
mask = 0x80;
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
{
if ( charcount >= 8 )
{
++data;
charcount = 0;
mask = 0x80;
}
*bP = ( *data & mask ) ? PBM_BLACK : PBM_WHITE;
++charcount;
mask >>= 1;
}
++data;
pbm_writepbmrow( stdout, bitrow, cols, 0 );
}

exit( 0 );
}

/* readatkraster
**
** Routine for reading rasters in .raster form. (BE2 rasters version 2.)
*/

/* codes for data stream */
#define WHITEZERO 'f'
#define WHITETWENTY 'z'
#define BLACKZERO 'F'
#define BLACKTWENTY 'Z'
#define OTHERZERO 0x1F

#define WHITEBYTE 0x00
#define BLACKBYTE 0xFF

/* error codes (copied from $ANDREW/atk/basics/common/dataobj.ch) */
/* return values from Read */
#define dataobject_NOREADERROR 0
#define dataobject_PREMATUREEOF 1
#define dataobject_NOTBE2DATASTREAM 2 /* backward compatibility */
#define dataobject_NOTATKDATASTREAM 2 /* preferred version */
#define dataobject_MISSINGENDDATAMARKER 3
#define dataobject_OBJECTCREATIONFAILED 4
#define dataobject_BADFORMAT 5

/* ReadRow(file, row, length)
** Reads from 'file' the encoding of bytes to fill in 'row'. Row will be
** truncated or padded (with WHITE) to exactly 'length' bytes.
**
** Returns the code that terminated the row. This may be
** '|' correct end of line
** '\0' if the length was satisfied (before a terminator)
** EOF if the file ended
** '\' '{' other recognized ends.
** The '|' is the expected end and pads the row with WHITE.
** The '\' and '{' are error conditions and may indicate the
** beginning of some other portion of the data stream.
** If the terminator is '\' or '{', it is left at the front of the input.
** '|' is gobbled up.
*/

/* macros to generate case entries for switch statement */
#define case1(v) case v
#define case4(v) case v: case (v)+1: case (v)+2: case(v)+3
#define case6(v) case4(v): case ((v)+4): case ((v)+5)
#define case8(v) case4(v): case4((v)+4)

static long
ReadRow(file, row, length)
register FILE *file; /* where to get them from */
register unsigned char *row; /* where to put bytes */
register long length; /* how many bytes in row must be filled */
{
/* Each input character is processed by the central loop. There are
** some input codes which require two or three characters for
** completion; these are handled by advancing the state machine.
** Errors are not processed; instead the state machine is reset
** to the Ready state whenever a character unacceptable to the
** current state is read.
*/
enum stateCode {
Ready, /* any input code is allowed */
HexDigitPending, /* have seen the first of a hex digit pair */
RepeatPending, /* repeat code has been seen:
must be followed by two hex digits */
RepeatAndDigit}; /* have seen repeat code and its first
following digit */
enum stateCode InputState; /* current state */
register c; /* the current input character */
register long repeatcount = 0; /* current repeat value */
register long hexval; /* current hex value */
long pendinghex = 0; /* the first of a pair of hex characters */

/* We cannot exit when length becomes zero because we need to check
** to see if a row ending character follows. Thus length is checked
** only when we get a data generating byte. If length then is
** zero, we ungetc the byte.
*/

InputState = Ready;
while ((c=getc(file)) != EOF) switch (c) {

case8(0x0):
case8(0x8):
case8(0x10):
case8(0x18):
case1(' '):
/* control characters and space are legal and ignored */
break;
case1(0x40): /* '@' */
case1(0x5B): /* '[' */
case4(0x5D): /* ']' '^' '_' '`' */
case4(0x7D): /* '}' '~' DEL 0x80 */
default: /* all above 0x80 */
/* error code: Ignored at present. Reset InputState. */
InputState = Ready;
break;

case1(0x7B): /* '{' */
case1(0x5C): /* '\\' */
/* illegal end of line: exit anyway */
ungetc(c, file); /* retain terminator in stream */
/* DROP THROUGH */
case1(0x7C): /* '|' */
/* legal end of row: may have to pad */
while (length-- > 0)
*row++ = WHITEBYTE;
return c;

case1(0x21):
case6(0x22):
case8(0x28):
/* punctuation characters: repeat byte given by two
** succeeding hex chars
*/
if (length <= 0) {
ungetc(c, file);
return('\0');
}
repeatcount = c - OTHERZERO;
InputState = RepeatPending;
break;

case8(0x30):
case8(0x38):
/* digit (or following punctuation) - hex digit */
hexval = c - 0x30;
goto hexdigit;
case6(0x41):
/* A ... F - hex digit */
hexval = c - (0x41 - 0xA);
goto hexdigit;
case6(0x61):
/* a ... f - hex digit */
hexval = c - (0x61 - 0xA);
goto hexdigit;

case8(0x67):
case8(0x6F):
case4(0x77):
/* g ... z - multiple WHITE bytes */
if (length <= 0) {
ungetc(c, file);
return('\0');
}
repeatcount = c - WHITEZERO;
hexval = WHITEBYTE;
goto store;
case8(0x47):
case8(0x4F):
case4(0x57):
/* G ... Z - multiple BLACK bytes */
if (length <= 0) {
ungetc(c, file);
return('\0');
}
repeatcount = c - BLACKZERO;
hexval = BLACKBYTE;
goto store;

hexdigit:
/* process a hex digit. Use InputState to determine
what to do with it. */
if (length <= 0) {
ungetc(c, file);
return('\0');
}
switch(InputState) {
case Ready:
InputState = HexDigitPending;
pendinghex = hexval << 4;
break;
case HexDigitPending:
hexval |= pendinghex;
repeatcount = 1;
goto store;
case RepeatPending:
InputState = RepeatAndDigit;
pendinghex = hexval << 4;
break;
case RepeatAndDigit:
hexval |= pendinghex;
goto store;
}
break;

store:
/* generate byte(s) into the output row
Use repeatcount, depending on state. */
if (length < repeatcount)
/* reduce repeat count if it would exceed
available space */
repeatcount = length;
length -= repeatcount; /* do this before repeatcount-- */
while (repeatcount-- > 0)
*row++ = hexval;
InputState = Ready;
break;

} /* end of while( - )switch( - ) */
return EOF;
}
#undef case1
#undef case4
#undef case6
#undef case8

void
ReadATKRaster(file, rwidth, rheight, destaddr)
FILE *file;
unsigned char **destaddr;
int *rwidth, *rheight;
{
register unsigned char *byteaddr; /* where to store next row */
register long row, rowlen; /* count rows; byte length of row */
long version, options, xscale, yscale;
long xoffset, yoffset, subwidth, subheight;
char keyword[6];
long discardid, objectid; /* id read for the incoming pixel image */
long tc; /* temp */
long width, height; /* dimensions of image */
long result;

if (fscanf(file, "\\begindata{raster,%ld", &discardid) != 1
|| getc(file) != '}' || getc(file) != '\n')
pm_error ("input file not Andrew raster object");

fscanf(file, " %d ", &version);
if (version < 2)
pm_error ("version too old to parse");

/* ignore all these features: */
fscanf(file, " %u %ld %ld %ld %ld %ld %ld",
&options, &xscale, &yscale, &xoffset,
&yoffset, &subwidth, &subheight);

/* scan to end of line in case this is actually something beyond V2 */
while (((tc=getc(file)) != '\n') && (tc != '\\') && (tc != EOF)) {}

/* read the keyword */
fscanf(file, " %5s", keyword);
if (strcmp(keyword, "bits") != 0)
pm_error ("keyword is not bits!");

fscanf(file, " %d %d %d ", &objectid, &width, &height);

if (width < 1 || height < 1 || width > 1000000 || height > 1000000)
pm_error ("bad width or height");

*rwidth = width;
*rheight = height;
rowlen = (width + 7) / 8;
*destaddr = (unsigned char *) malloc (sizeof(unsigned char) * height *
rowlen);
for (row = 0; row < height; row++)
{
long c;

c = ReadRow(file, *destaddr + (row * rowlen), rowlen);
if (c != '|')
{
if (c == EOF)
pm_error ("premature EOF");
else
pm_error ("bad format");
break;
}
}
while (! feof(file) && getc(file) != '\\') {}; /* scan for \enddata */
if (fscanf(file, "enddata{raster,%d", &discardid) != 1
|| getc(file) != '}' || getc(file) != '\n')
pm_error ("missing end-of-object marker");
}
) case4(v): case4((v)+4)

statpbmplus05oct91/pbm/pbmtoascii.1 444 3010 34 1420 5067476431 11630 .TH pbmtoascii 1 "31 August 1988"
.SH NAME
pbmtoascii - convert a portable bitmap into ASCII graphics
.SH SYNOPSIS
.B pbmtoascii
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a somewhat crude ASCII graphic as output.
.PP
Note that there is no asciitopbm tool - this transformation is one-way.
.SH "SEE ALSO"
pbm(5)
.SH AUTHOR
Copyright (C) 1988 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
omacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtoascii.c 444 3010 34 3134 5067477522 11720 /* pbmtoascii.c - read a portable bitmap and produce ASCII graphics
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
bit** bits;
register bit* bP;
register bit* b1P;
int rows, cols, row, lastcol;
register int col;

pbm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

bits = pbm_readpbm( ifp, &cols, &rows );

pm_close( ifp );

/* Write out rows by twos. */
for ( row = 0; row < rows; row += 2 )
{
/* Find end of lines. */
for ( lastcol = cols-1; lastcol > 0; --lastcol )
{
if ( bits[row][lastcol] == PBM_BLACK )
break;
if ( row+1 < rows && bits[row+1][lastcol] == PBM_BLACK )
break;
}
for ( col = 0, bP = bits[row], b1P = bits[row+1]; col <= lastcol; ++col, ++bP, ++b1P )
{
if ( *bP == PBM_WHITE )
{
if ( row+1 >= rows || *b1P == PBM_WHITE )
putchar( ' ' );
else
putchar( 'o' );
}
else
{
if ( row+1 >= rows || *b1P == PBM_WHITE )
putchar( '"' );
else
putchar( '$' );
}
}
putchar( '\n' );
}

exit( 0 );
}

pbmtogem.cc.»
ybmtopbm.1
.¼
ybmtopbm.c
.½ pbmtoplot.1Vù.¾
pbmtopi3.cD.¿ pbmtozinc.1¾9.À pbmtoplot.cUq.Á
pi3topbm.1
.Â
pi3topbm.c.Ã pbmtoepson.c31.Ä pbmtozinc.cUv.Å
atktopbm.cw.Æ pbmtoascii.1.Ç pbmtoascii.cma.È
pbmtoatk.c.É
atktopbm.1.Ê
pbmtoatk.1tnd of line in case this is actually something beyond V2 pbmplus05oct91/pbm/pbmtoatk.c 444 3010 34 10373 5070507133 11414 /* pbmtoatk.c - convert portable bitmap to Andrew Toolkit raster object
**
** Copyright (C) 1991 by Bill Janssen.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pbm.h"

#define DEFAULTSCALE (1<<16)
#define RASTERVERSION 2
#define TRUE 1
#define FALSE 0

void
main( argc, argv )
int argc;
char *argv[];
{
FILE *ifd;
bit *bitrow;
register bit *bP;
int rows, cols, format, padright, row;
register int col;
char name[100], *cp;
static char hexchar[] = "0123456789abcdef";
unsigned char curbyte, newbyte;
int curcount, gather, line;

pbm_init ( &argc, argv );

if ( argc > 2 )
pm_usage( "[pbmfile]" );

if ( argc == 2 )
{
ifd = pm_openr( argv[1] );
strcpy( name, argv[1] );
if ( strcmp( name, "-" ) == 0 )
strcpy( name, "noname" );

if ( ( cp = index( name, '.' ) ) != 0 )
*cp = '\0';
}
else
{
ifd = stdin;
strcpy( name, "noname" );
}

pbm_readpbminit( ifd, &cols, &rows, &format );
bitrow = pbm_allocrow( cols );

/* Compute padding to round cols up to the nearest multiple of 16. */
padright = ( ( cols + 15 ) / 16 ) * 16 - cols;

printf ("\\begindata{raster,%d}\n", 1);
printf ("%ld %ld %ld %ld ", RASTERVERSION,
0, DEFAULTSCALE, DEFAULTSCALE);
printf ("%ld %ld %ld %ld\n",
0, 0, cols, rows); /* subraster */
printf ("bits %ld %ld %ld\n", 1, cols, rows);

for ( row = 0; row < rows; row++ )
{
pbm_readpbmrow( ifd, bitrow, cols, format );
bP = bitrow;
gather = 0;
newbyte = 0;
curbyte = 0;
curcount = 0;
col = 0;
while (col < cols)
{
if (gather > 7)
{
process_atk_byte (&curcount, &curbyte, stdout, newbyte, FALSE);
gather = 0;
newbyte = 0;
}
newbyte = (newbyte << 1) | (*bP++);
gather += 1;
col += 1;
}

if (gather > 0)
{
newbyte = (newbyte << (8 - gather));
process_atk_byte (&curcount, &curbyte, stdout, newbyte, TRUE);
}
}

pm_close( ifd );

printf ("\\enddata{raster, %d}\n", 1);

exit( 0 );
}

write_atk_bytes (file, curbyte, curcount)
FILE *file;
unsigned char curbyte;
unsigned int curcount;
{
/* codes for data stream */
#define WHITEZERO 'f'
#define WHITETWENTY 'z'
#define BLACKZERO 'F'
#define BLACKTWENTY 'Z'
#define OTHERZERO 0x1F

#define WHITEBYTE 0x00
#define BLACKBYTE 0xFF

/* WriteRow table for conversion of a byte value to two character
hex representation */

static unsigned char hex[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};

switch (curbyte) {
case WHITEBYTE:
while (curcount > 20)
fputc(WHITETWENTY, file),
curcount -= 20;
fputc(WHITEZERO + curcount, file);
break;
case BLACKBYTE:
while (curcount > 20)
fputc(BLACKTWENTY, file),
curcount -= 20;
fputc(BLACKZERO + curcount, file);
break;
default:
while (curcount > 16)
fputc(OTHERZERO+16, file),
fputc(hex[curbyte / 16], file),
fputc(hex[curbyte & 15], file),
curcount -= 16;
if (curcount > 1)
fputc(OTHERZERO+curcount, file);
else ; /* the byte written will represent a single instance */
fputc(hex[curbyte / 16], file);
fputc(hex[curbyte & 15], file);
}
}

process_atk_byte (pcurcount, pcurbyte, file, newbyte, eolflag)
int *pcurcount;
unsigned char *pcurbyte;
FILE *file;
unsigned char newbyte;
int eolflag;
{
int curcount = *pcurcount;
unsigned char curbyte = *pcurbyte;

if (curcount < 1)
{
*pcurbyte = curbyte = newbyte;
*pcurcount = curcount = 1;
}
else if (newbyte == curbyte)
{
*pcurcount = (curcount += 1);
}

if (curcount > 0 && newbyte != curbyte)
{
write_atk_bytes (file, curbyte, curcount);
*pcurcount = 1;
*pcurbyte = newbyte;
}

if (eolflag)
{
write_atk_bytes (file, *pcurbyte, *pcurcount);
fprintf (file, " |\n");
*pcurcount = 0;
*pcurbyte = 0;
}
}
t be followed by two hex digits */
RepeatAndDigit}; /* have seen repeat code and its first
following digit */
enum stateCode InputState; /* current state */
register c; /* the current input character */
register long repeatcount = 0; /* current pbmplus05oct91/pbm/atktopbm.1 444 3010 34 1410 5070507337 11310 .TH atktopbm 1 "26 September 1991"
.IX atktopbm
.SH NAME
atktopbm - convert Andrew Toolkit raster object to portable bitmap
.SH SYNOPSIS
.B atktopbm
.RI [ atkfile ]
.SH DESCRIPTION
Reads an Andrew Toolkit raster object as input.
.IX "Andrew Toolkit raster object"
Produces a portable bitmap as output.
.SH "SEE ALSO"
pbmtoatk(1), pbm(5)
.SH AUTHOR
Copyright (C) 1991 by Bill Janssen.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
 pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pbm/pbmtoatk.1 444 3010 34 1407 5070507432 11312 .TH pbmtoatk 1 "26 September 1991"
.IX pbmtoatk
.SH NAME
pbmtoatk - convert portable bitmap to Andrew Toolkit raster object
.SH SYNOPSIS
.B pbmtoatk
.RI [ pbmfile ]
.SH DESCRIPTION
Reads a portable bitmap as input.
Produces a Andrew Toolkit raster object as output.
.IX "Andrew Toolkit raster object"
.SH "SEE ALSO"
atktopbm(1), pbm(5)
.SH AUTHOR
Copyright (C) 1991 by Bill Janssen.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
‘ pbmtomacp.c-ema.’g3.htp.“ pbmtog3.1X.”Makefile.• icontopbm.cndt.– pbmmake.1Ø.— macptopbm.ckip0.˜ pbmreduce.1crip.™
xbmtopbm.1ƒ.š pbmtoicon.1.›
pbmtoptx.1t.œ
pbmto10xpbmplus05oct91/pgm/ 755 3010 34 0 5073531564 7335 pbmplus05oct91/pgm/fitstopgm.c 444 3010 34 13655 5070272170 11622 /* fitstopgm.c - read a FITS file and produce a portable graymap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

struct FITS_Header {
int simple; /* basic format or not */
int bitpix; /* number of bits per pixel */
int naxis; /* number of axes */
int naxis1; /* number of points on axis 1 */
int naxis2; /* number of points on axis 2 */
int naxis3; /* number of points on axis 3 */
double datamin; /* min # */
double datamax; /* max # */
double bzer; /* ??? */
double bscale; /* ??? */
};

static void read_fits_header ARGS(( FILE* fp, struct FITS_Header* hP ));
static void read_card ARGS(( FILE* fp, char* buf ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray* grayrow;
register gray* gP;
int argn, imagenum, image, row;
register int col;
gray maxval;
double fmaxval, scale;
int rows, cols, images;
struct FITS_Header h;
char* usage = "[-image N] [FITSfile]";

pgm_init( &argc, argv );

argn = 1;
imagenum = 1;

if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-image", 2 ) )
{
++argn;
if ( argn == argc || sscanf( argv[argn], "%d", &imagenum ) != 1 )
pm_usage( usage );
}
else
pm_usage( usage );
++argn;
}

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

read_fits_header( ifp, &h );

if ( ! h.simple )
pm_error( "FITS file is not in simple format, can't read" );
switch ( h.bitpix )
{
case 8:
fmaxval = 255.0;
break;

case 16:
fmaxval = 65535.0;
break;

case 32:
fmaxval = 4294967295.0;
break;

default:
pm_error( "unusual bits per pixel (%d), can't read", h.bitpix );
}
if ( h.naxis != 2 && h.naxis != 3 )
pm_error( "FITS file has %d axes, can't read", h.naxis );
cols = h.naxis1;
rows = h.naxis2;
if ( h.naxis == 2 )
images = 1;
else
images = h.naxis3;
if ( imagenum > images )
pm_error( "only %d image%s in this file",
images, images > 1 ? "s" : "" );
maxval = min( fmaxval, PGM_MAXMAXVAL );
if ( h.datamin != 0.0 || h.datamax != 1.0 )
scale = maxval / ( h.datamax - h.datamin );
else
{
/* FITS images are not required to contain DATAMIN and DATAMAX cards
** In this case, it would be necessary to read through the image
** twice to properly scale. Take this shortcut instead, remembering
** that all FITS integers are signed values. This scheme works
** on most images because most astronomical data reduction packages
** scale the images when writing so as to make maximal use of the
** dynamic range of the output format. */
h.bscale = 1.;
h.bzer = ( fmaxval + 1.0 ) * 0.5;
scale = maxval / fmaxval;
}

pgm_writepgminit( stdout, cols, rows, maxval, 0 );
grayrow = pgm_allocrow( cols );
for ( image = 1; image <= imagenum; ++image )
{
if ( image != imagenum )
pm_message( "skipping image %d of %d", image, images );
else if ( images > 1 )
pm_message( "reading image %d of %d", image, images );
for ( row = 0; row < rows; ++row)
{
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
{
int ich;
double val;

switch ( h.bitpix )
{
case 8:
ich = getc( ifp );
if ( ich == EOF )
pm_error( "EOF / read error" );
val = ich;
break;

case 16:
ich = getc( ifp );
if ( ich == EOF )
pm_error( "EOF / read error" );
val = ich << 8;
ich = getc( ifp );
if ( ich == EOF )
pm_error( "EOF / read error" );
val += ich;
break;

case 32:
ich = getc( ifp );
if ( ich == EOF )
pm_error( "EOF / read error" );
val = ich << 24;
ich = getc( ifp );
if ( ich == EOF )
pm_error( "EOF / read error" );
val += ich << 16;
ich = getc( ifp );
if ( ich == EOF )
pm_error( "EOF / read error" );
val += ich << 8;
ich = getc( ifp );
if ( ich == EOF )
pm_error( "EOF / read error" );
val += ich;
break;

default:
pm_error( "can't happen" );
}
*gP = (gray) ( scale * ( val * h.bscale + h.bzer - h.datamin) );
}
if ( image == imagenum )
pgm_writepgmrow( stdout, grayrow, cols, maxval, 0 );
}
}
pm_close( ifp );

exit( 0 );
}

static void
read_fits_header( fp, hP )
FILE* fp;
struct FITS_Header* hP;
{
char buf[80];
int seen_end;
int i;
char c;

seen_end = 0;
hP->simple = 0;
hP->bzer = 0.0;
hP->bscale = 1.0;
hP->datamin = 0.0;
hP->datamax = 1.0;

while ( ! seen_end )
for ( i = 0; i < 36; ++i )
{
read_card( fp, buf );

if ( sscanf( buf, "SIMPLE = %c", &c ) == 1 )
{
if ( c == 'T' || c == 't' )
hP->simple = 1;
}
else if ( sscanf( buf, "BITPIX = %d", &(hP->bitpix) ) == 1 );
else if ( sscanf( buf, "NAXIS = %d", &(hP->naxis) ) == 1 );
else if ( sscanf( buf, "NAXIS1 = %d", &(hP->naxis1) ) == 1 );
else if ( sscanf( buf, "NAXIS2 = %d", &(hP->naxis2) ) == 1 );
else if ( sscanf( buf, "NAXIS3 = %d", &(hP->naxis3) ) == 1 );
else if ( sscanf( buf, "DATAMIN = %lf", &(hP->datamin) ) == 1 );
else if ( sscanf( buf, "DATAMAX = %lf", &(hP->datamax) ) == 1 );
else if ( sscanf( buf, "BZERO = %lf", &(hP->bzer) ) == 1 );
else if ( sscanf( buf, "BSCALE = %lf", &(hP->bscale) ) == 1 );
else if ( strncmp( buf, "END ", 4 ) == 0 ) seen_end = 1;
}
}

static void
read_card( fp, buf )
FILE* fp;
char* buf;
{
if ( fread( buf, 1, 80, fp ) == 0 )
pm_error( "error reading header" );
}
CK bytes */
if (length <= 0) {
ungetc(c, file);
return('\0');
}
repeatcpbmplus05oct91/pgm/fitstopgm.1 444 3010 34 2410 5022775030 11503 .TH fitstopgm 1 "20 September 89"
.IX fitstopgm
.SH NAME
fitstopgm - convert a FITS file into a portable graymap
.SH SYNOPSIS
.B fitstopgm
.RB [ -image
.IR N ]
.RI [ FITSfile ]
.SH DESCRIPTION
Reads a FITS file as input.
.IX FITS
Produces a portable graymap as output.
The results may need to be flipped top for bottom; if so, just
pipe the output through
.B pnmflip -tb.
.IX pnmflip
.SH OPTIONS
.PP
The
.B -image
option is for FITS files with three axes.
The assumption is that the third axis is for multiple images,
and this option lets you select which one you want.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH REFERENCES
FITS stands for Flexible Image Transport System. A full description
can be found in Astronomy & Astrophysics Supplement Series 44 (1981),
page 363.
.SH "SEE ALSO"
pgmtofits(1), pgm(5), pnmflip(1)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
int rows, cols, images;
struct FITS_Header h;
char* usage = "[-image N] [FITSfile]";

pgm_init( &argc, argv );

argn = 1;
imagenum = 1;

if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymapbmplus05oct91/pgm/fstopgm.1 444 3010 34 3204 5022775065 11160 .TH fstopgm 1 "06 April 89"
.IX fstopgm
.SH NAME
fstopgm - convert a Usenix FaceSaver(tm) file into a portable graymap
.SH SYNOPSIS
.B fstopgm
.RI [ fsfile ]
.SH DESCRIPTION
Reads a Usenix FaceSaver(tm) file as input.
.IX FaceSaver
Produces a portable graymap as output.
.PP
FaceSaver(tm) files sometimes have rectangular pixels.
While
.I fstopgm
won't re-scale them into square pixels for you,
it will give you the precise
.I pnmscale
command that will do the job.
Because of this, reading a FaceSaver(tm) image is a two-step process.
First you do:
.nf
fstopgm > /dev/null
.fi
This will tell you whether you need to use
.I pnmscale.
Then use one of the following pipelines:
.nf
fstopgm | pgmnorm
fstopgm | pnmscale -whatever | pgmnorm
.fi
To go to PBM, you want something more like one of these:
.nf
fstopgm | pnmenlarge 3 | pgmnorm | pgmtopbm
fstopgm | pnmenlarge 3 | pnmscale | pgmnorm | pgmtopbm
.fi
You want to enlarge when going to a bitmap because otherwise you lose
information; but enlarging by more than 3 does not look good.
.PP
FaceSaver is a registered trademark of Metron Computerware Ltd. of
Oakland, CA.
.SH "SEE ALSO"
pgmtofs(1), pgm(5), pgmnorm(1), pnmenlarge(1), pnmscale(1), pgmtopbm(1)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
ge( usage );
}
else
pm_usage( usage );
++argn;
}

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

read_fits_header( ifp, &h );

if ( ! h.simple )
pm_error( "FITS file is not in simple format, can't read" );
switch ( h.bitpix )
{
case 8:
fmaxval = 255.0;
break;pbmplus05oct91/pgm/hipstopgm.1 444 3010 34 1614 5022775075 11517 .TH hipstopgm 1 "24 August 89"
.IX hipstopgm
.SH NAME
hipstopgm - convert a HIPS file into a portable graymap
.SH SYNOPSIS
.B hipstopgm
.RI [ hipsfile ]
.SH DESCRIPTION
Reads a HIPS file as input.
.IX HIPS
Produces a portable graymap as output.
.PP
If the HIPS file contains more than one frame in sequence, hipstopgm
will concatenate all the frames vertically.
.PP
HIPS is a format developed at the Human Information Processing
Laboratory, NYU.
.SH "SEE ALSO"
pgm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
pgmoil.c.˜=u pgmbentley.c.™=v pgmbentley.1 =wpgmoil.1.›=x pgmtexture.c
=º pbmplus05oct91/pgm/libpgm.3 444 3010 34 5734 4747204071 10764 .TH libpgm 3
.SH NAME
libpgm - functions to support portable graymap programs
.SH SYNOPSIS
.de Ss
.sp
.ft CW
.nf
..
.de Se
.fi
.ft P
.sp
..
.Ss
#include
cc ... libpgm.a libpbm.a
.Se
.SH DESCRIPTION
.SS TYPES AND CONSTANTS
.Ss
typedef ... gray;
#define PGM_MAXMAXVAL ...
extern gray pgm_pbmmaxval;
.Se
Each
.BR gray
should contain only the values between
.BR 0
and
.BR PGM_MAXMAXVAL .
.BR pgm_pbmmaxval
is the maxval used when a PGM program reads a PBM file.
Normally it is 1; however, for some programs, a larger value gives better
results.
.Ss
#define PGM_FORMAT ...
#define RPGM_FORMAT ...
#define PGM_TYPE PGM_FORMAT
int PGM_FORMAT_TYPE( int format )
.Se
For distinguishing different file formats and types.
.SS INITIALIZATION
.Ss
void pgm_init( int* argcP, char* argv[] )
.Se
All PGM programs must call this routine.
.SS MEMORY MANAGEMENT
.Ss
gray** pgm_allocarray( int cols, int rows )
.Se
Allocate an array of grays.
.Ss
gray* pgm_allocrow( int cols )
.Se
Allocate a row of the given number of grays.
.Ss
void pgm_freearray( gray** grays, int rows )
.Se
Free the array allocated with
.BR pgm_allocarray()
containing the given number
of rows.
.Ss
void pgm_freerow( gray* grayrow )
.Se
Free a row of grays.
.SS READING FILES
.Ss
void pgm_readpgminit( FILE* fp, int* colsP, int* rowsP, gray* maxvalP, int* formatP )
.Se
Read the header from a PGM file, filling in the rows, cols, maxval and format
variables.
.Ss
void pgm_readpgmrow( FILE* fp, gray* grayrow, int cols, gray maxval, int format )
.Se
Read a row of grays into the grayrow array.
Format, cols, and maxval were filled in by
.BR pgm_readpgminit() .
.Ss
gray** pgm_readpgm( FILE* fp, int* colsP, int* rowsP, gray* maxvalP )
.Se
Read an entire graymap file into memory, returning the allocated array and
filling in the rows, cols and maxval variables.
This function combines
.BR pgm_readpgminit() ,
.BR pgm_allocarray()
and
.BR pgm_readpgmrow() .
.SS WRITING FILES
.Ss
void pgm_writepgminit( FILE* fp, int cols, int rows, gray maxval, int forceplain )
.Se
Write the header for a portable graymap file.
The forceplain flag forces a plain-format file to be written, as opposed
to a raw-format one.
.Ss
void pgm_writepgmrow( FILE* fp, gray* grayrow, int cols, gray maxval, int forceplain )
.Se
Write a row from a portable graymap.
.Ss
void pgm_writepgm( FILE* fp, gray** grays, int cols, int rows, gray maxval, int forceplain )
.Se
Write the header and all data for a portable graymap.
This function combines
.BR pgm_writepgminit()
and
.BR pgm_writepgmrow() .
.SH "SEE ALSO"
libpbm(3), libppm(3), libpnm(3)
.SH AUTHOR
Copyright (C) 1989, 1991 by Tony Hansen and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
s when writing so as to make maximalpbmplus05oct91/pgm/pgmtofits.1 444 3010 34 1603 5022775500 11510 .TH pgmtofits 1 "20 September 1989"
.IX pgmtofits
.SH NAME
pgmtofits - convert a portable graymap into FITS format
.SH SYNOPSIS
.B pgmtofits
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Produces a FITS file as output.
.IX FITS
.PP
FITS stands for Flexible Image Transport System. A full description
can be found in Astronomy & Astrophysics Supplement Series 44 (1981),
page 363.
.SH "SEE ALSO"
fitstopgm(1), pgm(5)
.SH AUTHOR
Copyright (C) 1989 by Wilson H. Bent ([email protected]).
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
c =tpgmoil.c.˜=u pgmbentley.c.™=v pgmbentley.1 =wpgmoil.1.›=x pgmtexture.c
=º pbmplus05oct91/pgm/fstopgm.c 444 3010 34 6336 5035376320 11246 /* fstopgm.c - read a Usenix FaceSaver(tm) file and produce a portable graymap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

static int gethexit ARGS(( FILE* ifp ));

void
main( argc, argv )
int argc;
char *argv[];
{
FILE *ifp;
register gray **grays, *gP;
int argn, row;
register int col;
int maxval;
int rows = 0, cols = 0, depth = 0, xrows = 0, xcols = 0, xdepth = 0;
#define STRSIZE 1000
char buf[STRSIZE], firstname[STRSIZE], lastname[STRSIZE], email[STRSIZE];

pgm_init( &argc, argv );

argn = 1;

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
argn++;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( "[fsfile]" );

/* Read the FaceSaver(tm) header. */
for ( ; ; )
{
if ( fgets( buf, STRSIZE, ifp ) == (char *) 0 )
pm_error( "error reading header" );

/* Blank line ends header. */
if ( strlen( buf ) == 1 )
break;

if ( sscanf( buf, "FirstName: %[^\n]", firstname ) == 1 )
;
else if ( sscanf( buf, "LastName: %[^\n]", lastname ) == 1 )
;
else if ( sscanf( buf, "E-mail: %[^\n]", email ) == 1 )
;
else if ( sscanf( buf, "PicData: %d %d %d\n",
&cols, &rows, &depth ) == 3 )
{
if ( depth != 8 )
pm_error(
"can't handle 'PicData' depth other than 8" );
}
else if ( sscanf( buf, "Image: %d %d %d\n",
&xcols, &xrows, &xdepth ) == 3 )
{
if ( xdepth != 8 )
pm_error(
"can't handle 'Image' depth other than 8" );
}
}
if ( cols <= 0 || rows <= 0 )
pm_error( "invalid header" );
maxval = pm_bitstomaxval( depth );
if ( maxval > PGM_MAXMAXVAL )
pm_error( "depth is too large - try reconfiguring with PGM_BIGGRAYS" );
if ( xcols != 0 && xrows != 0 && ( xcols != cols || xrows != rows ) )
{
float rowratio, colratio;

rowratio = (float) xrows / (float) rows;
colratio = (float) xcols / (float) cols;
pm_message(
"warning, non-square pixels; to fix do a 'pnmscale -%cscale %g'",
rowratio > colratio ? 'y' : 'x',
rowratio > colratio ? rowratio / colratio : colratio / rowratio );
}

/* Now read the hex bits. */
grays = pgm_allocarray( cols, rows );
for ( row = rows - 1; row >= 0; row--)
{
for ( col = 0, gP = grays[row]; col < cols; col++, gP++ )
{
*gP = gethexit( ifp ) << 4;
*gP += gethexit( ifp );
}
}
pm_close( ifp );

/* And write out the graymap. */
pgm_writepgm( stdout, grays, cols, rows, (gray) maxval, 0 );

exit( 0 );
}

static int
gethexit( ifp )
FILE *ifp;
{
register int i;
register char c;

for ( ; ; )
{
i = getc( ifp );
if ( i == EOF )
pm_error( "EOF / read error" );
c = (char) i;
if ( c >= '0' && c <= '9' )
return c - '0';
else if ( c >= 'A' && c <= 'F' )
return c - 'A' + 10;
else if ( c >= 'a' && c <= 'f' )
return c - 'a' + 10;
/* Else ignore - whitespace. */
}
}
ls );
for ( image = 1; image <= imagenum; ++image )
{
if ( image != imagenum )
pm_message( "skipping image %d of %d", image, images );
else if ( images > 1 )
pm_message( "reading image %d of %d", image, images );
for ( row = 0; row < rows; ++row)
{
for ( col = 0pbmplus05oct91/pgm/pgmnorm.c 444 3010 34 11734 5032732334 11262 /* pgmnorm.c - read a portable graymap and normalize the contrast
**
** Copyright (C) 1989, 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

static int hist[PGM_MAXMAXVAL+1];

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray maxval;
gray** grays;
gray* grayrow;
register gray* gP;
int argn, rows, cols, format, row;
register int col;
int i, size, cutoff, count, val;
float bpercent, wpercent;
int bvalue, wvalue, range;
int specbpercent, specbvalue, specwpercent, specwvalue;
char* usage = "[-bpercent N | -bvalue N] [-wpercent N | -wvalue N] [pgmfile]";

pgm_init( &argc, argv );

argn = 1;
bpercent = 2.0;
wpercent = 1.0;
specbpercent = specbvalue = specwpercent = specwvalue = 0;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-bpercent", 3 ) )
{
if ( specbvalue )
pm_error( "only one of -bpercent and -bvalue may be specified" );
++argn;
if ( argn == argc || sscanf( argv[argn], "%f", &bpercent ) != 1 )
pm_usage( usage );
if ( bpercent < 0.0 || bpercent > 100.0 )
pm_error( "black percentage must between 0 and 100" );
specbpercent = 1;
}
else if ( pm_keymatch( argv[argn], "-bvalue", 3 ) )
{
if ( specbpercent )
pm_error( "only one of -bpercent and -bvalue may be specified" );
++argn;
if ( argn == argc || sscanf( argv[argn], "%d", &bvalue ) != 1 )
pm_usage( usage );
if ( bvalue < 0 )
pm_error( "black value must be >= 0" );
specbvalue = 1;
}
else if ( pm_keymatch( argv[argn], "-wpercent", 3 ) )
{
if ( specwvalue )
pm_error( "only one of -wpercent and -wvalue may be specified" );
++argn;
if ( argn == argc || sscanf( argv[argn], "%f", &wpercent ) != 1 )
pm_usage( usage );
if ( wpercent < 0.0 || wpercent > 100.0 )
pm_error( "white percentage must be between 0 and 100" );
specwpercent = 1;
}
else if ( pm_keymatch( argv[argn], "-wvalue", 3 ) )
{
if ( specwpercent )
pm_error( "only one of -wpercent and -wvalue may be specified" );
++argn;
if ( argn == argc || sscanf( argv[argn], "%d", &wvalue ) != 1 )
pm_usage( usage );
if ( wvalue < 0 )
pm_error( "white value must be >= 0" );
specwvalue = 1;
}
else
pm_usage( usage );
++argn;
}

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

if ( specbvalue && specwvalue )
{
/* Rescale so that bvalue maps to 0, wvalue maps to maxval. */
pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
grayrow = pgm_allocrow( cols );
pgm_writepgminit( stdout, cols, rows, maxval, 0 );
for ( i = 0; i <= bvalue; ++i )
hist[i] = 0;
for ( i = wvalue; i <= maxval; ++i )
hist[i] = maxval;
range = wvalue - bvalue;
for ( i = bvalue+1, val = maxval; i < wvalue; ++i, val += maxval )
hist[i] = val / range;
for ( row = 0; row < rows; ++row )
{
pgm_readpgmrow( ifp, grayrow, cols, maxval, format );
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
*gP = hist[*gP];
pgm_writepgmrow( stdout, grayrow, cols, maxval, 0 );
}
pm_close( ifp );
}
else
{
grays = pgm_readpgm( ifp, &cols, &rows, &maxval );
pm_close( ifp );

/* Build histogram. */
for ( i = 0; i <= maxval; ++i )
hist[i] = 0;
for ( row = 0; row < rows; ++row )
for ( col = 0, gP = grays[row]; col < cols; ++col, ++gP )
++hist[*gP];
size = rows * cols;
if ( ! specbvalue )
{ /* Compute bvalue from bpercent. */
cutoff = size * bpercent / 100.0;
count = 0;
for ( bvalue = 0; bvalue <= maxval; ++bvalue )
{
count += hist[bvalue];
if ( count > cutoff )
break;
}
}
if ( ! specwvalue )
{ /* Compute wvalue from wpercent. */
cutoff = size * wpercent / 100.0;
count = 0;
for ( wvalue = maxval; wvalue >= 0; wvalue-- )
{
count += hist[wvalue];
if ( count > cutoff )
break;
}
}

/* Now rescale so that bvalue maps to 0, wvalue maps to maxval. */
pm_message(
"remapping %d..%d to %d..%d", bvalue, wvalue, 0, maxval, 0 );
pgm_writepgminit( stdout, cols, rows, maxval, 0 );
for ( i = 0; i <= bvalue; ++i )
hist[i] = 0;
for ( i = wvalue; i <= maxval; ++i )
hist[i] = maxval;
range = wvalue - bvalue;
for ( i = bvalue + 1, val = maxval; i < wvalue; ++i, val += maxval )
hist[i] = val / range;
for ( row = 0; row < rows; ++row )
{
for ( col = 0, gP = grays[row]; col < cols; ++col, ++gP )
*gP = hist[*gP];
pgm_writepgmrow( stdout, grays[row], cols, maxval, 0 );
}
}

exit( 0 );
}
++argn;
if ( argn == argc || pbmplus05oct91/pgm/pgmtofs.c 444 3010 34 6365 5032726477 11261 /* pgmtofs.c - convert portable graymap to Usenix FaceSaver(tm) format
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

static void putinit ARGS(( int cols, int rows, int bps ));
static void putitem ARGS(( void ));
static void putgray ARGS(( gray g ));
static void putrest ARGS(( void ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray** grays;
register gray* gP;
int argn, rows, cols, bps, padright, row, col;
gray maxval, nmaxval;
char* usage = "[pgmfile]";

pgm_init( &argc, argv );

argn = 1;

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
{
ifp = stdin;
}

if ( argn != argc )
pm_usage( usage );

grays = pgm_readpgm( ifp, &cols, &rows, &maxval );
pm_close( ifp );

/* Figure out bps. */
bps = pm_maxvaltobits( (int) maxval );
if ( bps > 2 && bps < 4 )
bps = 4;
else if ( bps > 4 && bps < 8 )
bps = 8;
else if ( bps > 8 )
pm_error(
"maxval of %d is too large for FaceSaver(tm)", maxval );
nmaxval = pm_bitstomaxval( bps );

/* Compute padding to round cols * bps up to the nearest multiple of 8. */
padright = ( ( cols * bps + 7 ) / 8 ) * 8 - cols * bps;

putinit( cols, rows, bps );
for ( row = rows - 1; row >= 0; --row )
{
for ( col = 0, gP = grays[row]; col < cols; ++col, ++gP )
{
if ( maxval != nmaxval )
*gP = (int) *gP * nmaxval / maxval;
putgray( *gP );
}
for ( col = 0; col < padright; ++col )
putgray( 0 );
}

putrest( );

exit( 0 );
}


static int bitspersample, item, bitsperitem, bitshift, itemsperline, items;

static void
putinit( cols, rows, bps )
int cols, rows, bps;
{
printf( "FirstName: \n" );
printf( "LastName: \n" );
printf( "E-mail: \n" );
printf( "Telephone: \n" );
printf( "Company: \n" );
printf( "Address1: \n" );
printf( "Address2: \n" );
printf( "CityStateZip: \n" );
printf( "Date: \n" );
printf( "PicData: %d %d %d\n", cols, rows, bps );
printf( "Image: %d %d %d\n", cols, rows, bps );
printf( "\n" );

bitspersample = bps;
itemsperline = items = 0;
item = 0;
bitsperitem = 0;
bitshift = 8 - bitspersample;
}

static void
putitem( )
{
char* hexits = "0123456789abcdef";

if ( itemsperline == 30 )
{
putchar( '\n' );
itemsperline = 0;
}
putchar( hexits[item >> 4] );
putchar( hexits[item & 15] );
++itemsperline;
++items;
item = 0;
bitsperitem = 0;
bitshift = 8 - bitspersample;
}

#if __STDC__
static void
putgray( gray g )
#else /*__STDC__*/
static void
putgray( g )
gray g;
#endif /*__STDC__*/
{
if ( bitsperitem == 8 )
putitem( );
item += g << bitshift;
bitsperitem += bitspersample;
bitshift -= bitspersample;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
printf( "\n" );
}
1; image <= imagenum; ++image )
{
if ( image != imagenum )
pm_message( "skipping image %d of %d", image, images );
else if ( images > 1 )
pm_message( "reading image %d of %d", image, images );
for ( row = 0; row < rows; ++row)
{
for ( col = 0pbmplus05oct91/pgm/pgmtofs.1 444 3010 34 1472 5022775512 11162 .TH pgmtofs 1 "18 May 1990"
.IX pgmtofs
.SH NAME
pgmtofs - convert portable graymap to Usenix FaceSaver(tm) format
.SH SYNOPSIS
.B pgmtofs
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Produces Usenix FaceSaver(tm) format as output.
.IX FaceSaver
.PP
FaceSaver is a registered trademark of Metron Computerware Ltd. of
Oakland, CA.
.SH "SEE ALSO"
fstopgm(1), pgm(5)
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
.1X=q lispmtopgm.c.•=r pgmtolispm.1.–=s pgmtolispm.c =tpgmoil.c.˜=u pgmbentley.c.™=v pgmbentley.1 =wpgmoil.1.›=x pgmtexture.c
=º pbmplus05oct91/pgm/pgmramp.c 444 3010 34 4511 5073524112 11217 /* pgmramp.c - generate a grayscale ramp
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

void
main( argc, argv )
int argc;
char *argv[];
{
gray *grayrow;
register gray *gP;
int rows, cols, rowso2, colso2, row;
register int col;
int ramptype;
#define RT_LR 1
#define RT_TB 2
#define RT_RECT 3
#define RT_ELLIP 4
char *usage = "-lr|-tb|-rectangle|-ellipse ";

pgm_init( &argc, argv );

if ( argc != 4 )
pm_usage( usage );

if ( pm_keymatch( argv[1], "-lr", 2 ) )
ramptype = RT_LR;
else if ( pm_keymatch( argv[1], "-tb", 2 ) )
ramptype = RT_TB;
else if ( pm_keymatch( argv[1], "-rectangle", 2 ) )
ramptype = RT_RECT;
else if ( pm_keymatch( argv[1], "-ellipse", 2 ) )
ramptype = RT_ELLIP;
else
pm_usage( usage );

if ( sscanf( argv[2], "%d", &cols ) != 1 )
pm_usage( usage );
if ( sscanf( argv[3], "%d", &rows ) != 1 )
pm_usage( usage );

colso2 = cols / 2;
rowso2 = rows / 2;

pgm_writepgminit( stdout, cols, rows, PGM_MAXMAXVAL, 0 );
grayrow = pgm_allocrow( cols );

for ( row = 0; row < rows; ++row )
{
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
{
switch ( ramptype )
{
case RT_LR:
*gP = col * PGM_MAXMAXVAL / ((cols == 1) ? 1 : (cols - 1));
break;

case RT_TB:
*gP = row * PGM_MAXMAXVAL / ((rows == 1) ? 1 : (rows - 1));
break;

case RT_RECT:
{
float r, c;
r = abs( rowso2 - row ) / (float) rowso2;
c = abs( colso2 - col ) / (float) colso2;
*gP = PGM_MAXMAXVAL - ( r + c ) / 2.0 * PGM_MAXMAXVAL;
}
break;

case RT_ELLIP:
{
float r, c, v;
r = abs( rowso2 - row ) / (float) rowso2;
c = abs( colso2 - col ) / (float) colso2;
v = r * r + c * c;
if ( v < 0.0 ) v = 0.0;
else if ( v > 1.0 ) v = 1.0;
*gP = PGM_MAXMAXVAL - v * PGM_MAXMAXVAL;
}
break;

default:
pm_error( "can't happen" );
}
}
pgm_writepgmrow( stdout, grayrow, cols, PGM_MAXMAXVAL, 0 );
}

exit( 0 );
}
\n" );
printf( "PicData: %d %d %d\n", cols, rows, bps );
printf( "Image: %d %d %d\n", cols, rows, bps );
printf( "\n" );

bitspersample = bps;
itemsperline = itemspbmplus05oct91/pgm/rawtopgm.c 444 3010 34 4515 5032725102 11415 /* rawtopgm.c - convert raw grayscale bytes into a portable graymap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray* grayrow;
register gray* gP;
int argn, headerskip, row, i;
float rowskip, toskip;
register int col, val;
int rows, cols;
char* usage = "[-headerskip N] [-rowskip N] [rawfile]";
double atof();

pgm_init( &argc, argv );

argn = 1;
headerskip = 0;
rowskip = 0.0;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-headerskip", 2 ) )
{
++argn;
if ( argn >= argc )
pm_usage( usage );
headerskip = atoi( argv[argn] );
}
else if ( pm_keymatch( argv[argn], "-rowskip", 2 ) )
{
++argn;
if ( argn >= argc )
pm_usage( usage );
rowskip = atof( argv[argn] );
}
else
pm_usage( usage );
++argn;
}

if ( argn + 2 > argc )
pm_usage( usage );

cols = atoi( argv[argn++] );
rows = atoi( argv[argn++] );
if ( cols <= 0 || rows <= 0 )
pm_usage( usage );

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pgm_writepgminit( stdout, cols, rows, (gray) 255, 0 );
grayrow = pgm_allocrow( cols );
for ( i = 0; i < headerskip; ++i )
{
val = getc( ifp );
if ( val == EOF )
pm_error( "EOF / read error" );
}
toskip = 0.00001;
for ( row = 0; row < rows; ++row)
{
for ( col = 0, gP = grayrow; col < cols; ++col )
{
val = getc( ifp );
if ( val == EOF )
pm_error( "EOF / read error" );
*gP++ = val;
}
for ( toskip += rowskip; toskip >= 1.0; toskip -= 1.0 )
{
val = getc( ifp );
if ( val == EOF )
pm_error( "EOF / read error" );
}
pgm_writepgmrow( stdout, grayrow, cols, (gray) 255, 0 );
}
pm_close( ifp );

exit( 0 );
}
);
printf( "PicData: %d %d %d\n", cols, rows, bps );
printf( "Image: %d %d %d\n", cols, rows, bps );
printf( "\n" );

bitspersample = bps;
itemsperline = itemspbmplus05oct91/pgm/pgm.5 444 3010 34 6211 5070464655 10274 .TH pgm 5 "27 September 1991"
.SH NAME
pgm - portable graymap file format
.SH DESCRIPTION
The portable graymap format is a lowest common denominator grayscale
file format.
.IX "PGM file format"
The definition is as follows:
.IP - 2
A "magic number" for identifying the file type.
A pgm file's magic number is the two characters "P2".
.IX "magic numbers"
.IP - 2
Whitespace (blanks, TABs, CRs, LFs).
.IP - 2
A width, formatted as ASCII characters in decimal.
.IP - 2
Whitespace.
.IP - 2
A height, again in ASCII decimal.
.IP - 2
Whitespace.
.IP - 2
The maximum gray value, again in ASCII decimal.
.IP - 2
Whitespace.
.IP - 2
Width * height gray values, each in ASCII decimal, between 0 and the specified
maximum value, separated by whitespace, starting at the top-left
corner of the graymap, proceeding in normal English reading order.
A value of 0 means black, and the maximum value means white.
.IP - 2
Characters from a "#" to the next end-of-line are ignored (comments).
.IP - 2
No line should be longer than 70 characters.
.PP
Here is an example of a small graymap in this format:
.nf
P2
# feep.pgm
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
.fi
.PP
Programs that read this format should be as lenient as possible,
accepting anything that looks remotely like a graymap.
.PP
There is also a variant on the format, available
by setting the RAWBITS option at compile time. This variant is
different in the following ways:
.IX RAWBITS
.IP - 2
The "magic number" is "P5" instead of "P2".
.IP - 2
The gray values are stored as plain bytes, instead of ASCII decimal.
.IP - 2
No whitespace is allowed in the grays section, and only a single character
of whitespace (typically a newline) is allowed after the maxval.
.IP - 2
The files are smaller and many times faster to read and write.
.PP
Note that this raw format can only be used for maxvals less than
or equal to 255.
If you use the
.I pgm
library and try to write a file with a larger maxval,
it will automatically fall back on the slower but more general plain
format.
.SH "SEE ALSO"
fitstopgm(1), fstopgm(1), hipstopgm(1), lispmtopgm(1), psidtopgm(1),
rawtopgm(1),
pgmbentley(1), pgmedge(1), pgmenhance(1), pgmhist(1), pgmnorm(1),
pgmoil(1), pgmramp(1), pgmtexture(1),
pgmtofits(1), pgmtofs(1), pgmtolispm(1), pgmtopbm(1),
pnm(5), pbm(5), ppm(5)
.SH AUTHOR
Copyright (C) 1989, 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
usage );

pgm_writepgminit( stdout, cols, rows, (gray) 255, 0 );
grayrow = pgm_allocrow( cols );
for ( i = 0; i < headerskip; ++i )
{
val = getc( ifp );
if ( val == EOF )
pm_error( "EOF / read error" );
}
toskip = 0.00001;
for ( row = 0; row < rows; ++row)
{
for ( col = 0, gP = grayrow; col < cols; ++col )
{
val = getc( ifp );
pbmplus05oct91/pgm/pgmmerge.c 444 3010 34 3075 5070471314 11365 /* pgmmerge.c - wrapper program for PGM
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pgm.h"

void
main( argc, argv )
int argc;
char *argv[];
{
register char *cp;

again:
if ( ( cp = rindex( argv[0], '/' ) ) != (char*) 0 )
++cp;
else
cp = argv[0];
if ( strcmp( cp, "pgmmerge" ) == 0 )
{
++argv;
--argc;
goto again;
}

#define TRY(s,m) { if ( strcmp( cp, s ) == 0 ) m( argc, argv ); }

TRY("fitstopgm", fitstopgm_main);
TRY("fstopgm", fstopgm_main);
TRY("hipstopgm", hipstopgm_main);
TRY("lispmtopgm", lispmtopgm_main);
TRY("pgmbentley", pgmbentley_main);
TRY("pgmedge", pgmedge_main);
TRY("pgmenhance", pgmenhance_main);
TRY("pgmhist", pgmhist_main);
TRY("pgmnorm", pgmnorm_main);
TRY("pgmoil", pgmoil_main);
TRY("pgmramp", pgmramp_main);
TRY("pgmtexture", pgmtexture_main);
TRY("pgmtopbm", pgmtopbm_main);
TRY("pgmtofits", pgmtofits_main);
TRY("pgmtofs", pgmtofs_main);
TRY("pgmtolispm", pgmtolispm_main);
TRY("psidtopgm", psidtopgm_main);
TRY("rawtopgm", rawtopgm_main);

(void) fprintf(
stderr, "pgmmerge: \"%s\" is an unknown PGM program!\n", cp );
exit( 1 );
}
This software is provided "as is" without express or
.\" implied warranty.
usage );

pgm_writepgminit( stdout, cols, rows, (gray) 255, 0 );
grayrow = pgm_allocrow( cols );
for ( i = 0; i < headerskip; ++i )
{
val = getc( ifp );
if ( val == EOF )
pm_error( "EOF / read error" );
}
toskip = 0.00001;
for ( row = 0; row < rows; ++row)
{
for ( col = 0, gP = grayrow; col < cols; ++col )
{
val = getc( ifp );
pbmplus05oct91/pgm/dithers.h 444 3010 34 6653 4434107401 11232 /*
** dithers.h
**
** Here are some dithering matrices. They are all taken from "Digital
** Halftoning" by Robert Ulichney, MIT Press, ISBN 0-262-21009-6.
*/

/*
** Order-6 ordered dithering matrix. Note that smaller ordered dithers
** have no advantage over larger ones, so use dither8 instead.
*/
static int dither6[8][8] = {
1, 59, 15, 55, 2, 56, 12, 52,
33, 17, 47, 31, 34, 18, 44, 28,
9, 49, 5, 63, 10, 50, 6, 60,
41, 25, 37, 21, 42, 26, 38, 22,
3, 57, 13, 53, 0, 58, 14, 54,
35, 19, 45, 29, 32, 16, 46, 30,
11, 51, 7, 61, 8, 48, 4, 62,
43, 27, 39, 23, 40, 24, 36, 20 };

/* Order-8 ordered dithering matrix. */
static int dither8[16][16] = {
1,235, 59,219, 15,231, 55,215, 2,232, 56,216, 12,228, 52,212,
129, 65,187,123,143, 79,183,119,130, 66,184,120,140, 76,180,116,
33,193, 17,251, 47,207, 31,247, 34,194, 18,248, 44,204, 28,244,
161, 97,145, 81,175,111,159, 95,162, 98,146, 82,172,108,156, 92,
9,225, 49,209, 5,239, 63,223, 10,226, 50,210, 6,236, 60,220,
137, 73,177,113,133, 69,191,127,138, 74,178,114,134, 70,188,124,
41,201, 25,241, 37,197, 21,255, 42,202, 26,242, 38,198, 22,252,
169,105,153, 89,165,101,149, 85,170,106,154, 90,166,102,150, 86,
3,233, 57,217, 13,229, 53,213, 0,234, 58,218, 14,230, 54,214,
131, 67,185,121,141, 77,181,117,128, 64,186,122,142, 78,182,118,
35,195, 19,249, 45,205, 29,245, 32,192, 16,250, 46,206, 30,246,
163, 99,147, 83,173,109,157, 93,160, 96,144, 80,174,110,158, 94,
11,227, 51,211, 7,237, 61,221, 8,224, 48,208, 4,238, 62,222,
139, 75,179,115,135, 71,189,125,136, 72,176,112,132, 68,190,126,
43,203, 27,243, 39,199, 23,253, 40,200, 24,240, 36,196, 20,254,
171,107,155, 91,167,103,151, 87,168,104,152, 88,164,100,148, 84 };

/* Order-3 clustered dithering matrix. */
static int cluster3[6][6] = {
9,11,10, 8, 6, 7,
12,17,16, 5, 0, 1,
13,14,15, 4, 3, 2,
8, 6, 7, 9,11,10,
5, 0, 1,12,17,16,
4, 3, 2,13,14,15 };

/* Order-4 clustered dithering matrix. */
static int cluster4[8][8] = {
18,20,19,16,13,11,12,15,
27,28,29,22, 4, 3, 2, 9,
26,31,30,21, 5, 0, 1,10,
23,25,24,17, 8, 6, 7,14,
13,11,12,15,18,20,19,16,
4, 3, 2, 9,27,28,29,22,
5, 0, 1,10,26,31,30,21,
8, 6, 7,14,23,25,24,17 };

/* Order-8 clustered dithering matrix. */
static int cluster8[16][16] = {
64, 69, 77, 87, 86, 76, 68, 67, 63, 58, 50, 40, 41, 51, 59, 60,
70, 94,100,109,108, 99, 93, 75, 57, 33, 27, 18, 19, 28, 34, 52,
78,101,114,116,115,112, 98, 83, 49, 26, 13, 11, 12, 15, 29, 44,
88,110,123,124,125,118,107, 85, 39, 17, 4, 3, 2, 9, 20, 42,
89,111,122,127,126,117,106, 84, 38, 16, 5, 0, 1, 10, 21, 43,
79,102,119,121,120,113, 97, 82, 48, 25, 8, 6, 7, 14, 30, 45,
71, 95,103,104,105, 96, 92, 74, 56, 32, 24, 23, 22, 31, 35, 53,
65, 72, 80, 90, 91, 81, 73, 66, 62, 55, 47, 37, 36, 46, 54, 61,
63, 58, 50, 40, 41, 51, 59, 60, 64, 69, 77, 87, 86, 76, 68, 67,
57, 33, 27, 18, 19, 28, 34, 52, 70, 94,100,109,108, 99, 93, 75,
49, 26, 13, 11, 12, 15, 29, 44, 78,101,114,116,115,112, 98, 83,
39, 17, 4, 3, 2, 9, 20, 42, 88,110,123,124,125,118,107, 85,
38, 16, 5, 0, 1, 10, 21, 43, 89,111,122,127,126,117,106, 84,
48, 25, 8, 6, 7, 14, 30, 45, 79,102,119,121,120,113, 97, 82,
56, 32, 24, 23, 22, 31, 35, 53, 71, 95,103,104,105, 96, 92, 74,
62, 55, 47, 37, 36, 46, 54, 61, 65, 72, 80, 90, 91, 81, 73, 66 };
0, 6, 60,
41, 25, 37, 21, 42, 26, 38, 22,
3, 57, 13, 53, 0, 58, 14, 54,
pbmplus05oct91/pgm/pgmedge.1 444 3010 34 2132 5022775214 11104 .TH pgmedge 1 "04 February 1990"
.IX pgmedge
.SH NAME
pgmedge - edge-detect a portable graymap
.SH SYNOPSIS
.B pgmedge
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Outlines the edges, and writes a portable graymap as output.
.IX "edge detection"
Piping the result through
.B pgmtopbm -threshold
and playing with the
threshold value will give a bitmap of the edges.
.IX thresholding
.PP
The edge detection technique used is to take the Pythagorean sum of
two Sobel gradient operators at 90 degrees to each other.
For more details see "Digital Image Processing" by Gonzalez and Wintz,
chapter 7.
.SH "SEE ALSO"
pgmenhance(1), pgmtopbm(1), pgm(5), pbm(5)
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
201, 25,241, 37,197, 21,255, 42,202, 26,242, 38,198, 22,252,
169,105,153, 89,165,101,149, 85,170,106,154, 90,166,102,150, 86,
3,233, 57,217, 13,229, 53,213, 0,234, 58,218, 14,230, 54,214,
131, 67,185,121,141, 77,181,117,128, 64,186,122,142, 78,182,118,
35,195, 19,249, 45,205, 29,245, 32,192, 16,250, 46,206, 30,246,
163, 99,147, 83,173,109,157, 93,160, 96,144, 80,174,110,158, 94,
11,227, 51,pbmplus05oct91/pgm/rawtopgm.1 444 3010 34 2724 5023000106 11321 .TH rawtopgm 1 "15 December 89"
.IX rawtopgm
.SH NAME
rawtopgm - convert raw grayscale bytes into a portable graymap
.SH SYNOPSIS
.B rawtopgm
.RB [ -headerskip
.IR N ]
.RB [ -rowskip
.IR N ]
.I width height
.RI [ imagedata ]
.SH DESCRIPTION
Reads raw grayscale bytes as input.
.IX "raw grayscale"
Produces a portable graymap as output.
The input file is just grayscale bytes.
You have to specify the width and height on the command line,
since the program obviously can't get them from the file.
The maxval is assumed to be 255.
If the resulting image is upside down, run it through
.B "pnmflip -tb" .
.IX pnmflip
.SH OPTIONS
.TP
.B -headerskip
If the file has a header, you can use this flag to
skip over it.
.TP
.B -rowskip
If there is padding at the ends of the rows, you can skip it with this flag.
Note that rowskip can be a real number.
Amazingly, I once had an image with 0.376 bytes of padding per row.
This turned out to be due to a file-transfer problem, but I was still
able to read the image.
.SH "SEE ALSO"
pgm(5), rawtoppm(1), pnmflip(1)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
96,144, 80,174,110,158, 94,
11,227, 51,pbmplus05oct91/pgm/Makefile 444 3010 34 10055 5070703627 11077 # Makefile for pgm tools.
#
# Copyright (C) 1989, 1991 by Jef Poskanzer.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted, provided
# that the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation. This software is provided "as is" without express or
# implied warranty.

# Default values, usually overridden by top-level Makefile.
#CC = cc
CC = gcc -ansi -pedantic -fcombine-regs -fpcc-struct-return
#CFLAGS = -O
CFLAGS = -g
#CFLAGS = -g -O
#LDFLAGS = -s
LDFLAGS =
INSTALLBINARIES = /usr/new/pbm
INSTALLMANUALS1 = /usr/man/man1
SUFFIXMANUALS1 = 1
INSTALLMANUALS3 = /usr/man/man3
SUFFIXMANUALS3 = 3
INSTALLMANUALS5 = /usr/man/man5
SUFFIXMANUALS5 = 5
MANCP = cp

PBMDIR = ../pbm
INCLUDEPBM = -I$(PBMDIR)
LIBPBM = $(PBMDIR)/libpbm.a
DEFPBM = $(PBMDIR)/pbm.h ../pbmplus.h
DEFLIBPBM = $(PBMDIR)/libpbm.h

SHELL = /bin/sh
INCLUDE = -I.. $(INCLUDEPBM)
ALLCFLAGS = $(CFLAGS) $(INCLUDE)
LIBPGM = libpgm.a

PORTBINARIES = fitstopgm fstopgm hipstopgm lispmtopgm pgmbentley \
pgmenhance pgmhist pgmnorm pgmoil pgmramp \
pgmtofits pgmtofs pgmtolispm pgmtopbm \
psidtopgm rawtopgm
MATHBINARIES = pgmedge pgmtexture
BINARIES = $(PORTBINARIES) $(MATHBINARIES)

OBJECTS = fitstopgm.o fstopgm.o hipstopgm.o lispmtopgm.o pgmbentley.o \
pgmenhance.o pgmhist.o pgmnorm.o pgmoil.o pgmramp.o \
pgmtofits.o pgmtofs.o pgmtolispm.o pgmtopbm.o \
psidtopgm.o rawtopgm.o pgmedge.o pgmtexture.o

MANUALS1 = $(BINARIES)
MANUALS3 = libpgm
MANUALS5 = pgm


#all: binaries
all: merge
#install: install.bin
install: install.merge


binaries: $(BINARIES)

install.bin: binaries
cd $(INSTALLBINARIES) ; rm -f $(BINARIES)
cp $(BINARIES) $(INSTALLBINARIES)


merge: pgmmerge
pgmmerge: pgmmerge.c $(OBJECTS) $(LIBPGM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] $(OBJECTS) -lm $(LIBPGM) $(LIBPBM)

install.merge: install.pgmmerge
install.pgmmerge: pgmmerge
cd $(INSTALLBINARIES) ; rm -f $(BINARIES)
cp pgmmerge $(INSTALLBINARIES)
cd $(INSTALLBINARIES) ; for i in $(BINARIES) ; do ln pgmmerge $$i ; done
rm $(INSTALLBINARIES)/pgmmerge


install.man:
for i in $(MANUALS1) ; do \
rm -f $(INSTALLMANUALS1)/$$i.$(SUFFIXMANUALS1) ; \
$(MANCP) $$i.1 $(INSTALLMANUALS1)/$$i.$(SUFFIXMANUALS1) ; \
done
for i in $(MANUALS3) ; do \
rm -f $(INSTALLMANUALS3)/$$i.$(SUFFIXMANUALS3) ; \
$(MANCP) $$i.3 $(INSTALLMANUALS3)/$$i.$(SUFFIXMANUALS3) ; \
done
for i in $(MANUALS5) ; do \
rm -f $(INSTALLMANUALS5)/$$i.$(SUFFIXMANUALS5) ; \
$(MANCP) $$i.5 $(INSTALLMANUALS5)/$$i.$(SUFFIXMANUALS5) ; \
done


# Rule for plain programs.
$(PORTBINARIES): pgm.h $(DEFPBM) $(LIBPGM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] $(LIBPGM) $(LIBPBM)

# Rule for math-dependent programs.
$(MATHBINARIES): pgm.h $(DEFPBM) $(LIBPGM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] -lm $(LIBPGM) $(LIBPBM)

# Rule for objects.
$(OBJECTS): pgm.h $(DEFPBM)
$(CC) $(ALLCFLAGS) "-Dmain=$*_main" -c $*.c

# And libraries.
$(LIBPBM):
cd $(PBMDIR) ; make lib
lib: $(LIBPGM)
$(LIBPGM): libpgm1.o libpgm2.o
-rm $(LIBPGM)
ar rc $(LIBPGM) libpgm1.o libpgm2.o
-ranlib $(LIBPGM)

libpgm1.o: pgm.h $(DEFPBM) libpgm.h libpgm1.c
$(CC) $(ALLCFLAGS) -c libpgm1.c
libpgm2.o: pgm.h $(DEFPBM) libpgm.h libpgm2.c $(DEFLIBPBM)
$(CC) $(ALLCFLAGS) -c libpgm2.c

# Other dependencies.
fitstopgm fitstopgm.o: fitstopgm.c
fstopgm fstopgm.o: fstopgm.c
hipstopgm hipstopgm.o: hipstopgm.c
lispmtopgm lispmtopgm.o: lispmtopgm.c
pgmbentley pgmbentley.o: pgmbentley.c
pgmedge pgmedge.o: pgmedge.c
pgmenhance pgmenhance.o: pgmenhance.c
pgmhist pgmhist.o: pgmhist.c
pgmnorm pgmnorm.o: pgmnorm.c
pgmoil pgmoil.o: pgmoil.c
pgmramp pgmramp.o: pgmramp.c
pgmtexture pgmtexture.o: pgmtexture.c
pgmtopbm pgmtopbm.o: pgmtopbm.c dithers.h $(DEFPBM)
pgmtofits pgmtofits.o: pgmtofits.c
pgmtofs pgmtofs.o: pgmtofs.c
pgmtolispm pgmtolispm.o: pgmtolispm.c
psidtopgm psidtopgm.o: psidtopgm.c
rawtopgm rawtopgm.o: rawtopgm.c

clean:
-rm -f *.o *.a *.cat core $(BINARIES) pgmmerge
LIBPGM = libpgm.a

PORTBINARIES = fitstopgm fstopgm hipstopgm lispmtopgm pgmbentley \
pgmenhance pgmhist pgmnorm pgmoil pgmramp \
pgmtofits pgmtofs pgmtolispm pgmtopbm \
psidtopgm rawtopgm
MATHBINARIES = pgmedge pgmtexture
BINARIES = $(PORTBINARIES) $(MATHBINARIES)

OBJECTS = fitstopgm.o fstopgm.o hipstopgm.o lispmtopgm.o pgmbentley.o \
pgmenhance.o pgmhist.o pgmnorm.o pgmoil.o pgmramp.o \
pgmtofits.o pgmtofs.o pgmtolispm.o pgmtopbm.o \
psidtopgm.o rapbmplus05oct91/pgm/pgmtopbm.c 444 3010 34 15024 5035730727 11433 /* pgmtopbm.c - read a portable graymap and write a portable bitmap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"
#include "pbm.h"
#include "dithers.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray* grayrow;
register gray* gP;
bit* bitrow;
register bit* bP;
int argn, rows, cols, format, row, col, limitcol;
float fthreshval;
gray maxval;
char* usage = "[-floyd|-fs | -threshold | -dither8|-d8 |\n -cluster3|-c3|-cluster4|-c4|-cluster8|-c8] [-value ] [pgmfile]";
int halftone;
#define QT_FS 1
#define QT_THRESH 2
#define QT_DITHER8 3
#define QT_CLUSTER3 4
#define QT_CLUSTER4 5
#define QT_CLUSTER8 6
long threshval, sum;
long* thiserr;
long* nexterr;
long* temperr;
#define FS_SCALE 1024
#define HALF_FS_SCALE 512
int fs_direction;

pgm_init( &argc, argv );

argn = 1;
halftone = QT_FS; /* default quantization is Floyd-Steinberg */
fthreshval = 0.5;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-fs", 2 ) ||
pm_keymatch( argv[argn], "-floyd", 2 ) )
halftone = QT_FS;
else if ( pm_keymatch( argv[argn], "-threshold", 2 ) )
halftone = QT_THRESH;
else if ( pm_keymatch( argv[argn], "-dither8", 2 ) ||
pm_keymatch( argv[argn], "-d8", 3 ) )
halftone = QT_DITHER8;
else if ( pm_keymatch( argv[argn], "-cluster3", 9 ) ||
pm_keymatch( argv[argn], "-c3", 3 ) )
halftone = QT_CLUSTER3;
else if ( pm_keymatch( argv[argn], "-cluster4", 9 ) ||
pm_keymatch( argv[argn], "-c4", 3 ) )
halftone = QT_CLUSTER4;
else if ( pm_keymatch( argv[argn], "-cluster8", 9 ) ||
pm_keymatch( argv[argn], "-c8", 3 ) )
halftone = QT_CLUSTER8;
else if ( pm_keymatch( argv[argn], "-value", 2 ) )
{
++argn;
if ( argn == argc || sscanf( argv[argn], "%f", &fthreshval ) != 1 ||
fthreshval < 0.0 || fthreshval > 1.0 )
pm_usage( usage );
}
else
pm_usage( usage );
++argn;
}

if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
grayrow = pgm_allocrow( cols );

pbm_writepbminit( stdout, cols, rows, 0 );
bitrow = pbm_allocrow( cols );

/* Initialize. */
switch ( halftone )
{
case QT_FS:
/* Initialize Floyd-Steinberg error vectors. */
thiserr = (long*) pm_allocrow( cols + 2, sizeof(long) );
nexterr = (long*) pm_allocrow( cols + 2, sizeof(long) );
srandom( (int) ( time( 0 ) ^ getpid( ) ) );
for ( col = 0; col < cols + 2; ++col )
thiserr[col] = ( random( ) % FS_SCALE - HALF_FS_SCALE ) / 4;
/* (random errors in [-FS_SCALE/8 .. FS_SCALE/8]) */
fs_direction = 1;
threshval = fthreshval * FS_SCALE;
break;

case QT_THRESH:
threshval = fthreshval * maxval + 0.999999;
break;

case QT_DITHER8:
/* Scale dither matrix. */
for ( row = 0; row < 16; ++row )
for ( col = 0; col < 16; ++col )
dither8[row][col] = dither8[row][col] * ( maxval + 1 ) / 256;
break;

case QT_CLUSTER3:
/* Scale order-3 clustered dither matrix. */
for ( row = 0; row < 6; ++row )
for ( col = 0; col < 6; ++col )
cluster3[row][col] = cluster3[row][col] * ( maxval + 1 ) / 18;
break;

case QT_CLUSTER4:
/* Scale order-4 clustered dither matrix. */
for ( row = 0; row < 8; ++row )
for ( col = 0; col < 8; ++col )
cluster4[row][col] = cluster4[row][col] * ( maxval + 1 ) / 32;
break;

case QT_CLUSTER8:
/* Scale order-8 clustered dither matrix. */
for ( row = 0; row < 16; ++row )
for ( col = 0; col < 16; ++col )
cluster8[row][col] = cluster8[row][col] * ( maxval + 1 ) / 128;
break;

default:
pm_error( "can't happen" );
exit( 1 );
}

for ( row = 0; row < rows; ++row )
{
pgm_readpgmrow( ifp, grayrow, cols, maxval, format );

switch ( halftone )
{
case QT_FS:
for ( col = 0; col < cols + 2; ++col )
nexterr[col] = 0;
if ( fs_direction )
{
col = 0;
limitcol = cols;
gP = grayrow;
bP = bitrow;
}
else
{
col = cols - 1;
limitcol = -1;
gP = &(grayrow[col]);
bP = &(bitrow[col]);
}
do
{
sum = ( (long) *gP * FS_SCALE ) / maxval + thiserr[col + 1];
if ( sum >= threshval )
{
*bP = PBM_WHITE;
sum = sum - threshval - HALF_FS_SCALE;
}
else
*bP = PBM_BLACK;

if ( fs_direction )
{
thiserr[col + 2] += ( sum * 7 ) / 16;
nexterr[col ] += ( sum * 3 ) / 16;
nexterr[col + 1] += ( sum * 5 ) / 16;
nexterr[col + 2] += ( sum ) / 16;

++col;
++gP;
++bP;
}
else
{
thiserr[col ] += ( sum * 7 ) / 16;
nexterr[col + 2] += ( sum * 3 ) / 16;
nexterr[col + 1] += ( sum * 5 ) / 16;
nexterr[col ] += ( sum ) / 16;

--col;
--gP;
--bP;
}
}
while ( col != limitcol );
temperr = thiserr;
thiserr = nexterr;
nexterr = temperr;
fs_direction = ! fs_direction;
break;

case QT_THRESH:
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
if ( *gP >= threshval )
*bP = PBM_WHITE;
else
*bP = PBM_BLACK;
break;

case QT_DITHER8:
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
if ( *gP >= dither8[row % 16][col % 16] )
*bP = PBM_WHITE;
else
*bP = PBM_BLACK;
break;

case QT_CLUSTER3:
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
if ( *gP >= cluster3[row % 6][col % 6] )
*bP = PBM_WHITE;
else
*bP = PBM_BLACK;
break;

case QT_CLUSTER4:
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
if ( *gP >= cluster4[row % 8][col % 8] )
*bP = PBM_WHITE;
else
*bP = PBM_BLACK;
break;

case QT_CLUSTER8:
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
if ( *gP >= cluster8[row % 16][col % 16] )
*bP = PBM_WHITE;
else
*bP = PBM_BLACK;
break;

default:
pm_error( "can't happen" );
exit( 1 );
}

pbm_writepbmrow( stdout, bitrow, cols, 0 );
}

pm_close( ifp );

exit( 0 );
}
bm.h"
#include "dithers.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray* grayrow;
register gray* gP;
bit* bitrow;
register bit* bP;
int argn, rows, cols, format, row, col, limitcol;
float fthreshval;
gray maxval;
char* usage = "[-floyd|-fs | -threshold | -dither8|-d8 |\n -cluster3|-c3|-cluster4|-c4|-cluster8|-c8] [-value ] [pgmfile]";
int halftone;
#define QT_FS 1
#define QT_THRESH 2
#define QT_DITHER8 3
#pbmplus05oct91/pgm/pgmnorm.1 444 3010 34 3536 5022775327 11171 .TH pgmnorm 1 "28 February 1989"
.IX pgmnorm
.SH NAME
pgmnorm - normalize the contrast in a portable graymap
.SH SYNOPSIS
.B pgmnorm
.RB [ -bpercent
.I N
|
.B -bvalue
.IR N ]
.RB [ -wpercent
.I N
|
.B -wvalue
.IR N ]
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Normalizes the contrast by forcing the lightest pixels to white, the
.IX "contrast normalization"
darkest pixels to black, and linearly rescaling the ones in between;
and produces a portable graymap as output.
.SH OPTIONS
.PP
By default, the darkest 2 percent of all pixels are mapped to black, and
the lightest 1 percent are mapped to white.
You can override these percentages by using the
.B -bpercent
and
.B -wpercent
flags,
or you can specify the exact pixel values to be mapped by using the
.B -bvalue
and
.B -wvalue
flags.
Appropriate numbers for the flags can be gotten from the
.I pgmhist
tool.
.IX pgmhist
If you just want to enhance the contrast, then choose values at elbows in the
histogram; e.g. if value 29 represents 3% of the image but value 30
represents 20%, choose 30 for
.IR bvalue .
If you want to lighten the
image, then set
.I bvalue
to 0 and just fiddle with
.IR wvalue ;
similarly, to darken the image, set
.I wvalue
to maxval and play with
.IR bvalue .
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH "SEE ALSO"
pgmhist(1), pgm(5)
.SH AUTHOR
Partially based on the fbnorm filter in Michael Mauldin's "Fuzzy Pixmap"
package.

Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
) )
halftone = QT_CLUSTER3;
else if ( pm_keymatch( argv[argn], "-cluster4", 9 ) ||
pm_keymatch( argv[argn], "-c4", 3 ) )
halftone = QT_CLUSTpbmplus05oct91/pgm/pgm.h 444 3010 34 3450 4743722051 10352 /* pgm.h - header file for libpgm portable graymap library
*/

#ifndef _PGM_H_
#define _PGM_H_

#include "pbm.h"

#ifdef PGM_BIGGRAYS
typedef unsigned short gray;
#define PGM_MAXMAXVAL 65535
#else /*PGM_BIGGRAYS*/
typedef unsigned char gray;
#define PGM_MAXMAXVAL 255
#endif /*PGM_BIGGRAYS*/


/* Magic constants. */

#define PGM_MAGIC1 'P'
#define PGM_MAGIC2 '2'
#define RPGM_MAGIC2 '5'
#define PGM_FORMAT (PGM_MAGIC1 * 256 + PGM_MAGIC2)
#define RPGM_FORMAT (PGM_MAGIC1 * 256 + RPGM_MAGIC2)
#define PGM_TYPE PGM_FORMAT


/* Macro for turning a format number into a type number. */

#define PGM_FORMAT_TYPE(f) ((f) == PGM_FORMAT || (f) == RPGM_FORMAT ? PGM_TYPE : PBM_FORMAT_TYPE(f))


/* Declarations of routines. */

void pgm_init ARGS(( int* argcP, char* argv[] ));

#define pgm_allocarray( cols, rows ) ((gray**) pm_allocarray( cols, rows, sizeof(gray) ))
#define pgm_allocrow( cols ) ((gray*) pm_allocrow( cols, sizeof(gray) ))
#define pgm_freearray( grays, rows ) pm_freearray( (char**) grays, rows )
#define pgm_freerow( grayrow ) pm_freerow( (char*) grayrow )

gray** pgm_readpgm ARGS(( FILE* file, int* colsP, int* rowsP, gray* maxvalP ));
void pgm_readpgminit ARGS(( FILE* file, int* colsP, int* rowsP, gray* maxvalP, int* formatP ));
void pgm_readpgmrow ARGS(( FILE* file, gray* grayrow, int cols, gray maxval, int format ));

void pgm_writepgm ARGS(( FILE* file, gray** grays, int cols, int rows, gray maxval, int forceplain ));
void pgm_writepgminit ARGS(( FILE* file, int cols, int rows, gray maxval, int forceplain ));
void pgm_writepgmrow ARGS(( FILE* file, gray* grayrow, int cols, gray maxval, int forceplain ));

extern gray pgm_pbmmaxval;
/* This is the maxval used when a PGM program reads a PBM file. Normally
** it is 1; however, for some programs, a larger value gives better results
*/

#endif /*_PGM_H_*/
ided "as is" without express or
.\" implied warranty.
) )
halftone = QT_CLUSTER3;
else if ( pm_keymatch( argv[argn], "-cluster4", 9 ) ||
pm_keymatch( argv[argn], "-c4", 3 ) )
halftone = QT_CLUSTpbmplus05oct91/pgm/libpgm.h 444 3010 34 432 4742173105 11015 /* libpgm.h - internal header file for libpgm portable graymap library
*/

#ifndef _LIBPGM_H_
#define _LIBPGM_H_

/* Here are some routines internal to the pgm library. */

void pgm_readpgminitrest ARGS(( FILE* file, int* colsP, int* rowsP, gray* maxvalP ));

#endif /*_LIBPGM_H_*/
mramp.c¾f9Õ
rawtopgm.c|:…pgm.5S;
pgmmerge.cl; dithers.hn.;% pgmedge.1f<
rawtopgm.1r<¥Makefilerts=\
pgmtopbm.ct=^ pgmnorm.1mt=`pgm.h.ƒ=alibpgm.h=b pbmplus05oct91/pgm/libpgm1.c 444 3010 34 6274 5032732663 11126 /* libpgm1.c - pgm utility library part 1
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"
#include "libpgm.h"
#include "pbm.h"
#include "libpbm.h"

void
pgm_init( argcP, argv )
int* argcP;
char* argv[];
{
pbm_init( argcP, argv );
}

void
pgm_readpgminitrest( file, colsP, rowsP, maxvalP )
FILE* file;
int* colsP;
int* rowsP;
gray* maxvalP;
{
int maxval;

/* Read size. */
*colsP = pbm_getint( file );
*rowsP = pbm_getint( file );

/* Read maxval. */
maxval = pbm_getint( file );
if ( maxval > PGM_MAXMAXVAL )
pm_error( "maxval is too large - try reconfiguring with PGM_BIGGRAYS" );
*maxvalP = maxval;
}

gray pgm_pbmmaxval = 1;

void
pgm_readpgminit( file, colsP, rowsP, maxvalP, formatP )
FILE* file;
int* colsP;
int* rowsP;
int* formatP;
gray* maxvalP;
{
/* Check magic number. */
*formatP = pbm_readmagicnumber( file );
switch ( PGM_FORMAT_TYPE(*formatP) )
{
case PGM_TYPE:
pgm_readpgminitrest( file, colsP, rowsP, maxvalP );
break;

case PBM_TYPE:
pbm_readpbminitrest( file, colsP, rowsP );
*maxvalP = pgm_pbmmaxval;
break;

default:
pm_error( "bad magic number - not a pgm or pbm file" );
}
}

#if __STDC__
void
pgm_readpgmrow( FILE* file, gray* grayrow, int cols, gray maxval, int format )
#else /*__STDC__*/
void
pgm_readpgmrow( file, grayrow, cols, maxval, format )
FILE* file;
gray* grayrow;
int cols;
gray maxval;
int format;
#endif /*__STDC__*/
{
register int col;
register gray* gP;
bit* bitrow;
register bit* bP;

switch ( format )
{
case PGM_FORMAT:
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
{
*gP = pbm_getint( file );
#ifdef DEBUG
if ( *gP > maxval )
pm_error( "value out of bounds (%u > %u)", *gP, maxval );
#endif /*DEBUG*/
}
break;

case RPGM_FORMAT:
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
{
*gP = pbm_getrawbyte( file );
#ifdef DEBUG
if ( *gP > maxval )
pm_error( "value out of bounds (%u > %u)", *gP, maxval );
#endif /*DEBUG*/
}
break;

case PBM_FORMAT:
case RPBM_FORMAT:
bitrow = pbm_allocrow( cols );
pbm_readpbmrow( file, bitrow, cols, format );
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
*gP = ( *bP == PBM_WHITE ) ? maxval : 0;
pbm_freerow( bitrow );
break;

default:
pm_error( "can't happen" );
}
}

gray**
pgm_readpgm( file, colsP, rowsP, maxvalP )
FILE* file;
int* colsP;
int* rowsP;
gray* maxvalP;
{
gray** grays;
int row;
int format;

pgm_readpgminit( file, colsP, rowsP, maxvalP, &format );

grays = pgm_allocarray( *colsP, *rowsP );

for ( row = 0; row < *rowsP; ++row )
pgm_readpgmrow( file, grays[row], *colsP, *maxvalP, format );

return grays;
}
locrow( cols );

/* Initialize. */
switch ( halftone )
{
case QT_FS:
/* Initialize Floyd-Steinberg error vectors. */
thiserr = (long*) pm_allocrow( cols + 2, sizeof(long) );
nexterr = (long*) pm_allocrow( cols + 2, sizeof(long) );
srandom( (int) ( time( 0 ) ^ getpid( ) ) );
for ( col = 0; col < cols + 2; ++cpbmplus05oct91/pgm/libpgm2.c 444 3010 34 7331 5032725055 11117 /* libpgm2.c - pgm utility library part 2
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"
#include "libpgm.h"

#if __STDC__
void
pgm_writepgminit( FILE* file, int cols, int rows, gray maxval, int forceplain )
#else /*__STDC__*/
void
pgm_writepgminit( file, cols, rows, maxval, forceplain )
FILE* file;
int cols, rows;
gray maxval;
int forceplain;
#endif /*__STDC__*/
{
#ifdef PBMPLUS_RAWBITS
if ( maxval <= 255 && ! forceplain )
fprintf(
file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, RPGM_MAGIC2,
cols, rows, maxval );
else
fprintf(
file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, PGM_MAGIC2,
cols, rows, maxval );
#else /*PBMPLUS_RAWBITS*/
fprintf(
file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, PGM_MAGIC2,
cols, rows, maxval );
#endif /*PBMPLUS_RAWBITS*/
}

static int
putus( n, file )
unsigned short n;
FILE* file;
{
if ( n >= 10 )
if ( putus( n / 10, file ) == EOF )
return EOF;
return putc( n % 10 + '0', file );
}

#ifdef PBMPLUS_RAWBITS
static void
pgm_writepgmrowraw( file, grayrow, cols, maxval )
FILE* file;
gray* grayrow;
int cols;
gray maxval;
{
register int col;
register gray* gP;

for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
{
#ifdef DEBUG
if ( *gP > maxval )
pm_error( "value out of bounds (%u > %u)", *gP, maxval );
#endif /*DEBUG*/
if ( putc( *gP, file ) == EOF )
pm_error( "write error" );
}
}
#endif /*PBMPLUS_RAWBITS*/

static void
pgm_writepgmrowplain( file, grayrow, cols, maxval )
FILE* file;
gray* grayrow;
int cols;
gray maxval;
{
register int col, charcount;
register gray* gP;

charcount = 0;
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
{
if ( charcount >= 65 )
{
if ( putc( '\n', file ) == EOF )
pm_error( "write error" );
charcount = 0;
}
else if ( charcount > 0 )
{
if ( putc( ' ', file ) == EOF )
pm_error( "write error" );
++charcount;
}
#ifdef DEBUG
if ( *gP > maxval )
pm_error( "value out of bounds (%u > %u)", *gP, maxval );
#endif /*DEBUG*/
if ( putus( (unsigned long) *gP, file ) == EOF )
pm_error( "write error" );
charcount += 3;
}
if ( charcount > 0 )
if ( putc( '\n', file ) == EOF )
pm_error( "write error" );
}

#if __STDC__
void
pgm_writepgmrow( FILE* file, gray* grayrow, int cols, gray maxval, int forceplain )
#else /*__STDC__*/
void
pgm_writepgmrow( file, grayrow, cols, maxval, forceplain )
FILE* file;
gray* grayrow;
int cols;
gray maxval;
int forceplain;
#endif /*__STDC__*/
{
#ifdef PBMPLUS_RAWBITS
if ( maxval <= 255 && ! forceplain )
pgm_writepgmrowraw( file, grayrow, cols, maxval );
else
pgm_writepgmrowplain( file, grayrow, cols, maxval );
#else /*PBMPLUS_RAWBITS*/
pgm_writepgmrowplain( file, grayrow, cols, maxval );
#endif /*PBMPLUS_RAWBITS*/
}

#if __STDC__
void
pgm_writepgm( FILE* file, gray** grays, int cols, int rows, gray maxval, int forceplain )
#else /*__STDC__*/
void
pgm_writepgm( file, grays, cols, rows, maxval, forceplain )
FILE* file;
gray** grays;
int cols, rows;
gray maxval;
int forceplain;
#endif /*__STDC__*/
{
int row;

pgm_writepgminit( file, cols, rows, maxval, forceplain );

for ( row = 0; row < rows; ++row )
pgm_writepgmrow( file, grays[row], cols, maxval, forceplain );
}
for ( row = 0; row < 8; ++row )
for ( col = 0; col < 8; ++col )
cluster4[row][col] = cluster4[row][col] * ( maxval + 1 ) / 32;
break;

case QT_CLUSTER8:
/* Scale order-8 clustered dither matrix. */
for ( row = 0; row < 16; ++row )
for ( col = 0; col < 16; ++col )
cluster8[rowpbmplus05oct91/pgm/pgmtopbm.1 444 3010 34 4165 5023045333 11322 .TH pgmtopbm 1 "26 July 1988"
.IX pgmtopbm
.SH NAME
pgmtopbm - convert a portable graymap into a portable bitmap
.SH SYNOPSIS
.B pgmtopbm
.RB [ -floyd | -fs | -threshold
.RB | -dither8 | -d8 | -cluster3
.RB | -c3 | -cluster4 | -c4
.RB | -cluster8 | -c8 ]
.RB [ -value
.IR val ]
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Produces a portable bitmap as output.
.IX halftoning
.PP
Note that there is no pbmtopgm converter, because any pgm program can
read pbm files automagically.
.SH OPTIONS
.PP
The default quantization method is boustrophedonic Floyd-Steinberg error
diffusion
.RB ( -floyd
or
.BR -fs ).
.IX Floyd-Steinberg
.IX "error diffusion"
Also available are simple thresholding
.RB ( -threshold );
.IX thresholding
Bayer's ordered dither
.RB ( -dither8 )
with a 16x16 matrix; and three different sizes of 45-degree clustered-dot dither
.RB ( -cluster3 ,
.BR -cluster4 ,
.BR -cluster8 ).
.IX dithering
.PP
Floyd-Steinberg will almost always give the best looking results; however,
looking good is not always what you want.
For instance, thresholding can be used in a pipeline with the
.I pnmconvol
.IX pnmconvol
tool, for tasks like edge and peak detection.
And clustered-dot dithering gives a newspaper-ish look, a useful special effect.
.PP
The
.B -value
flag alters the thresholding value for Floyd-Steinberg and
simple thresholding.
It should be a real number between 0 and 1.
Above 0.5 means darker images; below 0.5 means lighter.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH REFERENCES
The only reference you need for this stuff is "Digital Halftoning" by
Robert Ulichney, MIT Press, ISBN 0-262-21009-6.
.SH "SEE ALSO"
pbmreduce(1), pgm(5), pbm(5), pnmconvol(1)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
= 65 )
{
if ( putc( '\n', file ) == EOF )
pm_error( "write error" );
charcount = 0;
}
else if ( charcount > 0 )
{
if ( putc( ' ', file ) == EOF )
pm_error( "write error" );
++charcount;
}
#ifdef DEBUG
if ( *gP > maxval )
pm_error( "value out of bounds (%u > %u)", *gP, maxval );
#endif /*DEBUG*/
if ( putus( (unsigned long) *gP, file ) == EOF pbmplus05oct91/pgm/pgmhist.c 444 3010 34 4007 5067544647 11251 /* pgmhist.c - print a histogram of the values in a portable graymap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

void
main( argc, argv )
int argc;
char *argv[];
{
FILE *ifp;
gray maxval, *grayrow;
register gray *gP;
int argn, rows, cols, format, row;
int i, *hist, *rcount, count, size;
register int col;
char *usage = "[pgmfile]";

pgm_init( &argc, argv );

argn = 1;

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
argn++;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
grayrow = pgm_allocrow( cols );

/* Build histogram. */
hist = (int *) malloc( ( maxval + 1 ) * sizeof(int) );
rcount = (int *) malloc( ( maxval + 1 ) * sizeof(int) );
if ( hist == (int *) 0 || rcount == (int *) 0 )
pm_error( "out of memory" );
for ( i = 0; i <= maxval; i++ )
hist[i] = 0;
for ( row = 0; row < rows; row++ )
{
pgm_readpgmrow( ifp, grayrow, cols, maxval, format );
for ( col = 0, gP = grayrow; col < cols; col++, gP++ )
hist[(int) *gP]++;
}

pm_close( ifp );

/* Compute count-down */
count = 0;
for ( i = maxval; i >= 0; i-- )
{
count += hist[i];
rcount[i] = count;
}

/* And print it. */
printf( "value\tcount\tb%%\tw%%\n" );
printf( "-----\t-----\t--\t--\n" );
count = 0;
size = rows * cols;
for ( i = 0; i <= maxval; i++ )
if ( hist[i] > 0 )
{
count += hist[i];
printf(
"%d\t%d\t%5.3g%%\t%5.3g%%\n", i, hist[i],
(float) count * 100.0 / size, (float) rcount[i] * 100.0 / size );
}

exit( 0 );
}
in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
= 65 )
{
if ( putc( '\n', file ) == EOF )
pm_error( "write error" );
charcount = 0;
}
else if ( charcount > 0 )
{
if ( putc( ' ', file ) == EOF )
pm_error( "write error" );
++charcount;
}
#ifdef DEBUG
if ( *gP > maxval )
pm_error( "value out of bounds (%u > %u)", *gP, maxval );
#endif /*DEBUG*/
if ( putus( (unsigned long) *gP, file ) == EOF pbmplus05oct91/pgm/pgmhist.1 444 3010 34 1336 5022753505 11153 .TH pgmhist 1 "28 February 1989"
.IX pgmhist
.SH NAME
pgmhist - print a histogram of the values in a portable graymap
.SH SYNOPSIS
.B pgmhist
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Prints a histogram of the gray values.
.SH "SEE ALSO"
pgmnorm(1), pgm(5), ppmhist(1)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
e.c =m Imakefile =n psidtopgm.cpbmt=o pgmtofits.cg3.h=p lispmtopgm.1X=q lispmtopgm.c.•=r pgmtolispm.1.–=s pgmtolispm.c =tpgmoil.c.˜=u pgmbentley.c.™=v pgmbentley.1 =wpgmoil.1.›=x pgmtexture.c
=º pbmplus05oct91/pgm/pgmenhance.1 444 3010 34 2301 5022775240 11576 .TH pgmenhance 1 "13 January 1989"
.IX pgmenhance
.SH NAME
pgmenhance - edge-enhance a portable graymap
.SH SYNOPSIS
.B pgmenhance
.RI [ -N ]
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Enhances the edges, and writes a portable graymap as output.
.IX "edge enhancement"
.PP
The edge enhancing technique is taken from Philip R. Thompson's "xim"
program, which in turn took it from section 6 of "Digital Halftones by
Dot Diffusion", D. E. Knuth, ACM Transaction on Graphics Vol. 6, No. 4,
October 1987, which in turn got it from two 1976 papers by J. F. Jarvis
et. al.
.SH OPTIONS
.PP
The optional
.I -N
flag should be a digit from 1 to 9.
1 is the lowest level of enhancement, 9 is the highest,
The default is 9.
.SH "SEE ALSO"
pgmedge(1), pgm(5), pbm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
ipstopgm.c =l pgmedge.c =m Imakefile =n psidtopgm.cpbmt=o pgmtofits.cg3.h=p lispmtopgm.1X=q lispmtopgm.c.•=r pgmtolispm.1.–=s pgmtolispm.c =tpgmoil.c.˜=u pgmbentley.c.™=v pgmbentley.1 =wpgmoil.1.›=x pgmtexture.c
=º pbmplus05oct91/pgm/pgmenhance.c 444 3010 34 6173 5032725063 11672 /* pgmenhance.c - edge-enhance a portable graymap
**
** Copyright (C) 1989, 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray* prevrow;
gray* thisrow;
gray* nextrow;
gray* temprow;
gray* newrow;
register gray* ngP;
int argn, n, rows, cols, row, col;
float phi, omphi;
gray maxval;
long sum, newval;
int format;
char* usage = "[-N] [pgmfile] ( 1 <= N <= 9, default = 9 )";

pgm_init( &argc, argv );

argn = 1;
n = 9;

if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( sscanf( &(argv[argn][1]), "%d", &n ) != 1 )
pm_usage( usage );
if ( n < 1 || n > 9 )
pm_usage( usage );
++argn;
}

if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pgm_pbmmaxval = 255; /* use a larger value for better (?) results */
pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
prevrow = pgm_allocrow( cols );
thisrow = pgm_allocrow( cols );
nextrow = pgm_allocrow( cols );

pgm_writepgminit( stdout, cols, rows, maxval, 0 );
newrow = pgm_allocrow( cols );

/* The edge enhancing technique is taken from Philip R. Thompson's "xim"
** program, which in turn took it from section 6 of "Digital Halftones by
** Dot Diffusion", D. E. Knuth, ACM Transaction on Graphics Vol. 6, No. 4,
** October 1987, which in turn got it from two 1976 papers by J. F. Jarvis
** et. al.
*/
phi = n / 10.0;
omphi = 1.0 - phi;

/* First row. */
pgm_readpgmrow( ifp, thisrow, cols, maxval, format );
pgm_writepgmrow( stdout, thisrow, cols, maxval, 0 );
pgm_readpgmrow( ifp, nextrow, cols, maxval, format );

/* Other rows. */
for ( row = 1; row < rows - 1; row++ )
{
temprow = prevrow;
prevrow = thisrow;
thisrow = nextrow;
nextrow = temprow;
pgm_readpgmrow( ifp, nextrow, cols, maxval, format );

ngP = newrow;
*ngP = thisrow[0];
ngP++;
for ( col = 1; col < cols - 1; col++, ngP++ )
{
/* Compute the sum of the neighborhood. */
sum =
(long) prevrow[col-1] + (long) prevrow[col] +
(long) prevrow[col+1] +
(long) thisrow[col-1] + (long) thisrow[col] +
(long) thisrow[col+1] +
(long) nextrow[col-1] + (long) nextrow[col] +
(long) nextrow[col+1];
/* Now figure new value. */
newval = ( ( thisrow[col] - phi * sum / 9 ) / omphi + 0.5 );
if ( newval < 0 )
*ngP = 0;
else if ( newval > maxval )
*ngP = maxval;
else
*ngP = newval;
}
*ngP = thisrow[cols - 1];
pgm_writepgmrow( stdout, newrow, cols, maxval, 0 );
}

/* Last row. */
pgm_writepgmrow( stdout, nextrow, cols, maxval, 0 );

pm_close( ifp );

exit( 0 );
}
*PBMPLUS_RAWBITS*/
pgm_writepgmrowplain( file, grayrow, cols, maxval );
#endif /*PBMPLUS_RAWBITS*/
}

#if __STDC__
void
pgm_writepgm( FILE* file, gray** grays, int cols, int rows, gray maxval, int forceplain )
#else /*__STDC__*/
void
pgm_writepgm( file, grays, cols, rows, maxval, forceplain )
FILE* file;
gray** grays;
int cols, rows;
gray maxval;
int forceplapbmplus05oct91/pgm/pgmramp.1 444 3010 34 2072 5022777003 11140 .TH pgmramp 1 "24 November 1989"
.IX pgmramp
.SH NAME
pgmramp - generate a grayscale ramp
.SH SYNOPSIS
.B pgmramp
.BR -lr | -tb
|
.BR -rectangle | -ellipse
.I width height
.SH DESCRIPTION
Generates a graymap of the specified size containing a black-to-white ramp.
.IX "generating graymaps"
These ramps are useful for multiplying with other images, using the
.I pnmarith
tool.
.IX pnmarith
.SH OPTIONS
.TP
.B -lr
A left to right ramp.
.TP
.B -tb
A top to bottom ramp.
.TP
.B -rectangle
A rectangular ramp.
.TP
.B -ellipse
An elliptical ramp.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH "SEE ALSO"
pnmarith(1), pgm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
);
if ( n < 1 || n > 9 )
pm_usage( usage );
++argn;
}

if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pgm_pbmmaxval = 255; /* use a larger value for better (?) results */
pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
prevrow = pgm_allocrow( cols );
thisrow = pgm_allocrow( cols );
nextrow = pgm_allocrow( cols );

pgm_wrpbmplus05oct91/pgm/psidtopgm.1 444 3010 34 2705 5022776324 11513 .TH psidtopgm 1 "02 August 89"
.IX psidtopgm
.SH NAME
psidtopgm - convert PostScript "image" data into a portable graymap
.SH SYNOPSIS
.B psidtopgm
.I width height bits/sample
.RI [ imagedata ]
.SH DESCRIPTION
Reads the "image" data from a PostScript file as input.
.IX PostScript
Produces a portable graymap as output.
.PP
This is a very simple and limited program, and is here only because
so many people have asked for it.
To use it you have to
.B manually
extract the readhexstring data portion from your PostScript file, and then
give the width, height, and bits/sample on the command line.
Before you attempt this, you should
.B at least
read the description of the "image" operator in the PostScript Language
Reference Manual.
.PP
It would probably not be too hard to write a script that uses this filter
to read a specific variety of PostScript image, but the variation is too
great to make a general-purpose reader.
Unless, of course, you want to write a full-fledged PostScript interpreter...
.SH "SEE ALSO"
pnmtops(1), pgm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
y.1 =wpgmoil.1.›=x pgmtexture.c
=º pbmplus05oct91/pgm/hipstopgm.c 444 3010 34 10440 5032731755 11614 /* hipstopgm.c - read a HIPS file and produce a portable graymap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

struct HIPS_Header {
char* orig_name; /* An indication of the originator of this sequence. */
char* seq_name; /* The sequence name. */
int num_frame; /* The number of frames in this sequence. */
char* orig_date; /* The date the sequence was originated. */
int rows; /* The number of rows in each image, the height. */
int cols; /* The number of columns in each image, the width. */
int bits_per_pixel; /* The number of significant bits per pixel. */
int bit_packing; /* Nonzero if the bits were packed such as to
eliminate any unused bits resulting from a
bits_per_pixel value which was not an even
multiple of eight. */
int pixel_format; /* An indication of the format of each pixel. */
char* seq_history; /* A description of the sequence of transformations
leading up to the current image. */
char* seq_desc; /* A free form description of the contents of the
sequence. */
};
#define HIPS_PFBYTE 0
#define HIPS_PFSHORT 1
#define HIPS_PFINT 2
#define HIPS_PFFLOAT 3
#define HIPS_PFCOMPLEX 4

static void read_hips_header ARGS(( FILE* fd, struct HIPS_Header* hP ));
static void read_line ARGS(( FILE* fd, char* buf, int size ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray* grayrow;
register gray* gP;
int argn, row;
register int col;
int maxval;
int rows, cols;
struct HIPS_Header h;

pgm_init( &argc, argv );

argn = 1;

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
argn++;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( "[hipsfile]" );

read_hips_header( ifp, &h );

cols = h.cols;
rows = h.rows * h.num_frame;

switch ( h.pixel_format )
{
case HIPS_PFBYTE:
if ( h.bits_per_pixel != 8 )
pm_error(
"can't handle unusual bits_per_pixel %d", h.bits_per_pixel );
if ( h.bit_packing != 0 )
pm_error( "can't handle bit_packing" );
maxval = 255;
break;

default:
pm_error( "unknown pixel format %d", h.pixel_format );
}
if ( maxval > PGM_MAXMAXVAL )
pm_error(
"bits_per_pixel is too large - try reconfiguring with PGM_BIGGRAYS" );

pgm_writepgminit( stdout, cols, rows, (gray) maxval, 0 );
grayrow = pgm_allocrow( cols );
for ( row = 0; row < rows; row++)
{
for ( col = 0, gP = grayrow; col < cols; col++, gP++ )
{
int ich;

switch ( h.pixel_format )
{
case HIPS_PFBYTE:
ich = getc( ifp );
if ( ich == EOF )
pm_error( "EOF / read error" );
*gP = (gray) ich;
break;

default:
pm_error( "can't happen" );
}
}
pgm_writepgmrow( stdout, grayrow, cols, (gray) maxval, 0 );
}
pm_close( ifp );

exit( 0 );
}

static void
read_hips_header( fd, hP )
FILE* fd;
struct HIPS_Header* hP;
{
char buf[5000];

/* Read and toss orig_name. */
read_line( fd, buf, 5000 );

/* Read and toss seq_name. */
read_line( fd, buf, 5000 );

/* Read num_frame. */
read_line( fd, buf, 5000 );
hP->num_frame = atoi( buf );

/* Read and toss orig_date. */
read_line( fd, buf, 5000 );

/* Read rows. */
read_line( fd, buf, 5000 );
hP->rows = atoi( buf );

/* Read cols. */
read_line( fd, buf, 5000 );
hP->cols = atoi( buf );

/* Read bits_per_pixel. */
read_line( fd, buf, 5000 );
hP->bits_per_pixel = atoi( buf );

/* Read bit_packing. */
read_line( fd, buf, 5000 );
hP->bit_packing = atoi( buf );

/* Read pixel_format. */
read_line( fd, buf, 5000 );
hP->pixel_format = atoi( buf );

/* Now read and toss lines until we get one with just a period. */
do
{
read_line( fd, buf, 5000 );
}
while ( strcmp( buf, ".\n" ) != 0 );
}

static void
read_line( fd, buf, size )
FILE* fd;
char* buf;
int size;
{
if ( fgets( buf, size, fd ) == NULL )
pm_error( "error reading header" );
}
s + 2; ++col )
nexterr[col] = 0;
if ( fs_direction )
{
col = 0;
limitcol = cols;
gP = grayrow;
bP = bitrow;
}
else
{
col = cols - 1;
limitcol = -1;
gP = &(grayrow[col]);
bP = &(bitrow[col]);pbmplus05oct91/pgm/pgmedge.c 444 3010 34 5334 5032725061 11171 /* pgmedge.c - edge-detect a portable graymap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"
#include

void
main( argc, argv )
int argc;
char *argv[];
{
FILE *ifp;
gray *row0, *row1, *row2, *tmprow, *orow;
int argn, rows, cols, format, row;
register int col;
gray maxval;
double sum1, sum2, sum;
char *usage = "[pgmfile]";

pgm_init( &argc, argv );

argn = 1;

if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
argn++;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pgm_pbmmaxval = 255; /* use larger value for better results */

pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
if ( cols < 3 || rows < 3 )
pm_error( "the image is too small" );

row0 = pgm_allocrow( cols );
row1 = pgm_allocrow( cols );
row2 = pgm_allocrow( cols );
orow = pgm_allocrow( cols );

pgm_writepgminit( stdout, cols, rows, maxval, 0 );

/* Read in the first two rows. */
pgm_readpgmrow( ifp, row0, cols, maxval, format );
pgm_readpgmrow( ifp, row1, cols, maxval, format );

/* Write out the first row, all zeros. */
for ( col = 0; col < cols; ++col )
orow[col] = 0;
pgm_writepgmrow( stdout, orow, cols, maxval, 0 );

/* Now the rest of the image -- read in the next row, and write
** write out the current row.
*/
for ( row = 1; row < rows - 1; row++ )
{
pgm_readpgmrow( ifp, row2, cols, maxval, format );

for ( col = 1; col < cols - 1; col++ )
{
sum1 = (double) row0[col+1] - (double) row0[col-1] +
2.0 * ( (double) row1[col+1] - (double) row1[col-1] ) +
(double) row2[col+1] - (double) row2[col-1];
sum2 = ( (double) row2[col-1] + 2.0 * (double) row2[col] +
(double) row2[col+1] ) -
( (double) row0[col-1] + 2.0 * (double) row0[col] +
(double) row0[col+1] );
sum = sqrt( sum1 * sum1 + sum2 * sum2 );
sum /= 1.8; /* arbitrary scaling factor */
if ( sum > maxval ) sum = maxval;
orow[col] = sum;
}

/* Write out a row. */
pgm_writepgmrow( stdout, orow, cols, maxval, 0 );

/* Rotate rows. */
tmprow = row0;
row0 = row1;
row1 = row2;
row2 = tmprow;
}
pm_close( ifp );

/* And write the last row, zeros again. */
for ( col = 0; col < cols; ++col )
orow[col] = 0;
pgm_writepgmrow( stdout, orow, cols, maxval, 0 );

exit( 0 );
}
( cols );
orow = pgm_allocrow( cols );

pgm_writepgminit( stdout, cols, rows, maxval, 0 );

/* Read in the first two rows. */
pgm_readpgmrow( ifp, row0, cols, maxval, format );
pgm_readpgmrow( ifp, row1, cols, maxval, format );

/* Write out the first row, all zeros. pbmplus05oct91/pgm/Imakefile 444 3010 34 3610 5070733251 11223 # Imakefile for pgm tools.
#
# Copyright (C) 1989, 1991 by Jef Poskanzer.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted, provided
# that the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation. This software is provided "as is" without express or
# implied warranty.

PBMDIR = ../pbm
INCLUDEPBM = -I$(PBMDIR)
LIBPBM = $(PBMDIR)/libpbm.a
DEFPBM = $(PBMDIR)/pbm.h ../pbmplus.h
DEFLIBPBM = $(PBMDIR)/libpbm.h

INCLUDE = -I.. $(INCLUDEPBM)
ALLCFLAGS = $(CFLAGS) $(INCLUDE)
LIBPGM = libpgm.a

PORTBINARIES = fitstopgm fstopgm hipstopgm lispmtopgm pgmbentley \
pgmenhance pgmhist pgmnorm pgmoil pgmramp \
pgmtofits pgmtofs pgmtolispm pgmtopbm \
psidtopgm rawtopgm
MATHBINARIES = pgmedge pgmtexture
BINARIES = $(PORTBINARIES) $(MATHBINARIES)

MANUALS1 = fitstopgm.1 fstopgm.1 hipstopgm.1 lispmtopgm.1 pgmbentley.1 \
pgmenhance.1 pgmhist.1 pgmnorm.1 pgmoil.1 pgmramp.1 \
pgmtofits.1 pgmtofs.1 pgmtolispm.1 pgmtopbm.1 \
psidtopgm.1 rawtopgm.1 pgmedge.1 pgmtexture.1
MANUALS3 = libpgm.3
MANUALS5 = pgm.5

all: $(BINARIES)

install:: all
cp $(BINARIES) $(BINDIR)

install.man::
cp $(MANUALS1) $(MANUALS3) $(MANUALS5) $(MANDIR)

# Rule for plain programs.
$(PORTBINARIES): pgm.h $(DEFPBM) $(LIBPGM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] $(LIBPGM) $(LIBPBM)

# Rule for math-dependent programs.
$(MATHBINARIES): pgm.h $(DEFPBM) $(LIBPGM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] -lm $(LIBPGM) $(LIBPBM)

# And library.
$(LIBPGM): libpgm1.o libpgm2.o
-rm $(LIBPGM)
$(AR) $(LIBPGM) libpgm1.o libpgm2.o
-$(RANLIB) $(LIBPGM)

libpgm1.o: pgm.h $(DEFPBM) libpgm.h libpgm1.c
$(CC) $(ALLCFLAGS) -c libpgm1.c
libpgm2.o: pgm.h $(DEFPBM) libpgm.h libpgm2.c $(DEFLIBPBM)
$(CC) $(ALLCFLAGS) -c libpgm2.c

DependTarget()
IPS_Header h;

pgm_init( &argc, argv );

argn = 1;

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
arpbmplus05oct91/pgm/psidtopgm.c 444 3010 34 5415 5032732547 11576 /* psidtopgm.c - convert PostScript "image" data into a portable graymap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

static int gethexit ARGS(( FILE* ifp ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray* grayrow;
register gray* gP;
int argn, row;
register int col, val;
int maxval;
int rows, cols, bitspersample;
char* usage = " [imagedata]";

pgm_init( &argc, argv );

argn = 1;

if ( argn + 3 > argc )
pm_usage( usage );

cols = atoi( argv[argn++] );
rows = atoi( argv[argn++] );
bitspersample = atoi( argv[argn++] );
if ( cols <= 0 || rows <= 0 || bitspersample <= 0 )
pm_usage( usage );

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

maxval = pm_bitstomaxval( bitspersample );
if ( maxval > PGM_MAXMAXVAL )
pm_error(
"bits/sample is too large - try reconfiguring with PGM_BIGGRAYS" );

pgm_writepgminit( stdout, cols, rows, (gray) maxval, 0 );
grayrow = pgm_allocrow( ( cols + 7 ) / 8 * 8 );
for ( row = 0; row < rows; ++row)
{
for ( col = 0, gP = grayrow; col < cols; )
{
val = gethexit( ifp ) << 4;
val += gethexit( ifp );
switch ( bitspersample )
{
case 1:
*gP++ = val >> 7;
*gP++ = ( val >> 6 ) & 0x1;
*gP++ = ( val >> 5 ) & 0x1;
*gP++ = ( val >> 4 ) & 0x1;
*gP++ = ( val >> 3 ) & 0x1;
*gP++ = ( val >> 2 ) & 0x1;
*gP++ = ( val >> 1 ) & 0x1;
*gP++ = val & 0x1;
col += 8;
break;

case 2:
*gP++ = val >> 6;
*gP++ = ( val >> 4 ) & 0x3;
*gP++ = ( val >> 2 ) & 0x3;
*gP++ = val & 0x3;
col += 4;
break;

case 4:
*gP++ = val >> 4;
*gP++ = val & 0xf;
col += 2;
break;

case 8:
*gP++ = val;
++col;
break;

default:
pm_error( "bitspersample of %d not supported", bitspersample );
}
}
pgm_writepgmrow( stdout, grayrow, cols, (gray) maxval, 0 );
}
pm_close( ifp );

exit( 0 );
}

static int
gethexit( ifp )
FILE* ifp;
{
register int i;
register char c;

for ( ; ; )
{
i = getc( ifp );
if ( i == EOF )
pm_error( "EOF / read error" );
c = (char) i;
if ( c >= '0' && c <= '9' )
return c - '0';
else if ( c >= 'A' && c <= 'F' )
return c - 'A' + 10;
else if ( c >= 'a' && c <= 'f' )
return c - 'a' + 10;
/* Else ignore - whitespace. */
}
}
yrow; col < cols; col++, gP++ )
{
int ich;

switch ( h.pixel_format )
{
case HIPS_PFBYTE:
ich = getc( ifp );
if ( ich == EOF )
pm_error( "EOF / read error" );
*gP = (gray) ich;
break;

default:
pm_error( "cpbmplus05oct91/pgm/pgmtofits.c 444 3010 34 6705 5032725075 11605 /* pgmtofits.c - read a portable pixmap and produce a FITS file
**
** Copyright (C) 1989 by Wilson H. Bent ([email protected]).
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"

static void putFitsHead ARGS(( int cols, int rows, gray maxval ));
static void write_card ARGS(( char* str ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray* grayrow;
register gray* gP;
int argn, rows, cols, i, format;
register int col, row;
gray maxval;

pgm_init( &argc, argv );

argn = 1;

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( "[pgmfile]" );

pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
if ( maxval > 255 )
pm_error( "maxval (%d) is greater than maximum of 255", maxval );
grayrow = pgm_allocrow( cols );

putFitsHead( cols, rows, maxval );

for ( row = 0; row < rows; ++row )
{
pgm_readpgmrow( ifp, grayrow, cols, maxval, format );
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
putchar( *gP );
}

for ( i = ( rows * cols ) % 2880; i < 2880; ++i )
putchar( '\0' );

pm_close( ifp );

exit( 0 );
}

#if __STDC__
static void
putFitsHead( int cols, int rows, gray maxval )
#else /*__STDC__*/
static void
putFitsHead( cols, rows, maxval )
int cols, rows;
gray maxval;
#endif /*__STDC__*/
{
int i = 0;
char card[81];

sprintf( card, "SIMPLE = T " );
write_card( card ); ++i;
sprintf( card, "BITPIX = 8 " );
write_card( card ); ++i;
sprintf( card, "NAXIS = 2 " );
write_card( card ); ++i;
sprintf( card, "NAXIS1 = %10d ", cols );
write_card( card ); ++i;
sprintf( card, "NAXIS2 = %10d ", rows );
write_card( card ); ++i;
sprintf( card, "DATAMIN = %10d ", 0 );
write_card( card ); ++i;
sprintf( card, "DATAMAX = %10d ", (int) maxval );
write_card( card ); ++i;
sprintf( card, "BZERO = 0.0 " );
write_card( card ); ++i;
sprintf( card, "BSCALE = 1.0 " );
write_card( card ); ++i;
sprintf( card, "HISTORY Created by fitstopgm. " );
write_card( card ); ++i;
sprintf( card, "END " );
write_card( card ); ++i;
sprintf( card, " " );
while ( i < 36 )
{
write_card( card ); ++i;
}
}

static void
write_card( str )
char* str;
{
fwrite( str, sizeof(char), 80, stdout );
}
buf );

/* Read and toss orig_date. */
read_line( pbmplus05oct91/pgm/lispmtopgm.1 444 3010 34 3153 5022775114 11672 .TH lispmtopgm 1 "06 March 1990"
.IX lispmtopgm
.SH NAME
lispmtopgm - convert a Lisp Machine bitmap file into pgm format
.SH SYNOPSIS
.B lispmtopgm
.RI [ lispmfile ]
.SH DESCRIPTION
Reads a Lisp Machine bitmap as input.
.IX "Lisp Machine bitmap"
Produces a portable graymap as output.
.PP
This is the file format written by the tv:write-bit-array-file function on
TI Explorer and Symbolics lisp machines.
.PP
Multi-plane bitmaps on lisp machines are color; but the lispm image file
format does not include a color map, so we must treat it as a graymap
instead. This is unfortunate.
.SH "SEE ALSO"
pgmtolispm(1), pgm(5)
.SH BUGS
The Lispm bitmap file format is a bit quirky; Usually the image in the file
has its width rounded up to the next higher multiple of 32, but not always.
If the width is not a multiple of 32, we don't deal with it properly, but
because of the Lispm microcode, such arrays are probably not image data
anyway.
.PP
Also, the lispm code for saving bitmaps has a bug, in that if you are writing a
bitmap which is not mod32 across, the file may be up to 7 bits too short! They
round down instead of up, and we don't handle this bug gracefully.
.PP
No color.
.SH AUTHOR
Copyright (C) 1991 by Jamie Zawinski and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
_*/
static void
putFitsHead( cols, rows, maxval )
int cols, rows;
gray maxval;
#endif /*__STDC__*/
{
int i = 0;
char card[81];

sprintf( card, "SIMPLE = T " );
write_card( card ); ++i;
sprintf( card, "BITPIX = 8 " );
write_card( card ); ++pbmplus05oct91/pgm/lispmtopgm.c 444 3010 34 12122 5032732115 11763 /* lispmtopgm.c - read a file written by the tv:write-bit-array-file function
** of TI Explorer and Symbolics Lisp Machines, and write a PGM.
**
** Written by Jamie Zawinski based on code (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
**
** When one writes a multi-plane bitmap with tv:write-bit-array-file, it is
** usually a color image; but a color map is not written in the file, so we
** treat this as a graymap instead. Since the pgm reader can also read pbms,
** this doesn't matter if you're using only single plane images.
*/

#include
#include "pgm.h"

#define LISPM_MAGIC "This is a BitMap file"

static void getinit ARGS(( FILE* file, short* colsP, short* rowsP, short* depthP, short* padrightP ));
static int depth_to_word_size ARGS(( int depth ));
static unsigned int getval ARGS(( FILE* file ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray* grayrow;
register gray* gP;
short rows, cols, padright, row, col;
short depth;
int maxval;

pgm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[lispmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

getinit( ifp, &cols, &rows, &depth, &padright );
maxval = 1 << depth;

if ( maxval > PGM_MAXMAXVAL )
pm_error( "depth is too large - try reconfiguring with PGM_BIGGRAYS" );

pgm_writepgminit( stdout, cols, rows, (gray) maxval, 0 );
grayrow = pgm_allocrow( ( cols + 7 ) / 8 * 8 );

for ( row = 0; row < rows; ++row )
{
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
*gP = getval( ifp );
pgm_writepgmrow( stdout, grayrow, cols, (gray) maxval, 0 );
}
pm_close( ifp );
exit( 0 );
}

static long item, bitmask;
static unsigned int bitsperitem, maxbitsperitem, bitshift;

static void
getinit( file, colsP, rowsP, depthP, padrightP )
FILE* file;
short* colsP;
short* rowsP;
short* padrightP;
short* depthP;
{
short cols_32;
char magic[sizeof(LISPM_MAGIC)];
int i;

for ( i = 0; i < sizeof(magic)-1; ++i )
magic[i] = getc( file );
magic[i]='\0';
if (0 != strcmp(LISPM_MAGIC, magic))
pm_error( "bad id string in Lispm file" );

if ( pm_readlittleshort( file, colsP ) == -1 )
pm_error( "EOF / read error" );
if ( pm_readlittleshort( file, rowsP ) == -1 )
pm_error( "EOF / read error" );
if ( pm_readlittleshort( file, &cols_32 ) == -1 )
pm_error( "EOF / read error" );
*depthP = getc( file );

if ( *depthP == 0 )
*depthP = 1; /* very old file */

*padrightP = ( ( *colsP + 31 ) / 32 ) * 32 - *colsP;

if ( *colsP != (cols_32 - *padrightP) ) {
/* pm_message( "inconsistent input: Width and Width(mod32) fields don't agree" ); */
/* *padrightP = cols_32 - *colsP; */ /* hmmmm.... */
/* This is a dilemma. Usually the output is rounded up to mod32, but not always.
* For the Lispm code to not round up, the array size must be the same size as the
* portion being written - that is, the array itself must be an odd size, not just
* the selected portion. Since arrays that are odd sizes can't be handed to bitblt,
* such arrays are probably not image data - so punt on it for now.
*
* Also, the lispm code for saving bitmaps has a bug, in that if you are writing a
* bitmap which is not mod32 across, the file may be up to 7 bits too short! They
* round down instead of up.
*
* The code in 'pgmtolispm.c' always rounds up to mod32, which is totally reasonable.
*/
}
bitsperitem = 0;
maxbitsperitem = depth_to_word_size( *depthP );
bitmask = ( 1 << maxbitsperitem ) - 1; /* for depth=3, mask=00000111 */

for ( i = 0; i < 9; ++i )
getc( file ); /* discard bytes reserved for future use */
}

static int
depth_to_word_size (depth) /* Lispm architecture specific - if a bitmap is written */
int depth; /* out with a depth of 5, it really has a depth of 8, and */
{ /* is stored that way in the file. */
if (depth==0 || depth==1) return ( 1);
else if (depth == 2) return ( 2);
else if (depth <= 4) return ( 4);
else if (depth <= 8) return ( 8);
else if (depth <= 16) return (16);
else if (depth <= 32) return (32);
else
pm_error( "depth was %d, which is not in the range 1-32.", depth );
}

static unsigned int
getval( file )
FILE* file;
{
unsigned int b;

if ( bitsperitem == 0 )
{
if ( pm_readlittlelong( file, &item ) == -1 )
pm_error( "EOF / read error" );
bitsperitem = 32;
bitshift = 0;
item = ~item;
}
b = ( ( item >> bitshift ) & bitmask );
bitsperitem = bitsperitem - maxbitsperitem;
bitshift = bitshift + maxbitsperitem;
return b;
}
s = atoi( buf );

/* Read cols. */
read_line( fd, buf, 5000 );
hP->cols = atoi( buf );

/* Read bits_per_pixel. */
read_line( fd, buf, 5000 );
hP->bits_per_pixel = atoi( buf );

/* Read bit_packing. */
read_line( fd, buf, 5000 );
hP->bit_packing = atoi( buf );

/* Read pixel_format. */
read_line( fd, buf, 5000 );
hP->pixel_format = atoi( buf );

/* Now read and toss lines untpbmplus05oct91/pgm/pgmtolispm.1 444 3010 34 2725 5022775526 11705 .TH pgmtolispm 1 "06 March 1990"
.IX pgmtolispm
.SH NAME
pgmtolispm - convert a portable graymap into Lisp Machine format
.SH SYNOPSIS
.B pgmtolispm
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Produces a Lisp Machine bitmap as output.
.IX "Lisp Machine bitmap"
.PP
This is the file format read by the tv:read-bit-array-file function on
TI Explorer and Symbolics lisp machines.
.PP
Given a pgm (instead of a pbm) a multi-plane image will be output.
This is probably not useful unless you have a color lisp machine.
.PP
Multi-plane bitmaps on lisp machines are color; but the lispm image file
format does not include a color map, so we must treat it as a graymap
instead. This is unfortunate.
.SH "SEE ALSO"
lispmtopgm(1), pgm(5)
.SH BUGS
Output width is always rounded up to the nearest multiple of 32; this might
not always be what you want, but it probably is (arrays which are not
modulo 32 cannot be passed to the Lispm BITBLT function, and thus cannot
easily be displayed on the screen).
.PP
No color.
.SH AUTHOR
Copyright (C) 1991 by Jamie Zawinski and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
P;

if ( *colsP != (cols_32 - *padrpbmplus05oct91/pgm/pgmtolispm.c 444 3010 34 7654 5032725077 11772 /* pgmtolispm.c - read a pgm and write a file acceptable to the
** tv:read-bit-array-file function of TI Explorer and Symbolics Lisp Machines.
**
** Written by Jamie Zawinski based on code (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
**
** When one writes a multi-plane bitmap with tv:write-bit-array-file, it is
** usually a color image; but a color map is not written in the file, so we
** treat this as a graymap instead. To convert a color image to Lispm
** format, you must convert it to a pgm, and hand-edit a color map... Ick.
*/

#include
#include "pgm.h"

#define LISPM_MAGIC "This is a BitMap file"

static void putinit ARGS(( int cols, int rows, int depth ));
static int depth_to_word_size ARGS(( int depth ));
static void putval ARGS(( gray b ));
static void putrest ARGS(( void ));
static void putitem ARGS(( void ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray *grayrow;
register gray* gP;
int rows, cols, depth, format, padright, row, col;
gray maxval;

pgm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[pgmfile]" );
if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
grayrow = pgm_allocrow( cols );
depth = pm_maxvaltobits( maxval );

/* Compute padding to round cols up to the nearest multiple of 32. */
padright = ( ( cols + 31 ) / 32 ) * 32 - cols;

putinit( cols, rows, depth );
for ( row = 0; row < rows; ++row )
{
pgm_readpgmrow( ifp, grayrow, cols, maxval, format );
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
putval( *gP );
for ( col = 0; col < padright; ++col )
putval( 0 );
}

pm_close( ifp );

putrest( );

exit( 0 );
}

static unsigned int item;
static unsigned int bitsperitem, maxbitsperitem, bitshift;

static void
putinit( cols, rows, depth )
int cols, rows, depth;
{
int i;
int cols32 = ( ( cols + 31 ) / 32 ) * 32; /* Lispms are able to write bit files that are not mod32 wide, but we */
/* don't. This should be ok, since bit arrays which are not mod32 wide */
printf(LISPM_MAGIC); /* are pretty useless on a lispm (can't hand them to bitblt). */
pm_writelittleshort( stdout, cols );
pm_writelittleshort( stdout, rows );
pm_writelittleshort( stdout, cols32 );
putchar(depth & 0xFF);

for ( i = 0; i < 9; ++i )
putchar( 0 ); /* pad bytes */

item = 0;
bitsperitem = 0;
maxbitsperitem = depth_to_word_size( depth );
bitshift = 0;
}

static int
depth_to_word_size (depth) /* Lispm architecture specific - if a bitmap is written */
int depth; /* out with a depth of 5, it really has a depth of 8, and */
{ /* is stored that way in the file. */
if (depth==0 || depth==1) return ( 1);
else if (depth == 2) return ( 2);
else if (depth <= 4) return ( 4);
else if (depth <= 8) return ( 8);
else if (depth <= 16) return (16);
else if (depth <= 32) return (32);
else
pm_error( "depth was %d, which is not in the range 1-32", depth );
}

#if __STDC__
static void
putval( gray b )
#else /*__STDC__*/
static void
putval( b )
gray b;
#endif /*__STDC__*/
{
if ( bitsperitem == 32 )
putitem( );
item = item | ( b << bitshift );
bitsperitem = bitsperitem + maxbitsperitem;
bitshift = bitshift + maxbitsperitem;
}

static void
putrest( )
{
if ( bitsperitem > 0 )
putitem( );
}

static void
putitem( )
{
pm_writelittlelong( stdout, ~item );
item = 0;
bitsperitem = 0;
bitshift = 0;
}
itsperitem = 0;
maxbitsperitem = depth_to_word_size( *depthP );
bitmask = ( pbmplus05oct91/pgm/pgmoil.c 444 3010 34 3766 5032725070 11057 /* pgmoil.c - read a portable graymap and turn into an oil painting
**
** Copyright (C) 1990 by Wilson Bent ([email protected])
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pgm.h"

static int hist[PGM_MAXMAXVAL+1];

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray midval, maxval;
gray** gin;
gray** gout;
int argn, rows, n, cols, row;
register int col, drow, dcol;
int i;
char* usage = "[-n ] [pgmfile]";

pgm_init( &argc, argv );

argn = 1;
n = 3; /* DEFAULT VALUE */

/* Check for flags. */
if ( argn < argc && argv[argn][0] == '-' )
{
if ( argv[argn][1] == 'n' )
{
++argn;
if ( argn == argc || sscanf( argv[argn], "%d", &n ) != 1 )
pm_usage( usage );
}
else
pm_usage( usage );
++argn;
}

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

gin = pgm_readpgm( ifp, &cols, &rows, &maxval );
pm_close( ifp );
gout = pgm_allocarray( cols, rows );

/* Build histogram. */
for ( row = n; row < rows - n; ++row )
for ( col = n; col < cols - n; ++col )
{
for ( i = 0; i <= maxval; ++i )
hist[i] = 0;

for ( drow = row - n; drow <= row + n; ++drow )
for ( dcol = col - n; dcol <= col + n; ++dcol )
++hist[ (int) (gin[drow][dcol]) ];

for ( drow = dcol = 0; dcol < maxval; ++dcol )
if ( hist[dcol] > drow )
{
drow = hist[dcol];
midval = dcol;
}
gout[row][col] = midval;
}

pgm_writepgm( stdout, gout, cols, rows, maxval, 0 );
pgm_freearray( gout, rows );

exit( 0 );
}
tatic voidpbmplus05oct91/pgm/pgmbentley.c 444 3010 34 2623 5032725060 11724 /* pgmbentley.c - read a portable graymap and smear it according to brightness
**
** Copyright (C) 1990 by Wilson Bent ([email protected])
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "pgm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray maxval;
gray** gin;
gray** gout;
int argn, rows, cols, row;
register int brow, col;
char* usage = "[pgmfile]";

pgm_init( &argc, argv );

argn = 1;

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

gin = pgm_readpgm( ifp, &cols, &rows, &maxval );
pm_close( ifp );
gout = pgm_allocarray( cols, rows );

#define N 4
for ( row = 0; row < rows; ++row )
for ( col = 0; col < cols; ++col )
{
brow = row + (int) (gin[row][col]) / N;
if ( brow >= rows )
brow = rows - 1;
gout[brow][col] = gin[row][col];
}

pgm_writepgm( stdout, gout, cols, rows, maxval, 0 );
pgm_freearray( gout, rows );

exit( 0 );
}
);

/* Build histogram. */
for ( row = n; row < rows - n; ++row )
for ( col = n; col < cols - n; ++pbmplus05oct91/pgm/pgmbentley.1 444 3010 34 1642 5022775145 11652 .TH pgmbentley 1 "11 January 1991"
.IX pgmbentley
.SH NAME
pgmbentley - Bentleyize a portable graymap
.SH SYNOPSIS
.B pgmbentley
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Performs The Bentley Effect, and writes a portable graymap as output.
.IX "Bentley Effect"
.PP
The Bentley Effect is described in "Beyond Photography" by Holzmann,
chapter 4, photo 4.
It's a vertical smearing based on brightness.
.SH "SEE ALSO"
pgmoil(1), ppmrelief(1), pgm(5)
.SH AUTHOR
Copyright (C) 1990 by Wilson Bent ([email protected])
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
htness.
.SH "SEE ALSO"
pgmoil(1), ppmrelief(1), pgm(5)
.SH AUTHOR
Copyright (C) 1990 by Wilsonpbmplus05oct91/pgm/pgmoil.1 444 3010 34 2055 5022775362 10773 .TH pgmoil 1 "11 January 1991"
.IX pgmoil
.SH NAME
pgmoil - turn a portable graymap into an oil painting
.SH SYNOPSIS
.B pgmoil
.RB [ -n
.IR N ]
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Does an "oil transfer", and writes a portable graymap as output.
.IX "oil transfer"
.PP
The oil transfer is described in "Beyond Photography" by Holzmann,
chapter 4, photo 7.
It's a sort of localized smearing.
.SH OPTIONS
.PP
The optional
.B -n
flag controls the size of the area smeared. The default value is 3.
.SH BUGS
Takes a long time to run.
.SH "SEE ALSO"
pgmbentley(1), ppmrelief(1), pgm(5)
.SH AUTHOR
Copyright (C) 1990 by Wilson Bent ([email protected])
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
( cols, rows );

#define N 4
for ( row = 0; row < rows; ++row )
for ( col = 0; col < cols; ++col )
{
brow = row + (int) (gin[row][col]) / N;
if ( brow >= rows )
brow = rows - 1;
gout[brow][col] = gin[row][col];
}

pgm_writepgm( stdout, gout, cols, rows, maxval, 0 );
pgm_freearray( gout, rows );

exit( 0 );
}
);

/* Build histogram. */
for ( row = n; row < rows - n; ++row )
for ( col = n; col < cols - n; ++pbmplus05oct91/pgm/pgmtexture.c 444 3010 34 56343 5070462375 12023 /* pgmtxtur.c - calculate textural features on a portable graymap
**
** Author: James Darrell McCauley
** Texas Agricultural Experiment Station
** Department of Agricultural Engineering
** Texas A&M University
** College Station, Texas 77843-2117 USA
**
** Code written partially taken from pgmtofs.c in the PBMPLUS package
** by Jef Poskanzer.
**
** Algorithms for calculating features (and some explanatory comments) are
** taken from:
**
** Haralick, R.M., K. Shanmugam, and I. Dinstein. 1973. Textural features
** for image classification. IEEE Transactions on Systems, Man, and
** Cybertinetics, SMC-3(6):610-621.
**
** Copyright (C) 1991 Texas Agricultural Experiment Station, employer for
** hire of James Darrell McCauley
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
**
** THE TEXAS AGRICULTURAL EXPERIMENT STATION (TAES) AND THE TEXAS A&M
** UNIVERSITY SYSTEM (TAMUS) MAKE NO EXPRESS OR IMPLIED WARRANTIES
** (INCLUDING BY WAY OF EXAMPLE, MERCHANTABILITY) WITH RESPECT TO ANY
** ITEM, AND SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL
** OR CONSEQUENTAL DAMAGES ARISING OUT OF THE POSESSION OR USE OF
** ANY SUCH ITEM. LICENSEE AND/OR USER AGREES TO INDEMNIFY AND HOLD
** TAES AND TAMUS HARMLESS FROM ANY CLAIMS ARISING OUT OF THE USE OR
** POSSESSION OF SUCH ITEMS.
**
** Modification History:
** 24 Jun 91 - J. Michael Carstensen supplied fix for
** correlation function.
*/

#include "pgm.h"
#include

#define RADIX 2.0
#define EPSILON 0.000000001
#define BL "Angle "
#define F1 "Angular Second Moment "
#define F2 "Contrast "
#define F3 "Correlation "
#define F4 "Variance "
#define F5 "Inverse Diff Moment "
#define F6 "Sum Average "
#define F7 "Sum Variance "
#define F8 "Sum Entropy "
#define F9 "Entropy "
#define F10 "Difference Variance "
#define F11 "Difference Entropy "
#define F12 "Meas of Correlation-1 "
#define F13 "Meas of Correlation-2 "
#define F14 "Max Correlation Coeff "

#define SIGN(x,y) ((y)<0 ? -fabs(x) : fabs(x))
#define DOT fprintf(stderr,".")
#define SWAP(a,b) {y=(a);(a)=(b);(b)=y;}

void results (), hessenberg (), mkbalanced (), reduction (), simplesrt ();
float f1_asm (), f2_contrast (), f3_corr (), f4_var (), f5_idm (),
f6_savg (), f7_svar (), f8_sentropy (), f9_entropy (), f10_dvar (),
f11_dentropy (), f12_icorr (), f13_icorr (), f14_maxcorr (), *vector (),
**matrix ();


void main (argc, argv)
int argc;
char *argv[];
{
FILE *ifp;
register gray **grays, *gP;
int tone[PGM_MAXMAXVAL], R0, R45, R90, angle, d = 1, x, y;
int argn, rows, cols, bps, padright, row, col;
int itone, jtone, tones;
float **P_matrix0, **P_matrix45, **P_matrix90, **P_matrix135;
float ASM[4], contrast[4], corr[4], var[4], idm[4], savg[4];
float sentropy[4], svar[4], entropy[4], dvar[4], dentropy[4];
float icorr[4], maxcorr[4];
gray maxval, nmaxval;
char *usage = "[-d ] [pgmfile]";

pgm_init( &argc, argv );

argn = 1;

/* Check for flags. */
if ( argn < argc && argv[argn][0] == '-' )
{
if ( argv[argn][1] == 'd' )
{
++argn;
if ( argn == argc || sscanf( argv[argn], "%d", &d ) != 1 )
pm_usage( usage );
}
else
pm_usage( usage );
++argn;
}

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

grays = pgm_readpgm (ifp, &cols, &rows, &maxval);
pm_close (ifp);

/* Determine the number of different gray scales (not maxval) */
for (row = PGM_MAXMAXVAL; row >= 0; --row)
tone[row] = -1;
for (row = rows - 1; row >= 0; --row)
for (col = 0; col < cols; ++col)
tone[grays[row][col]] = grays[row][col];
for (row = PGM_MAXMAXVAL, tones = 0; row >= 0; --row)
if (tone[row] != -1)
tones++;
fprintf (stderr, "(Image has %d graylevels.)\n", tones);

/* Collapse array, taking out all zero values */
for (row = 0, itone = 0; row <= PGM_MAXMAXVAL; row++)
if (tone[row] != -1)
tone[itone++] = tone[row];
/* Now array contains only the gray levels present (in ascending order) */

/* Allocate memory for gray-tone spatial dependence matrix */
P_matrix0 = matrix (0, tones, 0, tones);
P_matrix45 = matrix (0, tones, 0, tones);
P_matrix90 = matrix (0, tones, 0, tones);
P_matrix135 = matrix (0, tones, 0, tones);
for (row = 0; row < tones; ++row)
for (col = 0; col < tones; ++col)
{
P_matrix0[row][col] = P_matrix45[row][col] = 0;
P_matrix90[row][col] = P_matrix135[row][col] = 0;
}

/* Find gray-tone spatial dependence matrix */
fprintf (stderr, "(Computing spatial dependence matrix...");
for (row = 0; row < rows; ++row)
for (col = 0; col < cols; ++col)
for (x = 0, angle = 0; angle <= 135; angle += 45)
{
while (tone[x] != grays[row][col])
x++;
if (angle == 0 && col + d < cols)
{
y = 0;
while (tone[y] != grays[row][col + d])
y++;
P_matrix0[x][y]++;
P_matrix0[y][x]++;
}
if (angle == 90 && row + d < rows)
{
y = 0;
while (tone[y] != grays[row + d][col])
y++;
P_matrix90[x][y]++;
P_matrix90[y][x]++;
}
if (angle == 45 && row + d < rows && col - d >= 0)
{
y = 0;
while (tone[y] != grays[row + d][col - d])
y++;
P_matrix45[x][y]++;
P_matrix45[y][x]++;
}
if (angle == 135 && row + d < rows && col + d < cols)
{
y = 0;
while (tone[y] != grays[row + d][col + d])
y++;
P_matrix135[x][y]++;
P_matrix135[y][x]++;
}
}
/* Gray-tone spatial dependence matrices are complete */

/* Find normalizing constants */
R0 = 2 * rows * (cols - 1);
R45 = 2 * (rows - 1) * (cols - 1);
R90 = 2 * (rows - 1) * cols;

/* Normalize gray-tone spatial dependence matrix */
for (itone = 0; itone < tones; ++itone)
for (jtone = 0; jtone < tones; ++jtone)
{
P_matrix0[itone][jtone] /= R0;
P_matrix45[itone][jtone] /= R45;
P_matrix90[itone][jtone] /= R90;
P_matrix135[itone][jtone] /= R45;
}

fprintf (stderr, " done.)\n");
fprintf (stderr, "(Computing textural features");
fprintf (stdout, "\n");
DOT;
fprintf (stdout,
"%s 0 45 90 135 Avg\n",
BL);

ASM[0] = f1_asm (P_matrix0, tones);
ASM[1] = f1_asm (P_matrix45, tones);
ASM[2] = f1_asm (P_matrix90, tones);
ASM[3] = f1_asm (P_matrix135, tones);
results (F1, ASM);

contrast[0] = f2_contrast (P_matrix0, tones);
contrast[1] = f2_contrast (P_matrix45, tones);
contrast[2] = f2_contrast (P_matrix90, tones);
contrast[3] = f2_contrast (P_matrix135, tones);
results (F2, contrast);


corr[0] = f3_corr (P_matrix0, tones);
corr[1] = f3_corr (P_matrix45, tones);
corr[2] = f3_corr (P_matrix90, tones);
corr[3] = f3_corr (P_matrix135, tones);
results (F3, corr);

var[0] = f4_var (P_matrix0, tones);
var[1] = f4_var (P_matrix45, tones);
var[2] = f4_var (P_matrix90, tones);
var[3] = f4_var (P_matrix135, tones);
results (F4, var);


idm[0] = f5_idm (P_matrix0, tones);
idm[1] = f5_idm (P_matrix45, tones);
idm[2] = f5_idm (P_matrix90, tones);
idm[3] = f5_idm (P_matrix135, tones);
results (F5, idm);

savg[0] = f6_savg (P_matrix0, tones);
savg[1] = f6_savg (P_matrix45, tones);
savg[2] = f6_savg (P_matrix90, tones);
savg[3] = f6_savg (P_matrix135, tones);
results (F6, savg);

sentropy[0] = f8_sentropy (P_matrix0, tones);
sentropy[1] = f8_sentropy (P_matrix45, tones);
sentropy[2] = f8_sentropy (P_matrix90, tones);
sentropy[3] = f8_sentropy (P_matrix135, tones);
svar[0] = f7_svar (P_matrix0, tones, sentropy[0]);
svar[1] = f7_svar (P_matrix45, tones, sentropy[1]);
svar[2] = f7_svar (P_matrix90, tones, sentropy[2]);
svar[3] = f7_svar (P_matrix135, tones, sentropy[3]);
results (F7, svar);
results (F8, sentropy);

entropy[0] = f9_entropy (P_matrix0, tones);
entropy[1] = f9_entropy (P_matrix45, tones);
entropy[2] = f9_entropy (P_matrix90, tones);
entropy[3] = f9_entropy (P_matrix135, tones);
results (F9, entropy);

dvar[0] = f10_dvar (P_matrix0, tones);
dvar[1] = f10_dvar (P_matrix45, tones);
dvar[2] = f10_dvar (P_matrix90, tones);
dvar[3] = f10_dvar (P_matrix135, tones);
results (F10, dvar);

dentropy[0] = f11_dentropy (P_matrix0, tones);
dentropy[1] = f11_dentropy (P_matrix45, tones);
dentropy[2] = f11_dentropy (P_matrix90, tones);
dentropy[3] = f11_dentropy (P_matrix135, tones);
results (F11, dentropy);

icorr[0] = f12_icorr (P_matrix0, tones);
icorr[1] = f12_icorr (P_matrix45, tones);
icorr[2] = f12_icorr (P_matrix90, tones);
icorr[3] = f12_icorr (P_matrix135, tones);
results (F12, icorr);

icorr[0] = f13_icorr (P_matrix0, tones);
icorr[1] = f13_icorr (P_matrix45, tones);
icorr[2] = f13_icorr (P_matrix90, tones);
icorr[3] = f13_icorr (P_matrix135, tones);
results (F13, icorr);

maxcorr[0] = f14_maxcorr (P_matrix0, tones);
maxcorr[1] = f14_maxcorr (P_matrix45, tones);
maxcorr[2] = f14_maxcorr (P_matrix90, tones);
maxcorr[3] = f14_maxcorr (P_matrix135, tones);
results (F14, maxcorr);


fprintf (stderr, " done.)\n");
exit (0);
}

float f1_asm (P, Ng)
float **P;
int Ng;

/* Angular Second Moment */
{
int i, j;
float sum = 0;

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
sum += P[i][j] * P[i][j];

return sum;

/*
* The angular second-moment feature (ASM) f1 is a measure of homogeneity
* of the image. In a homogeneous image, there are very few dominant
* gray-tone transitions. Hence the P matrix for such an image will have
* fewer entries of large magnitude.
*/
}


float f2_contrast (P, Ng)
float **P;
int Ng;

/* Contrast */
{
int i, j, n;
float sum = 0, bigsum = 0;

for (n = 0; n < Ng; ++n)
{
for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
if ((i - j) == n || (j - i) == n)
sum += P[i][j];
bigsum += n * n * sum;

sum = 0;
}
return bigsum;

/*
* The contrast feature is a difference moment of the P matrix and is a
* measure of the contrast or the amount of local variations present in an
* image.
*/
}

float f3_corr (P, Ng)
float **P;
int Ng;

/* Correlation */
{
int i, j;
float sum_sqrx = 0, sum_sqry = 0, tmp, *px;
float meanx =0 , meany = 0 , stddevx, stddevy;

px = vector (0, Ng);
for (i = 0; i < Ng; ++i)
px[i] = 0;

/*
* px[i] is the (i-1)th entry in the marginal probability matrix obtained
* by summing the rows of p[i][j]
*/
for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
px[i] += P[i][j];


/* Now calculate the means and standard deviations of px and py */
/*- fix supplied by J. Michael Christensen, 21 Jun 1991 */
/*- further modified by James Darrell McCauley, 16 Aug 1991
* after realizing that meanx=meany and stddevx=stddevy
*/
for (i = 0; i < Ng; ++i)
{
meanx += px[i]*i;
sum_sqrx += px[i]*i*i;
}
meany = meanx;
sum_sqry = sum_sqrx;
stddevx = sqrt (sum_sqrx - (meanx * meanx));
stddevy = stddevx;

/* Finally, the correlation ... */
for (tmp = 0, i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
tmp += i*j*P[i][j];

return (tmp - meanx * meany) / (stddevx * stddevy);
/*
* This correlation feature is a measure of gray-tone linear-dependencies
* in the image.
*/
}


float f4_var (P, Ng)
float **P;
int Ng;

/* Sum of Squares: Variance */
{
int i, j;
float mean = 0, var = 0;

/*- Corrected by James Darrell McCauley, 16 Aug 1991
* calculates the mean intensity level instead of the mean of
* cooccurrence matrix elements
*/
for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
mean += i * P[i][j];

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
var += (i + 1 - mean) * (i + 1 - mean) * P[i][j];

return var;
}

float f5_idm (P, Ng)
float **P;
int Ng;

/* Inverse Difference Moment */
{
int i, j;
float idm = 0;

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
idm += P[i][j] / (1 + (i - j) * (i - j));

return idm;
}

float Pxpy[2 * PGM_MAXMAXVAL];

float f6_savg (P, Ng)
float **P;
int Ng;

/* Sum Average */
{
int i, j;
extern float Pxpy[2 * PGM_MAXMAXVAL];
float savg = 0;

for (i = 0; i <= 2 * Ng; ++i)
Pxpy[i] = 0;

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
Pxpy[i + j + 2] += P[i][j];
for (i = 2; i <= 2 * Ng; ++i)
savg += i * Pxpy[i];

return savg;
}


float f7_svar (P, Ng, S)
float **P, S;
int Ng;

/* Sum Variance */
{
int i, j;
extern float Pxpy[2 * PGM_MAXMAXVAL];
float var = 0;

for (i = 0; i <= 2 * Ng; ++i)
Pxpy[i] = 0;

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
Pxpy[i + j + 2] += P[i][j];

for (i = 2; i <= 2 * Ng; ++i)
var += (i - S) * (i - S) * Pxpy[i];

return var;
}

float f8_sentropy (P, Ng)
float **P;
int Ng;

/* Sum Entropy */
{
int i, j;
extern float Pxpy[2 * PGM_MAXMAXVAL];
float sentropy = 0;

for (i = 0; i <= 2 * Ng; ++i)
Pxpy[i] = 0;

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
Pxpy[i + j + 2] += P[i][j];

for (i = 2; i <= 2 * Ng; ++i)
sentropy -= Pxpy[i] * log10 (Pxpy[i] + EPSILON);

return sentropy;
}


float f9_entropy (P, Ng)
float **P;
int Ng;

/* Entropy */
{
int i, j;
float entropy = 0;

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
entropy += P[i][j] * log10 (P[i][j] + EPSILON);

return -entropy;
}


float f10_dvar (P, Ng)
float **P;
int Ng;

/* Difference Variance */
{
int i, j, tmp;
extern float Pxpy[2 * PGM_MAXMAXVAL];
float sum = 0, sum_sqr = 0, var = 0;

for (i = 0; i <= 2 * Ng; ++i)
Pxpy[i] = 0;

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
Pxpy[abs (i - j)] += P[i][j];

/* Now calculate the variance of Pxpy (Px-y) */
for (i = 0; i < Ng; ++i)
{
sum += Pxpy[i];
sum_sqr += Pxpy[i] * Pxpy[i];
}
tmp = Ng * Ng;
var = ((tmp * sum_sqr) - (sum * sum)) / (tmp * tmp);

return var;
}

float f11_dentropy (P, Ng)
float **P;
int Ng;

/* Difference Entropy */
{
int i, j, tmp;
extern float Pxpy[2 * PGM_MAXMAXVAL];
float sum = 0, sum_sqr = 0, var = 0;

for (i = 0; i <= 2 * Ng; ++i)
Pxpy[i] = 0;

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
Pxpy[abs (i - j)] += P[i][j];

for (i = 0; i < Ng; ++i)
sum += Pxpy[i] * log10 (Pxpy[i] + EPSILON);

return -sum;
}

float f12_icorr (P, Ng)
float **P;
int Ng;

/* Information Measures of Correlation */
{
int i, j, tmp;
float *px, *py;
float hx = 0, hy = 0, hxy = 0, hxy1 = 0, hxy2 = 0;

px = vector (0, Ng);
py = vector (0, Ng);

/*
* px[i] is the (i-1)th entry in the marginal probability matrix obtained
* by summing the rows of p[i][j]
*/
for (i = 0; i < Ng; ++i)
{
for (j = 0; j < Ng; ++j)
{
px[i] += P[i][j];
py[j] += P[i][j];
}
}

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
{
hxy1 -= P[i][j] * log10 (px[i] * py[j] + EPSILON);
hxy2 -= px[i] * py[j] * log10 (px[i] * py[j] + EPSILON);
hxy -= P[i][j] * log10 (P[i][j] + EPSILON);
}

/* Calculate entropies of px and py - is this right? */
for (i = 0; i < Ng; ++i)
{
hx -= px[i] * log10 (px[i] + EPSILON);
hy -= py[i] * log10 (py[i] + EPSILON);
}
/* fprintf(stderr,"hxy1=%f\thxy=%f\thx=%f\thy=%f\n",hxy1,hxy,hx,hy); */
return ((hxy - hxy1) / (hx > hy ? hx : hy));
}

float f13_icorr (P, Ng)
float **P;
int Ng;

/* Information Measures of Correlation */
{
int i, j;
float *px, *py;
float hx = 0, hy = 0, hxy = 0, hxy1 = 0, hxy2 = 0;

px = vector (0, Ng);
py = vector (0, Ng);

/*
* px[i] is the (i-1)th entry in the marginal probability matrix obtained
* by summing the rows of p[i][j]
*/
for (i = 0; i < Ng; ++i)
{
for (j = 0; j < Ng; ++j)
{
px[i] += P[i][j];
py[j] += P[i][j];
}
}

for (i = 0; i < Ng; ++i)
for (j = 0; j < Ng; ++j)
{
hxy1 -= P[i][j] * log10 (px[i] * py[j] + EPSILON);
hxy2 -= px[i] * py[j] * log10 (px[i] * py[j] + EPSILON);
hxy -= P[i][j] * log10 (P[i][j] + EPSILON);
}

/* Calculate entropies of px and py */
for (i = 0; i < Ng; ++i)
{
hx -= px[i] * log10 (px[i] + EPSILON);
hy -= py[i] * log10 (py[i] + EPSILON);
}
/* fprintf(stderr,"hx=%f\thxy2=%f\n",hx,hxy2); */
return (sqrt (abs (1 - exp (-2.0 * (hxy2 - hxy)))));
}

float f14_maxcorr (P, Ng)
float **P;
int Ng;

/* Returns the Maximal Correlation Coefficient */
{
int i, j, k;
float *px, *py, **Q;
float *x, *iy, tmp;

px = vector (0, Ng);
py = vector (0, Ng);
Q = matrix (1, Ng + 1, 1, Ng + 1);
x = vector (1, Ng);
iy = vector (1, Ng);

/*
* px[i] is the (i-1)th entry in the marginal probability matrix obtained
* by summing the rows of p[i][j]
*/
for (i = 0; i < Ng; ++i)
{
for (j = 0; j < Ng; ++j)
{
px[i] += P[i][j];
py[j] += P[i][j];
}
}

/* Find the Q matrix */
for (i = 0; i < Ng; ++i)
{
for (j = 0; j < Ng; ++j)
{
Q[i + 1][j + 1] = 0;
for (k = 0; k < Ng; ++k)
Q[i + 1][j + 1] += P[i][k] * P[j][k] / px[i] / py[k];
}
}

/* Balance the matrix */
mkbalanced (Q, Ng);
/* Reduction to Hessenberg Form */
reduction (Q, Ng);
/* Finding eigenvalue for nonsymetric matrix using QR algorithm */
hessenberg (Q, Ng, x, iy);
/* simplesrt(Ng,x); */
/* Returns the sqrt of the second largest eigenvalue of Q */
for (i = 2, tmp = x[1]; i <= Ng; ++i)
tmp = (tmp > x[i]) ? tmp : x[i];
return sqrt (x[Ng - 1]);
}

float *vector (nl, nh)
int nl, nh;
{
float *v;

v = (float *) malloc ((unsigned) (nh - nl + 1) * sizeof (float));
if (!v)
fprintf (stderr, "memory allocation failure"), exit (1);
return v - nl;
}


float **matrix (nrl, nrh, ncl, nch)
int nrl, nrh, ncl, nch;

/* Allocates a float matrix with range [nrl..nrh][ncl..nch] */
{
int i;
float **m;

/* allocate pointers to rows */
m = (float **) malloc ((unsigned) (nrh - nrl + 1) * sizeof (float *));
if (!m)
fprintf (stderr, "memory allocation failure"), exit (1);
m -= ncl;

/* allocate rows and set pointers to them */
for (i = nrl; i <= nrh; i++)
{
m[i] = (float *) malloc ((unsigned) (nch - ncl + 1) * sizeof (float));
if (!m[i])
fprintf (stderr, "memory allocation failure"), exit (2);
m[i] -= ncl;
}
/* return pointer to array of pointers to rows */
return m;
}

void results (c, a)
char *c;
float *a;
{
int i;

DOT;
fprintf (stdout, "%s", c);
for (i = 0; i < 4; ++i)
fprintf (stdout, "% 1.3e ", a[i]);
fprintf (stdout, "% 1.3e\n", (a[0] + a[1] + a[2] + a[3]) / 4);
}

void simplesrt (n, arr)
int n;
float arr[];
{
int i, j;
float a;

for (j = 2; j <= n; j++)
{
a = arr[j];
i = j - 1;
while (i > 0 && arr[i] > a)
{
arr[i + 1] = arr[i];
i--;
}
arr[i + 1] = a;
}
}

void mkbalanced (a, n)
float **a;
int n;
{
int last, j, i;
float s, r, g, f, c, sqrdx;

sqrdx = RADIX * RADIX;
last = 0;
while (last == 0)
{
last = 1;
for (i = 1; i <= n; i++)
{
r = c = 0.0;
for (j = 1; j <= n; j++)
if (j != i)
{
c += fabs (a[j][i]);
r += fabs (a[i][j]);
}
if (c && r)
{
g = r / RADIX;
f = 1.0;
s = c + r;
while (c < g)
{
f *= RADIX;
c *= sqrdx;
}
g = r * RADIX;
while (c > g)
{
f /= RADIX;
c /= sqrdx;
}
if ((c + r) / f < 0.95 * s)
{
last = 0;
g = 1.0 / f;
for (j = 1; j <= n; j++)
a[i][j] *= g;
for (j = 1; j <= n; j++)
a[j][i] *= f;
}
}
}
}
}


void reduction (a, n)
float **a;
int n;
{
int m, j, i;
float y, x;

for (m = 2; m < n; m++)
{
x = 0.0;
i = m;
for (j = m; j <= n; j++)
{
if (fabs (a[j][m - 1]) > fabs (x))
{
x = a[j][m - 1];
i = j;
}
}
if (i != m)
{
for (j = m - 1; j <= n; j++)
SWAP (a[i][j], a[m][j])
for (j = 1; j <= n; j++)
SWAP (a[j][i], a[j][m])
a[j][i] = a[j][i];
}
if (x)
{
for (i = m + 1; i <= n; i++)
{
if (y = a[i][m - 1])
{
y /= x;
a[i][m - 1] = y;
for (j = m; j <= n; j++)
a[i][j] -= y * a[m][j];
for (j = 1; j <= n; j++)
a[j][m] += y * a[j][i];
}
}
}
}
}

void hessenberg (a, n, wr, wi)
float **a, wr[], wi[];
int n;

{
int nn, m, l, k, j, its, i, mmin;
float z, y, x, w, v, u, t, s, r, q, p, anorm;

anorm = fabs (a[1][1]);
for (i = 2; i <= n; i++)
for (j = (i - 1); j <= n; j++)
anorm += fabs (a[i][j]);
nn = n;
t = 0.0;
while (nn >= 1)
{
its = 0;
do
{
for (l = nn; l >= 2; l--)
{
s = fabs (a[l - 1][l - 1]) + fabs (a[l][l]);
if (s == 0.0)
s = anorm;
if ((float) (fabs (a[l][l - 1]) + s) == s)
break;
}
x = a[nn][nn];
if (l == nn)
{
wr[nn] = x + t;
wi[nn--] = 0.0;
}
else
{
y = a[nn - 1][nn - 1];
w = a[nn][nn - 1] * a[nn - 1][nn];
if (l == (nn - 1))
{
p = 0.5 * (y - x);
q = p * p + w;
z = sqrt (fabs (q));
x += t;
if (q >= 0.0)
{
z = p + SIGN (z, p);
wr[nn - 1] = wr[nn] = x + z;
if (z)
wr[nn] = x - w / z;
wi[nn - 1] = wi[nn] = 0.0;
}
else
{
wr[nn - 1] = wr[nn] = x + p;
wi[nn - 1] = -(wi[nn] = z);
}
nn -= 2;
}
else
{
if (its == 30)
fprintf (stderr,
"Too many iterations to required to find %s\ngiving up\n",
F14), exit (1);
if (its == 10 || its == 20)
{
t += x;
for (i = 1; i <= nn; i++)
a[i][i] -= x;
s = fabs (a[nn][nn - 1]) + fabs (a[nn - 1][nn - 2]);
y = x = 0.75 * s;
w = -0.4375 * s * s;
}
++its;
for (m = (nn - 2); m >= l; m--)
{
z = a[m][m];
r = x - z;
s = y - z;
p = (r * s - w) / a[m + 1][m] + a[m][m + 1];
q = a[m + 1][m + 1] - z - r - s;
r = a[m + 2][m + 1];
s = fabs (p) + fabs (q) + fabs (r);
p /= s;
q /= s;
r /= s;
if (m == l)
break;
u = fabs (a[m][m - 1]) * (fabs (q) + fabs (r));
v = fabs (p) * (fabs (a[m - 1][m - 1]) + fabs (z) + fabs (a[m + 1][m + 1]));
if ((float) (u + v) == v)
break;
}
for (i = m + 2; i <= nn; i++)
{
a[i][i - 2] = 0.0;
if (i != (m + 2))
a[i][i - 3] = 0.0;
}
for (k = m; k <= nn - 1; k++)
{
if (k != m)
{
p = a[k][k - 1];
q = a[k + 1][k - 1];
r = 0.0;
if (k != (nn - 1))
r = a[k + 2][k - 1];
if (x = fabs (p) + fabs (q) + fabs (r))
{
p /= x;
q /= x;
r /= x;
}
}
if (s = SIGN (sqrt (p * p + q * q + r * r), p))
{
if (k == m)
{
if (l != m)
a[k][k - 1] = -a[k][k - 1];
}
else
a[k][k - 1] = -s * x;
p += s;
x = p / s;
y = q / s;
z = r / s;
q /= p;
r /= p;
for (j = k; j <= nn; j++)
{
p = a[k][j] + q * a[k + 1][j];
if (k != (nn - 1))
{
p += r * a[k + 2][j];
a[k + 2][j] -= p * z;
}
a[k + 1][j] -= p * y;
a[k][j] -= p * x;
}
mmin = nn < k + 3 ? nn : k + 3;
for (i = l; i <= mmin; i++)
{
p = x * a[i][k] + y * a[i][k + 1];
if (k != (nn - 1))
{
p += z * a[i][k + 2];
a[i][k + 2] -= p * r;
}
a[i][k + 1] -= p * q;
a[i][k] -= p;
}
}
}
}
}
} while (l < nn - 1);
}
}
Ng; ++i)
{
hx -= px[i] * log10 (px[i] + EPSILON);
hy -= py[i] * log10 (py[i] + EPSILON);
}
/* fprintf(stderr,"hxy1=%f\thxy=%f\thx=%f\thy=%f\n",hxy1,hxy,hx,hy); */
return ((hxy - hxy1) / (hx > hy ? hx : hy));
}

float f13_icorr (P, Ng)
float **P;
int Ng;

/* Informatpbmplus05oct91/pgm/pgmtexture.1 444 3010 34 4547 5070462636 11720 .TH pgmtexture 1 "22 Aug 1991"
.IX pgmtexture
.SH NAME
pgmtexture - calculate textural features on a portable graymap
.SH SYNOPSIS
.B pgmtexture
.RB [ -d
.IR d ]
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input. Calculates textural features
based on spatial dependence matrices at 0, 45, 90, and 135 degrees for
a distance
.IR d
(default = 1).
Textural features include:
.IP
(1) Angular Second Moment,
.br
(2) Contrast,
.br
(3) Correlation,
.br
(4) Variance,
.br
(5) Inverse Difference Moment,
.br
(6) Sum Average,
.br
(7) Sum Variance,
.br
(8) Sum Entropy,
.br
(9) Entropy,
.br
(10) Difference Variance,
.br
(11) Difference Entropy,
.br
(12, 13) Information Measures of Correlation, and
.br
(14) Maximal Correlation Coefficient.
.PP
Algorithm taken from:
.br
Haralick, R.M., K. Shanmugam, and I. Dinstein. 1973. Textural features
for image classification.
.I IEEE Transactions on Systems, Man,
.I and Cybertinetics,
SMC-3(6):610-621.
.SH BUGS
The program can run incredibly slow for large images (larger than 64 x 64)
and command line options are limited.
The method for finding (14) the maximal correlation coefficient, which
requires finding the second largest eigenvalue of a matrix Q, does not
always converge.
.SH REFERENCES
.I IEEE Transactions on Systems, Man,
.I and Cybertinetics,
SMC-3(6):610-621.
.SH "SEE ALSO"
pgm(5), pnmcut(1)
.SH AUTHOR
Copyright (C) 1991 by Texas Agricultural Experiment Station, employer for
hire of James Darrell McCauley.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
.\"
.\" THE TEXAS AGRICULTURAL EXPERIMENT STATION (TAES) AND THE TEXAS A&M
.\" UNIVERSITY SYSTEM (TAMUS) MAKE NO EXPRESS OR IMPLIED WARRANTIES
.\" (INCLUDING BY WAY OF EXAMPLE, MERCHANTABILITY) WITH RESPECT TO ANY
.\" ITEM, AND SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL
.\" OR CONSEQUENTAL DAMAGES ARISING OUT OF THE POSESSION OR USE OF
.\" ANY SUCH ITEM. LICENSEE AND/OR USER AGREES TO INDEMNIFY AND HOLD
.\" TAES AND TAMUS HARMLESS FROM ANY CLAIMS ARISING OUT OF THE USE OR
.\" POSSESSION OF SUCH ITEMS.
hxy=%f\thx=%f\thy=%f\n",hxy1,hxy,hx,hy); */
return ((hxy - hxy1) / (hx > hy ? hx : hy));
}

float f13_icorr (P, Ng)
float **P;
int Ng;

/* Informatpbmplus05oct91/ppm/ 755 3010 34 0 5073531736 7347 pbmplus05oct91/ppm/rawtoppm.1 444 3010 34 4173 5070251452 11361 .TH rawtoppm 1 "06 February 1991"
.IX rawtoppm
.SH NAME
rawtoppm - convert raw RGB bytes into a portable pixmap
.SH SYNOPSIS
.B rawtoppm
.RB [ -headerskip
.IR N ]
.RB [ -rowskip
.IR N ]
.RB [ -rgb | -rbg | -grb
.RB | -gbr | -brg | -bgr
.RB ]
.RB [ -interpixel | -interrow ]
.I width height
.RI [ imagedata ]
.SH DESCRIPTION
Reads raw RGB bytes as input.
.IX "raw RGB"
Produces a portable pixmap as output.
The input file is just RGB bytes.
You have to specify the width and height on the command line,
since the program obviously can't get them from the file.
The maxval is assumed to be 255.
If the resulting image is upside down, run it through
.B "pnmflip -tb" .
.IX pnmflip
.SH OPTIONS
.TP
.B -headerskip
If the file has a header, you can use this flag to
skip over it.
.TP
.B -rowskip
If there is padding at the ends of the rows, you can skip it with this flag.
.TP
.B -rgb -rbg -grb -gbr -brg -bgr
These flags let you specify alternate color orders. The default is
.BR -rgb .
.TP
.B -interpixel -interrow
These flags let you specify how the colors are interleaved.
The default is
.BR -interpixel ,
meaning interleaved by pixel.
A byte of red, a byte of green, and a byte
of blue, or whatever color order you specified.
.B -interrow
means interleaved by row - a row of red, a row of green, a row of blue,
assuming standard rgb color order.
An
.B -interplane
flag - all the red pixels, then all the green, then all the blue - would
be an obvious extension, but is not implemented.
You could get the same effect by splitting the file into three parts
(perhaps using
.IR dd ),
turning each part into a PGM file with rawtopgm, and then combining them
with rgb3toppm.
.SH "SEE ALSO"
ppm(5), rawtopgm(1), rgb3toppm(1), pnmflip(1)
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
it through
.B "pnmflip -tb" .
.IX pnmflip
.SH OPTIONS
.TP
.B -headerskip
If the file has a header, you can use this flag to
skip over it.
.TP
.B -rowskip
If there is padding at the ends of the rows, you can skip it with this flag.
.TP
.B -rgb -rbg -grb -gbr -brg -bgr
These flags let you specify alternate color orders. The default is
.BR -rgb .
.TP
.B -interpixel -interrow
These flags pbmplus05oct91/ppm/rawtoppm.c 444 3010 34 12723 5032725233 11464 /* rawtoppm.c - convert raw RGB bytes into a portable pixmap
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

static void dorowskip ARGS(( FILE* ifp, int rowskip ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel* pixrow;
register pixel* pP;
int argn, headerskip, rowskip, rows, cols, row, i;
register int col;
int order;
#define ORD_RGB 1
#define ORD_RBG 2
#define ORD_GRB 3
#define ORD_GBR 4
#define ORD_BRG 5
#define ORD_BGR 6
int interleave;
#define INT_PIX 1
#define INT_ROW 2
int val1, val2, val3;
gray* grow1;
gray* grow2;
gray* grow3;
register gray* g1P;
register gray* g2P;
register gray* g3P;
char* usage = "[-headerskip N] [-rowskip N] [-rgb|-rbg|-grb|-gbr|-brg|-bgr] [-interpixel|-interrow] [rawfile]";
double atof();

ppm_init( &argc, argv );

argn = 1;
headerskip = 0;
rowskip = 0;
order = ORD_RGB;
interleave = INT_PIX;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-headerskip", 2 ) )
{
++argn;
if ( argn >= argc )
pm_usage( usage );
headerskip = atoi( argv[argn] );
}
else if ( pm_keymatch( argv[argn], "-rowskip", 3 ) )
{
++argn;
if ( argn >= argc )
pm_usage( usage );
rowskip = atoi( argv[argn] );
}
else if ( pm_keymatch( argv[argn], "-rgb", 3 ) )
order = ORD_RGB;
else if ( pm_keymatch( argv[argn], "-rbg", 3 ) )
order = ORD_RBG;
else if ( pm_keymatch( argv[argn], "-grb", 3 ) )
order = ORD_GRB;
else if ( pm_keymatch( argv[argn], "-gbr", 3 ) )
order = ORD_GBR;
else if ( pm_keymatch( argv[argn], "-brg", 3 ) )
order = ORD_BRG;
else if ( pm_keymatch( argv[argn], "-bgr", 3 ) )
order = ORD_BGR;
else if ( pm_keymatch( argv[argn], "-interpixel", 7 ) )
interleave = INT_PIX;
else if ( pm_keymatch( argv[argn], "-interrow", 7 ) )
interleave = INT_ROW;
else
pm_usage( usage );
++argn;
}

if ( argn + 2 > argc )
pm_usage( usage );

cols = atoi( argv[argn++] );
rows = atoi( argv[argn++] );
if ( cols <= 0 || rows <= 0 )
pm_usage( usage );

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

ppm_writeppminit( stdout, cols, rows, (pixval) 255, 0 );
pixrow = ppm_allocrow( cols );

if ( interleave == INT_ROW )
{
grow1 = pgm_allocrow( cols );
grow2 = pgm_allocrow( cols );
grow3 = pgm_allocrow( cols );
}

for ( i = 0; i < headerskip; ++i )
{
val1 = getc( ifp );
if ( val1 == EOF )
pm_error( "EOF / read error" );
}

for ( row = 0; row < rows; ++row)
{
switch ( interleave )
{
case INT_PIX:
for ( col = 0, pP = pixrow; col < cols; ++col, ++pP )
{
val1 = getc( ifp );
if ( val1 == EOF )
pm_error( "EOF / read error" );
val2 = getc( ifp );
if ( val2 == EOF )
pm_error( "EOF / read error" );
val3 = getc( ifp );
if ( val3 == EOF )
pm_error( "EOF / read error" );
switch ( order )
{
case ORD_RGB:
PPM_ASSIGN( *pP, val1, val2, val3 );
break;
case ORD_RBG:
PPM_ASSIGN( *pP, val1, val3, val2 );
break;
case ORD_GRB:
PPM_ASSIGN( *pP, val2, val1, val3 );
break;
case ORD_GBR:
PPM_ASSIGN( *pP, val3, val1, val2 );
break;
case ORD_BRG:
PPM_ASSIGN( *pP, val2, val3, val1 );
break;
case ORD_BGR:
PPM_ASSIGN( *pP, val3, val2, val1 );
break;
}
}
dorowskip( ifp, rowskip );
break;

case INT_ROW:
for ( col = 0, g1P = grow1; col < cols; ++col, ++g1P )
{
val1 = getc( ifp );
if ( val1 == EOF )
pm_error( "EOF / read error" );
*g1P = val1;
}
dorowskip( ifp, rowskip );
for ( col = 0, g2P = grow2; col < cols; ++col, ++g2P )
{
val2 = getc( ifp );
if ( val2 == EOF )
pm_error( "EOF / read error" );
*g2P = val2;
}
dorowskip( ifp, rowskip );
for ( col = 0, g3P = grow3; col < cols; ++col, ++g3P )
{
val3 = getc( ifp );
if ( val3 == EOF )
pm_error( "EOF / read error" );
*g3P = val3;
}
dorowskip( ifp, rowskip );
for ( col = 0, pP = pixrow, g1P = grow1, g2P = grow2, g3P = grow3;
col < cols; ++col, ++pP, ++g1P, ++g2P, ++g3P )
{
switch ( order )
{
case ORD_RGB:
PPM_ASSIGN( *pP, *g1P, *g2P, *g3P );
break;
case ORD_RBG:
PPM_ASSIGN( *pP, *g1P, *g3P, *g2P );
break;
case ORD_GRB:
PPM_ASSIGN( *pP, *g2P, *g1P, *g3P );
break;
case ORD_GBR:
PPM_ASSIGN( *pP, *g3P, *g1P, *g2P );
break;
case ORD_BRG:
PPM_ASSIGN( *pP, *g2P, *g3P, *g1P );
break;
case ORD_BGR:
PPM_ASSIGN( *pP, *g3P, *g2P, *g1P );
break;
}
}
break;
}
ppm_writeppmrow( stdout, pixrow, cols, (pixval) 255, 0 );
}
pm_close( ifp );

exit( 0 );
}

static void
dorowskip( ifp, rowskip )
FILE* ifp;
int rowskip;
{
int i, val;

for ( i = 0; i < rowskip; ++i )
{
val = getc( ifp );
if ( val == EOF )
pm_error( "EOF / read error" );
}
}
(stdout, "%s", c);
for (i = 0; i < 4; ++i)
pbmplus05oct91/ppm/imgtoppm.c 444 3010 34 6225 5032725160 11426 /* imgtoppm.c - read an Img-whatnot file and produce a portable pixmap
**
** Based on a simple conversion program posted to comp.graphics by Ed Falk.
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel* pixelrow;
pixel colormap[256];
register pixel* pP;
int argn, rows, cols, row, i;
register int col;
pixval maxval;
int len, cmaplen, gotAT, gotCM;
unsigned char buf[4096];
register unsigned char* bP;

ppm_init( &argc, argv );

argn = 1;

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
argn++;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( "[imgfile]" );

/* Get signature. */
fread( buf, 8, 1, ifp );
buf[8] = '\0';

/* Get entries. */
gotAT = 0;
gotCM = 0;
while ( fread( buf, 2, 1, ifp ) == 1 )
{
if ( strncmp( (char*) buf, "AT", 2 ) == 0 )
{
if ( fread( buf, 8, 1, ifp ) != 1 )
pm_error( "bad attributes header" );
buf[8] = '\0';
len = atoi( buf );
if ( fread( buf, len, 1, ifp ) != 1 )
pm_error( "bad attributes buf" );
buf[len] = '\0';
sscanf( (char*) buf, "%4u%4u%4u", &cols, &rows, &cmaplen );
maxval = 255;
gotAT = 1;
}

else if ( strncmp( (char*) buf, "CM", 2 ) == 0 )
{
if ( ! gotAT )
pm_error( "missing attributes header" );
if ( fread( buf, 8, 1, ifp ) != 1 )
pm_error( "bad colormap header" );
buf[8] = '\0';
len = atoi( buf );
if ( fread( buf, len, 1, ifp ) != 1 )
pm_error( "bad colormap buf" );
if ( cmaplen * 3 != len )
{
pm_message(
"cmaplen (%d) and colormap buf length (%d) do not match",
cmaplen, len, 0, 0, 0 );
if ( cmaplen * 3 < len )
len = cmaplen * 3;
else if ( cmaplen * 3 > len )
cmaplen = len / 3;
}
for ( i = 0; i < len; i += 3 )
PPM_ASSIGN( colormap[i / 3], buf[i], buf[i + 1], buf[i + 2] );
gotCM = 1;
}

else if ( strncmp( (char*) buf, "PD", 2 ) == 0 )
{
if ( fread( buf, 8, 1, ifp ) != 1 )
pm_error( "bad pixel data header" );
buf[8] = '\0';
len = atoi( buf );
if ( len != cols * rows )
pm_message(
"pixel data length (%d) does not match image size (%d)",
len, cols * rows, 0, 0, 0 );

ppm_writeppminit( stdout, cols, rows, maxval, 0 );
pixelrow = ppm_allocrow( cols );

for ( row = 0; row < rows; row++ )
{
if ( fread( buf, 1, cols, ifp ) != cols )
pm_error( "EOF / read error" );
for ( col = 0, pP = pixelrow, bP = buf;
col < cols; col++, pP++, bP++ )
{
if ( gotCM )
*pP = colormap[*bP];
else
PPM_ASSIGN( *pP, *bP, *bP, *bP );
}
ppm_writeppmrow( stdout, pixelrow, cols, maxval, 0 );
}
pm_close( ifp );
exit( 0 );
}
}
}
usage( usage );

ppm_writeppminit( stdout, cols, rows, (pixval) 255, 0 );
pixrow = ppm_allocrow( cols );

if ( interleave == INT_ROW )
{
grow1 = pgm_allocrow( cols );
grow2 = pgm_allocrow( cols );
grow3 = pgm_allocrow( cols );
}

for ( i = 0; i < headerskip; ++i )
{
val1 = getc( ifp );
if ( val1 == EOF )
pm_error( "EOF / read error"pbmplus05oct91/ppm/ppmrelief.c 444 3010 34 5137 5073520525 11561 /* ppmrelief.c - generate a relief map of a portable pixmap
**
** Copyright (C) 1990 by Wilson H. Bent, Jr.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "ppm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel** inputbuf;
pixel* outputrow;
int argn, rows, cols, format, row, rowa, rowb;
register int col;
pixval maxval, mv2, r, g, b;
char* usage = "[ppmfile]";

ppm_init( &argc, argv );

argn = 1;

if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

ppm_pbmmaxval = PPM_MAXMAXVAL; /* use larger value for better results */

ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
mv2 = maxval / 2;

/* Allocate space for 3 input rows, plus an output row. */
inputbuf = ppm_allocarray( cols, 3 );
outputrow = ppm_allocrow( cols );

ppm_writeppminit( stdout, cols, rows, maxval, 0 );

/* Read in the first two rows. */
ppm_readppmrow( ifp, inputbuf[0], cols, maxval, format );
ppm_readppmrow( ifp, inputbuf[1], cols, maxval, format );

/* Write out the first row, all zeros. */
for ( col = 0; col < cols; ++col )
PPM_ASSIGN( outputrow[col], 0, 0, 0 );
ppm_writeppmrow( stdout, outputrow, cols, maxval, 0 );

/* Now the rest of the image - read in the 3rd row of inputbuf,
** and convolve with the first row into the output buffer.
*/
for ( row = 2 ; row < rows; ++row )
{
rowa = row % 3;
rowb = (row + 2) % 3;
ppm_readppmrow( ifp, inputbuf[rowa], cols, maxval, format );

for ( col = 0; col < cols - 2; ++col )
{
r = PPM_GETR( inputbuf[rowa][col] ) +
( mv2 - PPM_GETR( inputbuf[rowb][col + 2] ) );
g = PPM_GETG( inputbuf[rowa][col] ) +
( mv2 - PPM_GETG( inputbuf[rowb][col + 2] ) );
b = PPM_GETB( inputbuf[rowa][col] ) +
( mv2 - PPM_GETB( inputbuf[rowb][col + 2] ) );
PPM_ASSIGN( outputrow[col + 1], r, g, b );
}
ppm_writeppmrow( stdout, outputrow, cols, maxval, 0 );
}

/* And write the last row, zeros again. */
for ( col = 0; col < cols; ++col )
PPM_ASSIGN( outputrow[col], 0, 0, 0 );
ppm_writeppmrow( stdout, outputrow, cols, maxval, 0 );

pm_close( ifp );

exit( 0 );
}
pm_close( ifp );
exit( 0 );
}
}
}
usage( usage );

ppm_writeppminit( stdout, cols, rows, (pixval) 255, 0 );
pixrow = ppm_allocrow( cols );

if ( interleave == INT_ROW )
{
grow1 = pgm_allocrow( cols );
grow2 = pgm_allocrow( cols );
grow3 = pgm_allocrow( cols );
}

for ( i = 0; i < headerskip; ++i )
{
val1 = getc( ifp );
if ( val1 == EOF )
pm_error( "EOF / read error"pbmplus05oct91/ppm/ppmtoxpm.1 444 3010 34 4204 5022777737 11407 .TH ppmtoxpm 1 "26 June 1990"
.IX ppmtoxpm
.SH NAME
ppmtoxpm - convert a portable pixmap into an X11 pixmap
.SH SYNOPSIS
.B ppmtoxpm
.RB [ -name
.IR xpmname ]
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Produces X11 pixmap (XPM) as output.
.IX XPM
.IX "X window system"
.PP
If the program was compiled with an rgb database specified, and
a RGB value from the ppm input matches a RGB value from the database,
then the corresponding color name mnemonic is printed in the XPM's colormap.
If no rgb database was compiled in, or if the RGB values don't match,
then the color
will be printed with the #RGB, #RRGGBB, #RRRGGGBBB, or #RRRRGGGGBBBB
hexadecimal format.
.SH OPTIONS
.TP
.B -name
Allows you to specify the prefix string which is printed
in the resulting XPM output. If not specified, will default to the
filename (without extension) of the ppmfile argument.
If
.B -name
is not specified and no ppmfile
is specified (i.e. piped input), the prefix string will default to
the string "noname".
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH EXAMPLE
To convert the file "dot" (found in /usr/include/X11/bitmaps),
from xbm to xpm one could specify
.IP
xbmtopbm dot | ppmtoxpm -name dot
.SH BUGS
An option to match the closest (rather than exact) color name mnemonic
from the rgb text would be a desirable enhancement.
.PP
Truncation of the least significant bits of a RGB value may result in
nonexact matches when performing color name mnemonic lookups.
.SH "SEE ALSO"
xpmtoppm(1), ppm(5)
.SH AUTHOR
Copyright (C) 1990 by Mark W. Snitily.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
.\"
.\" This tool was developed for Schlumberger Technologies, ATE Division, and
.\" with their permission is being made available to the public with the above
.\" copyright notice and permission notice.
u\
sputoppm.1hu]
spctoppm.1u^
ppmquantall.1Zu_ ppmmake.cZu`
ppmtoicr.1Nua ppmtopict.1»Ov~ ppmtopuzz.1Z“v
ximtoppm.1”v€
ximtoppm.c•v
ppmtoxpm.c–v‚
xpmtoppm.c®vƒ ppmtopuzz.c
v„
qrttoppm.1
v…
qrttoppm.cv†
tgatoppm.c
v‡
ppmtopi1.c vˆ
spctoppm.c v‰
sputoppm.c vŠpbmplus05oct91/ppm/rgb3toppm.1 444 3010 34 1460 5022753567 11434 .TH rgb3toppm 1 "15 February 1990"
.IX rgb3toppm
.SH NAME
rgb3toppm - combine three portable graymaps into one portable pixmap
.SH SYNOPSIS
.B rgb3toppm
.I redpgmfile greenpgmfile bluepgmfile
.SH DESCRIPTION
Reads three portable graymaps as input.
Combines them and produces one portable pixmap as output.
.SH "SEE ALSO"
ppmtorgb3(1), pgmtoppm(1), ppmtopgm(1), ppm(5), pgm(5)
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
s^
ppmtogif.cqs_ ppmtoilbm.c=rs`ppm.h.1sa
mtvtoppm.cssb picttoppm.1il.cscppm.5mbtp
ppmtopi1.1 tê ppmmake.1=wtëxim.h
tì ppmrelief.1bmttípbmplus05oct91/ppm/ppmtouil.c 444 3010 34 17463 5043064440 11470 /* ppmtouil.c - read a portable pixmap and produce a Motif UIL icon file
**
** Converted by Jef Poskanzer from ppmtoxpm.c, which is
** Copyright (C) 1990 by Mark W. Snitily.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "ppm.h"
#include "ppmcmap.h"

/* Max number of colors allowed in ppm input. */
#define MAXCOLORS 256

/* Lower bound and upper bound of character-pixels printed in UIL output. */
#define LOW_CHAR '`'
#define HIGH_CHAR '~'

typedef struct { /* character-pixel mapping */
char* cixel; /* character string printed for pixel */
char* rgbname; /* ascii rgb color, either mnemonic or #rgb value */
char* barname; /* ascii rgb color with spaces replaced by underbars */
} cixel_map;

static char* gen_numstr ARGS(( int i, int base, char low_char, int digits ));
static void gen_cmap ARGS(( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel** pixels;
register pixel* pP;
int argn, rows, cols, ncolors, row, col, i;
pixval maxval;
colorhash_table cht;
colorhist_vector chv;
cixel_map cmap[MAXCOLORS];
int charspp;
char out_name[100];
char* cp;
int printed_one;
char* usage = "[-name ] [ppmfile]";

ppm_init( &argc, argv );
out_name[0] = '\0';

argn = 1;

/* Check for command line options. */
while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-name", 2 ) )
{
++argn;
if ( argn == argc )
pm_usage( usage );
(void) strcpy( out_name, argv[argn] );
}
else
pm_usage( usage );
++argn;
}

if ( argn != argc )
{
/* Open the input file. */
ifp = pm_openr( argv[argn] );

/* If output filename not specified, use input filename as default. */
if ( out_name[0] == '\0' )
{
(void) strcpy( out_name, argv[argn] );
cp = index( out_name, '.' );
if ( cp != 0 )
*cp = '\0'; /* remove extension */
if ( strcmp( out_name, "-" ) == 0 )
(void) strcpy( out_name, "noname" );
/* Remove trailing _icon in name. */
cp = rindex( out_name, '_' );
if ( cp[1] == 'i' && cp[2] == 'c' && cp[3] == 'o' && cp[4] == 'n' &&
cp[5] == '\0' )
*cp = '\0';
}
++argn;
}
else
{
/* No input file specified. */
ifp = stdin;
if ( out_name[0] == '\0' )
(void) strcpy( out_name, "noname" );
}

if ( argn != argc )
pm_usage( usage );

/* Read in the ppm file. */
pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
pm_close( ifp );

/* Figure out the colormap. */
pm_message( "computing colormap..." );
chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &ncolors );
if ( chv == (colorhist_vector) 0 )
pm_error(
"too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
pm_message( "%d colors found", ncolors );

/* Make a hash table for fast color lookup. */
cht = ppm_colorhisttocolorhash( chv, ncolors );

/* Now generate the character-pixel colormap table. */
gen_cmap( chv, ncolors, maxval, cmap, &charspp );

/* Write out the UIL header. */
printf( "module %s\n", out_name );
printf( "version = 'V1.0'\n" );
printf( "names = case_sensitive\n" );
printf( "include file 'XmAppl.uil';\n" );

/* Write out the colors. */
printf( "\n" );
printf( "value\n" );
for ( i = 0; i < ncolors; ++i )
if ( cmap[i].barname != (char*) 0 )
printf(
" %s : color( '%s' );\n", cmap[i].barname, cmap[i].rgbname );

/* Write out the ascii colormap. */
printf( "\n" );
printf( "value\n" );
printf( " %s_rgb : color_table (\n", out_name );
printed_one = 0;
for ( i = 0; i < ncolors; ++i )
if ( cmap[i].barname != (char*) 0 )
{
if ( printed_one )
printf( ",\n" );
printf( " %s = '%s'", cmap[i].barname, cmap[i].cixel );
printed_one = 1;
}
printf( "\n );\n" );

/* Write out the ascii character-pixel image. */
printf( "\n" );
printf(
"%s_icon : exported icon( color_table = %s_rgb,\n",
out_name, out_name );
for ( row = 0; row < rows; ++row )
{
printf( " '" );
for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
{
if ( ( col * charspp ) % 70 == 0 && col > 0 )
printf( "\\\n" ); /* line continuation */
printf( "%s", cmap[ppm_lookupcolor(cht, pP)].cixel );
}
if ( row != rows - 1 )
printf( "',\n" );
else
printf( "'\n") ;
}
printf( ");\n" );
printf( "\n" );
printf( "end module;\n" );

exit( 0 );
}

/* Given a number and a base, this routine prints the number into a
** malloc'ed string and returns it. The length of the string is
** specified by "digits". The ascii characters of the printed
** number range from low_char to low_char + base. The string is
** low_char filled.
*/

#if __STDC__
static char*
gen_numstr( int i, int base, char low_char, int digits )
#else /*__STDC__*/
static char*
gen_numstr( i, base, low_char, digits )
int i, base, digits;
char low_char;
#endif /*__STDC__*/
{
char* str;
char* p;
int d;

/* Allocate memory for printed number. Abort if error. */
str = (char*) malloc( digits + 1 );
if ( str == 0 )
pm_error( "out of memory allocating number string" );

/* Generate characters starting with least significant digit. */
p = str + digits;
*p-- = '\0'; /* nul terminate string */
while ( p >= str )
{
d = i % base;
i /= base;
*p-- = low_char + d;
}

return str;
}

#if __STDC__
static void
gen_cmap( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP )
#else /*__STDC__*/
static void
gen_cmap( chv, ncolors, maxval, cmap, charsppP )
colorhist_vector chv;
int ncolors;
pixval maxval;
cixel_map cmap[MAXCOLORS];
int* charsppP;
#endif /*__STDC__*/
{
int i, j, base;
char* colorname;
char* cp1;
char* cp2;

/* Figure out how many characters per pixel we'll be using. Don't want
** to be forced to link with libm.a, so using a division loop rather than
** a log function.
*/
base = (int) HIGH_CHAR - (int) LOW_CHAR + 1;
for ( *charsppP = 0, i = ncolors; i > 0; ++(*charsppP) )
i /= base;

/* Generate the character-pixel string and the rgb name for each colormap
** entry.
*/
for ( i = 0; i < ncolors; ++i )
{
/* Generate color name string. */
colorname = ppm_colorname( &(chv[i].color), maxval, 0 );

/* Check whether we've already assigned a character to this name,
** via the closest-match code.
*/
for ( j = 0; j < i; ++j )
{
if ( cmap[j].rgbname != (char*) 0 &&
strcmp( colorname, cmap[j].rgbname ) == 0 )
{
cmap[i].cixel = cmap[j].cixel;
cmap[i].rgbname = (char*) 0;
cmap[i].barname = (char*) 0;
goto nexti;
}
}

/* Copy it. */
cmap[i].rgbname = (char*) malloc( strlen( colorname ) + 1 );
if ( cmap[i].rgbname == 0 )
pm_error( "out of memory allocating color name" );
(void) strcpy( cmap[i].rgbname, colorname );

/* Copy it again and replace the blanks with underbars. */
cmap[i].barname = malloc( strlen( colorname ) + 1 );
if ( cmap[i].barname == 0 )
pm_error( "out of memory allocating color name", 0,0,0,0,0 );
cp1 = colorname;
cp2 = cmap[i].barname;
for ( ; ; )
{
if ( *cp1 == ' ' )
*cp2 = '_';
else
*cp2 = *cp1;
if ( *cp1 == '\0' )
break;
++cp1;
++cp2;
}

/* Generate color value characters. */
cmap[i].cixel = gen_numstr( i, base, LOW_CHAR, *charsppP );

nexti: ;
}
}
h( chv, ncolors );

/* Now generate the character-pixel colormap table. */
gen_cmap( chv, ncolors, maxval, cmap, &charspp );

/* Write out the UIL header. */
printf( "module %s\n", out_namepbmplus05oct91/ppm/ppmtouil.1 444 3010 34 3130 5022777706 11365 .TH ppmtouil 1 "31 August 1990"
.IX ppmtouil
.SH NAME
ppmtouil - convert a portable pixmap into a Motif UIL icon file
.SH SYNOPSIS
.B ppmtouil
.RB [ -name
.IR uilname ]
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Produces a Motif UIL icon file as output.
.IX Motif
.IX UIL
.IX "X window system"
.PP
If the program was compiled with an rgb database specified, and
a RGB value from the ppm input matches a RGB value from the database,
then the corresponding color name mnemonic is printed in the UIL's colormap.
If no rgb database was compiled in, or if the RGB values don't match,
then the color
will be printed with the #RGB, #RRGGBB, #RRRGGGBBB, or #RRRRGGGGBBBB
hexadecimal format.
.SH OPTIONS
.TP
.B -name
Allows you to specify the prefix string which is printed
in the resulting UIL output. If not specified, will default to the
filename (without extension) of the ppmfile argument.
If
.B -name
is not specified and no ppmfile
is specified (i.e. piped input), the prefix string will default to
the string "noname".
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH "SEE ALSO"
ppm(5)
.SH AUTHOR
Converted by Jef Poskanzer from ppmtoxpm.c, which is
Copyright (C) 1990 by Mark W. Snitily
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
Makefilemtv
ppmmerge.ctv
ppmtopcx.1tv‘ ppmtopict.c^ãv’ ppmtorgb3.1^äv“
pcxtoppm.cv”
ppmtopcx.c3v• ppmtorgb3.cc.1v– ppmquantall^žv— gouldtoppm.c
v˜
ppmtoyuv.1 v™ pjtoppm.1^ëvš ppmdither.1^ìvÇ ppmtopj.1opvÈ pjtoppm.c.ovÊ ppmdither.c.onvö ppmtopj.c
v÷
ppmtotga.c vø
ppmtotga.1 vù ppmtosixel.1 pbmplus05oct91/ppm/pi1toppm.c 444 3010 34 4123 5070743131 11336 /* pi1toppm.c - read a Degas PI1 file and produce a portable pixmap
**
** Copyright (C) 1991 by Steve Belczyk ([email protected]) and Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

#define ROWS 200
#define COLS 320
#define MAXVAL 7

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel pal[16]; /* Degas palette */
short screen[ROWS*COLS/4]; /* simulates the Atari's video RAM */
short i;
long j;
pixel* pixelrow;
register pixel* pP;
int row, col;

ppm_init( &argc, argv );

/* Check args. */
if ( argc > 2 )
pm_usage( "[pi1file]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

/* Check resolution word */
(void) pm_readbiglong( ifp, &j );
if ( j != 0 )
pm_error( "not a PI1 file" );

/* Read the palette. */
for ( i = 0; i < 16; ++i )
{
(void) pm_readbiglong( ifp, &j );
PPM_ASSIGN( pal[i],
( j & 0x700 ) >> 8,
( j & 0x070 ) >> 4,
( j & 0x007 ) );
}

/* Read the screen data */
for ( i = 0; i < ROWS*COLS/4; ++i )
(void) pm_readbigshort( ifp, &screen[i] );

pm_close( ifp );

/* Ok, get set for writing PPM. */
ppm_writeppminit( stdout, COLS, ROWS, (pixval) MAXVAL, 0 );
pixelrow = ppm_allocrow( COLS );

/* Now do the conversion. */
for ( row = 0; row < ROWS; ++row )
{
for ( col = 0, pP = pixelrow; col < COLS; ++col, ++pP )
{
register int c, ind, b, plane;

ind = 80 * row + ( ( col >> 4 ) << 2 );
b = 0x8000 >> ( col & 0xf );
c = 0;
for ( plane = 0; plane < 4; ++plane )
if ( b & screen[ind+plane] )
c |= (1 << plane);
*pP = pal[c];
}
ppm_writeppmrow( stdout, pixelrow, COLS, (pixval) MAXVAL, 0 );
}

exit( 0 );
}
e MAXVAL 7

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel pal[16]; /* Degas palette */
short screen[ROWS*COLS/4]; /* simulates the Atari's video RAM */
short i;
long j;
pixel* pixelrow;
register pixel* pP;
int row, col;

ppm_init( &argc, argv );

/* Check args. */
if ( argc > 2 )
pm_usage( "[pi1file]" );

if ( argc == 2 )
ifp = pm_openr( argpbmplus05oct91/ppm/giftoppm.1 444 3010 34 2314 5022776432 11337 .TH giftoppm 1 "21 December 1990"
.IX giftoppm
.SH NAME
giftoppm - convert a GIF file into a portable pixmap
.SH SYNOPSIS
.B giftoppm
.RB [ -verbose ]
.RB [ -comments ]
.RB [ -image
.IR N ]
.RI [ GIFfile ]
.SH DESCRIPTION
Reads a GIF file for input, and outputs portable pixmap.
.IX GIF
.SH OPTIONS
.TP
.B -verbose
Produces verbose output about the GIF file input.
.TP
.B -comments
Only outputs GIF89 comment fields.
.TP
.B -image
Output the specified gif image from the
input gif archive (where
.I N
is '1', '2', '20'...).
Normally there is only one image per file, so this option
is not needed.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH BUGS
This does not correctly handle the Plain Text Extension of the GIF89
standard, since I did not have any example input files containing them.
.SH "SEE ALSO"
ppmtogif(1), ppm(5)
.SH AUTHOR
Copyright (c) 1990 by David Koblas ([email protected])
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted,
.\" provided that the above copyright notice appear in all copies and that
.\" both that copyright notice and this permission notice appear in
.\" supporting documentation.
ppmmake.cZu`
ppmtoicr.1Nua ppmtopict.1»Ov~ ppmtopuzz.1Z“v
ximtoppm.1”v€
ximtoppm.c•v
ppmtoxpm.c–v‚
xpmtoppm.c®vƒ ppmtopuzz.c
v„
qrttoppm.1
v…
qrttoppm.cv†
tgatoppm.c
v‡
ppmtopi1.c vˆ
spctoppm.c v‰
sputoppm.c vŠpbmplus05oct91/ppm/rgb3toppm.c 444 3010 34 4757 5032725234 11521 /* rgb3toppm - combine three portable graymaps into one portable pixmap
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* rfd;
FILE* gfd;
FILE* bfd;
gray* rrow;
gray* rP;
gray* grow;
gray* gP;
gray* brow;
gray* bP;
pixel* pixelrow;
register pixel* pP;
int rows, cols, trows, tcols, row, col;
gray rmaxval, gmaxval, bmaxval;
int rformat, gformat, bformat;
pixval pmaxval;

ppm_init( &argc, argv );

if ( argc != 4 )
pm_usage( " " );

rfd = pm_openr( argv[1] );
gfd = pm_openr( argv[2] );
bfd = pm_openr( argv[3] );

pgm_readpgminit( rfd, &cols, &rows, &rmaxval, &rformat );
pgm_readpgminit( gfd, &tcols, &trows, &gmaxval, &gformat );
if ( tcols != cols || trows != rows )
pm_error( "all three graymaps must be the same size" );
pgm_readpgminit( bfd, &tcols, &trows, &bmaxval, &bformat );
if ( tcols != cols || trows != rows )
pm_error( "all three graymaps must be the same size" );

pmaxval = rmaxval;
if ( gmaxval > pmaxval ) pmaxval = gmaxval;
if ( bmaxval > pmaxval ) pmaxval = bmaxval;
rrow = pgm_allocrow( cols );
grow = pgm_allocrow( cols );
brow = pgm_allocrow( cols );

ppm_writeppminit( stdout, cols, rows, pmaxval, 0 );
pixelrow = ppm_allocrow( cols );

for ( row = 0; row < rows; row++ )
{
pgm_readpgmrow( rfd, rrow, cols, rmaxval, rformat );
pgm_readpgmrow( gfd, grow, cols, gmaxval, gformat );
pgm_readpgmrow( bfd, brow, cols, bmaxval, bformat );

for ( col = 0, rP = rrow, gP = grow, bP = brow, pP = pixelrow;
col < cols;
++col, ++rP, ++gP, ++bP, ++pP )
{
if ( rmaxval != pmaxval ) *rP = (int) *rP * pmaxval / rmaxval;
if ( gmaxval != pmaxval ) *gP = (int) *gP * pmaxval / gmaxval;
if ( bmaxval != pmaxval ) *bP = (int) *bP * pmaxval / bmaxval;
PPM_ASSIGN( *pP, *rP, *gP, *bP );
}
ppm_writeppmrow( stdout, pixelrow, cols, pmaxval, 0 );
}

pm_close( rfd );
pm_close( gfd );
pm_close( bfd );

exit( 0 );
}
cmap[j].cixel;
pbmplus05oct91/ppm/ilbmtoppm.1 444 3010 34 1427 5022776500 11515 .TH ilbmtoppm 1 "30 March 1989"
.IX ilbmtoppm
.SH NAME
ilbmtoppm - convert IFF ILBM file into a portable pixmap
.SH SYNOPSIS
.B ilbmtoppm
.RI [ ilbmfile ]
.SH DESCRIPTION
Reads an IFF ILBM file as input.
.IX IFF
.IX ILBM
Produces a portable pixmap as output.
Handles the Amiga's HAM and EXTRA_HALFBRIGHT modes.
.IX Amiga
.IX HAM
.SH "SEE ALSO"
ppm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
1Z{s]
pi1toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/ppmtogif.1 444 3010 34 2212 5022777301 11330 .TH ppmtogif 1 "01 September 1989"
.IX ppmtogif
.SH NAME
ppmtogif - convert a portable pixmap into a GIF file
.SH SYNOPSIS
.B ppmtogif
.RB [ -interlace ]
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Produces a GIF file as output.
.IX GIF
.SH OPTIONS
.TP
.B -interlace
Tells the program to produce an interlaced GIF file.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH "SEE ALSO"
giftoppm(1), ppm(5)
.SH AUTHOR
Based on GIFENCOD by David Rowley .
Lempel-Ziv compression based on "compress".

Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
.\"
.\" The Graphics Interchange Format(c) is the Copyright property of
.\" CompuServe Incorporated. GIF(sm) is a Service Mark property of
.\" CompuServe Incorporated.

sputoppm.1hu]
spctoppm.1u^
ppmquantall.1Zu_ ppmmake.cZu`
ppmtoicr.1Nua ppmtopict.1»Ov~ ppmtopuzz.1Z“v
ximtoppm.1”v€
ximtoppm.c•v
ppmtoxpm.c–v‚
xpmtoppm.c®vƒ ppmtopuzz.c
v„
qrttoppm.1
v…
qrttoppm.cv†
tgatoppm.c
v‡
ppmtopi1.c vˆ
spctoppm.c v‰
sputoppm.c vŠpbmplus05oct91/ppm/imgtoppm.1 444 3010 34 1615 5022776514 11352 .TH imgtoppm 1 "05 September 1989"
.IX imgtoppm
.SH NAME
imgtoppm - convert an Img-whatnot file into a portable pixmap
.SH SYNOPSIS
.B imgtoppm
.RI [ imgfile ]
.SH DESCRIPTION
Reads an Img-whatnot file as input.
Produces a portable pixmap as output.
The Img-whatnot toolkit is available for FTP on venera.isi.edu,
along with numerous images in this format.
.IX Img-whatnot
.SH "SEE ALSO"
ppm(5)
.SH AUTHOR
Based on a simple conversion program posted to comp.graphics by Ed Falk.

Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
oppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/tga.h 444 3010 34 2620 4476610520 10351 /* tga.h - header file for Targa files
*/

/* Header definition. */
struct ImageHeader {
unsigned char IDLength; /* length of Identifier String */
unsigned char CoMapType; /* 0 = no map */
unsigned char ImgType; /* image type (see below for values) */
unsigned char Index_lo, Index_hi; /* index of first color map entry */
unsigned char Length_lo, Length_hi; /* number of entries in color map */
unsigned char CoSize; /* size of color map entry (15,16,24,32) */
unsigned char X_org_lo, X_org_hi; /* x origin of image */
unsigned char Y_org_lo, Y_org_hi; /* y origin of image */
unsigned char Width_lo, Width_hi; /* width of image */
unsigned char Height_lo, Height_hi; /* height of image */
unsigned char PixelSize; /* pixel size (8,16,24,32) */
unsigned char AttBits; /* 4 bits, number of attribute bits per pixel */
unsigned char Rsrvd; /* 1 bit, reserved */
unsigned char OrgBit; /* 1 bit, origin: 0=lower left, 1=upper left */
unsigned char IntrLve; /* 2 bits, interleaving flag */
};

typedef char ImageIDField[256];

/* Definitions for image types. */
#define TGA_Null 0
#define TGA_Map 1
#define TGA_RGB 2
#define TGA_Mono 3
#define TGA_RLEMap 9
#define TGA_RLERGB 10
#define TGA_RLEMono 11
#define TGA_CompMap 32
#define TGA_CompMap4 33

/* Definitions for interleave flag. */
#define TGA_IL_None 0
#define TGA_IL_Two 1
#define TGA_IL_Four 2
oppm.1
v…
qrttoppm.cv†
tgatoppm.c
v‡
ppmtopi1.c vˆ
spctoppm.c v‰
sputoppm.c vŠpbmplus05oct91/ppm/ppmtoilbm.1 444 3010 34 1667 5022777432 11530 .TH ppmtoilbm 1 "07 September 1989"
.IX ppmtoilbm
.SH NAME
ppmtoilbm - convert a portable pixmap into an IFF ILBM file
.SH SYNOPSIS
.B ppmtoilbm
.RB [ -hamif ]
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Produces an IFF ILBM file as output.
.IX IFF
.IX ILBM
.SH OPTIONS
.TP
.B -hamif
If the pixmap won't fit into the Amiga's
maximum of 5 planes, a HAM file is written.
.IX Amiga
.IX HAM
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH "SEE ALSO"
ilbmtoppm(1), ppm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/mtvtoppm.1 444 3010 34 1516 5022776552 11406 .TH mtvtoppm 1 "02 February 1989"
.IX mtvtoppm
.SH NAME
mtvtoppm - convert output from the MTV or PRT ray tracers into a portable pixmap
.SH SYNOPSIS
.B mtvtoppm
.RI [ mtvfile ]
.SH DESCRIPTION
Reads an input file from Mark VanDeWettering's MTV ray tracer.
.IX "MTV raytracer"
Produces a portable pixmap as output.
.PP
The PRT raytracer also produces this format.
.IX "PRT raytracer"
.SH "SEE ALSO"
ppm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
mtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/libppm4.c 444 3010 34 20100 5073527426 11157 /* libppm4.c - ppm utility library part 4
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

static void
canonstr( str )
char* str;
{
while ( *str != '\0' )
{
if ( *str == ' ' )
{
(void) strcpy( str, &(str[1]) );
continue;
}
if ( isupper( *str ) )
*str = tolower( *str );
++str;
}
}

static long
rgbnorm( rgb, lmaxval, n, colorname )
long rgb, lmaxval;
int n;
char* colorname;
{
switch ( n )
{
case 1:
if ( lmaxval != 15 )
rgb = rgb * lmaxval / 15;
break;
case 2:
if ( lmaxval != 255 )
rgb = rgb * lmaxval / 255;
break;
case 3:
if ( lmaxval != 4095 )
rgb = rgb * lmaxval / 4095;
break;
case 4:
if ( lmaxval != 65535L )
rgb = rgb * lmaxval / 65535L;
break;
default:
pm_error( "invalid color specifier - \"%s\"", colorname );
}
return rgb;
}

#if __STDC__
pixel
ppm_parsecolor( char* colorname, pixval maxval )
#else /*__STDC__*/
pixel
ppm_parsecolor( colorname, maxval )
char* colorname;
pixval maxval;
#endif /*__STDC__*/
{
int hexit[256], i;
pixel p;
long lmaxval, r, g, b;
char* inval = "invalid color specifier - \"%s\"";

for ( i = 0; i < 256; ++i )
hexit[i] = 1234567890;
hexit['0'] = 0;
hexit['1'] = 1;
hexit['2'] = 2;
hexit['3'] = 3;
hexit['4'] = 4;
hexit['5'] = 5;
hexit['6'] = 6;
hexit['7'] = 7;
hexit['8'] = 8;
hexit['9'] = 9;
hexit['a'] = hexit['A'] = 10;
hexit['b'] = hexit['B'] = 11;
hexit['c'] = hexit['C'] = 12;
hexit['d'] = hexit['D'] = 13;
hexit['e'] = hexit['E'] = 14;
hexit['f'] = hexit['F'] = 15;

lmaxval = maxval;
if ( strncmp( colorname, "rgb:", 4 ) == 0 )
{
/* It's a new-X11-style hexadecimal rgb specifier. */
char* cp;

cp = colorname + 4;
r = g = b = 0;
for ( i = 0; *cp != '/'; ++i, ++cp )
r = r * 16 + hexit[*cp];
r = rgbnorm( r, lmaxval, i, colorname );
for ( i = 0, ++cp; *cp != '/'; ++i, ++cp )
g = g * 16 + hexit[*cp];
g = rgbnorm( g, lmaxval, i, colorname );
for ( i = 0, ++cp; *cp != '\0'; ++i, ++cp )
b = b * 16 + hexit[*cp];
b = rgbnorm( b, lmaxval, i, colorname );
if ( r < 0 || r > lmaxval || g < 0 || g > lmaxval || b < 0 || b > lmaxval )
pm_error( inval, colorname );
}
else if ( strncmp( colorname, "rgbi:", 5 ) == 0 )
{
/* It's a new-X11-style decimal/float rgb specifier. */
float fr, fg, fb;

if ( sscanf( colorname, "rgbi:%f/%f/%f", &fr, &fg, &fb ) != 3 )
pm_error( inval, colorname );
if ( fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 || fb < 0.0 || fb > 1.0 )
pm_error( "invalid color specifier - \"%s\" - values must be between 0.0 and 1.0", colorname );
r = fr * lmaxval;
g = fg * lmaxval;
b = fb * lmaxval;
}
else if ( colorname[0] == '#' )
{
/* It's an old-X11-style hexadecimal rgb specifier. */
switch ( strlen( colorname ) )
{
case 4:
r = hexit[colorname[1]];
g = hexit[colorname[2]];
b = hexit[colorname[3]];
r = rgbnorm( r, lmaxval, 1, colorname );
g = rgbnorm( g, lmaxval, 1, colorname );
b = rgbnorm( b, lmaxval, 1, colorname );
break;

case 7:
r = ( hexit[colorname[1]] << 4 ) + hexit[colorname[2]];
g = ( hexit[colorname[3]] << 4 ) + hexit[colorname[4]];
b = ( hexit[colorname[5]] << 4 ) + hexit[colorname[6]];
r = rgbnorm( r, lmaxval, 2, colorname );
g = rgbnorm( g, lmaxval, 2, colorname );
b = rgbnorm( b, lmaxval, 2, colorname );
break;

case 10:
r = ( hexit[colorname[1]] << 8 ) + ( hexit[colorname[2]] << 4 ) +
hexit[colorname[3]];
g = ( hexit[colorname[4]] << 8 ) + ( hexit[colorname[5]] << 4 ) +
hexit[colorname[6]];
b = ( hexit[colorname[7]] << 8 ) + ( hexit[colorname[8]] << 4 ) +
hexit[colorname[9]];
r = rgbnorm( r, lmaxval, 3, colorname );
g = rgbnorm( g, lmaxval, 3, colorname );
b = rgbnorm( b, lmaxval, 3, colorname );
break;

case 13:
r = ( hexit[colorname[1]] << 12 ) + ( hexit[colorname[2]] << 8 ) +
( hexit[colorname[3]] << 4 ) + hexit[colorname[4]];
g = ( hexit[colorname[5]] << 12 ) + ( hexit[colorname[6]] << 8 ) +
( hexit[colorname[7]] << 4 ) + hexit[colorname[8]];
b = ( hexit[colorname[9]] << 12 ) + ( hexit[colorname[10]] << 8 ) +
( hexit[colorname[11]] << 4 ) + hexit[colorname[12]];
r = rgbnorm( r, lmaxval, 4, colorname );
g = rgbnorm( g, lmaxval, 4, colorname );
b = rgbnorm( b, lmaxval, 4, colorname );
break;

default:
pm_error( inval, colorname );
}
if ( r < 0 || r > lmaxval || g < 0 || g > lmaxval || b < 0 || b > lmaxval )
pm_error( inval, colorname );
}
else if ( ( colorname[0] >= '0' && colorname[0] <= '9' ) ||
colorname[0] == '.' )
{
/* It's an old-style decimal/float rgb specifier. */
float fr, fg, fb;

if ( sscanf( colorname, "%f,%f,%f", &fr, &fg, &fb ) != 3 )
pm_error( inval, colorname );
if ( fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 || fb < 0.0 || fb > 1.0 )
pm_error( "invalid color specifier - \"%s\" - values must be between 0.0 and 1.0", colorname );
r = fr * lmaxval;
g = fg * lmaxval;
b = fb * lmaxval;
}
else
{
/* Must be a name from the X-style rgb file. */
#ifndef RGB_DB
pm_error( "color names database required - please reconfigure with RGBDEF" );
#else /*RGB_DB*/
FILE* f;
char buf1[200], buf2[200];

if ( ( f = fopen( RGB_DB, "r" ) ) == NULL )
pm_error( "can't open color names database - reconfigure with correct RGBDEF" );
canonstr( colorname );
while ( fgets( buf1, sizeof(buf1), f ) != NULL )
{
if ( sscanf( buf1, "%ld %ld %ld %[^\n]", &r, &g, &b, buf2 ) != 4 )
{
pm_message(
"can't parse color names database line - \"%s\"", buf1 );
continue;
}
canonstr( buf2 );
if ( strcmp( colorname, buf2 ) == 0 )
goto gotit;
}
(void) fclose( f );
pm_error( "unknown color - \"%s\"", colorname );

gotit:
(void) fclose( f );
/* Rescale from [0..255] if necessary. */
if ( lmaxval != 255 )
{
r = r * lmaxval / 255;
g = g * lmaxval / 255;
b = b * lmaxval / 255;
}
#endif /*RGB_DB*/
}

PPM_ASSIGN( p, r, g, b );
return p;
}

static char colorname[200];

#if __STDC__
char*
ppm_colorname( pixel* colorP, pixval maxval, int hexok )
#else /*__STDC__*/
char*
ppm_colorname( colorP, maxval, hexok )
pixel* colorP;
pixval maxval;
int hexok;
#endif /*__STDC__*/
{
int r, g, b;
#ifdef RGB_DB
FILE* f;
char buf[200];
int this_r, this_g, this_b;
int best_diff, this_diff;
char this_colorname[200];
#endif /*RGB_DB*/

if ( maxval == 255 )
{
r = PPM_GETR( *colorP );
g = PPM_GETG( *colorP );
b = PPM_GETB( *colorP );
}
else
{
r = (int) PPM_GETR( *colorP ) * 255 / (int) maxval;
g = (int) PPM_GETG( *colorP ) * 255 / (int) maxval;
b = (int) PPM_GETB( *colorP ) * 255 / (int) maxval;
}

#ifdef RGB_DB
if ( ( f = fopen( RGB_DB, "r" ) ) == NULL )
pm_error( "can't open color names database - reconfigure with correct RGBDEF" );
best_diff = 32767;
while ( fgets( buf, sizeof(buf), f ) != NULL )
{
if ( sscanf( buf, "%d %d %d %[^\n]", &this_r, &this_g, &this_b,
this_colorname ) != 4 )
{
pm_message(
"can't parse color names database line - \"%s\"",
buf );
continue;
}
this_diff = abs( r - this_r ) + abs( g - this_g ) + abs( b - this_b );
if ( this_diff < best_diff )
{
best_diff = this_diff;
(void) strcpy( colorname, this_colorname );
}
}
(void) fclose( f );
if ( best_diff != 32767 && ( best_diff == 0 || ! hexok ) )
return colorname;
#endif /*RGB_DB*/

/* Color lookup failed; generate an X11-style hex specifier. */
if ( ! hexok )
pm_error(
"color names database required - please reconfigure with RGBDEF" );
sprintf( colorname, "#%02x%02x%02x", r, g, b );
return colorname;
}
if ( *str == ' ' )
{
(void) strcpy( str, &(str[1]) );
continue;
}
if ( isupper( *str ) )
*str = tolower( *str );
++str;
}
}

static long
rgbnorm( rgb, lmaxval, n, colorname )
long rgb, lmaxval;
int n;
char* colorname;
{
switch ( n )
{
case 1:
if ( lmaxval != 15 )
rgb = rgb * lmaxval / 15;
break;
case 2:
if ( lmaxval != 255 )
rgb = rgb * lmaxval / 255;
break;
case 3:
if ( lmapbmplus05oct91/ppm/libppm.3 444 3010 34 11017 4755037332 11020 .TH libppm 3
.SH NAME
libppm - functions to support portable pixmap programs
.SH SYNOPSIS
.de Ss
.sp
.ft CW
.nf
..
.de Se
.fi
.ft P
.sp
..
.Ss
#include
cc ... libppm.a libpgm.a libpbm.a
.Se
.SH DESCRIPTION
.SS TYPES AND CONSTANTS
.Ss
typedef ... pixel;
typedef ... pixval;
#define PPM_MAXMAXVAL ...
extern pixval ppm_pbmmaxval;
.Se
Each
.BR pixel
contains three
.BR pixval s,
each of which should contain only the values between
.BR 0
and
.BR PPM_MAXMAXVAL .
.BR ppm_pbmmaxval
is the maxval used when a PPM program reads a PBM file.
Normally it is 1; however, for some programs, a larger value gives better
results.
.Ss
#define PPM_FORMAT ...
#define RPPM_FORMAT ...
#define PPM_TYPE PPM_FORMAT
int PPM_FORMAT_TYPE( int format )
.Se
For distinguishing different file formats and types.
.Ss
pixval PPM_GETR( pixel p )
pixval PPM_GETG( pixel p )
pixval PPM_GETB( pixel p )
.Se
These three macros retrieve the red, green or blue value from the given
pixel.
.Ss
void PPM_ASSIGN( pixel p, pixval red, pixval grn, pixval blu )
.Se
This macro assigns the given red, green and blue values to the pixel.
.Ss
int PPM_EQUAL( pixel p, pixel q )
.Se
This macro checks two pixels for equality.
.Ss
void PPM_DEPTH( pixel newp, pixel p, pixval oldmaxval, pixval newmaxval )
.Se
This macro scales the colors of pixel
.BR p
according the old and new maximum values and assigns the new values to
.BR newp .
It is intended to make writing ppmtowhatever easier.
.Ss
float PPM_LUMIN( pixel p )
.Se
This macro determines the luminance of the pixel
.BR p .
.SS MEMORY MANAGEMENT
.Ss
pixel** ppm_allocarray( int cols, int rows )
.Se
Allocate an array of pixels.
.Ss
pixel* ppm_allocrow( int cols )
.Se
Allocate a row of the given number of pixels.
.Ss
void ppm_freearray( pixel** pixels, int rows )
.Se
Free the array allocated with
.BR ppm_allocarray()
containing the given number
of rows.
.Ss
void pbm_freerow( pixel* pixelrow )
.Se
Free a row of pixels.
.SS READING PBM FILES
.Ss
void ppm_readppminit( FILE* fp, int* colsP, int* rowsP, pixval* maxvalP, int* formatP )
.Se
Read the header from a PPM file, filling in the rows, cols, maxval and format
variables.
.Ss
void ppm_readppmrow( FILE* fp, pixel* pixelrow, int cols, pixval maxval, int format )
.Se
Read a row of pixels into the pixelrow array.
Format, cols, and maxval were filled in by
.BR ppm_readppminit() .
.Ss
pixel** ppm_readppm( FILE* fp, int* colsP, int* rowsP, pixval* maxvalP )
.Se
Read an entire pixmap file into memory, returning the allocated array and
filling in the rows, cols and maxval variables.
This function combines
.BR ppm_readppminit() ,
.BR ppm_allocarray()
and
.BR ppm_readppmrow() .
.SS WRITING FILES
.Ss
void ppm_writeppminit( FILE* fp, int cols, int rows, pixval maxval, int forceplain )
.Se
Write the header for a portable pixmap file.
The forceplain flag forces a plain-format file to be written, as opposed
to a raw-format one.
.Ss
void ppm_writeppmrow( FILE* fp, pixel* pixelrow, int cols, pixval maxval, int forceplain )
.Se
Write a row from a portable pixmap.
.Ss
void ppm_writeppm( FILE* fp, pixel** pixels, int cols, int rows, pixval maxval, int forceplain )
.Se
Write the header and all data for a portable pixmap.
This function combines
.BR ppm_writeppminit()
and
.BR ppm_writeppmrow() .
.SS COLOR NAMES
.Ss
pixel ppm_parsecolor( char* colorname, pixval maxval )
.Se
Parses an ASCII color name into a pixel.
The color can be specified in three ways. One, as a name, assuming
that a pointer to an X11-style color names file was compiled in. Two,
as an X11-style hexadecimal number: #rgb, #rrggbb, #rrrgggbbb, or
#rrrrggggbbbb. Three, as a triplet of decimal floating point numbers
separated by commas: r.r,g.g,b.b.
.Ss
char* ppm_colorname( pixel* colorP, pixval maxval, int hexok )
.Se
Returns a pointer to a string describing the given color.
If the X11 color names file is available and the color appears in
it, that name is returned.
Otherwise, if the hexok flag is true then a hexadecimal colorspec
is returned; if hexok is false and the X11 color names file is
available, then the closest matching color is returned;
otherwise, it's an error.
.SH "SEE ALSO"
pbm(3), pgm(3)
.SH AUTHOR
Copyright (C) 1989, 1991 by Tony Hansen and Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
( hexit[colorname[10]] << 8 ) +
( hexit[colorname[11]] << 4 ) + hexit[colorname[12]];
r = rgbnorm( r, lmaxval, 4, colorname );
g = rgbnorm( g, lmaxval, 4, colorname );
b = rgbnorm( b, lmaxval, 4, colorname );
break;

default:
pm_error( inval, colorname );
}
if ( r < 0 || r > lmaxval || g < 0 || g > lmaxval || b < 0 || b > lmaxval )
pm_error( inval, colorname );
}
else if ( ( colorname[0] >= '0' && colorname[0] <= '9' ) ||
colorname[0] ==pbmplus05oct91/ppm/ppmcmap.h 444 3010 34 2537 4756403273 11250 /* ppmcmap.h - header file for colormap routines in libppm
*/

/* Color histogram stuff. */

typedef struct colorhist_item* colorhist_vector;
struct colorhist_item
{
pixel color;
int value;
};

typedef struct colorhist_list_item* colorhist_list;
struct colorhist_list_item
{
struct colorhist_item ch;
colorhist_list next;
};

colorhist_vector ppm_computecolorhist ARGS(( pixel** pixels, int cols, int rows, int maxcolors, int* colorsP ));
/* Returns a colorhist *colorsP long (with space allocated for maxcolors. */

void ppm_addtocolorhist ARGS(( colorhist_vector chv, int* colorsP, int maxcolors, pixel* colorP, int value, int position ));

void ppm_freecolorhist ARGS(( colorhist_vector chv ));


/* Color hash table stuff. */

typedef colorhist_list* colorhash_table;

colorhash_table ppm_computecolorhash ARGS(( pixel** pixels, int cols, int rows, int maxcolors, int* colorsP ));

int
ppm_lookupcolor ARGS(( colorhash_table cht, pixel* colorP ));

colorhist_vector ppm_colorhashtocolorhist ARGS(( colorhash_table cht, int maxcolors ));
colorhash_table ppm_colorhisttocolorhash ARGS(( colorhist_vector chv, int colors ));

int ppm_addtocolorhash ARGS(( colorhash_table cht, pixel* colorP, int value ));
/* Returns -1 on failure. */

colorhash_table ppm_alloccolorhash ARGS(( void ));

void ppm_freecolorhash ARGS(( colorhash_table cht ));
};

colorhist_vector ppm_computecolorhist ARGS(( pixel** pixels, int cols, int rows, int maxcolors, int* colorsP ));
/* Returns a colorhist *colorsP long (witpbmplus05oct91/ppm/ppmhist.c 444 3010 34 3473 5067544654 11277 /* ppmhist.c - read a portable pixmap and compute a color histogram
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "ppmcmap.h"

#define MAXCOLORS 100000

static int
countcompare( ch1, ch2 )
colorhist_vector ch1, ch2;
{
return ch2->value - ch1->value;
}

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel** pixels;
colorhist_vector chv;
int argn, rows, cols, colors, i;
pixval maxval;
int countcompare();
char* usage = "[ppmfile]";

ppm_init( &argc, argv );

argn = 1;

if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
argn++;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pixels = ppm_readppm( ifp, &cols, &rows, &maxval );

pm_close( ifp );

chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
if ( chv == (colorhist_vector) 0 )
pm_error( "too many colors - try doing a ppmquant" );

/* Sort by count. */
qsort( (char*) chv, colors, sizeof(struct colorhist_item), countcompare );

/* And print the histogram. */
printf( " r g b \tlum\tcount\n" );
printf( "--- --- ---\t---\t-----\n" );
for ( i = 0; i < colors; i++ )
printf(
"%3d %3d %3d\t%d\t%d\n", PPM_GETR(chv[i].color),
PPM_GETG(chv[i].color), PPM_GETB(chv[i].color),
(int) ( PPM_LUMIN( chv[i].color ) + 0.5 ),
chv[i].value );

ppm_freecolorhist( chv );

exit( 0 );
}
v.1 v™ pjtoppm.1.cvš ppmdither.1c.cvÇ ppmtopj.1opvÈ pjtoppm.cuwvÊ ppmdither.ciconvö ppmtopj.c
v÷
ppmtotga.c vø
ppmtotga.1 vù ppmtosixel.1 pbmplus05oct91/ppm/ppmquant.1 444 3010 34 4376 5070471053 11363 .TH ppmquant 1 "12 January 1991"
.IX ppmquant
.SH NAME
ppmquant - quantize the colors in a portable pixmap down to a specified number
.SH SYNOPSIS
.B ppmquant
.RB [ -floyd | -fs ]
.I ncolors
.RI [ ppmfile ]
.br
.B ppmquant
.RB [ -floyd | -fs ]
.B -map
.I mapfile
.RI [ ppmfile ]
.fi
.SH DESCRIPTION
Reads a portable pixmap as input.
Chooses
.I ncolors
colors to best represent the image, maps the existing colors
to the new ones, and writes a portable pixmap as output.
.IX "colormap reduction"
.PP
The quantization method is Heckbert's "median cut".
.IX "median cut"
.PP
Alternately, you can skip the color-choosing step by
specifying your own set of colors with the
.B -map
flag. The
.I mapfile
is just a
.I ppm
file; it can be any shape, all that matters is the colors in it.
For instance, to quantize down to the 8-color IBM TTL color set, you
might use:
.nf
P3
8 1
255
0 0 0
255 0 0
0 255 0
0 0 255
255 255 0
255 0 255
0 255 255
255 255 255
.fi
If you want to quantize one pixmap to use the colors in another one,
just use the second one as the mapfile.
You don't have to reduce it down to only one pixel of each color,
just use it as is.
.PP
The
.BR -floyd / -fs
flag enables a Floyd-Steinberg error diffusion step.
.IX Floyd-Steinberg
.IX "error diffusion"
Floyd-Steinberg gives vastly better results on images where the unmodified
quantization has banding or other artifacts, especially when going to a
small number of colors such as the above IBM set.
However, it does take substantially more CPU time, so the default is off.
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH REFERENCES
"Color Image Quantization for Frame Buffer Display" by Paul Heckbert,
SIGGRAPH '82 Proceedings, page 297.
.SH "SEE ALSO"
ppmquantall(1), pnmdepth(1), ppmdither(1), ppm(5)
.SH AUTHOR
Copyright (C) 1989, 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
nd maxval were filled in by
.BR ppm_readppminit() .
.Ss
pixel** ppm_readppm( FILE* fp, int* colsP, int* rowsP, pixval* maxvalP )
.Se
Read an entire pixmap file into memory, returning the allocated array and
filling in the rows, cols and maxval variables.
Thipbmplus05oct91/ppm/ppmhist.1 444 3010 34 1313 5022753547 11176 .TH ppmhist 1 "03 April 1989"
.IX ppmhist
.SH NAME
ppmhist - print a histogram of a portable pixmap
.SH SYNOPSIS
.B ppmhist
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Generates a histogram of the colors in the pixmap.
.SH "SEE ALSO"
ppm(5), pgmhist(1)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
Y
pgmtoppm.1esZ
tgatoppm.1ks[
giftoppm.cds\ gouldtoppm.1Z{s]
pi1toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/yuvtoppm.1 444 3010 34 2132 5070566667 11425 .TH yuvtoppm 1 "25 March 91"
.IX yuvtoppm
.SH NAME
yuvtoppm - convert Abekas YUV bytes into a portable pixmap
.SH SYNOPSIS
.B yuvtoppm
.I width height
.RI [ imagedata ]
.SH DESCRIPTION
Reads raw Abekas YUV bytes as input.
.IX Abekas
Produces a portable pixmap as output.
The input file is just YUV bytes.
You have to specify the width and height on the command line,
since the program obviously can't get them from the file.
The maxval is assumed to be 255.
.SH "SEE ALSO"
ppmtoyuv(1), ppm(5)
.SH AUTHOR
Marc Boucher ,
based on Example Conversion Program, A60/A64 Digital Video Interface
Manual, page 69.
.PP
Copyright (C) 1991 by DHD PostImage Inc.
.PP
Copyright (C) 1987 by Abekas Video Systems Inc.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
ZŠu libppm3.c u
xpmtoppm.1Iu\
sputoppm.1hu]
spctoppm.1u^
ppmquantall.1Zu_ ppmmake.cZu`
ppmtoicr.1Nua ppmtopict.1»Ov~ ppmtopuzz.1Z“v
ximtoppm.1”v€
ximtoppm.c•v
ppmtoxpm.c–v‚
xpmtoppm.c®vƒ ppmtopuzz.c
v„
qrttoppm.1
v…
qrttoppm.cv†
tgatoppm.c
v‡
ppmtopi1.c vˆ
spctoppm.c v‰
sputoppm.c vŠpbmplus05oct91/ppm/pcxtoppm.1 444 3010 34 1311 5022776564 11366 .TH pcxtoppm 1 "9 April 1990"
.IX pcxtoppm
.SH NAME
pcxtoppm - convert a PCX file into a portable pixmap
.SH SYNOPSIS
.B pcxtoppm
.RI [ pcxfile ]
.SH DESCRIPTION
Reads a PCX file as input.
.IX PCX
Produces a portable pixmap as output.
.SH "SEE ALSO"
ppmtopcx(1), ppm(5)
.SH AUTHOR
Copyright (C) 1990 by Michael Davidson.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
sY
pgmtoppm.1esZ
tgatoppm.1ks[
giftoppm.cds\ gouldtoppm.1Z{s]
pi1toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/libppm5.c 444 3010 34 40302 5032725170 11155 /* libppm5.c - ppm utility library part 5
**
** This library module contains the ppmdraw routines.
**
** Copyright (C) 1989, 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "ppmdraw.h"

#define DDA_SCALE 8192

#if __STDC__
void
ppmd_point_drawproc( pixel** pixels, int cols, int rows, pixval maxval, int x, int y, char* clientdata )
#else /*__STDC__*/
void
ppmd_point_drawproc( pixels, cols, rows, maxval, x, y, clientdata )
pixel** pixels;
int cols, rows, x, y;
pixval maxval;
char* clientdata;
#endif /*__STDC__*/
{
if ( x >= 0 && x < cols && y >= 0 && y < rows )
pixels[y][x] = *( (pixel*) clientdata );
}


/* Simple fill routine. */

#if __STDC__
void
ppmd_filledrectangle( pixel** pixels, int cols, int rows, pixval maxval, int x, int y, int width, int height, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata )
#else /*__STDC__*/
void
ppmd_filledrectangle( pixels, cols, rows, maxval, x, y, width, height, drawprocP, clientdata )
pixel** pixels;
int cols, rows, x, y, width, height;
pixval maxval;
void (*drawprocP)();
char* clientdata;
#endif /*__STDC__*/
{
register int cx, cy, cwidth, cheight, col, row;

/* Clip. */
cx = x;
cy = y;
cwidth = width;
cheight = height;
if ( cx < 0 )
{
cx = 0;
cwidth += x;
}
if ( cy < 0 )
{
cy = 0;
cheight += y;
}
if ( cx + cwidth > cols )
cwidth = cols - cx;
if ( cy + cheight > rows )
cheight = rows - cy;

/* Draw. */
for ( row = cy; row < cy + cheight; ++row )
for ( col = cx; col < cx + cwidth; ++col )
if ( drawprocP == PPMD_NULLDRAWPROC )
pixels[row][col] = *( (pixel*) clientdata );
else
(*drawprocP)(
pixels, cols, rows, maxval, col, row, clientdata );
}


/* Outline drawing stuff. */

static int ppmd_linetype = PPMD_LINETYPE_NORMAL;

int
ppmd_setlinetype( type )
int type;
{
int old;

old = ppmd_linetype;
ppmd_linetype = type;
return old;
}

static int ppmd_lineclip = 1;

int
ppmd_setlineclip( clip )
int clip;
{
int old;

old = ppmd_lineclip;
ppmd_lineclip = clip;
return old;
}

#if __STDC__
void
ppmd_line( pixel** pixels, int cols, int rows, pixval maxval, int x0, int y0, int x1, int y1, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata )
#else /*__STDC__*/
void
ppmd_line( pixels, cols, rows, maxval, x0, y0, x1, y1, drawprocP, clientdata )
pixel** pixels;
int cols, rows, x0, y0, x1, y1;
pixval maxval;
void (*drawprocP)();
char* clientdata;
#endif /*__STDC__*/
{
register int cx0, cy0, cx1, cy1;

/* Special case zero-length lines. */
if ( x0 == x1 && y0 == y1 )
{
if ( ( ! ppmd_lineclip ) ||
( x0 >= 0 && x0 < cols && y0 >= 0 && y0 < rows ) )
if ( drawprocP == PPMD_NULLDRAWPROC )
ppmd_point_drawproc(
pixels, cols, rows, maxval, x0, y0, clientdata );
else
(*drawprocP)( pixels, cols, rows, maxval, x0, y0, clientdata );
return;
}

/* Clip. */
cx0 = x0;
cy0 = y0;
cx1 = x1;
cy1 = y1;
if ( ppmd_lineclip )
{
if ( cx0 < 0 )
{
if ( cx1 < 0 ) return;
cy0 = cy0 + ( cy1 - cy0 ) * ( -cx0 ) / ( cx1 - cx0 );
cx0 = 0;
}
else if ( cx0 >= cols )
{
if ( cx1 >= cols ) return;
cy0 = cy0 + ( cy1 - cy0 ) * ( cols - 1 - cx0 ) / ( cx1 - cx0 );
cx0 = cols - 1;
}
if ( cy0 < 0 )
{
if ( cy1 < 0 ) return;
cx0 = cx0 + ( cx1 - cx0 ) * ( -cy0 ) / ( cy1 - cy0 );
cy0 = 0;
}
else if ( cy0 >= rows )
{
if ( cy1 >= rows ) return;
cx0 = cx0 + ( cx1 - cx0 ) * ( rows - 1 - cy0 ) / ( cy1 - cy0 );
cy0 = rows - 1;
}
if ( cx1 < 0 )
{
cy1 = cy1 + ( cy0 - cy1 ) * ( -cx1 ) / ( cx0 - cx1 );
cx1 = 0;
}
else if ( cx1 >= cols )
{
cy1 = cy1 + ( cy0 - cy1 ) * ( cols - 1 - cx1 ) / ( cx0 - cx1 );
cx1 = cols - 1;
}
if ( cy1 < 0 )
{
cx1 = cx1 + ( cx0 - cx1 ) * ( -cy1 ) / ( cy0 - cy1 );
cy1 = 0;
}
else if ( cy1 >= rows )
{
cx1 = cx1 + ( cx0 - cx1 ) * ( rows - 1 - cy1 ) / ( cy0 - cy1 );
cy1 = rows - 1;
}

/* Check again for zero-length lines. */
if ( cx0 == cx1 && cy0 == cy1 )
{
if ( drawprocP == PPMD_NULLDRAWPROC )
ppmd_point_drawproc(
pixels, cols, rows, maxval, cx0, cy0, clientdata );
else
(*drawprocP)(
pixels, cols, rows, maxval, cx0, cy0, clientdata );
return;
}
}

/* Draw, using a simple DDA. */
if ( abs( cx1 - cx0 ) > abs( cy1 - cy0 ) )
{ /* Loop over X domain. */
register long dy, srow;
register int dx, col, row, prevrow;

if ( cx1 > cx0 )
dx = 1;
else
dx = -1;
dy = ( cy1 - cy0 ) * DDA_SCALE / abs( cx1 - cx0 );
prevrow = row = cy0;
srow = row * DDA_SCALE + DDA_SCALE / 2;
col = cx0;
for ( ; ; )
{
if ( ppmd_linetype == PPMD_LINETYPE_NODIAGS && row != prevrow )
{
if ( drawprocP == PPMD_NULLDRAWPROC )
pixels[prevrow][col] = *( (pixel*) clientdata );
else
(*drawprocP)(
pixels, cols, rows, maxval, col, prevrow, clientdata );
prevrow = row;
}
if ( drawprocP == PPMD_NULLDRAWPROC )
pixels[row][col] = *( (pixel*) clientdata );
else
(*drawprocP)(
pixels, cols, rows, maxval, col, row, clientdata );
if ( col == cx1 )
break;
srow += dy;
row = srow / DDA_SCALE;
col += dx;
}
}
else
{ /* Loop over Y domain. */
register long dx, scol;
register int dy, col, row, prevcol;

if ( cy1 > cy0 )
dy = 1;
else
dy = -1;
dx = ( cx1 - cx0 ) * DDA_SCALE / abs( cy1 - cy0 );
row = cy0;
prevcol = col = cx0;
scol = col * DDA_SCALE + DDA_SCALE / 2;
for ( ; ; )
{
if ( ppmd_linetype == PPMD_LINETYPE_NODIAGS && col != prevcol )
{
if ( drawprocP == PPMD_NULLDRAWPROC )
pixels[row][prevcol] = *( (pixel*) clientdata );
else
(*drawprocP)(
pixels, cols, rows, maxval, prevcol, row, clientdata );
prevcol = col;
}
if ( drawprocP == PPMD_NULLDRAWPROC )
pixels[row][col] = *( (pixel*) clientdata );
else
(*drawprocP)(
pixels, cols, rows, maxval, col, row, clientdata );
if ( row == cy1 )
break;
row += dy;
scol += dx;
col = scol / DDA_SCALE;
}
}
}

#define SPLINE_THRESH 3
#if __STDC__
void
ppmd_spline3( pixel** pixels, int cols, int rows, pixval maxval, int x0, int y0, int x1, int y1, int x2, int y2, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata )
#else /*__STDC__*/
void
ppmd_spline3( pixels, cols, rows, maxval, x0, y0, x1, y1, x2, y2, drawprocP, clientdata )
pixel** pixels;
int cols, rows, x0, y0, x1, y1, x2, y2;
pixval maxval;
void (*drawprocP)();
char* clientdata;
#endif /*__STDC__*/
{
register int xa, ya, xb, yb, xc, yc, xp, yp;

xa = ( x0 + x1 ) / 2;
ya = ( y0 + y1 ) / 2;
xc = ( x1 + x2 ) / 2;
yc = ( y1 + y2 ) / 2;
xb = ( xa + xc ) / 2;
yb = ( ya + yc ) / 2;

xp = ( x0 + xb ) / 2;
yp = ( y0 + yb ) / 2;
if ( abs( xa - xp ) + abs( ya - yp ) > SPLINE_THRESH )
ppmd_spline3(
pixels, cols, rows, maxval, x0, y0, xa, ya, xb, yb, drawprocP,
clientdata );
else
ppmd_line(
pixels, cols, rows, maxval, x0, y0, xb, yb, drawprocP, clientdata );

xp = ( x2 + xb ) / 2;
yp = ( y2 + yb ) / 2;
if ( abs( xc - xp ) + abs( yc - yp ) > SPLINE_THRESH )
ppmd_spline3(
pixels, cols, rows, maxval, xb, yb, xc, yc, x2, y2, drawprocP,
clientdata );
else
ppmd_line(
pixels, cols, rows, maxval, xb, yb, x2, y2, drawprocP, clientdata );
}

#if __STDC__
void
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)(pixel**, int, int, pixval, int, int, char*), char* clientdata )
#else /*__STDC__*/
void
ppmd_polyspline( pixels, cols, rows, maxval, x0, y0, nc, xc, yc, x1, y1, drawprocP, clientdata )
pixel** pixels;
int cols, rows, x0, y0, nc, x1, y1;
int* xc;
int* yc;
pixval maxval;
void (*drawprocP)();
char* clientdata;
#endif /*__STDC__*/
{
register int i, x, y, xn, yn;

x = x0;
y = y0;
for ( i = 0; i < nc - 1; ++i )
{
xn = ( xc[i] + xc[i + 1] ) / 2;
yn = ( yc[i] + yc[i + 1] ) / 2;
ppmd_spline3(
pixels, cols, rows, maxval, x, y, xc[i], yc[i], xn, yn, drawprocP,
clientdata );
x = xn;
y = yn;
}
ppmd_spline3(
pixels, cols, rows, maxval, x, y, xc[nc - 1], yc[nc - 1], x1, y1,
drawprocP, clientdata );
}

#if __STDC__
void
ppmd_circle( pixel** pixels, int cols, int rows, pixval maxval, int cx, int cy, int radius, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata )
#else /*__STDC__*/
void
ppmd_circle( pixels, cols, rows, maxval, cx, cy, radius, drawprocP, clientdata )
pixel** pixels;
int cols, rows, cx, cy, radius;
pixval maxval;
void (*drawprocP)();
char* clientdata;
#endif /*__STDC__*/
{
register int x0, y0, x, y, prevx, prevy, nopointsyet;
register long sx, sy, e;

x0 = x = radius;
y0 = y = 0;
sx = x * DDA_SCALE + DDA_SCALE / 2;
sy = y * DDA_SCALE + DDA_SCALE / 2;
e = DDA_SCALE / radius;
if ( drawprocP == PPMD_NULLDRAWPROC )
pixels[y + cy][x + cx] = *( (pixel*) clientdata );
else
(*drawprocP)( pixels, cols, rows, maxval, x + cx, y + cy, clientdata );
nopointsyet = 1;
do
{
prevx = x;
prevy = y;
sx += e * sy / DDA_SCALE;
sy -= e * sx / DDA_SCALE;
x = sx / DDA_SCALE;
y = sy / DDA_SCALE;
if ( x != prevx || y != prevy )
{
nopointsyet = 0;
if ( drawprocP == PPMD_NULLDRAWPROC )
pixels[y + cy][x + cx] = *( (pixel*) clientdata );
else
(*drawprocP)(
pixels, cols, rows, maxval, x + cx, y + cy, clientdata );
}
}
while ( nopointsyet || x != x0 || y != y0 );
}


/* Arbitrary fill stuff. */

typedef struct
{
short x;
short y;
short edge;
} coord;
typedef struct
{
int n;
int size;
int curedge;
int segstart;
int ydir;
int startydir;
coord* coords;
} fillobj;

#define SOME 1000

static int oldclip;

char*
ppmd_fill_init( )
{
fillobj* fh;

fh = (fillobj*) malloc( sizeof(fillobj) );
if ( fh == 0 )
pm_error( "out of memory allocating a fillhandle" );
fh->n = 0;
fh->coords = (coord*) malloc( SOME * sizeof(coord) );
if ( fh->coords == 0 )
pm_error( "out of memory allocating a fillhandle" );
fh->size = SOME;
fh->curedge = 0;

/* Turn off line clipping. */
oldclip = ppmd_setlineclip( 0 );

return (char*) fh;
}

#if __STDC__
void
ppmd_fill_drawproc( pixel** pixels, int cols, int rows, pixval maxval, int x, int y, char* clientdata )
#else /*__STDC__*/
void
ppmd_fill_drawproc( pixels, cols, rows, maxval, x, y, clientdata )
pixel** pixels;
int cols, rows, x, y;
pixval maxval;
char* clientdata;
#endif /*__STDC__*/
{
register fillobj* fh;
register coord* cp;
register coord* ocp;

fh = (fillobj*) clientdata;

if ( fh->n > 0 )
{
/* If these are the same coords we saved last time, don't bother. */
ocp = &(fh->coords[fh->n - 1]);
if ( x == ocp->x && y == ocp->y )
return;
}

/* Ok, these are new; check if there's room for two more coords. */
if ( fh->n + 1 >= fh->size )
{
fh->size += SOME;
fh->coords = (coord*) realloc(
(char*) fh->coords, fh->size * sizeof(coord) );
if ( fh->coords == 0 )
pm_error( "out of memory enlarging a fillhandle" );
}

/* Check for extremum and set the edge number. */
if ( fh->n == 0 )
{ /* Start first segment. */
fh->segstart = fh->n;
fh->ydir = 0;
fh->startydir = 0;
}
else
{
register int dx, dy;

dx = x - ocp->x;
dy = y - ocp->y;
if ( dx < -1 || dx > 1 || dy < -1 || dy > 1 )
{ /* Segment break. Close off old one. */
if ( fh->startydir != 0 && fh->ydir != 0 )
if ( fh->startydir == fh->ydir )
{ /* Oops, first edge and last edge are the same.
** Renumber the first edge in the old segment. */
register coord* fcp;
int oldedge;

fcp = &(fh->coords[fh->segstart]);
oldedge = fcp->edge;
for ( ; fcp->edge == oldedge; ++fcp )
fcp->edge = ocp->edge;
}
/* And start new segment. */
++(fh->curedge);
fh->segstart = fh->n;
fh->ydir = 0;
fh->startydir = 0;
}
else
{ /* Segment continues. */
if ( dy != 0 )
{
if ( fh->ydir != 0 && fh->ydir != dy )
{ /* Direction changed. Insert a fake coord, old
** position but new edge number. */
++(fh->curedge);
cp = &(fh->coords[fh->n]);
cp->x = ocp->x;
cp->y = ocp->y;
cp->edge = fh->curedge;
++(fh->n);
}
fh->ydir = dy;
if ( fh->startydir == 0 )
fh->startydir = dy;
}
}
}

/* Save this coord. */
cp = &(fh->coords[fh->n]);
cp->x = x;
cp->y = y;
cp->edge = fh->curedge;
++(fh->n);
}

static int
yx_compare( c1, c2 )
coord* c1;
coord* c2;
{
if ( c1->y > c2->y )
return 1;
if ( c1->y < c2->y )
return -1;
if ( c1->x > c2->x )
return 1;
if ( c1->x < c2->x )
return -1;
return 0;
}

#if __STDC__
void
ppmd_fill( pixel** pixels, int cols, int rows, pixval maxval, char* fillhandle, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata )
#else /*__STDC__*/
void
ppmd_fill( pixels, cols, rows, maxval, fillhandle, drawprocP, clientdata )
pixel** pixels;
int cols, rows;
pixval maxval;
char* fillhandle;
void (*drawprocP)();
char* clientdata;
#endif /*__STDC__*/
{
register fillobj* fh;
int pedge, eq;
register int i, leftside, edge, lx, rx, py;
register coord* cp;

fh = (fillobj*) fillhandle;

/* Close off final segment. */
if ( fh->n > 0 && fh->startydir != 0 && fh->ydir != 0 )
if ( fh->startydir == fh->ydir )
{ /* Oops, first edge and last edge are the same. */
register coord* fcp;
int lastedge, oldedge;

lastedge = fh->coords[fh->n - 1].edge;
fcp = &(fh->coords[fh->segstart]);
oldedge = fcp->edge;
for ( ; fcp->edge == oldedge; ++fcp )
fcp->edge = lastedge;
}

/* Restore clipping now. */
(void) ppmd_setlineclip( oldclip );

/* Sort the coords by Y, secondarily by X. */
qsort( (char*) fh->coords, fh->n, sizeof(coord), yx_compare );

/* Find equal coords with different edge numbers, and swap if necessary. */
edge = -1;
for ( i = 0; i < fh->n; ++i )
{
cp = &(fh->coords[i]);
if ( i > 1 && eq && cp->edge != edge && cp->edge == pedge )
{ /* Swap .-1 and .-2. */
coord t;

t = fh->coords[i-1];
fh->coords[i-1] = fh->coords[i-2];
fh->coords[i-2] = t;
}
if ( i > 0 )
{
if ( cp->x == lx && cp->y == py )
{
eq = 1;
if ( cp->edge != edge && cp->edge == pedge )
{ /* Swap . and .-1. */
coord t;

t = *cp;
*cp = fh->coords[i-1];
fh->coords[i-1] = t;
}
}
else
eq = 0;
}
lx = cp->x;
py = cp->y;
pedge = edge;
edge = cp->edge;
}

/* Ok, now run through the coords filling spans. */
for ( i = 0; i < fh->n; ++i )
{
cp = &(fh->coords[i]);
if ( i == 0 )
{
lx = rx = cp->x;
py = cp->y;
edge = cp->edge;
leftside = 1;
}
else
{
if ( cp->y != py )
{ /* Row changed. Emit old span and start a new one. */
ppmd_filledrectangle(
pixels, cols, rows, maxval, lx, py, rx - lx + 1, 1,
drawprocP, clientdata);
lx = rx = cp->x;
py = cp->y;
edge = cp->edge;
leftside = 1;
}
else
{
if ( cp->edge == edge )
{ /* Continuation of side. */
rx = cp->x;
}
else
{ /* Edge changed. Is it a span? */
if ( leftside )
{
rx = cp->x;
leftside = 0;
}
else
{ /* Got a span to fill. */
ppmd_filledrectangle(
pixels, cols, rows, maxval, lx, py, rx - lx + 1,
1, drawprocP, clientdata);
lx = rx = cp->x;
leftside = 1;
}
edge = cp->edge;
}
}
}
}

/* All done. Free up the fillhandle and leave. */
free( fh->coords );
free( fh );
}
ows, x0, y0, nc, x1, y1;
int* xc;
int* yc;
pixval maxval;
void (*drawprocP)();
char* clientdata;
#endif /*__STDC__*/
{
register int i, x, y, xn, yn;

x = x0;
y = y0;
for ( i = 0; i < nc - 1; ++i )
{
xn = ( xc[i] + xc[i + 1] ) / 2;
yn = ( yc[i] + yc[i + 1] ) / 2;
ppmd_splinepbmplus05oct91/ppm/ppmquant.c 444 3010 34 41441 5070744125 11462 /* ppmquant.c - quantize the colors in a pixmap down to a specified number
**
** Copyright (C) 1989, 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "ppmcmap.h"

#define MAXCOLORS 32767

/* #define LARGE_NORM */
#define LARGE_LUM

/* #define REP_CENTER_BOX */
/* #define REP_AVERAGE_COLORS */
#define REP_AVERAGE_PIXELS

typedef struct box* box_vector;
struct box
{
int ind;
int colors;
int sum;
};

static colorhist_vector mediancut ARGS(( colorhist_vector chv, int colors, int sum, pixval maxval, int newcolors ));
static int redcompare ARGS(( colorhist_vector ch1, colorhist_vector ch2 ));
static int greencompare ARGS(( colorhist_vector ch1, colorhist_vector ch2 ));
static int bluecompare ARGS(( colorhist_vector ch1, colorhist_vector ch2 ));
static int sumcompare ARGS(( box_vector b1, box_vector b2 ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel** pixels;
pixel** mappixels;
register pixel* pP;
int argn, rows, cols, maprows, mapcols, row;
register int col, limitcol;
pixval maxval, newmaxval, mapmaxval;
int newcolors, colors;
register int ind;
colorhist_vector chv, colormap;
colorhash_table cht;
int floyd;
int usehash;
long* thisrerr;
long* nextrerr;
long* thisgerr;
long* nextgerr;
long* thisberr;
long* nextberr;
long* temperr;
register long sr, sg, sb, err;
#define FS_SCALE 1024
int fs_direction;
char* usage = "[-floyd|-fs] [ppmfile]\n [-floyd|-fs] -map mapfile [ppmfile]";

ppm_init( &argc, argv );

argn = 1;
floyd = 0;
mappixels = (pixel**) 0;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-fs", 2 ) ||
pm_keymatch( argv[argn], "-floyd", 2 ) )
floyd = 1;
else if ( pm_keymatch( argv[argn], "-nofs", 2 ) ||
pm_keymatch( argv[argn], "-nofloyd", 2 ) )
floyd = 0;
else if ( pm_keymatch( argv[argn], "-map", 2 ) )
{
++argn;
if ( argn == argc )
pm_usage( usage );
ifp = pm_openr( argv[argn] );
mappixels = ppm_readppm( ifp, &mapcols, &maprows, &mapmaxval );
pm_close( ifp );
if ( mapcols == 0 || maprows == 0 )
pm_error( "null colormap??" );
}
else
pm_usage( usage );
++argn;
}

if ( mappixels == (pixel**) 0 )
{
if ( argn == argc )
pm_usage( usage );
if ( sscanf( argv[argn], "%d", &newcolors ) != 1 )
pm_usage( usage );
if ( newcolors <= 1 )
pm_error( "number of colors must be > 1" );
++argn;
}

if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

/*
** Step 1: read in the image.
*/
pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
pm_close( ifp );


if ( mappixels == (pixel**) 0 )
{
/*
** Step 2: attempt to make a histogram of the colors, unclustered.
** If at first we don't succeed, lower maxval to increase color
** coherence and try again. This will eventually terminate, with
** maxval at worst 15, since 32^3 is approximately MAXCOLORS.
*/
for ( ; ; )
{
pm_message( "making histogram..." );
chv = ppm_computecolorhist(
pixels, cols, rows, MAXCOLORS, &colors );
if ( chv != (colorhist_vector) 0 )
break;
pm_message( "too many colors!" );
newmaxval = maxval / 2;
pm_message(
"scaling colors from maxval=%d to maxval=%d to improve clustering...",
maxval, newmaxval );
for ( row = 0; row < rows; ++row )
for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
PPM_DEPTH( *pP, *pP, maxval, newmaxval );
maxval = newmaxval;
}
pm_message( "%d colors found", colors );

/*
** Step 3: apply median-cut to histogram, making the new colormap.
*/
pm_message( "choosing %d colors...", newcolors );
colormap = mediancut( chv, colors, rows * cols, maxval, newcolors );
ppm_freecolorhist( chv );
}
else
{
/*
** Alternate steps 2 & 3 : Turn mappixels into a colormap.
*/
if ( mapmaxval != maxval )
{
if ( mapmaxval > maxval )
pm_message( "rescaling colormap colors" );
for ( row = 0; row < maprows; ++row )
for ( col = 0, pP = mappixels[row]; col < mapcols; ++col, ++pP )
PPM_DEPTH( *pP, *pP, mapmaxval, maxval );
mapmaxval = maxval;
}
colormap = ppm_computecolorhist(
mappixels, mapcols, maprows, MAXCOLORS, &newcolors );
if ( colormap == (colorhist_vector) 0 )
pm_error( "too many colors in colormap!" );
ppm_freearray( mappixels, maprows );
pm_message( "%d colors found in colormap", newcolors );
}

/*
** Step 4: map the colors in the image to their closest match in the
** new colormap, and write 'em out.
*/
pm_message( "mapping image to new colors..." );
cht = ppm_alloccolorhash( );
usehash = 1;
ppm_writeppminit( stdout, cols, rows, maxval, 0 );
if ( floyd )
{
/* Initialize Floyd-Steinberg error vectors. */
thisrerr = (long*) pm_allocrow( cols + 2, sizeof(long) );
nextrerr = (long*) pm_allocrow( cols + 2, sizeof(long) );
thisgerr = (long*) pm_allocrow( cols + 2, sizeof(long) );
nextgerr = (long*) pm_allocrow( cols + 2, sizeof(long) );
thisberr = (long*) pm_allocrow( cols + 2, sizeof(long) );
nextberr = (long*) pm_allocrow( cols + 2, sizeof(long) );
srandom( (int) ( time( 0 ) ^ getpid( ) ) );
for ( col = 0; col < cols + 2; ++col )
{
thisrerr[col] = random( ) % ( FS_SCALE * 2 ) - FS_SCALE;
thisgerr[col] = random( ) % ( FS_SCALE * 2 ) - FS_SCALE;
thisberr[col] = random( ) % ( FS_SCALE * 2 ) - FS_SCALE;
/* (random errors in [-1 .. 1]) */
}
fs_direction = 1;
}
for ( row = 0; row < rows; ++row )
{
if ( floyd )
for ( col = 0; col < cols + 2; ++col )
nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
if ( ( ! floyd ) || fs_direction )
{
col = 0;
limitcol = cols;
pP = pixels[row];
}
else
{
col = cols - 1;
limitcol = -1;
pP = &(pixels[row][col]);
}
do
{
if ( floyd )
{
/* Use Floyd-Steinberg errors to adjust actual color. */
sr = PPM_GETR(*pP) + thisrerr[col + 1] / FS_SCALE;
sg = PPM_GETG(*pP) + thisgerr[col + 1] / FS_SCALE;
sb = PPM_GETB(*pP) + thisberr[col + 1] / FS_SCALE;
if ( sr < 0 ) sr = 0;
else if ( sr > maxval ) sr = maxval;
if ( sg < 0 ) sg = 0;
else if ( sg > maxval ) sg = maxval;
if ( sb < 0 ) sb = 0;
else if ( sb > maxval ) sb = maxval;
PPM_ASSIGN( *pP, sr, sg, sb );
}

/* Check hash table to see if we have already matched this color. */
ind = ppm_lookupcolor( cht, pP );
if ( ind == -1 )
{ /* No; search colormap for closest match. */
register int i, r1, g1, b1, r2, g2, b2;
register long dist, newdist;
r1 = PPM_GETR( *pP );
g1 = PPM_GETG( *pP );
b1 = PPM_GETB( *pP );
dist = 2000000000;
for ( i = 0; i < newcolors; ++i )
{
r2 = PPM_GETR( colormap[i].color );
g2 = PPM_GETG( colormap[i].color );
b2 = PPM_GETB( colormap[i].color );
newdist = ( r1 - r2 ) * ( r1 - r2 ) +
( g1 - g2 ) * ( g1 - g2 ) +
( b1 - b2 ) * ( b1 - b2 );
if ( newdist < dist )
{
ind = i;
dist = newdist;
}
}
if ( usehash )
{
if ( ppm_addtocolorhash( cht, pP, ind ) < 0 )
{
pm_message(
"out of memory adding to hash table, proceeding without it");
usehash = 0;
}
}
}

if ( floyd )
{
/* Propagate Floyd-Steinberg error terms. */
if ( fs_direction )
{
err = ( sr - (long) PPM_GETR( colormap[ind].color ) ) * FS_SCALE;
thisrerr[col + 2] += ( err * 7 ) / 16;
nextrerr[col ] += ( err * 3 ) / 16;
nextrerr[col + 1] += ( err * 5 ) / 16;
nextrerr[col + 2] += ( err ) / 16;
err = ( sg - (long) PPM_GETG( colormap[ind].color ) ) * FS_SCALE;
thisgerr[col + 2] += ( err * 7 ) / 16;
nextgerr[col ] += ( err * 3 ) / 16;
nextgerr[col + 1] += ( err * 5 ) / 16;
nextgerr[col + 2] += ( err ) / 16;
err = ( sb - (long) PPM_GETB( colormap[ind].color ) ) * FS_SCALE;
thisberr[col + 2] += ( err * 7 ) / 16;
nextberr[col ] += ( err * 3 ) / 16;
nextberr[col + 1] += ( err * 5 ) / 16;
nextberr[col + 2] += ( err ) / 16;
}
else
{
err = ( sr - (long) PPM_GETR( colormap[ind].color ) ) * FS_SCALE;
thisrerr[col ] += ( err * 7 ) / 16;
nextrerr[col + 2] += ( err * 3 ) / 16;
nextrerr[col + 1] += ( err * 5 ) / 16;
nextrerr[col ] += ( err ) / 16;
err = ( sg - (long) PPM_GETG( colormap[ind].color ) ) * FS_SCALE;
thisgerr[col ] += ( err * 7 ) / 16;
nextgerr[col + 2] += ( err * 3 ) / 16;
nextgerr[col + 1] += ( err * 5 ) / 16;
nextgerr[col ] += ( err ) / 16;
err = ( sb - (long) PPM_GETB( colormap[ind].color ) ) * FS_SCALE;
thisberr[col ] += ( err * 7 ) / 16;
nextberr[col + 2] += ( err * 3 ) / 16;
nextberr[col + 1] += ( err * 5 ) / 16;
nextberr[col ] += ( err ) / 16;
}
}

*pP = colormap[ind].color;

if ( ( ! floyd ) || fs_direction )
{
++col;
++pP;
}
else
{
--col;
--pP;
}
}
while ( col != limitcol );

if ( floyd )
{
temperr = thisrerr;
thisrerr = nextrerr;
nextrerr = temperr;
temperr = thisgerr;
thisgerr = nextgerr;
nextgerr = temperr;
temperr = thisberr;
thisberr = nextberr;
nextberr = temperr;
fs_direction = ! fs_direction;
}

ppm_writeppmrow( stdout, pixels[row], cols, maxval, 0 );
}

exit( 0 );
}

/*
** Here is the fun part, the median-cut colormap generator. This is based
** on Paul Heckbert's paper "Color Image Quantization for Frame Buffer
** Display", SIGGRAPH '82 Proceedings, page 297.
*/

#if __STDC__
static colorhist_vector
mediancut( colorhist_vector chv, int colors, int sum, pixval maxval, int newcolors )
#else /*__STDC__*/
static colorhist_vector
mediancut( chv, colors, sum, maxval, newcolors )
colorhist_vector chv;
int colors, sum, newcolors;
pixval maxval;
#endif /*__STDC__*/
{
colorhist_vector colormap;
box_vector bv;
register int bi, i;
int boxes;

bv = (box_vector) malloc( sizeof(struct box) * newcolors );
colormap =
(colorhist_vector) malloc( sizeof(struct colorhist_item) * newcolors );
if ( bv == (box_vector) 0 || colormap == (colorhist_vector) 0 )
pm_error( "out of memory" );
for ( i = 0; i < newcolors; ++i )
PPM_ASSIGN( colormap[i].color, 0, 0, 0 );

/*
** Set up the initial box.
*/
bv[0].ind = 0;
bv[0].colors = colors;
bv[0].sum = sum;
boxes = 1;

/*
** Main loop: split boxes until we have enough.
*/
while ( boxes < newcolors )
{
register int indx, clrs;
int sm;
register int minr, maxr, ming, maxg, minb, maxb, v;
int halfsum, lowersum;

/*
** Find the first splittable box.
*/
for ( bi = 0; bi < boxes; ++bi )
if ( bv[bi].colors >= 2 )
break;
if ( bi == boxes )
break; /* ran out of colors! */
indx = bv[bi].ind;
clrs = bv[bi].colors;
sm = bv[bi].sum;

/*
** Go through the box finding the minimum and maximum of each
** component - the boundaries of the box.
*/
minr = maxr = PPM_GETR( chv[indx].color );
ming = maxg = PPM_GETG( chv[indx].color );
minb = maxb = PPM_GETB( chv[indx].color );
for ( i = 1; i < clrs; ++i )
{
v = PPM_GETR( chv[indx + i].color );
if ( v < minr ) minr = v;
if ( v > maxr ) maxr = v;
v = PPM_GETG( chv[indx + i].color );
if ( v < ming ) ming = v;
if ( v > maxg ) maxg = v;
v = PPM_GETB( chv[indx + i].color );
if ( v < minb ) minb = v;
if ( v > maxb ) maxb = v;
}

/*
** Find the largest dimension, and sort by that component. I have
** included two methods for determining the "largest" dimension;
** first by simply comparing the range in RGB space, and second
** by transforming into luminosities before the comparison. You
** can switch which method is used by switching the commenting on
** the LARGE_ defines at the beginning of this source file.
*/
#ifdef LARGE_NORM
if ( maxr - minr >= maxg - ming && maxr - minr >= maxb - minb )
qsort(
(char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
redcompare );
else if ( maxg - ming >= maxb - minb )
qsort(
(char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
greencompare );
else
qsort(
(char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
bluecompare );
#endif /*LARGE_NORM*/
#ifdef LARGE_LUM
{
pixel p;
float rl, gl, bl;

PPM_ASSIGN(p, maxr - minr, 0, 0);
rl = PPM_LUMIN(p);
PPM_ASSIGN(p, 0, maxg - ming, 0);
gl = PPM_LUMIN(p);
PPM_ASSIGN(p, 0, 0, maxb - minb);
bl = PPM_LUMIN(p);

if ( rl >= gl && rl >= bl )
qsort(
(char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
redcompare );
else if ( gl >= bl )
qsort(
(char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
greencompare );
else
qsort(
(char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
bluecompare );
}
#endif /*LARGE_LUM*/

/*
** Now find the median based on the counts, so that about half the
** pixels (not colors, pixels) are in each subdivision.
*/
lowersum = chv[indx].value;
halfsum = sm / 2;
for ( i = 1; i < clrs - 1; ++i )
{
if ( lowersum >= halfsum )
break;
lowersum += chv[indx + i].value;
}

/*
** Split the box, and sort to bring the biggest boxes to the top.
*/
bv[bi].colors = i;
bv[bi].sum = lowersum;
bv[boxes].ind = indx + i;
bv[boxes].colors = clrs - i;
bv[boxes].sum = sm - lowersum;
++boxes;
qsort( (char*) bv, boxes, sizeof(struct box), sumcompare );
}

/*
** Ok, we've got enough boxes. Now choose a representative color for
** each box. There are a number of possible ways to make this choice.
** One would be to choose the center of the box; this ignores any structure
** within the boxes. Another method would be to average all the colors in
** the box - this is the method specified in Heckbert's paper. A third
** method is to average all the pixels in the box. You can switch which
** method is used by switching the commenting on the REP_ defines at
** the beginning of this source file.
*/
for ( bi = 0; bi < boxes; ++bi )
{
#ifdef REP_CENTER_BOX
register int indx = bv[bi].ind;
register int clrs = bv[bi].colors;
register int minr, maxr, ming, maxg, minb, maxb, v;

minr = maxr = PPM_GETR( chv[indx].color );
ming = maxg = PPM_GETG( chv[indx].color );
minb = maxb = PPM_GETB( chv[indx].color );
for ( i = 1; i < clrs; ++i )
{
v = PPM_GETR( chv[indx + i].color );
minr = min( minr, v );
maxr = max( maxr, v );
v = PPM_GETG( chv[indx + i].color );
ming = min( ming, v );
maxg = max( maxg, v );
v = PPM_GETB( chv[indx + i].color );
minb = min( minb, v );
maxb = max( maxb, v );
}
PPM_ASSIGN(
colormap[bi].color, ( minr + maxr ) / 2, ( ming + maxg ) / 2,
( minb + maxb ) / 2 );
#endif /*REP_CENTER_BOX*/
#ifdef REP_AVERAGE_COLORS
register int indx = bv[bi].ind;
register int clrs = bv[bi].colors;
register long r = 0, g = 0, b = 0;

for ( i = 0; i < clrs; ++i )
{
r += PPM_GETR( chv[indx + i].color );
g += PPM_GETG( chv[indx + i].color );
b += PPM_GETB( chv[indx + i].color );
}
r = r / clrs;
g = g / clrs;
b = b / clrs;
PPM_ASSIGN( colormap[bi].color, r, g, b );
#endif /*REP_AVERAGE_COLORS*/
#ifdef REP_AVERAGE_PIXELS
register int indx = bv[bi].ind;
register int clrs = bv[bi].colors;
register long r = 0, g = 0, b = 0, sum = 0;

for ( i = 0; i < clrs; ++i )
{
r += PPM_GETR( chv[indx + i].color ) * chv[indx + i].value;
g += PPM_GETG( chv[indx + i].color ) * chv[indx + i].value;
b += PPM_GETB( chv[indx + i].color ) * chv[indx + i].value;
sum += chv[indx + i].value;
}
r = r / sum;
if ( r > maxval ) r = maxval; /* avoid math errors */
g = g / sum;
if ( g > maxval ) g = maxval;
b = b / sum;
if ( b > maxval ) b = maxval;
PPM_ASSIGN( colormap[bi].color, r, g, b );
#endif /*REP_AVERAGE_PIXELS*/
}

/*
** All done.
*/
return colormap;
}

static int
redcompare( ch1, ch2 )
colorhist_vector ch1, ch2;
{
return (int) PPM_GETR( ch1->color ) - (int) PPM_GETR( ch2->color );
}

static int
greencompare( ch1, ch2 )
colorhist_vector ch1, ch2;
{
return (int) PPM_GETG( ch1->color ) - (int) PPM_GETG( ch2->color );
}

static int
bluecompare( ch1, ch2 )
colorhist_vector ch1, ch2;
{
return (int) PPM_GETB( ch1->color ) - (int) PPM_GETB( ch2->color );
}

static int
sumcompare( b1, b2 )
box_vector b1, b2;
{
return b2->sum - b1->sum;
}
lormap[ind].color ) ) * FS_SCALE;
thisgerr[col ] += ( err * 7 ) / 16;
nextgerr[col + 2] += ( err * 3 ) / 16;
nextgerr[col + 1] += ( err * 5 ) / 16;
nextgerr[col ] += ( err ) / 16;
errpbmplus05oct91/ppm/ilbm.h 444 3010 34 1270 4537105744 10526 /* ilbm.h - header file for IFF ILBM files
*/

#define RowBytes(cols) ( ( ( (cols) + 15 ) / 16 ) * 2 )

/* definitions for BMHD */

typedef struct
{
unsigned short w, h;
short x, y;
unsigned char nPlanes, masking, compression, pad1;
unsigned short transparentColor;
unsigned char xAspect, yAspect;
short pageWidth, pageHeight;
} BitMapHeader;

#define mskNone 0
#define mskHasMask 1
#define mskHasTransparentColor 2
#define mskLasso 3

#define cmpNone 0
#define cmpByteRun1 1

/* definitions for CMAP */

typedef struct
{
unsigned char r, g, b;
} ColorRegister;

/* definitions for CAMG */

#define vmEXTRA_HALFBRITE 0x80
#define vmHAM 0x800
ppmpat.1ogsY
pgmtoppm.1esZ
tgatoppm.1ks[
giftoppm.cds\ gouldtoppm.1Z{s]
pi1toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/ilbmtoppm.c 444 3010 34 24046 5070565412 11622 /* ilbmtoppm.c - read an IFF ILBM file and produce a portable pixmap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
**
** Modified by Mark Thompson on 10/4/90 to accomodate 24 bit IFF files
** as used by ASDG, NewTek, etc.
*/

#include "ppm.h"
#include "ilbm.h"

static void getfourchars ARGS(( FILE* f, char fourchars[4] ));
static unsigned char get_byte ARGS(( FILE* f ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel* pixelrow;
pixel* colormap = 0;
int argn, colors, i, j, r, g, b, byte, bytes;
short rows, cols = 0, row, col;
int maxval;
char iffid[5];
unsigned char* body = 0;
unsigned char* bp;
unsigned char* ubp;
unsigned char* rawrow;
unsigned char* runbuf;
unsigned char* Rrow;
unsigned char* Grow;
unsigned char* Brow;
long formsize, bytesread, chunksize, viewportmodes = 0;
int nPlanes, masking, compression, xAsp, yAsp, ham, hammask, allPlanes;

ppm_init( &argc, argv );

argn = 1;

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
argn++;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( "[ilbmfile]" );

/* Read in the ILBM file. */
iffid[4] = '\0';
getfourchars( ifp, iffid );
if ( strcmp( iffid, "FORM" ) != 0 )
pm_error( "input is not a FORM type IFF file" );
if ( pm_readbiglong( ifp, &formsize ) == -1 )
pm_error( "EOF / read error" );
getfourchars( ifp, iffid );
if ( strcmp( iffid, "ILBM" ) != 0 )
pm_error( "input is not an ILBM type FORM IFF file" );
bytesread = 12;

/* Main loop, parsing the IFF FORM. */
while ( bytesread < formsize )
{
getfourchars( ifp, iffid );
if ( pm_readbiglong( ifp, &chunksize ) == -1 )
pm_error( "EOF / read error" );
bytesread += 8;

if ( body != 0 )
{
pm_message(
"\"%s\" chunk found after BODY chunk - skipping", iffid );
for ( i = 0; i < chunksize; i++ )
(void) get_byte( ifp );
}
else if ( strcmp( iffid, "BMHD" ) == 0 )
{
short junk;
if ( pm_readbigshort( ifp, &cols ) == -1 )
pm_error( "EOF / read error" );
if ( pm_readbigshort( ifp, &rows ) == -1 )
pm_error( "EOF / read error" );
if ( pm_readbigshort( ifp, &junk ) == -1 )
pm_error( "EOF / read error" );
if ( pm_readbigshort( ifp, &junk ) == -1 )
pm_error( "EOF / read error" );
nPlanes = get_byte( ifp );
masking = get_byte( ifp );
compression = get_byte( ifp );
(void) get_byte( ifp ); /* pad1 */
if ( pm_readbigshort( ifp, &junk ) == -1 ) /* transparentColor */
pm_error( "EOF / read error" );
xAsp = get_byte( ifp );
yAsp = get_byte( ifp );
if ( pm_readbigshort( ifp, &junk ) == -1 ) /* pageWidth */
pm_error( "EOF / read error" );
if ( pm_readbigshort( ifp, &junk ) == -1 ) /* pageHeight */
pm_error( "EOF / read error" );
}
else if ( strcmp( iffid, "CMAP" ) == 0 )
{
colors = chunksize / 3;
if ( colors > 0 )
{
colormap = ppm_allocrow( colors );
for ( i = 0; i < colors; i++ )
{
r = get_byte( ifp );
g = get_byte( ifp );
b = get_byte( ifp );
PPM_ASSIGN( colormap[i], r, g, b );
}
if ( colors * 3 != chunksize )
(void) get_byte( ifp );
}
}
else if ( strcmp( iffid, "CAMG" ) == 0 )
{
if ( pm_readbiglong( ifp, &viewportmodes ) == -1 )
pm_error( "EOF / read error" );
}
else if ( strcmp( iffid, "BODY" ) == 0 )
{
body = (unsigned char*) malloc( chunksize );
if ( body == 0 )
pm_error( "out of memory" );
if ( fread( body, 1, chunksize, ifp ) != chunksize )
pm_error( "EOF / read error reading BODY chunk" );
}
else if ( strcmp( iffid, "GRAB" ) == 0 ||
strcmp( iffid, "DEST" ) == 0 ||
strcmp( iffid, "SPRT" ) == 0 ||
strcmp( iffid, "CRNG" ) == 0 ||
strcmp( iffid, "CCRT" ) == 0 ||
strcmp( iffid, "DPPV" ) == 0 )
{
for ( i = 0; i < chunksize; i++ )
(void) get_byte( ifp );
}
else
{
pm_message( "unknown chunk type \"%s\" - skipping", iffid );
for ( i = 0; i < chunksize; i++ )
(void) get_byte( ifp );
}

bytesread += chunksize;
}

pm_close( ifp );

/* Done reading. Now interpret what we got. */
if ( cols == 0 )
pm_error( "no BMHD chunk found" );
if ( body == 0 )
pm_error( "no BODY chunk found" );
if ( xAsp != yAsp )
pm_message(
"warning - non-square pixels; to fix do a 'pnmscale -%cscale %g'",
xAsp > yAsp ? 'x' : 'y',
xAsp > yAsp ? (float) xAsp / yAsp : (float) yAsp / xAsp );
if ( ( viewportmodes & vmHAM ) && nPlanes != 24 )
{
ham = 1;
hammask = ( 1 << ( nPlanes - 2 ) ) - 1;
maxval = pm_bitstomaxval( nPlanes - 2 );
if ( maxval > PPM_MAXMAXVAL )
pm_error(
"nPlanes is too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS" );
if ( colormap != 0 )
for ( i = 0; i < colors; i++ )
{
r = PPM_GETR( colormap[i] ) >> ( 10 - nPlanes );
g = PPM_GETG( colormap[i] ) >> ( 10 - nPlanes );
b = PPM_GETB( colormap[i] ) >> ( 10 - nPlanes );
PPM_ASSIGN( colormap[i], r, g, b );
}
}
else
{
ham = 0;
if ( colormap != 0 )
maxval = 255; /* colormap contains bytes */
else if ( nPlanes == 24 )
maxval = 255;
else
maxval = pm_bitstomaxval( nPlanes );
if ( maxval > PPM_MAXMAXVAL )
pm_error(
"nPlanes is too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS" );
}
if ( viewportmodes & vmEXTRA_HALFBRITE )
{
pixel* tempcolormap;

tempcolormap = ppm_allocrow( colors * 2 );
for ( i = 0; i < colors; i++ )
{
tempcolormap[i] = colormap[i];
PPM_ASSIGN(
tempcolormap[colors + i], PPM_GETR(colormap[i]) / 2,
PPM_GETG(colormap[i]) / 2, PPM_GETB(colormap[i]) / 2 );
}
ppm_freerow( colormap );
colormap = tempcolormap;
colors *= 2;
}
if ( colormap == 0 && nPlanes != 24 )
pm_message( "no colormap - interpreting values as grayscale" );
allPlanes = nPlanes + ( masking == mskHasMask ? 1 : 0 );

ppm_writeppminit( stdout, cols, rows, (pixval) maxval, 0 );
pixelrow = ppm_allocrow( cols );
if ( nPlanes == 24 )
{
Rrow = (unsigned char*) malloc( cols );
Grow = (unsigned char*) malloc( cols );
Brow = (unsigned char*) malloc( cols );
if ( Rrow == 0 || Grow == 0 || Brow == 0 )
pm_error( "out of memory" );
}
else
{
rawrow = (unsigned char*) malloc( cols );
if ( rawrow == 0 )
pm_error( "out of memory" );
}
runbuf = (unsigned char*) malloc( RowBytes( cols ) );
if ( runbuf == 0 )
pm_error( "out of memory" );

bp = body;
for ( row = 0; row < rows; row++ )
{
/* Extract rawrow from the image. */
if ( nPlanes == 24 )
for ( col = 0; col < cols; ++col )
Rrow[col] = Grow[col] = Brow[col] = 0;
else
for ( col = 0; col < cols; ++col )
rawrow[col] = 0;
for ( i = 0; i < allPlanes; i++ )
{
switch ( compression )
{
case cmpNone:
ubp = bp;
bp += RowBytes( cols );
break;

case cmpByteRun1:
ubp = runbuf;
bytes = RowBytes( cols );
do
{
byte = *bp++;
if ( byte <= 127 )
for ( j = byte, bytes -= j + 1; j >= 0; j-- )
*ubp++ = *bp++;
else if ( byte != 128 )
for ( j = 256 - byte, bytes -= j + 1, byte = *bp++;
j >= 0; j-- )
*ubp++ = byte;
}
while ( bytes > 0 );
if ( bytes < 0 )
pm_error( "error doing ByteRun decompression" );
ubp = runbuf;
break;

default:
pm_error( "unknown compression type" );
}

if ( i >= nPlanes )
continue; /* ignore mask plane */

if ( nPlanes == 24 )
{
for ( col = 0; col < cols; col++ )
if ( i < 8 )
{ /* red */
if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
Rrow[col] |= 1 << i;
}
else if ( i > 15 )
{ /* blue */
if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
Brow[col] |= 1 << (i-16);
}
else
{ /* green */
if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
Grow[col] |= 1 << (i-8);
}
}
else
for ( col = 0; col < cols; col++ )
if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
rawrow[col] |= 1 << i;
}

/* Interpret rawrow into pixels. */
r = g = b = 0;
for ( col = 0; col < cols; col++ )
if ( ham )
{ /* HAM mode. */
switch ( ( rawrow[col] >> nPlanes - 2 ) & 0x3 )
{
case 0:
if ( colormap != 0 && colors >= maxval )
pixelrow[col] = colormap[rawrow[col] & hammask];
else
PPM_ASSIGN(
pixelrow[col], rawrow[col] & hammask,
rawrow[col] & hammask, rawrow[col] & hammask );
r = PPM_GETR( pixelrow[col] );
g = PPM_GETG( pixelrow[col] );
b = PPM_GETB( pixelrow[col] );
break;

case 1:
b = rawrow[col] & hammask;
PPM_ASSIGN( pixelrow[col], r, g, b );
break;

case 2:
r = rawrow[col] & hammask;
PPM_ASSIGN( pixelrow[col], r, g, b );
break;

case 3:
g = rawrow[col] & hammask;
PPM_ASSIGN( pixelrow[col], r, g, b );
break;

default:
pm_error( "impossible HAM code" );
}
}
else if ( nPlanes == 24 )
/* 24bit image. */
PPM_ASSIGN( pixelrow[col], Rrow[col], Grow[col], Brow[col] );
else if ( colormap != 0 )
/* Non-HAM colormapped. */
pixelrow[col] = colormap[rawrow[col]];
else
/* Non-HAM direct - weird. */
PPM_ASSIGN(
pixelrow[col], rawrow[col], rawrow[col], rawrow[col] );

/* And write out the row. */
ppm_writeppmrow( stdout, pixelrow, cols, (pixval) maxval, 0 );
}

exit( 0 );
}

static unsigned char
get_byte( f )
FILE* f;
{
int i;

i = getc( f );
if ( i == EOF )
pm_error( "EOF / read error" );

return (unsigned char) i;
}

static void
getfourchars( f, fourchars )
FILE* f;
char fourchars[4];
{
fourchars[0] = get_byte( f );
fourchars[1] = get_byte( f );
fourchars[2] = get_byte( f );
fourchars[3] = get_byte( f );
}
nksize ) == -1 )
pm_error( "EOF / read error" );
bytesread += 8;

if ( body != 0 )
{
pm_message(
"\"%s\" chunk found after BODY chunk - skipping", iffid );
for ( i = 0; i < chunksize; i++ )
(void) get_byte( ifp );
}
else if ( strcmp( iffid, "BMHD" ) == 0 )
{
short junk;
if ( pm_readbigshort( ifp, &cols ) == -1 )
pm_error( "EOF / read error" );
if ( pm_readbigshort( ifp, &rows ) == -1 )
pm_error( "EOF / read error" pbmplus05oct91/ppm/ppmpat.c 444 3010 34 75434 5035730733 11130 /* ppmpat.c - make a pixmap
**
** Copyright (C) 1989, 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "ppmdraw.h"
#include
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif /*M_PI*/

static pixel random_color ARGS(( pixval maxval ));
static pixel random_bright_color ARGS(( pixval maxval ));
static pixel random_dark_color ARGS(( pixval maxval ));
static pixel average_two_colors ARGS(( pixel p1, pixel p2 ));
static void average_drawproc ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int col, int row, char* clientdata ));
static void gingham2 ARGS(( pixel** pixels, int cols, int rows, pixval maxval ));
static void gingham3 ARGS(( pixel** pixels, int cols, int rows, pixval maxval ));
static void madras ARGS(( pixel** pixels, int cols, int rows, pixval maxval ));
static void tartan ARGS(( pixel** pixels, int cols, int rows, pixval maxval ));
static void poles ARGS(( pixel** pixels, int cols, int rows, pixval maxval ));
static void sq_measurecircle_drawproc ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int col, int row, char* clientdata ));
static void sq_rainbowcircle_drawproc ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int col, int row, char* clientdata ));
static void squig ARGS(( pixel** pixels, int cols, int rows, pixval maxval ));
static void sq_assign_colors ARGS(( int circlecount, pixval maxval, pixel* colors ));
static pixel random_camo_color ARGS(( pixval maxval ));
static pixel random_anticamo_color ARGS(( pixval maxval ));
static float rnduni ARGS(( void ));
static void camo ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int antiflag ));
static void test ARGS(( pixel** pixels, int cols, int rows, pixval maxval ));

void
main( argc, argv )
int argc;
char* argv[];
{
pixel** pixels;
int argn, pattern, cols, rows;
#define PAT_NONE 0
#define PAT_GINGHAM2 1
#define PAT_GINGHAM3 2
#define PAT_MADRAS 3
#define PAT_TARTAN 4
#define PAT_POLES 5
#define PAT_SQUIG 6
#define PAT_CAMO 7
#define PAT_ANTICAMO 8
#define PAT_TEST 9
char* usage = "-gingham|-g2|-gingham3|-g3|-madras|-tartan|-poles|-squig|-camo|-anticamo ";

ppm_init( &argc, argv );

argn = 1;
pattern = PAT_NONE;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-gingham2", 9 ) ||
pm_keymatch( argv[argn], "-g2", 3 ) )
{
if ( pattern != PAT_NONE )
pm_error( "only one base pattern may be specified" );
pattern = PAT_GINGHAM2;
}
else if ( pm_keymatch( argv[argn], "-gingham3", 9 ) ||
pm_keymatch( argv[argn], "-g3", 3 ) )
{
if ( pattern != PAT_NONE )
pm_error( "only one base pattern may be specified" );
pattern = PAT_GINGHAM3;
}
else if ( pm_keymatch( argv[argn], "-madras", 2 ) )
{
if ( pattern != PAT_NONE )
pm_error( "only one base pattern may be specified" );
pattern = PAT_MADRAS;
}
else if ( pm_keymatch( argv[argn], "-tartan", 2 ) )
{
if ( pattern != PAT_NONE )
pm_error( "only one base pattern may be specified" );
pattern = PAT_TARTAN;
}
else if ( pm_keymatch( argv[argn], "-poles", 2 ) )
{
if ( pattern != PAT_NONE )
pm_error( "only one base pattern may be specified" );
pattern = PAT_POLES;
}
else if ( pm_keymatch( argv[argn], "-squig", 2 ) )
{
if ( pattern != PAT_NONE )
pm_error( "only one base pattern may be specified" );
pattern = PAT_SQUIG;
}
else if ( pm_keymatch( argv[argn], "-camo", 2 ) )
{
if ( pattern != PAT_NONE )
pm_error( "only one base pattern may be specified" );
pattern = PAT_CAMO;
}
else if ( pm_keymatch( argv[argn], "-anticamo", 2 ) )
{
if ( pattern != PAT_NONE )
pm_error( "only one base pattern may be specified" );
pattern = PAT_ANTICAMO;
}
else if ( pm_keymatch( argv[argn], "-test", 3 ) )
{
if ( pattern != PAT_NONE )
pm_error( "only one base pattern may be specified" );
pattern = PAT_TEST;
}
else
pm_usage( usage );
++argn;
}
if ( pattern == PAT_NONE )
pm_error( "a base pattern must be specified" );

if ( argn == argc )
pm_usage( usage);
if ( sscanf( argv[argn], "%d", &cols ) != 1 )
pm_usage( usage );
++argn;
if ( argn == argc )
pm_usage( usage);
if ( sscanf( argv[argn], "%d", &rows ) != 1 )
pm_usage( usage );
++argn;

if ( argn != argc )
pm_usage( usage);

srandom( (int) ( time( 0 ) ^ getpid( ) ) );
pixels = ppm_allocarray( cols, rows );

switch ( pattern )
{
case PAT_GINGHAM2:
gingham2( pixels, cols, rows, PPM_MAXMAXVAL );
break;

case PAT_GINGHAM3:
gingham3( pixels, cols, rows, PPM_MAXMAXVAL );
break;

case PAT_MADRAS:
madras( pixels, cols, rows, PPM_MAXMAXVAL );
break;

case PAT_TARTAN:
tartan( pixels, cols, rows, PPM_MAXMAXVAL );
break;

case PAT_POLES:
poles( pixels, cols, rows, PPM_MAXMAXVAL );
break;

case PAT_SQUIG:
squig( pixels, cols, rows, PPM_MAXMAXVAL );
break;

case PAT_CAMO:
camo( pixels, cols, rows, PPM_MAXMAXVAL, 0 );
break;

case PAT_ANTICAMO:
camo( pixels, cols, rows, PPM_MAXMAXVAL, 1 );
break;

case PAT_TEST:
test( pixels, cols, rows, PPM_MAXMAXVAL );
break;

default:
pm_error( "can't happen!" );
}

/* All done, write it out. */
ppm_writeppm( stdout, pixels, cols, rows, PPM_MAXMAXVAL, 0 );

exit( 0 );
}

#if __STDC__
static pixel
random_color( pixval maxval )
#else /*__STDC__*/
static pixel
random_color( maxval )
pixval maxval;
#endif /*__STDC__*/
{
pixel p;

PPM_ASSIGN(
p, random() % ( maxval + 1 ), random() % ( maxval + 1 ),
random() % ( maxval + 1 ) );

return p;
}

#define DARK_THRESH 0.25

#if __STDC__
static pixel
random_bright_color( pixval maxval )
#else /*__STDC__*/
static pixel
random_bright_color( maxval )
pixval maxval;
#endif /*__STDC__*/
{
pixel p;

do
{
p = random_color( maxval );
}
while ( PPM_LUMIN( p ) <= maxval * DARK_THRESH );

return p;
}

#if __STDC__
static pixel
random_dark_color( pixval maxval )
#else /*__STDC__*/
static pixel
random_dark_color( maxval )
pixval maxval;
#endif /*__STDC__*/
{
pixel p;

do
{
p = random_color( maxval );
}
while ( PPM_LUMIN( p ) > maxval * DARK_THRESH );

return p;
}

static pixel
average_two_colors( p1, p2 )
pixel p1, p2;
{
pixel p;

PPM_ASSIGN(
p, ( (int) PPM_GETR(p1) + (int) PPM_GETR(p2) ) / 2,
( (int) PPM_GETG(p1) + (int) PPM_GETG(p2) ) / 2,
( (int) PPM_GETB(p1) + (int) PPM_GETB(p2) ) / 2 );

return p;
}

#if __STDC__
static void
average_drawproc( pixel** pixels, int cols, int rows, pixval maxval, int col, int row, char* clientdata )
#else /*__STDC__*/
static void
average_drawproc( pixels, cols, rows, maxval, col, row, clientdata )
pixel** pixels;
int cols, rows, col, row;
pixval maxval;
char* clientdata;
#endif /*__STDC__*/
{
if ( col >= 0 && col < cols && row >= 0 && row < rows )
pixels[row][col] =
average_two_colors( pixels[row][col], *( (pixel*) clientdata ) );
}

/* Gingham stuff. */

#if __STDC__
static void
gingham2( pixel** pixels, int cols, int rows, pixval maxval )
#else /*__STDC__*/
static void
gingham2( pixels, cols, rows, maxval )
pixel** pixels;
int cols, rows;
pixval maxval;
#endif /*__STDC__*/
{
int colso2, rowso2;
pixel backcolor, forecolor;

colso2 = cols / 2;
rowso2 = rows / 2;
backcolor = random_dark_color( maxval );
forecolor = random_bright_color( maxval );

/* Warp. */
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, colso2, rows, PPMD_NULLDRAWPROC,
(char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, colso2, 0, cols - colso2, rows,
PPMD_NULLDRAWPROC, (char*) &forecolor );

/* Woof. */
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, cols, rowso2, average_drawproc,
(char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rowso2, cols, rows - rowso2,
average_drawproc, (char*) &forecolor );
}

#if __STDC__
static void
gingham3( pixel** pixels, int cols, int rows, pixval maxval )
#else /*__STDC__*/
static void
gingham3( pixels, cols, rows, maxval )
pixel** pixels;
int cols, rows;
pixval maxval;
#endif /*__STDC__*/
{
int colso4, rowso4;
pixel backcolor, fore1color, fore2color;

colso4 = cols / 4;
rowso4 = rows / 4;
backcolor = random_dark_color( maxval );
fore1color = random_bright_color( maxval );
fore2color = random_bright_color( maxval );

/* Warp. */
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, colso4, rows, PPMD_NULLDRAWPROC,
(char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, colso4, 0, colso4, rows, PPMD_NULLDRAWPROC,
(char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 2 * colso4, 0, colso4, rows,
PPMD_NULLDRAWPROC, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 3 * colso4, 0, cols - colso4, rows,
PPMD_NULLDRAWPROC, (char*) &fore1color );

/* Woof. */
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, cols, rowso4, average_drawproc,
(char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rowso4, cols, rowso4, average_drawproc,
(char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 2 * rowso4, cols, rowso4,
average_drawproc, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 3 * rowso4, cols, rows - rowso4,
average_drawproc, (char*) &fore1color );
}

#if __STDC__
static void
madras( pixel** pixels, int cols, int rows, pixval maxval )
#else /*__STDC__*/
static void
madras( pixels, cols, rows, maxval )
pixel** pixels;
int cols, rows;
pixval maxval;
#endif /*__STDC__*/
{
int cols2, rows2, cols3, rows3, cols12, rows12, cols6a, rows6a, cols6b,
rows6b;
pixel backcolor, fore1color, fore2color;

cols2 = cols * 2 / 44;
rows2 = rows * 2 / 44;
cols3 = cols * 3 / 44;
rows3 = rows * 3 / 44;
cols12 = cols - 10 * cols2 - 4 * cols3;
rows12 = rows - 10 * rows2 - 4 * rows3;
cols6a = cols12 / 2;
rows6a = rows12 / 2;
cols6b = cols12 - cols6a;
rows6b = rows12 - rows6a;
backcolor = random_dark_color( maxval );
fore1color = random_bright_color( maxval );
fore2color = random_bright_color( maxval );

/* Warp. */
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, cols2, rows, PPMD_NULLDRAWPROC,
(char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, cols2, 0, cols3, rows, PPMD_NULLDRAWPROC,
(char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, cols2 + cols3, 0, cols2, rows,
PPMD_NULLDRAWPROC, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 2 * cols2 + cols3, 0, cols2, rows,
PPMD_NULLDRAWPROC, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 3 * cols2 + cols3, 0, cols2, rows,
PPMD_NULLDRAWPROC, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 4 * cols2 + cols3, 0, cols6a, rows,
PPMD_NULLDRAWPROC, (char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 4 * cols2 + cols3 + cols6a, 0, cols2, rows,
PPMD_NULLDRAWPROC, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 5 * cols2 + cols3 + cols6a, 0, cols3, rows,
PPMD_NULLDRAWPROC, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 5 * cols2 + 2 * cols3 + cols6a, 0, cols2,
rows, PPMD_NULLDRAWPROC, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 6 * cols2 + 2 * cols3 + cols6a, 0, cols3,
rows, PPMD_NULLDRAWPROC, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 6 * cols2 + 3 * cols3 + cols6a, 0, cols2,
rows, PPMD_NULLDRAWPROC, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 7 * cols2 + 3 * cols3 + cols6a, 0, cols6b,
rows, PPMD_NULLDRAWPROC, (char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 7 * cols2 + 3 * cols3 + cols6a + cols6b, 0,
cols2, rows, PPMD_NULLDRAWPROC, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 8 * cols2 + 3 * cols3 + cols6a + cols6b, 0,
cols2, rows, PPMD_NULLDRAWPROC, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 9 * cols2 + 3 * cols3 + cols6a + cols6b, 0,
cols2, rows, PPMD_NULLDRAWPROC, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 10 * cols2 + 3 * cols3 + cols6a + cols6b, 0,
cols3, rows, PPMD_NULLDRAWPROC, (char*) &fore1color );

/* Woof. */
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, cols, rows2, average_drawproc,
(char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rows2, cols, rows3, average_drawproc,
(char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rows2 + rows3, cols, rows2,
average_drawproc, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 2 * rows2 + rows3, cols, rows2,
average_drawproc, (char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 3 * rows2 + rows3, cols, rows2,
average_drawproc, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 4 * rows2 + rows3, cols, rows6a,
average_drawproc, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 4 * rows2 + rows3 + rows6a, cols, rows2,
average_drawproc, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 5 * rows2 + rows3 + rows6a, cols, rows3,
average_drawproc, (char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 5 * rows2 + 2 * rows3 + rows6a, cols,
rows2, average_drawproc, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 6 * rows2 + 2 * rows3 + rows6a, cols,
rows3, average_drawproc, (char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 6 * rows2 + 3 * rows3 + rows6a, cols,
rows2, average_drawproc, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 7 * rows2 + 3 * rows3 + rows6a, cols,
rows6b, average_drawproc, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 7 * rows2 + 3 * rows3 + rows6a + rows6b,
cols, rows2, average_drawproc, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 8 * rows2 + 3 * rows3 + rows6a + rows6b,
cols, rows2, average_drawproc, (char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 9 * rows2 + 3 * rows3 + rows6a + rows6b,
cols, rows2, average_drawproc, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 10 * rows2 + 3 * rows3 + rows6a + rows6b,
cols, rows3, average_drawproc, (char*) &fore2color );
}

#if __STDC__
static void
tartan( pixel** pixels, int cols, int rows, pixval maxval )
#else /*__STDC__*/
static void
tartan( pixels, cols, rows, maxval )
pixel** pixels;
int cols, rows;
pixval maxval;
#endif /*__STDC__*/
{
int cols1, rows1, cols3, rows3, cols10, rows10, cols5a, rows5a, cols5b,
rows5b;
pixel backcolor, fore1color, fore2color;

cols1 = cols / 22;
rows1 = rows / 22;
cols3 = cols * 3 / 22;
rows3 = rows * 3 / 22;
cols10 = cols - 3 * cols1 - 3 * cols3;
rows10 = rows - 3 * rows1 - 3 * rows3;
cols5a = cols10 / 2;
rows5a = rows10 / 2;
cols5b = cols10 - cols5a;
rows5b = rows10 - rows5a;
backcolor = random_dark_color( maxval );
fore1color = random_bright_color( maxval );
fore2color = random_bright_color( maxval );

/* Warp. */
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, cols5a, rows, PPMD_NULLDRAWPROC,
(char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, cols5a, 0, cols1, rows, PPMD_NULLDRAWPROC,
(char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, cols5a + cols1, 0, cols5b, rows,
PPMD_NULLDRAWPROC, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, cols10 + cols1, 0, cols3, rows,
PPMD_NULLDRAWPROC, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, cols10 + cols1 + cols3, 0, cols1, rows,
PPMD_NULLDRAWPROC, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, cols10 + 2 * cols1 + cols3, 0, cols3, rows,
PPMD_NULLDRAWPROC, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, cols10 + 2 * cols1 + 2 * cols3, 0, cols1,
rows, PPMD_NULLDRAWPROC, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, cols10 + 3 * cols1 + 2 * cols3, 0, cols3,
rows, PPMD_NULLDRAWPROC, (char*) &fore2color );

/* Woof. */
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, cols, rows5a, average_drawproc,
(char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rows5a, cols, rows1, average_drawproc,
(char*) &fore1color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rows5a + rows1, cols, rows5b,
average_drawproc, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rows10 + rows1, cols, rows3,
average_drawproc, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rows10 + rows1 + rows3, cols, rows1,
average_drawproc, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rows10 + 2 * rows1 + rows3, cols, rows3,
average_drawproc, (char*) &fore2color );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rows10 + 2 * rows1 + 2 * rows3, cols,
rows1, average_drawproc, (char*) &backcolor );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, rows10 + 3 * rows1 + 2 * rows3, cols,
rows3, average_drawproc, (char*) &fore2color );
}

/* Poles stuff. */

#define MAXPOLES 500

#if __STDC__
static void
poles( pixel** pixels, int cols, int rows, pixval maxval )
#else /*__STDC__*/
static void
poles( pixels, cols, rows, maxval )
pixel** pixels;
int cols, rows;
pixval maxval;
#endif /*__STDC__*/
{
int poles, i, xs[MAXPOLES], ys[MAXPOLES], col, row;
pixel colors[MAXPOLES];

poles = cols * rows / 30000;

/* Place and color poles randomly. */
for ( i = 0; i < poles; ++i )
{
xs[i] = random() % cols;
ys[i] = random() % rows;
colors[i] = random_bright_color( maxval );
}

/* Now interpolate points. */
for ( row = 0; row < rows; ++row )
for ( col = 0; col < cols; ++col )
{
register long dist1, dist2, newdist, r, g, b;
pixel color1, color2;

/* Find two closest poles. */
dist1 = dist2 = 2000000000;
for ( i = 0; i < poles; ++i )
{
newdist = ( col - xs[i] ) * ( col - xs[i] ) +
( row - ys[i] ) * ( row - ys[i] );
if ( newdist < dist1 )
{
dist1 = newdist;
color1 = colors[i];
}
else if ( newdist < dist2 )
{
dist2 = newdist;
color2 = colors[i];
}
}

/* And assign interpolated color. */
newdist = dist1 + dist2;
r = PPM_GETR(color1)*dist2/newdist + PPM_GETR(color2)*dist1/newdist;
g = PPM_GETG(color1)*dist2/newdist + PPM_GETG(color2)*dist1/newdist;
b = PPM_GETB(color1)*dist2/newdist + PPM_GETB(color2)*dist1/newdist;
PPM_ASSIGN( pixels[row][col], r, g, b );
}
}

/* Squig stuff. */

#define SQUIGS 5
#define SQ_POINTS 7
#define SQ_MAXCIRCLE_POINTS 5000

static int sq_radius, sq_circlecount;
static pixel sq_colors[SQ_MAXCIRCLE_POINTS];
static int sq_xoffs[SQ_MAXCIRCLE_POINTS], sq_yoffs[SQ_MAXCIRCLE_POINTS];

#if __STDC__
static void
sq_measurecircle_drawproc( pixel** pixels, int cols, int rows, pixval maxval, int col, int row, char* clientdata )
#else /*__STDC__*/
static void
sq_measurecircle_drawproc( pixels, cols, rows, maxval, col, row, clientdata )
pixel** pixels;
int cols, rows, col, row;
pixval maxval;
char* clientdata;
#endif /*__STDC__*/
{
sq_xoffs[sq_circlecount] = col;
sq_yoffs[sq_circlecount] = row;
++sq_circlecount;
}

#if __STDC__
static void
sq_rainbowcircle_drawproc( pixel** pixels, int cols, int rows, pixval maxval, int col, int row, char* clientdata )
#else /*__STDC__*/
static void
sq_rainbowcircle_drawproc( pixels, cols, rows, maxval, col, row, clientdata )
pixel** pixels;
int cols, rows, col, row;
pixval maxval;
char* clientdata;
#endif /*__STDC__*/
{
int i;

for ( i = 0; i < sq_circlecount; ++i )
ppmd_point_drawproc(
pixels, cols, rows, maxval, col + sq_xoffs[i], row + sq_yoffs[i],
(char*) &(sq_colors[i]) );
}

#if __STDC__
static void
squig( pixel** pixels, int cols, int rows, pixval maxval )
#else /*__STDC__*/
static void
squig( pixels, cols, rows, maxval )
pixel** pixels;
int cols, rows;
pixval maxval;
#endif /*__STDC__*/
{
pixel color;
int i, j, xc[SQ_POINTS], yc[SQ_POINTS], x0, y0, x1, y1, x2, y2, x3, y3;

/* Clear image to black. */
PPM_ASSIGN( color, 0, 0, 0 );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC,
(char*) &color );

/* Draw the squigs. */
(void) ppmd_setlinetype( PPMD_LINETYPE_NODIAGS );
(void) ppmd_setlineclip( 0 );
for ( i = SQUIGS; i > 0; --i )
{
/* Measure circle. */
sq_radius = ( cols + rows ) / 2 / ( 25 + i * 2 );
sq_circlecount = 0;
ppmd_circle(
pixels, cols, rows, maxval, 0, 0, sq_radius,
sq_measurecircle_drawproc, 0 );
sq_assign_colors( sq_circlecount, maxval, sq_colors );

/* Choose wrap-around point. */
switch ( random() % 4 )
{
case 0:
x1 = random() % cols;
y1 = 0;
if ( x1 < cols / 2 )
xc[0] = random() % ( x1 * 2 );
else
xc[0] = cols - 1 - random() % ( ( cols - x1 ) * 2 );
yc[0] = random() % rows;
x2 = x1;
y2 = rows - 1;
xc[SQ_POINTS - 1] = 2 * x2 - xc[0];
yc[SQ_POINTS - 1] = y2 - yc[0];
x0 = xc[SQ_POINTS - 1];
y0 = yc[SQ_POINTS - 1] - rows;
x3 = xc[0];
y3 = yc[0] + rows;
break;

case 1:
x2 = random() % cols;
y2 = 0;
if ( x2 < cols / 2 )
xc[SQ_POINTS - 1] = random() % ( x2 * 2 );
else
xc[SQ_POINTS - 1] = cols - 1 - random() % ( ( cols - x2 ) * 2 );
yc[SQ_POINTS - 1] = random() % rows;
x1 = x2;
y1 = rows - 1;
xc[0] = 2 * x1 - xc[SQ_POINTS - 1];
yc[0] = y1 - yc[SQ_POINTS - 1];
x0 = xc[SQ_POINTS - 1];
y0 = yc[SQ_POINTS - 1] + rows;
x3 = xc[0];
y3 = yc[0] - rows;
break;

case 2:
x1 = 0;
y1 = random() % rows;
xc[0] = random() % cols;
if ( y1 < rows / 2 )
yc[0] = random() % ( y1 * 2 );
else
yc[0] = rows - 1 - random() % ( ( rows - y1 ) * 2 );
x2 = cols - 1;
y2 = y1;
xc[SQ_POINTS - 1] = x2 - xc[0];
yc[SQ_POINTS - 1] = 2 * y2 - yc[0];
x0 = xc[SQ_POINTS - 1] - cols;
y0 = yc[SQ_POINTS - 1];
x3 = xc[0] + cols;
y3 = yc[0];
break;

case 3:
x2 = 0;
y2 = random() % rows;
xc[SQ_POINTS - 1] = random() % cols;
if ( y2 < rows / 2 )
yc[SQ_POINTS - 1] = random() % ( y2 * 2 );
else
yc[SQ_POINTS - 1] = rows - 1 - random() % ( ( rows - y2 ) * 2 );
x1 = cols - 1;
y1 = y2;
xc[0] = x1 - xc[SQ_POINTS - 1];
yc[0] = 2 * y1 - yc[SQ_POINTS - 1];
x0 = xc[SQ_POINTS - 1] + cols;
y0 = yc[SQ_POINTS - 1];
x3 = xc[0] - cols;
y3 = yc[0];
break;
}

for ( j = 1; j < SQ_POINTS - 1; ++j )
{
xc[j] = ( random() % ( cols - 2 * sq_radius ) ) + sq_radius;
yc[j] = ( random() % ( rows - 2 * sq_radius ) ) + sq_radius;
}

ppmd_line(
pixels, cols, rows, maxval, x0, y0, x1, y1,
sq_rainbowcircle_drawproc, 0 );
ppmd_polyspline(
pixels, cols, rows, maxval, x1, y1, SQ_POINTS, xc, yc, x2, y2,
sq_rainbowcircle_drawproc, 0 );
ppmd_line(
pixels, cols, rows, maxval, x2, y2, x3, y3,
sq_rainbowcircle_drawproc, 0 );
}
}

#if __STDC__
static void
sq_assign_colors( int circlecount, pixval maxval, pixel* colors )
#else /*__STDC__*/
static void
sq_assign_colors( circlecount, maxval, colors )
int circlecount;
pixval maxval;
pixel* colors;
#endif /*__STDC__*/
{
pixel rc1, rc2, rc3;
float cco3;
int i;

rc1 = random_bright_color( maxval );
rc2 = random_bright_color( maxval );
rc3 = random_bright_color( maxval );
cco3 = ( circlecount - 1 ) / 3.0;

for ( i = 0; i < circlecount ; ++i )
{
if ( i < cco3 )
PPM_ASSIGN(
colors[i],
(float) PPM_GETR(rc1) +
( (float) PPM_GETR(rc2) - (float) PPM_GETR(rc1) ) *
(float) i / cco3,
(float) PPM_GETG(rc1) +
( (float) PPM_GETG(rc2) - (float) PPM_GETG(rc1) ) *
(float) i / cco3,
(float) PPM_GETB(rc1) +
( (float) PPM_GETB(rc2) - (float) PPM_GETB(rc1) ) *
(float) i / cco3 );
else if ( i < 2.0 * cco3 )
PPM_ASSIGN(
colors[i],
(float) PPM_GETR(rc2) +
( (float) PPM_GETR(rc3) - (float) PPM_GETR(rc2) ) *
( (float) i / cco3 - 1.0 ),
(float) PPM_GETG(rc2) +
( (float) PPM_GETG(rc3) - (float) PPM_GETG(rc2) ) *
( (float) i / cco3 - 1.0 ),
(float) PPM_GETB(rc2) +
( (float) PPM_GETB(rc3) - (float) PPM_GETB(rc2) ) *
( (float) i / cco3 - 1.0 ) );
else
PPM_ASSIGN(
colors[i],
(float) PPM_GETR(rc3) +
( (float) PPM_GETR(rc1) - (float) PPM_GETR(rc3) ) *
( (float) i / cco3 - 2.0 ),
(float) PPM_GETG(rc3) +
( (float) PPM_GETG(rc1) - (float) PPM_GETG(rc3) ) *
( (float) i / cco3 - 2.0 ),
(float) PPM_GETB(rc3) +
( (float) PPM_GETB(rc1) - (float) PPM_GETB(rc3) ) *
( (float) i / cco3 - 2.0 ) );
}
}

/* Camouflage stuff. */

#if __STDC__
static pixel
random_camo_color( pixval maxval )
#else /*__STDC__*/
static pixel
random_camo_color( maxval )
pixval maxval;
#endif /*__STDC__*/
{
int v1, v2, v3;
pixel p;

v1 = ( (int) maxval + 1 ) / 8;
v2 = ( (int) maxval + 1 ) / 4;
v3 = ( (int) maxval + 1 ) / 2;

switch ( random() % 10 )
{
case 0: case 1: case 2: /* light brown */
PPM_ASSIGN(
p, random() % v3 + v3, random() % v3 + v2, random() % v3 + v2 );
break;

case 3: case 4: case 5: /* dark green */
PPM_ASSIGN( p, random() % v2, random() % v2 + 3 * v1, random() % v2 );
break;

case 6: case 7: /* brown */
PPM_ASSIGN( p, random() % v2 + v2, random() % v2, random() % v2 );
break;

case 8: case 9: /* dark brown */
PPM_ASSIGN( p, random() % v1 + v1, random() % v1, random() % v1 );
break;
}

return p;
}

#if __STDC__
static pixel
random_anticamo_color( pixval maxval )
#else /*__STDC__*/
static pixel
random_anticamo_color( maxval )
pixval maxval;
#endif /*__STDC__*/
{
int v1, v2, v3;
pixel p;

v1 = ( (int) maxval + 1 ) / 4;
v2 = ( (int) maxval + 1 ) / 2;
v3 = 3 * v1;

switch ( random() % 15 )
{
case 0: case 1:
PPM_ASSIGN( p, random() % v1 + v3, random() % v2, random() % v2 );
break;

case 2: case 3:
PPM_ASSIGN( p, random() % v2, random() % v1 + v3, random() % v2 );
break;

case 4: case 5:
PPM_ASSIGN( p, random() % v2, random() % v2, random() % v1 + v3 );
break;

case 6: case 7: case 8:
PPM_ASSIGN( p, random() % v2, random() % v1 + v3, random() % v1 + v3 );
break;

case 9: case 10: case 11:
PPM_ASSIGN( p, random() % v1 + v3, random() % v2, random() % v1 + v3 );
break;

case 12: case 13: case 14:
PPM_ASSIGN( p, random() % v1 + v3, random() % v1 + v3, random() % v2 );
break;

}

return p;
}

static float
rnduni( )
{
return random() % 32767 / 32767.0;
}

#define BLOBRAD 50

#define MIN_POINTS 7
#define MAX_POINTS 13

#define MIN_ELLIPSE_FACTOR 0.5
#define MAX_ELLIPSE_FACTOR 2.0

#define MIN_POINT_FACTOR 0.5
#define MAX_POINT_FACTOR 2.0

#if __STDC__
static void
camo( pixel** pixels, int cols, int rows, pixval maxval, int antiflag )
#else /*__STDC__*/
static void
camo( pixels, cols, rows, maxval, antiflag )
pixel** pixels;
int cols, rows, antiflag;
pixval maxval;
#endif /*__STDC__*/
{
pixel color;
int n, i, cx, cy;
char* fh;

/* Clear background. */
if ( antiflag )
color = random_anticamo_color( maxval );
else
color = random_camo_color( maxval );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC,
(char*) &color );

n = ( rows * cols ) / ( BLOBRAD * BLOBRAD ) * 5;
for ( i = 0; i < n; ++i )
{
int points, p, xs[MAX_POINTS], ys[MAX_POINTS], x0, y0;
float a, b, c, theta, tang, tx, ty;

cx = random() % cols;
cy = random() % rows;

points = random() % ( MAX_POINTS - MIN_POINTS + 1 ) + MIN_POINTS;
a = rnduni() * ( MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR ) +
MIN_ELLIPSE_FACTOR;
b = rnduni() * ( MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR ) +
MIN_ELLIPSE_FACTOR;
theta = rnduni() * 2.0 * M_PI;
for ( p = 0; p < points; ++p )
{
tx = a * sin( p * 2.0 * M_PI / points );
ty = b * cos( p * 2.0 * M_PI / points );
tang = atan2( ty, tx ) + theta;
c = rnduni() * ( MAX_POINT_FACTOR - MIN_POINT_FACTOR ) +
MIN_POINT_FACTOR;
xs[p] = cx + BLOBRAD * c * sin( tang );
ys[p] = cy + BLOBRAD * c * cos( tang );
}
x0 = ( xs[0] + xs[points - 1] ) / 2;
y0 = ( ys[0] + ys[points - 1] ) / 2;

fh = ppmd_fill_init();

ppmd_polyspline(
pixels, cols, rows, maxval, x0, y0, points, xs, ys, x0, y0,
ppmd_fill_drawproc, fh );

if ( antiflag )
color = random_anticamo_color( maxval );
else
color = random_camo_color( maxval );
ppmd_fill( pixels, cols, rows, maxval, fh, PPMD_NULLDRAWPROC, (char*) &color );
}
}

/* Test pattern. Just a place to put ppmdraw exercises. */

#if __STDC__
static void
test( pixel** pixels, int cols, int rows, pixval maxval )
#else /*__STDC__*/
static void
test( pixels, cols, rows, maxval )
pixel** pixels;
int cols, rows;
pixval maxval;
#endif /*__STDC__*/
{
pixel color;
char* fh;

/* Clear image to black. */
PPM_ASSIGN( color, 0, 0, 0 );
ppmd_filledrectangle(
pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC,
(char*) &color );

fh = ppmd_fill_init();

ppmd_line( pixels, cols, rows, maxval, cols/8, rows/8, cols/2, rows/4, ppmd_fill_drawproc, fh );
ppmd_line( pixels, cols, rows, maxval, cols/2, rows/4, cols-cols/8, rows/8, ppmd_fill_drawproc, fh );
ppmd_line( pixels, cols, rows, maxval, cols-cols/8, rows/8, cols/2, rows/2, ppmd_fill_drawproc, fh );
ppmd_spline3( pixels, cols, rows, maxval, cols/2, rows/2, cols/2-cols/16, rows/2-rows/10, cols/2-cols/8, rows/2, ppmd_fill_drawproc, fh );
ppmd_spline3( pixels, cols, rows, maxval, cols/2-cols/8, rows/2, cols/4+cols/16, rows/2+rows/10, cols/4, rows/2, ppmd_fill_drawproc, fh );
ppmd_line( pixels, cols, rows, maxval, cols/4, rows/2, cols/8, rows/2, ppmd_fill_drawproc, fh );
ppmd_line( pixels, cols, rows, maxval, cols/8, rows/2, cols/8, rows/8, ppmd_fill_drawproc, fh );

PPM_ASSIGN( color, maxval, maxval, maxval );
ppmd_fill( pixels, cols, rows, maxval, fh, PPMD_NULLDRAWPROC, (char*) &color );
}
S - 1] - cols;
y0 = yc[SQ_POINTS - 1];
x3 = xc[0] + cols;
y3 = yc[0];
break;

case 3:
x2 = 0;
y2 = random() % rows;
xc[SQ_POINTS - 1] = random() % cols;
if ( y2 < rows / 2 )
yc[SQ_Ppbmplus05oct91/ppm/ppmdraw.h 444 3010 34 11502 5020311562 11255 /* ppmdraw.h - header file for simple drawing routines in libppm
**
** Simple, yes, and also fairly slow if the truth be told; but also very
** flexible and powerful.
**
** The two basic concepts are the drawproc and clientdata. All the drawing
** routines take a drawproc that does the actual drawing. A drawproc draws
** a single point, and it looks like this:
*/
void ppmd_point_drawproc ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int x, int y, char* clientdata ));
/*
** So, you call a drawing routine, e.g. ppmd_line(), and pass it a drawproc;
** it calls the drawproc for each point it wants to draw. Why so complicated?
** Because you can define your own drawprocs to do more interesting things than
** simply draw the point. For example, you could make one that calls back into
** another drawing routine, say ppmd_circle() to draw a circle at each point
** of a line.
**
** Slow? Well sure, we're talking results here, not realtime. You can do
** tricks with this arrangement that you couldn't even think of before.
** Still, to speed things up for the 90% case you can use this:
*/
#if __STDC__
#define PPMD_NULLDRAWPROC (void (*)(pixel**, int, int, pixval, int, int, char*)) 0
#else /*__STDC__*/
#define PPMD_NULLDRAWPROC (void (*)()) 0
#endif /*__STDC__*/
/*
** Just like ppmd_point_drawproc() it simply draws the point, but it's done
** inline, and clipping is assumed to be handled at a higher level.
**
** Now, what about clientdata. Well, it's an arbitrary pointer, and can
** mean something different to each different drawproc. For the above two
** drawprocs, clientdata should be a pointer to a pixel holding the color
** to be drawn. Other drawprocs can use it to point to something else,
** e.g. some structure to be modified, or they can ignore it.
*/


/* Outline drawing routines. Lines, splines, circles, etc. */

int ppmd_setlinetype ARGS(( int type ));
#define PPMD_LINETYPE_NORMAL 0
#define PPMD_LINETYPE_NODIAGS 1
/* If you set NODIAGS, all pixels drawn by ppmd_line() will be 4-connected
** instead of 8-connected; in other words, no diagonals. This is useful
** for some applications, for example when you draw many parallel lines
** and you want them to fit together without gaps.
*/

int ppmd_setlineclipping ARGS(( int clip ));
/* Normally, ppmd_line() clips to the edges of the pixmap. You can use this
** routine to disable the clipping, for example if you are using a drawproc
** that wants to do its own clipping.
*/

void ppmd_line ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int x0, int y0, int x1, int y1, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata ));
/* Draws a line from (x0, y0) to (x1, y1).
*/

void ppmd_spline3 ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int x0, int y0, int x1, int y1, int x2, int y2, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata ));
/* Draws a three-point spline from (x0, y0) to (x2, y2), with (x1, y1) as
** the control point. All drawing is done via ppmd_line(), so the routines
** that control it control ppmd_spline3() as well.
*/

void ppmd_polyspline ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int x0, int y0, int nc, int* xc, int* yc, int x1, int y1, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata ));
/* Draws a bunch of splines end to end. (x0, y0) and (x1, y1) are the initial
** and final points, and the xc and yc are the intermediate control points.
** nc is the number of these control points.
*/

void ppmd_circle ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int cx, int cy, int radius, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata ));
/* Draws a circle centered at (cx, cy) with the specified radius.
*/


/* Simple filling routines. Ok, so there's only one. */

void ppmd_filledrectangle ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int x, int y, int width, int height, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata ));
/* Fills in the rectangle [x, y, width, height].
*/


/* Arbitrary filling routines. With these you can fill any outline that
** you can draw with the outline routines.
*/

char* ppmd_fill_init( );
/* Returns a blank fillhandle.
*/

void ppmd_fill_drawproc ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int x, int y, char* clientdata ));
/* Use this drawproc to trace the outline you want filled. Be sure to use
** the fillhandle as the clientdata.
*/

void ppmd_fill ARGS(( pixel** pixels, int cols, int rows, pixval maxval, char* fillhandle, void (*drawprocP)(pixel**, int, int, pixval, int, int, char*), char* clientdata ));
/* Once you've traced the outline, give the fillhandle to this routine to
** do the actual drawing. As usual, it takes a drawproc and clientdata;
** you could define drawprocs to do stipple fills and such.
*/
);
break;
}

return p;
}

#if __STDC__
static pixel
random_anticamo_color( pixval maxval )
#else /*__STDC__*/
static pixel
random_anticamo_color( maxval )
pixval maxval;
#endipbmplus05oct91/ppm/ppmpat.1 444 3010 34 4006 5022777034 11012 .TH ppmpat 1 "04 September 1989"
.IX ppmpat
.SH NAME
ppmpat - make a pretty pixmap
.SH SYNOPSIS
.B ppmpat
.BR -gingham2 | -g2 | -gingham3 |
.BR -g3 | -madras | -tartan |
.BR -poles | -squig | -camo |
.BR -anticamo
.I width height
.SH DESCRIPTION
Produces a portable pixmap of the specified width and height,
with a pattern in it.
.IX "generating pixmaps"
.PP
This program is mainly to demonstrate use of the ppmdraw routines, a
simple but powerful drawing library.
See the ppmdraw.h include file for more info on using these routines.
Still, some of the patterns can be rather pretty.
If you have a color workstation, something like
.B "ppmpat -squig 300 300" | "ppmquant 128"
should generate a nice background.
.SH OPTIONS
.PP
The different flags specify various different pattern types:
.TP
.B -gingham2
A gingham check pattern. Can be tiled.
.TP
.B -gingham3
A slightly more complicated gingham. Can be tiled.
.TP
.B -madras
A madras plaid. Can be tiled.
.TP
.B -tartan
A tartan plaid. Can be tiled.
.TP
.B -poles
Color gradients centered on randomly-placed poles.
May need to be run through
.IR ppmquant .
.TP
.B -squig
Squiggley tubular pattern. Can be tiled.
May need to be run through
.IR ppmquant .
.TP
.B -camo
Camouflage pattern.
May need to be run through
.IR ppmquant .
.TP
.B -anticamo
Anti-camouflage pattern - like -camo, but ultra-bright colors.
May need to be run through
.IR ppmquant .
.PP
All flags can be abbreviated to their shortest unique prefix.
.SH REFERENCES
Some of the patterns are from "Designer's Guide to Color 3" by Jeanne Allen.
.SH "SEE ALSO"
pnmtile(1), ppmquant(1), ppm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
mtoicr.c v‹
pgmtoppm.c vŒ picttoppm.c
v ImakefilevŽMakefilebmtv
ppmmerge.ctv
ppmtopcx.1tv‘ ppmtopict.copbmv’ ppmtorgb3.1.cäv“
pcxtoppm.cv”
ppmtopcx.c3v• ppmtorgb3.cc.1v– ppmquantallt.cv— gouldtoppm.c1
v˜
ppmtoyuv.1 v™ pjtoppm.1.cvš ppmdither.1c.cvÇ ppmtopj.1opvÈ pjtoppm.cuwvÊ ppmdither.ciconvö ppmtopj.c
v÷
ppmtotga.c vø
ppmtotga.1 vù ppmtosixel.1 pbmplus05oct91/ppm/pgmtoppm.1 444 3010 34 4323 5070270650 11351 .TH pgmtoppm 1 "11 January 1991"
.IX pgmtoppm
.SH NAME
pgmtoppm - colorize a portable graymap into a portable pixmap
.SH SYNOPSIS
.B pgmtoppm
.I colorspec
.RI [ pgmfile ]
.br
.B pgmtoppm
.IB colorspec1 - colorspec2
.RI [ pgmfile ]
.br
.B pgmtoppm -map
.I mapfile
.RI [ pgmfile ]
.SH DESCRIPTION
Reads a portable graymap as input.
Colorizes it by multiplying the the gray values by specified color or colors,
and produces a portable pixmap as output.
.IX colorization
.PP
If only one color is specified, black in the pgm file stays black and
white in the pgm file turns into the specified color in the ppm file.
If two colors (separated by a dash) are specified, then black gets mapped
to the first color and white gets mapped to the second.
.PP
The color can be specified in five ways:
.IX "specifying colors"
.TP
o
A name, assuming
that a pointer to an X11-style color names file was compiled in.
.TP
o
An X11-style hexadecimal specifier: rgb:r/g/b, where r g and b are
each 1- to 4-digit hexadecimal numbers.
.TP
o
An X11-style decimal specifier: rgbi:r/g/b, where r g and b are
floating point numbers between 0 and 1.
.TP
o
For backwards compatibility, an old-X11-style hexadecimal
number: #rgb, #rrggbb, #rrrgggbbb, or #rrrrggggbbbb.
.TP
o
For backwards compatibility, a triplet of numbers
separated by commas: r,g,b, where r g and b are
floating point numbers between 0 and 1.
(This style was added before MIT came up with the similar rgbi style.)
.PP
Also, the
.B -map
flag lets you specify an entire colormap to be used.
The mapfile is just a
.I ppm
file; it can be any shape, all that matters
is the colors in it and their order.
In this case, black gets mapped into the first
color in the map file, and white gets mapped to the last.
.SH "SEE ALSO"
rgb3toppm(1), ppmtopgm(1), ppmtorgb3(1), ppm(5), pgm(5)
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
clipping ARGS(( int clip ));
/* Normally, ppmd_line() clips to the edges of the pixmap. You can use this
** routine to disable the clipping, for example if you are using a drawproc
** that wants to do its own clipping.
*/

void ppmd_line ARGS(( pixel** pixels, int cols, int rows, pixval maxval, int pbmplus05oct91/ppm/tgatoppm.1 444 3010 34 1773 5070474213 11350 .TH tgatoppm 1 "26 August 1989"
.IX tgatoppm
.SH NAME
tgatoppm - convert TrueVision Targa file into a portable pixmap
.SH SYNOPSIS
.B tgatoppm
.RB [ -debug ]
.RI [ tgafile ]
.SH DESCRIPTION
Reads a TrueVision Targa file as input.
.IX TrueVision
.IX Targa
Produces a portable pixmap as output.
.SH OPTIONS
.TP
.B -debug
Causes the header information to be dumped to stderr.
.PP
All flags can be abbreviated to their shortest unique prefix.
.BUGS
Should really be in PNM, not PPM.
.SH "SEE ALSO"
ppmtotga(1), ppm(5)
.SH AUTHOR
Partially based on tga2rast, version 1.0, by Ian J. MacPhedran.

Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
ípbmplus05oct91/ppm/giftoppm.c 444 3010 34 30464 5073520356 11446 /* +-------------------------------------------------------------------+ */
/* | Copyright 1990, David Koblas. | */
/* | Permission to use, copy, modify, and distribute this software | */
/* | and its documentation for any purpose and without fee is hereby | */
/* | granted, provided that the above copyright notice appear in all | */
/* | copies and that both that copyright notice and this permission | */
/* | notice appear in supporting documentation. This software is | */
/* | provided "as is" without express or implied warranty. | */
/* +-------------------------------------------------------------------+ */


#include "ppm.h"

#define MAXCOLORMAPSIZE 256

#define TRUE 1
#define FALSE 0

#define CM_RED 0
#define CM_GREEN 1
#define CM_BLUE 2

#define MAX_LWZ_BITS 12

#define INTERLACE 0x40
#define LOCALCOLORMAP 0x80
#define BitSet(byte, bit) (((byte) & (bit)) == (bit))

#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)

#define LM_to_uint(a,b) (((b)<<8)|(a))

struct {
unsigned int Width;
unsigned int Height;
unsigned char ColorMap[3][MAXCOLORMAPSIZE];
unsigned int BitPixel;
unsigned int ColorResolution;
unsigned int Background;
unsigned int AspectRatio;
} GifScreen;

struct {
int transparent;
int delayTime;
int inputFlag;
int disposal;
} Gif89 = { -1, -1, -1, 0 };

pixel *Image = NULL;
int verbose;
int showComment;

static char usage[] = "[-verbose] [-comments] [-image N] [GIFfile]";

static void ReadGIF ARGS(( FILE *fd, int imageNumber ));
static int ReadColorMap ARGS(( FILE *fd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] ));
static int DoExtension ARGS(( FILE *fd, int label ));
static int GetDataBlock ARGS(( FILE *fd, unsigned char *buf ));
static int GetCode ARGS(( FILE *fd, int code_size, int flag ));
static int LWZReadByte ARGS(( FILE *fd, int flag, int input_code_size ));
static void ReadImage ARGS(( FILE *fd, int len, int height, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore ));

void
main(argc,argv)
int argc;
char **argv;
{
int argn;
FILE *in;
int imageNumber;

ppm_init(&argc, argv);

argn = 1;
imageNumber = 1;
verbose = FALSE;
showComment = FALSE;

while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
if (pm_keymatch(argv[argn], "-verbose", 2)) {
verbose = TRUE;
showComment = TRUE;
} else if (pm_keymatch(argv[argn], "-comments", 2)) {
showComment = TRUE;
} else if (pm_keymatch(argv[argn], "-image", 2)) {
++argn;
if (argn == argc || sscanf(argv[argn], "%d", &imageNumber) != 1)
pm_usage(usage);
} else {
pm_usage(usage);
}
++argn;
}
if (argn != argc) {
in = pm_openr(argv[argn]);
++argn;
} else {
in = stdin;
}

if (argn != argc)
pm_usage(usage);

ReadGIF(in, imageNumber);
pm_close(in);
exit(0);
}

static void
ReadGIF(fd, imageNumber)
FILE *fd;
int imageNumber;
{
unsigned char buf[16];
unsigned char c;
unsigned char localColorMap[3][MAXCOLORMAPSIZE];
int useGlobalColormap;
int bitPixel;
int imageCount = 0;
char version[4];

if (! ReadOK(fd,buf,6))
pm_error("error reading magic number" );

if (strncmp(buf,"GIF",3) != 0)
pm_error("not a GIF file" );

strncpy(version, buf + 3, 3);
version[3] = '\0';

if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0))
pm_error("bad version number, not '87a' or '89a'" );

if (! ReadOK(fd,buf,7))
pm_error("failed to read screen descriptor" );

GifScreen.Width = LM_to_uint(buf[0],buf[1]);
GifScreen.Height = LM_to_uint(buf[2],buf[3]);
GifScreen.BitPixel = 2<<(buf[4]&0x07);
GifScreen.ColorResolution = (((buf[4]&0x70)>>3)+1);
GifScreen.Background = buf[5];
GifScreen.AspectRatio = buf[6];

if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
if (ReadColorMap(fd,GifScreen.BitPixel,GifScreen.ColorMap))
pm_error("error reading global colormap" );
}

if (GifScreen.AspectRatio != 0 && GifScreen.AspectRatio != 49) {
float r;
r = ( (float) GifScreen.AspectRatio + 15.0 ) / 64.0;
pm_message("warning - non-square pixels; to fix do a 'pnmscale -%cscale %g'",
r < 1.0 ? 'x' : 'y',
r < 1.0 ? 1.0 / r : r );
}

for (;;) {
if (! ReadOK(fd,&c,1))
pm_error("EOF / read error on image data" );

if (c == ';') { /* GIF terminator */
if (imageCount < imageNumber)
pm_error("only %d image%s found in file",
imageCount, imageCount>1?"s":"" );
return;
}

if (c == '!') { /* Extension */
if (! ReadOK(fd,&c,1))
pm_error("OF / read error on extention function code");
DoExtension(fd, c);
continue;
}

if (c != ',') { /* Not a valid start character */
pm_message("bogus character 0x%02x, ignoring", (int) c );
continue;
}

++imageCount;

if (! ReadOK(fd,buf,9))
pm_error("couldn't read left/top/width/height");

useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);

bitPixel = 1<<((buf[8]&0x07)+1);

if (! useGlobalColormap) {
if (ReadColorMap(fd, bitPixel, localColorMap))
pm_error("error reading local colormap" );
ReadImage(fd, LM_to_uint(buf[4],buf[5]),
LM_to_uint(buf[6],buf[7]), localColorMap,
BitSet(buf[8], INTERLACE), imageCount != imageNumber);
} else {
ReadImage(fd, LM_to_uint(buf[4],buf[5]),
LM_to_uint(buf[6],buf[7]), GifScreen.ColorMap,
BitSet(buf[8], INTERLACE), imageCount != imageNumber);
}

}
}

static int
ReadColorMap(fd,number,buffer)
FILE *fd;
int number;
unsigned char buffer[3][MAXCOLORMAPSIZE];
{
int i;
unsigned char rgb[3];

for (i = 0; i < number; ++i) {
if (! ReadOK(fd, rgb, sizeof(rgb)))
pm_error("bad colormap" );

buffer[CM_RED][i] = rgb[0] ;
buffer[CM_GREEN][i] = rgb[1] ;
buffer[CM_BLUE][i] = rgb[2] ;
}
return FALSE;
}

static int
DoExtension(fd, label)
FILE *fd;
int label;
{
static char buf[256];
char *str;

switch (label) {
case 0x01: /* Plain Text Extension */
str = "Plain Text Extension";
#ifdef notdef
if (GetDataBlock(fd, (unsigned char*) buf) == 0)
;

lpos = LM_to_uint(buf[0], buf[1]);
tpos = LM_to_uint(buf[2], buf[3]);
width = LM_to_uint(buf[4], buf[5]);
height = LM_to_uint(buf[6], buf[7]);
cellw = buf[8];
cellh = buf[9];
foreground = buf[10];
background = buf[11];

while (GetDataBlock(fd, (unsigned char*) buf) != 0) {
PPM_ASSIGN(image[ypos][xpos],
cmap[CM_RED][v],
cmap[CM_GREEN][v],
cmap[CM_BLUE][v]);
++index;
}

return FALSE;
#else
break;
#endif
case 0xff: /* Application Extension */
str = "Application Extension";
break;
case 0xfe: /* Comment Extension */
str = "Comment Extension";
while (GetDataBlock(fd, (unsigned char*) buf) != 0) {
if (showComment)
pm_message("gif comment: %s", buf );
}
return FALSE;
case 0xf9: /* Graphic Control Extension */
str = "Graphic Control Extension";
(void) GetDataBlock(fd, (unsigned char*) buf);
Gif89.disposal = (buf[0] >> 2) & 0x7;
Gif89.inputFlag = (buf[0] >> 1) & 0x1;
Gif89.delayTime = LM_to_uint(buf[1],buf[2]);
if ((buf[0] & 0x1) != 0)
Gif89.transparent = buf[3];

while (GetDataBlock(fd, (unsigned char*) buf) != 0)
;
return FALSE;
default:
str = buf;
sprintf(buf, "UNKNOWN (0x%02x)", label);
break;
}

pm_message("got a '%s' extension - please report this to [email protected]",
str );

while (GetDataBlock(fd, (unsigned char*) buf) != 0)
;

return FALSE;
}

int ZeroDataBlock = FALSE;

static int
GetDataBlock(fd, buf)
FILE *fd;
unsigned char *buf;
{
unsigned char count;

if (! ReadOK(fd,&count,1)) {
pm_message("error in getting DataBlock size" );
return -1;
}

ZeroDataBlock = count == 0;

if ((count != 0) && (! ReadOK(fd, buf, count))) {
pm_message("error in reading DataBlock" );
return -1;
}

return count;
}

static int
GetCode(fd, code_size, flag)
FILE *fd;
int code_size;
int flag;
{
static unsigned char buf[280];
static int curbit, lastbit, done, last_byte;
int i, j, ret;
unsigned char count;

if (flag) {
curbit = 0;
lastbit = 0;
done = FALSE;
return 0;
}

if ( (curbit+code_size) >= lastbit) {
if (done) {
if (curbit >= lastbit)
pm_error("ran off the end of my bits" );
return -1;
}
buf[0] = buf[last_byte-2];
buf[1] = buf[last_byte-1];

if ((count = GetDataBlock(fd, &buf[2])) == 0)
done = TRUE;

last_byte = 2 + count;
curbit = (curbit - lastbit) + 16;
lastbit = (2+count)*8 ;
}

ret = 0;
for (i = curbit, j = 0; j < code_size; ++i, ++j)
ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;

curbit += code_size;

return ret;
}

static int
LWZReadByte(fd, flag, input_code_size)
FILE *fd;
int flag;
int input_code_size;
{
static int fresh = FALSE;
int code, incode;
static int code_size, set_code_size;
static int max_code, max_code_size;
static int firstcode, oldcode;
static int clear_code, end_code;
static int table[2][(1<< MAX_LWZ_BITS)];
static int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
register int i;

if (flag) {
set_code_size = input_code_size;
code_size = set_code_size+1;
clear_code = 1 << set_code_size ;
end_code = clear_code + 1;
max_code_size = 2*clear_code;
max_code = clear_code+2;

GetCode(fd, 0, TRUE);

fresh = TRUE;

for (i = 0; i < clear_code; ++i) {
table[0][i] = 0;
table[1][i] = i;
}
for (; i < (1< table[0][i] = table[1][0] = 0;

sp = stack;

return 0;
} else if (fresh) {
fresh = FALSE;
do {
firstcode = oldcode =
GetCode(fd, code_size, FALSE);
} while (firstcode == clear_code);
return firstcode;
}

if (sp > stack)
return *--sp;

while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
if (code == clear_code) {
for (i = 0; i < clear_code; ++i) {
table[0][i] = 0;
table[1][i] = i;
}
for (; i < (1< table[0][i] = table[1][i] = 0;
code_size = set_code_size+1;
max_code_size = 2*clear_code;
max_code = clear_code+2;
sp = stack;
firstcode = oldcode =
GetCode(fd, code_size, FALSE);
return firstcode;
} else if (code == end_code) {
int count;
unsigned char buf[260];

if (ZeroDataBlock)
return -2;

while ((count = GetDataBlock(fd, buf)) > 0)
;

if (count != 0)
pm_message("missing EOD in data stream (common occurence)");
return -2;
}

incode = code;

if (code >= max_code) {
*sp++ = firstcode;
code = oldcode;
}

while (code >= clear_code) {
*sp++ = table[1][code];
if (code == table[0][code])
pm_error("circular table entry BIG ERROR");
code = table[0][code];
}

*sp++ = firstcode = table[1][code];

if ((code = max_code) <(1< table[0][code] = oldcode;
table[1][code] = firstcode;
++max_code;
if ((max_code >= max_code_size) &&
(max_code_size < (1< max_code_size *= 2;
++code_size;
}
}

oldcode = incode;

if (sp > stack)
return *--sp;
}
return code;
}

static void
ReadImage(fd, len, height, cmap, interlace, ignore)
FILE *fd;
int len, height;
unsigned char cmap[3][MAXCOLORMAPSIZE];
int interlace, ignore;
{
unsigned char c;
int v;
int xpos = 0, ypos = 0, pass = 0;
pixel **image;

/*
** Initialize the Compression routines
*/
if (! ReadOK(fd,&c,1))
pm_error("EOF / read error on image data" );

if (LWZReadByte(fd, TRUE, c) < 0)
pm_error("error reading image" );

/*
** If this is an "uninteresting picture" ignore it.
*/
if (ignore) {
if (verbose)
pm_message("skipping image..." );

while (LWZReadByte(fd, FALSE, c) >= 0)
;
return;
}

if ((image = ppm_allocarray(len, height)) == NULL)
pm_error("couldn't alloc space for image" );

if (verbose)
pm_message("reading %d by %d%s GIF image",
len, height, interlace ? " interlaced" : "" );

while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
PPM_ASSIGN(image[ypos][xpos], cmap[CM_RED][v],
cmap[CM_GREEN][v], cmap[CM_BLUE][v]);

++xpos;
if (xpos == len) {
xpos = 0;
if (interlace) {
switch (pass) {
case 0:
case 1:
ypos += 8; break;
case 2:
ypos += 4; break;
case 3:
ypos += 2; break;
}

if (ypos >= height) {
++pass;
switch (pass) {
case 1:
ypos = 4; break;
case 2:
ypos = 2; break;
case 3:
ypos = 1; break;
default:
goto fini;
}
}
} else {
++ypos;
}
}
if (ypos >= height)
break;
}

fini:
if (LWZReadByte(fd,FALSE,c)>=0)
pm_message("too much input data, ignoring extra...");

if (verbose)
pm_message("writing output");
ppm_writeppm(stdout, image, len, height, (pixval) 255, 0 );
}
mage%s found in file",
imageCount, imageCount>1?"s":"" );
return;
}

if (c == '!') { /* Extension */
if (! ReadOK(fd,&c,1))
pm_error("OF / read error on extention function code");
pbmplus05oct91/ppm/gouldtoppm.1 444 3010 34 1370 5022776445 11711 .TH gouldtoppm 1 "20 May 1990"
.IX gouldtoppm
.SH NAME
gouldtoppm - convert Gould scanner file into a portable pixmap
.SH SYNOPSIS
.B gouldtoppm
.RI [ gouldfile ]
.SH DESCRIPTION
Reads a file produced by the Gould scanner as input.
.IX "Gould scanner"
Produces a portable pixmap as output.
.SH "SEE ALSO"
ppm(5)
.SH AUTHOR
Copyright(C) 1990 by Stephen Paul Lesniewski
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
giftoppm.cds\ gouldtoppm.1Z{s]
pi1toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/pi1toppm.1 444 3010 34 1452 5023000323 11241 .TH pi1toppm 1 "19 July 1990"
.IX pi1toppm
.SH NAME
pi1toppm - convert an Atari Degas .pi1 into a portable pixmap
.SH SYNOPSIS
.B pi1toppm
.RI [ pi1file ]
.SH DESCRIPTION
Reads an Atari Degas .pi1 file as input.
.IX Atari
.IX "Degas .pi1"
Produces a portable pixmap as output.
.SH "SEE ALSO"
ppmtopi1(1), ppm(5), pi3topbm(1), pbmtopi3(1)
.SH AUTHOR
Copyright (C) 1991 by Steve Belczyk ([email protected]) and Jef Poskanzer.
.\" Permission to use, copy, modify and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
pm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/ppmtogif.c 444 3010 34 51301 5032726543 11440 /* ppmtogif.c - read a portable pixmap and produce a GIF file
**
** Based on GIFENCOD by David Rowley .A
** Lempel-Zim compression based on "compress".
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
**
** The Graphics Interchange Format(c) is the Copyright property of
** CompuServe Incorporated. GIF(sm) is a Service Mark property of
** CompuServe Incorporated.
*/

#include "ppm.h"
#include "ppmcmap.h"

#define MAXCOLORS 256

/*
* Pointer to function returning an int
*/
typedef int (* ifunptr)();

/*
* a code_int must be able to hold 2**BITS values of type int, and also -1
*/
typedef int code_int;

#ifdef SIGNED_COMPARE_SLOW
typedef unsigned long int count_int;
typedef unsigned short int count_short;
#else /*SIGNED_COMPARE_SLOW*/
typedef long int count_int;
#endif /*SIGNED_COMPARE_SLOW*/

static int colorstobpp ARGS(( int colors ));
static int GetPixel ARGS(( int x, int y ));
static void BumpPixel ARGS(( void ));
static int GIFNextPixel ARGS(( ifunptr getpixel ));
static void GIFEncode ARGS(( FILE* fp, int GWidth, int GHeight, int GInterlace, int Background, int BitsPerPixel, int Red[], int Green[], int Blue[], ifunptr GetPixel ));
static void Putword ARGS(( int w, FILE* fp ));
static void compress ARGS(( int init_bits, FILE* outfile, ifunptr ReadValue ));
static void output ARGS(( code_int code ));
static void cl_block ARGS(( void ));
static void cl_hash ARGS(( count_int hsize ));
static void writeerr ARGS(( void ));
static void char_init ARGS(( void ));
static void char_out ARGS(( int c ));
static void flush_char ARGS(( void ));

static pixel** pixels;
static colorhash_table cht;

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
int argn, rows, cols, colors, i, BitsPerPixel;
int interlace;
pixval maxval;
colorhist_vector chv;
int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
char* usage = "[-interlace] [ppmfile]";

ppm_init( &argc, argv );

argn = 1;
interlace = 0;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-interlace", 2 ) )
interlace = 1;
else if ( pm_keymatch( argv[argn], "-nointerlace", 2 ) )
interlace = 0;
else
pm_usage( usage );
++argn;
}

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pixels = ppm_readppm( ifp, &cols, &rows, &maxval );

pm_close( ifp );

/* Figure out the colormap. */
pm_message( "computing colormap..." );
chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
if ( chv == (colorhist_vector) 0 )
pm_error(
"too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
pm_message( "%d colors found", colors );

/* Now turn the ppm colormap into the appropriate GIF colormap. */
if ( maxval > 255 )
pm_message(
"maxval is not 255 - automatically rescaling colors" );
for ( i = 0; i < colors; ++i )
{
if ( maxval == 255 )
{
Red[i] = PPM_GETR( chv[i].color );
Green[i] = PPM_GETG( chv[i].color );
Blue[i] = PPM_GETB( chv[i].color );
}
else
{
Red[i] = (int) PPM_GETR( chv[i].color ) * 255 / maxval;
Green[i] = (int) PPM_GETG( chv[i].color ) * 255 / maxval;
Blue[i] = (int) PPM_GETB( chv[i].color ) * 255 / maxval;
}
}
BitsPerPixel = colorstobpp( colors );

/* And make a hash table for fast lookup. */
cht = ppm_colorhisttocolorhash( chv, colors );
ppm_freecolorhist( chv );

/* All set, let's do it. */
GIFEncode(
stdout, cols, rows, interlace, 0, BitsPerPixel,
Red, Green, Blue, GetPixel );

exit( 0 );
}

static int
colorstobpp( colors )
int colors;
{
int bpp;

if ( colors <= 2 )
bpp = 1;
else if ( colors <= 4 )
bpp = 2;
else if ( colors <= 8 )
bpp = 3;
else if ( colors <= 16 )
bpp = 4;
else if ( colors <= 32 )
bpp = 5;
else if ( colors <= 64 )
bpp = 6;
else if ( colors <= 128 )
bpp = 7;
else if ( colors <= 256 )
bpp = 8;
else
pm_error( "can't happen" );

return bpp;
}

static int
GetPixel( x, y )
int x, y;
{
int color;

color = ppm_lookupcolor( cht, &pixels[y][x] );
return color;
}


/*****************************************************************************
*
* GIFENCODE.C - GIF Image compression interface
*
* GIFEncode( FName, GHeight, GWidth, GInterlace, Background,
* BitsPerPixel, Red, Green, Blue, GetPixel )
*
*****************************************************************************/

#define TRUE 1
#define FALSE 0

static int Width, Height;
static int curx, cury;
static long CountDown;
static int Pass = 0;
static int Interlace;

/*
* Bump the 'curx' and 'cury' to point to the next pixel
*/
static void
BumpPixel()
{
/*
* Bump the current X position
*/
++curx;

/*
* If we are at the end of a scan line, set curx back to the beginning
* If we are interlaced, bump the cury to the appropriate spot,
* otherwise, just increment it.
*/
if( curx == Width ) {
curx = 0;

if( !Interlace )
++cury;
else {
switch( Pass ) {

case 0:
cury += 8;
if( cury >= Height ) {
++Pass;
cury = 4;
}
break;

case 1:
cury += 8;
if( cury >= Height ) {
++Pass;
cury = 2;
}
break;

case 2:
cury += 4;
if( cury >= Height ) {
++Pass;
cury = 1;
}
break;

case 3:
cury += 2;
break;
}
}
}
}

/*
* Return the next pixel from the image
*/
static int
GIFNextPixel( getpixel )
ifunptr getpixel;
{
int r;

if( CountDown == 0 )
return EOF;

--CountDown;

r = ( * getpixel )( curx, cury );

BumpPixel();

return r;
}

/* public */

static void
GIFEncode( fp, GWidth, GHeight, GInterlace, Background,
BitsPerPixel, Red, Green, Blue, GetPixel )

FILE* fp;
int GWidth, GHeight;
int GInterlace;
int Background;
int BitsPerPixel;
int Red[], Green[], Blue[];
ifunptr GetPixel;
{
int B;
int RWidth, RHeight;
int LeftOfs, TopOfs;
int Resolution;
int ColorMapSize;
int InitCodeSize;
int i;

Interlace = GInterlace;

ColorMapSize = 1 << BitsPerPixel;

RWidth = Width = GWidth;
RHeight = Height = GHeight;
LeftOfs = TopOfs = 0;

Resolution = BitsPerPixel;

/*
* Calculate number of bits we are expecting
*/
CountDown = (long)Width * (long)Height;

/*
* Indicate which pass we are on (if interlace)
*/
Pass = 0;

/*
* The initial code size
*/
if( BitsPerPixel <= 1 )
InitCodeSize = 2;
else
InitCodeSize = BitsPerPixel;

/*
* Set up the current x and y position
*/
curx = cury = 0;

/*
* Write the Magic header
*/
fwrite( "GIF87a", 1, 6, fp );

/*
* Write out the screen width and height
*/
Putword( RWidth, fp );
Putword( RHeight, fp );

/*
* Indicate that there is a global colour map
*/
B = 0x80; /* Yes, there is a color map */

/*
* OR in the resolution
*/
B |= (Resolution - 1) << 5;

/*
* OR in the Bits per Pixel
*/
B |= (BitsPerPixel - 1);

/*
* Write it out
*/
fputc( B, fp );

/*
* Write out the Background colour
*/
fputc( Background, fp );

/*
* Byte of 0's (future expansion)
*/
fputc( 0, fp );

/*
* Write out the Global Colour Map
*/
for( i=0; i fputc( Red[i], fp );
fputc( Green[i], fp );
fputc( Blue[i], fp );
}

/*
* Write an Image separator
*/
fputc( ',', fp );

/*
* Write the Image header
*/

Putword( LeftOfs, fp );
Putword( TopOfs, fp );
Putword( Width, fp );
Putword( Height, fp );

/*
* Write out whether or not the image is interlaced
*/
if( Interlace )
fputc( 0x40, fp );
else
fputc( 0x00, fp );

/*
* Write out the initial code size
*/
fputc( InitCodeSize, fp );

/*
* Go and actually compress the data
*/
compress( InitCodeSize+1, fp, GetPixel );

/*
* Write out a Zero-length packet (to end the series)
*/
fputc( 0, fp );

/*
* Write the GIF file terminator
*/
fputc( ';', fp );

/*
* And close the file
*/
fclose( fp );
}

/*
* Write out a word to the GIF file
*/
static void
Putword( w, fp )
int w;
FILE* fp;
{
fputc( w & 0xff, fp );
fputc( (w / 256) & 0xff, fp );
}


/***************************************************************************
*
* GIFCOMPR.C - GIF Image compression routines
*
* Lempel-Ziv compression based on 'compress'. GIF modifications by
* David Rowley ([email protected])
*
***************************************************************************/

/*
* General DEFINEs
*/

#define BITS 12

#define HSIZE 5003 /* 80% occupancy */

#ifdef NO_UCHAR
typedef char char_type;
#else /*NO_UCHAR*/
typedef unsigned char char_type;
#endif /*NO_UCHAR*/

/*
*
* GIF Image compression - modified 'compress'
*
* Based on: compress.c - File compression ala IEEE Computer, June 1984.
*
* By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
* Jim McKie (decvax!mcvax!jim)
* Steve Davies (decvax!vax135!petsd!peora!srd)
* Ken Turkowski (decvax!decwrl!turtlevax!ken)
* James A. Woods (decvax!ihnp4!ames!jaw)
* Joe Orost (decvax!vax135!petsd!joe)
*
*/
#include

#define ARGVAL() (*++(*argv) || (--argc && *++argv))

static int n_bits; /* number of bits/code */
static int maxbits = BITS; /* user settable max # bits/code */
static code_int maxcode; /* maximum code, given n_bits */
static code_int maxmaxcode = (code_int)1 << BITS; /* should NEVER generate this code */
#ifdef COMPATIBLE /* But wrong! */
# define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1)
#else /*COMPATIBLE*/
# define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
#endif /*COMPATIBLE*/

static count_int htab [HSIZE];
static unsigned short codetab [HSIZE];
#define HashTabOf(i) htab[i]
#define CodeTabOf(i) codetab[i]

static code_int hsize = HSIZE; /* for dynamic table sizing */

/*
* To save much memory, we overlay the table used by compress() with those
* used by decompress(). The tab_prefix table is the same size and type
* as the codetab. The tab_suffix table needs 2**BITS characters. We
* get this from the beginning of htab. The output stack uses the rest
* of htab, and contains characters. There is plenty of room for any
* possible stack (stack used to be 8000 characters).
*/

#define tab_prefixof(i) CodeTabOf(i)
#define tab_suffixof(i) ((char_type*)(htab))[i]
#define de_stack ((char_type*)&tab_suffixof((code_int)1<
static code_int free_ent = 0; /* first unused entry */

/*
* block compression parameters -- after all codes are used up,
* and compression rate changes, start over.
*/
static int clear_flg = 0;

static int offset;
static long int in_count = 1; /* length of input */
static long int out_count = 0; /* # of codes output (for debugging) */

/*
* compress stdin to stdout
*
* Algorithm: use open addressing double hashing (no chaining) on the
* prefix code / next character combination. We do a variant of Knuth's
* algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
* secondary probe. Here, the modular division first probe is gives way
* to a faster exclusive-or manipulation. Also do block compression with
* an adaptive reset, whereby the code table is cleared when the compression
* ratio decreases, but after the table fills. The variable-length output
* codes are re-sized at this point, and a special CLEAR code is generated
* for the decompressor. Late addition: construct the table according to
* file size for noticeable speed improvement on small files. Please direct
* questions about this implementation to ames!jaw.
*/

static int g_init_bits;
static FILE* g_outfile;

static int ClearCode;
static int EOFCode;

static void
compress( init_bits, outfile, ReadValue )
int init_bits;
FILE* outfile;
ifunptr ReadValue;
{
register long fcode;
register code_int i /* = 0 */;
register int c;
register code_int ent;
register code_int disp;
register code_int hsize_reg;
register int hshift;

/*
* Set up the globals: g_init_bits - initial number of bits
* g_outfile - pointer to output file
*/
g_init_bits = init_bits;
g_outfile = outfile;

/*
* Set up the necessary values
*/
offset = 0;
out_count = 0;
clear_flg = 0;
in_count = 1;
maxcode = MAXCODE(n_bits = g_init_bits);

ClearCode = (1 << (init_bits - 1));
EOFCode = ClearCode + 1;
free_ent = ClearCode + 2;

char_init();

ent = GIFNextPixel( ReadValue );

hshift = 0;
for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
++hshift;
hshift = 8 - hshift; /* set hash code range bound */

hsize_reg = hsize;
cl_hash( (count_int) hsize_reg); /* clear hash table */

output( (code_int)ClearCode );

#ifdef SIGNED_COMPARE_SLOW
while ( (c = GIFNextPixel( ReadValue )) != (unsigned) EOF ) {
#else /*SIGNED_COMPARE_SLOW*/
while ( (c = GIFNextPixel( ReadValue )) != EOF ) { /* } */
#endif /*SIGNED_COMPARE_SLOW*/

++in_count;

fcode = (long) (((long) c << maxbits) + ent);
i = (((code_int)c << hshift) ^ ent); /* xor hashing */

if ( HashTabOf (i) == fcode ) {
ent = CodeTabOf (i);
continue;
} else if ( (long)HashTabOf (i) < 0 ) /* empty slot */
goto nomatch;
disp = hsize_reg - i; /* secondary hash (after G. Knott) */
if ( i == 0 )
disp = 1;
probe:
if ( (i -= disp) < 0 )
i += hsize_reg;

if ( HashTabOf (i) == fcode ) {
ent = CodeTabOf (i);
continue;
}
if ( (long)HashTabOf (i) > 0 )
goto probe;
nomatch:
output ( (code_int) ent );
++out_count;
ent = c;
#ifdef SIGNED_COMPARE_SLOW
if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
#else /*SIGNED_COMPARE_SLOW*/
if ( free_ent < maxmaxcode ) { /* } */
#endif /*SIGNED_COMPARE_SLOW*/
CodeTabOf (i) = free_ent++; /* code -> hashtable */
HashTabOf (i) = fcode;
} else
cl_block();
}
/*
* Put out the final code.
*/
output( (code_int)ent );
++out_count;
output( (code_int) EOFCode );
}

/*****************************************************************
* TAG( output )
*
* Output the given code.
* Inputs:
* code: A n_bits-bit integer. If == -1, then EOF. This assumes
* that n_bits =< (long)wordsize - 1.
* Outputs:
* Outputs code to the file.
* Assumptions:
* Chars are 8 bits long.
* Algorithm:
* Maintain a BITS character long buffer (so that 8 codes will
* fit in it exactly). Use the VAX insv instruction to insert each
* code in turn. When the buffer fills up empty it and start over.
*/

static unsigned long cur_accum = 0;
static int cur_bits = 0;

static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
0x001F, 0x003F, 0x007F, 0x00FF,
0x01FF, 0x03FF, 0x07FF, 0x0FFF,
0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };

static void
output( code )
code_int code;
{
cur_accum &= masks[ cur_bits ];

if( cur_bits > 0 )
cur_accum |= ((long)code << cur_bits);
else
cur_accum = code;

cur_bits += n_bits;

while( cur_bits >= 8 ) {
char_out( (unsigned int)(cur_accum & 0xff) );
cur_accum >>= 8;
cur_bits -= 8;
}

/*
* If the next entry is going to be too big for the code size,
* then increase it, if possible.
*/
if ( free_ent > maxcode || clear_flg ) {

if( clear_flg ) {

maxcode = MAXCODE (n_bits = g_init_bits);
clear_flg = 0;

} else {

++n_bits;
if ( n_bits == maxbits )
maxcode = maxmaxcode;
else
maxcode = MAXCODE(n_bits);
}
}

if( code == EOFCode ) {
/*
* At EOF, write the rest of the buffer.
*/
while( cur_bits > 0 ) {
char_out( (unsigned int)(cur_accum & 0xff) );
cur_accum >>= 8;
cur_bits -= 8;
}

flush_char();

fflush( g_outfile );

if( ferror( g_outfile ) )
writeerr();
}
}

/*
* Clear out the hash table
*/
static void
cl_block () /* table clear for block compress */
{

cl_hash ( (count_int) hsize );
free_ent = ClearCode + 2;
clear_flg = 1;

output( (code_int)ClearCode );
}

static void
cl_hash(hsize) /* reset code table */
register count_int hsize;
{

register count_int *htab_p = htab+hsize;

register long i;
register long m1 = -1;

i = hsize - 16;
do { /* might use Sys V memset(3) here */
*(htab_p-16) = m1;
*(htab_p-15) = m1;
*(htab_p-14) = m1;
*(htab_p-13) = m1;
*(htab_p-12) = m1;
*(htab_p-11) = m1;
*(htab_p-10) = m1;
*(htab_p-9) = m1;
*(htab_p-8) = m1;
*(htab_p-7) = m1;
*(htab_p-6) = m1;
*(htab_p-5) = m1;
*(htab_p-4) = m1;
*(htab_p-3) = m1;
*(htab_p-2) = m1;
*(htab_p-1) = m1;
htab_p -= 16;
} while ((i -= 16) >= 0);

for ( i += 16; i > 0; --i )
*--htab_p = m1;
}

static void
writeerr()
{
pm_error( "error writing output file" );
}

/******************************************************************************
*
* GIF Specific routines
*
******************************************************************************/

/*
* Number of characters so far in this 'packet'
*/
static int a_count;

/*
* Set up the 'byte output' routine
*/
static void
char_init()
{
a_count = 0;
}

/*
* Define the storage for the packet accumulator
*/
static char accum[ 256 ];

/*
* Add a character to the end of the current packet, and if it is 254
* characters, flush the packet to disk.
*/
static void
char_out( c )
int c;
{
accum[ a_count++ ] = c;
if( a_count >= 254 )
flush_char();
}

/*
* Flush the packet to disk, and reset the accumulator
*/
static void
flush_char()
{
if( a_count > 0 ) {
fputc( a_count, g_outfile );
fwrite( accum, 1, a_count, g_outfile );
a_count = 0;
}
}

/* The End */
re used up,
* and compression rate changes, start over.
*/
static int clear_flg = 0;

static int offset;
static long int in_count = 1; /* length of input */
static long int out_count = 0; /* # of codes output (for debugging) */

/*
* compress stdin to stdout
*
* Algorithm: use open addressinpbmplus05oct91/ppm/ppmtoilbm.c 444 3010 34 20177 5032726546 11630 /* ppmtoilbm.c - read a portable pixmap and produce an IFF ILBM file
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "ppmcmap.h"
#include "ilbm.h"

#define MAX_COLORS 256
#define MAX_HAMIF_COLORS 32

static int colorstobpp ARGS(( int colors ));
static void put_chunk_head ARGS(( char* str, long size ));
static void put_fourchars ARGS(( char* str ));
static void put_big_short ARGS(( short s ));
static void put_big_long ARGS(( long l ));
static void put_byte ARGS(( unsigned char b ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
int argn, rows, cols, colors, i, hamif, ham, nPlanes, formsize, cmapsize;
pixel** pixels;
pixel* pP;
int row, col, plane;
pixval maxval;
colorhash_table cht;
colorhist_vector chv;
unsigned char* raw_rowbuf;
unsigned char* coded_rowbuf;
char* usage = "[-hamif] [ppmfile]";

ppm_init( &argc, argv );

argn = 1;
hamif = 0;

if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-hamif", 2 ) )
hamif = 1;
else if ( pm_keymatch( argv[argn], "-nohamif", 2 ) )
hamif = 0;
else
pm_usage( usage );
++argn;
}

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pixels = ppm_readppm( ifp, &cols, &rows, &maxval );

pm_close( ifp );

/* Figure out the colormap. */
pm_message( "computing colormap..." );
chv = ppm_computecolorhist( pixels, cols, rows, MAX_COLORS, &colors );
if ( hamif && chv == (colorhist_vector) 0 )
{
pm_message(
"too many colors - proceeding to write a HAM file" );
pm_message(
"if you want a non-HAM file, try doing a 'ppmquant %d'",
MAX_HAMIF_COLORS );
ham = 1;
colors = 16;
nPlanes = 6;
}
else if ( chv == (colorhist_vector) 0 )
pm_error( "too many colors - try doing a ppmquant" );
else if ( hamif && colors > MAX_HAMIF_COLORS )
{
pm_message(
"%d colors found - proceeding to write a HAM file", colors );
pm_message(
"if you want a non-HAM file, try doing a 'ppmquant %d'",
MAX_HAMIF_COLORS );
ham = 1;
colors = 16;
nPlanes = 6;
}
else
{
pm_message( "%d colors found", colors );
ham = 0;
nPlanes = colorstobpp( colors );
/* Make a hash table for fast color lookup. */
cht = ppm_colorhisttocolorhash( chv, colors );
}

/* Start off the ILBM with a FORM ILBM. */
cmapsize = colors * 3;
if ( odd( colors ) )
cmapsize++; /* pad CMAP to word */
formsize =
4 + /* ILBM */
4 + 4 + 20 + /* BMHD size header*/
4 + 4 + cmapsize + /* CMAP size colors */
4 + 4 + 4 + /* CAMG size val */
4 + 4 + rows * nPlanes * RowBytes(cols); /* BODY size data */
put_chunk_head( "FORM", formsize );
put_fourchars( "ILBM" );

/* Write out the BMHD. */
put_chunk_head( "BMHD", 20 );
put_big_short( cols );
put_big_short( rows );
put_big_short( 0 ); /* x */
put_big_short( 0 ); /* y */
put_byte( nPlanes );
put_byte( mskNone );
put_byte( cmpNone );
put_byte( 0 ); /* pad1 */
put_big_short( 0 ); /* transparentColor */
put_byte( 10 ); /* xAsp */
put_byte( 10 ); /* yAsp */
put_big_short( cols ); /* pageWidth */
put_big_short( rows ); /* pageHeight */

/* Write out the CMAP. */
if ( maxval > 255 )
pm_message( "maxval is not 255 - automatically rescaling colors" );
put_chunk_head( "CMAP", cmapsize );
for ( i = 0; i < colors; i++ )
{
if ( ham )
{ /* Grayscale colormap for HAM. */
put_byte( i << 4 );
put_byte( i << 4 );
put_byte( i << 4 );
}
else if ( maxval == 255 )
{
put_byte( PPM_GETR( chv[i].color ) );
put_byte( PPM_GETG( chv[i].color ) );
put_byte( PPM_GETB( chv[i].color ) );
}
else
{
put_byte( (char) ( (int) PPM_GETR(chv[i].color) * 255 / maxval ) );
put_byte( (char) ( (int) PPM_GETG(chv[i].color) * 255 / maxval ) );
put_byte( (char) ( (int) PPM_GETB(chv[i].color) * 255 / maxval ) );
}
}
if ( odd( colors ) )
put_byte( 0 ); /* Pad to word. */

/* Write out the CAMG. */
put_chunk_head( "CAMG", 4 );
if ( ham )
put_big_long( vmHAM );
else
put_big_long( 0 );

/* And finally, encode and write out the BODY. */
raw_rowbuf = (unsigned char *) malloc( cols );
coded_rowbuf = (unsigned char *) malloc( RowBytes(cols) );
if ( raw_rowbuf == 0 || coded_rowbuf == 0 )
pm_error( "out of memory" );
put_chunk_head( "BODY", rows * nPlanes * RowBytes(cols) );
for ( row = 0; row < rows; row++ )
{
/* Go from pixels to raw bytes. */
if ( ham )
{ /* HAM mode. */
register int noprev, pr, pg, pb, r, g, b, l;

noprev = 1;
for ( col = 0, pP = pixels[row]; col < cols; col++, pP++ )
{
r = PPM_GETR( *pP );
g = PPM_GETG( *pP );
b = PPM_GETB( *pP );
l = PPM_LUMIN( *pP );
if ( maxval != 15 )
{
r = r * 15 / maxval;
g = g * 15 / maxval;
b = b * 15 / maxval;
l = l * 15 / maxval;
}
if ( noprev )
{ /* No previous pixels, gotta use the gray option. */
raw_rowbuf[col] = l;
pr = pg = pb = l;
noprev = 0;
}
else
{
register int dred, dgreen, dblue, dgray;

/* Compute distances for the four options. */
dred = abs( g - pg ) + abs( b - pb );
dgreen = abs( r - pr ) + abs( b - pb );
dblue = abs( r - pr ) + abs( g - pg );
dgray = abs( r - l ) + abs( g - l ) + abs( b - l );

if ( dgray < dred && dgray < dgreen && dgray < dblue )
{
raw_rowbuf[col] = l;
pr = pg = pb = l;
}
else if ( dblue < dred && dblue < dgreen )
{
raw_rowbuf[col] = ( 1 << 4 ) + b;
pb = b;
}
else if ( dred < dgreen )
{
raw_rowbuf[col] = ( 2 << 4 ) + r;
pr = r;
}
else
{
raw_rowbuf[col] = ( 3 << 4 ) + g;
pg = g;
}
}
}
}
else
/* Non-HAM. */
for ( col = 0, pP = pixels[row]; col < cols; col++, pP++ )
raw_rowbuf[col] = ppm_lookupcolor( cht, pP );

/* Encode and write raw bytes in plane-interleaved form. */
for ( plane = 0; plane < nPlanes; plane++ )
{
int mask;
unsigned char *cp;

mask = 1 << plane;
cp = coded_rowbuf;
*cp = 0;
for ( col = 0; col < cols; col++ )
{
int b;

b = ( raw_rowbuf[col] & mask ) ? 1 : 0;
*cp |= b << ( 7 - col % 8 );
if ( col % 8 == 7 )
{
cp++;
*cp = 0;
}
}
fwrite( coded_rowbuf, RowBytes(cols), 1, stdout );
}
}

exit( 0 );
}

static int
colorstobpp( colors )
int colors;
{
int bpp;

if ( colors <= 2 )
bpp = 1;
else if ( colors <= 4 )
bpp = 2;
else if ( colors <= 8 )
bpp = 3;
else if ( colors <= 16 )
bpp = 4;
else if ( colors <= 32 )
bpp = 5;
else if ( colors <= 64 )
bpp = 6;
else if ( colors <= 128 )
bpp = 7;
else if ( colors <= 256 )
bpp = 8;
else
pm_error( "can't happen" );

return bpp;
}

static void
put_chunk_head( str, size )
char* str;
long size;
{
put_fourchars( str );
put_big_long( size );
}

static void
put_fourchars( str )
char* str;
{
fputs( str, stdout );
}

#if __STDC__
static void
put_big_short( short s )
#else /*__STDC__*/
static void
put_big_short( s )
short s;
#endif /*__STDC__*/
{
if ( pm_writebigshort( stdout, s ) == -1 )
pm_error( "write error" );
}

#if __STDC__
static void
put_big_long( long l )
#else /*__STDC__*/
static void
put_big_long( l )
long l;
#endif /*__STDC__*/
{
if ( pm_writebiglong( stdout, l ) == -1 )
pm_error( "write error" );
}

#if __STDC__
static void
put_byte( unsigned char b )
#else /*__STDC__*/
static void
put_byte( b )
unsigned char b;
#endif /*__STDC__*/
{
if ( putc( b, stdout ) == EOF )
pm_error( "write error" );
}
e size for noticeable speed improvement on small files. Please direct
* questions about this implementation to ames!jaw.
*/

static int g_init_bits;
static FILE* g_outfile;

static int ClearCode;
static int EOFCode;

static void
compress( init_bits, outfile, ReadValue )
int init_bits;
FILE* outfile;
ifunptr ReadValue;
{
register long fcode;
register code_int i /* = 0 */;
pbmplus05oct91/ppm/ppm.h 444 3010 34 5711 4747203177 10405 /* ppm.h - header file for libppm portable pixmap library
*/

#ifndef _PPM_H_
#define _PPM_H_

#include "pgm.h"

typedef gray pixval;

#ifdef PPM_PACKCOLORS

#define PPM_MAXMAXVAL 1023
typedef unsigned long pixel;
#define PPM_GETR(p) (((p) & 0x3ff00000) >> 20)
#define PPM_GETG(p) (((p) & 0xffc00) >> 10)
#define PPM_GETB(p) ((p) & 0x3ff)
#define PPM_ASSIGN(p,red,grn,blu) (p) = ((pixel) (red) << 20) | ((pixel) (grn) << 10) | (pixel) (blu)
#define PPM_EQUAL(p,q) ((p) == (q))

#else /*PPM_PACKCOLORS*/

#define PPM_MAXMAXVAL PGM_MAXMAXVAL
typedef struct
{
pixval r, g, b;
} pixel;
#define PPM_GETR(p) ((p).r)
#define PPM_GETG(p) ((p).g)
#define PPM_GETB(p) ((p).b)
#define PPM_ASSIGN(p,red,grn,blu) do { (p).r = (red); (p).g = (grn); (p).b = (blu); } while ( 0 )
#define PPM_EQUAL(p,q) ( (p).r == (q).r && (p).g == (q).g && (p).b == (q).b )

#endif /*PPM_PACKCOLORS*/


/* Magic constants. */

#define PPM_MAGIC1 'P'
#define PPM_MAGIC2 '3'
#define RPPM_MAGIC2 '6'
#define PPM_FORMAT (PPM_MAGIC1 * 256 + PPM_MAGIC2)
#define RPPM_FORMAT (PPM_MAGIC1 * 256 + RPPM_MAGIC2)
#define PPM_TYPE PPM_FORMAT


/* Macro for turning a format number into a type number. */

#define PPM_FORMAT_TYPE(f) ((f) == PPM_FORMAT || (f) == RPPM_FORMAT ? PPM_TYPE : PGM_FORMAT_TYPE(f))


/* Declarations of routines. */

void ppm_init ARGS(( int* argcP, char* argv[] ));

#define ppm_allocarray( cols, rows ) ((pixel**) pm_allocarray( cols, rows, sizeof(pixel) ))
#define ppm_allocrow( cols ) ((pixel*) pm_allocrow( cols, sizeof(pixel) ))
#define ppm_freearray( pixels, rows ) pm_freearray( (char**) pixels, rows )
#define ppm_freerow( pixelrow ) pm_freerow( (char*) pixelrow )

pixel** ppm_readppm ARGS(( FILE* file, int* colsP, int* rowsP, pixval* maxvalP ));
void ppm_readppminit ARGS(( FILE* file, int* colsP, int* rowsP, pixval* maxvalP, int* formatP ));
void ppm_readppmrow ARGS(( FILE* file, pixel* pixelrow, int cols, pixval maxval, int format ));

void ppm_writeppm ARGS(( FILE* file, pixel** pixels, int cols, int rows, pixval maxval, int forceplain ));
void ppm_writeppminit ARGS(( FILE* file, int cols, int rows, pixval maxval, int forceplain ));
void ppm_writeppmrow ARGS(( FILE* file, pixel* pixelrow, int cols, pixval maxval, int forceplain ));

pixel ppm_parsecolor ARGS(( char* colorname, pixval maxval ));
char* ppm_colorname ARGS(( pixel* colorP, pixval maxval, int hexok ));

extern pixval ppm_pbmmaxval;
/* This is the maxval used when a PPM program reads a PBM file. Normally
** it is 1; however, for some programs, a larger value gives better results
*/


/* Color scaling macro -- to make writing ppmtowhatever easier. */

#define PPM_DEPTH(newp,p,oldmaxval,newmaxval) \
PPM_ASSIGN( (newp), \
(int) PPM_GETR(p) * (newmaxval) / (oldmaxval), \
(int) PPM_GETG(p) * (newmaxval) / (oldmaxval), \
(int) PPM_GETB(p) * (newmaxval) / (oldmaxval) )


/* Luminance macro. */

#define PPM_LUMIN(p) ( 0.299 * PPM_GETR(p) + 0.587 * PPM_GETG(p) + 0.114 * PPM_GETB(p) )

#endif /*_PPM_H_*/
L(p,q) ((p) == (q))

#else /*PPM_PACKCOLORS*/

#define pbmplus05oct91/ppm/mtvtoppm.c 444 3010 34 3264 5032725171 11462 /* mtvtoppm.c - read an MTV ray-tracer output file and produce a portable pixmap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel* pixelrow;
register pixel* pP;
int rows, cols, row, col;
pixval maxval;
#define MAXLINE 500
char line[MAXLINE];
unsigned char buf[3];

ppm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[mtvfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

/* Read in the MTV file. First the header. */
if ( fgets( line, MAXLINE, ifp ) == NULL )
pm_error( "unable to read MTV file header" );
if ( sscanf( line, "%d%d", &cols, &rows ) != 2 )
pm_error( "unable to parse MTV file header" );

if ( cols <= 0 || rows <= 0 )
pm_error( "invalid size: %d %d", cols, rows );
maxval = 255;

ppm_writeppminit( stdout, cols, rows, maxval, 0 );
pixelrow = ppm_allocrow( cols );

for ( row = 0; row < rows; row++ )
{
for ( col = 0, pP = pixelrow; col < cols; col++, pP++ )
{
if ( fread( buf, sizeof(buf), 1, ifp ) != 1 )
pm_error( "EOF / read error" );
PPM_ASSIGN( *pP, buf[0], buf[1], buf[2] );
}
ppm_writeppmrow( stdout, pixelrow, cols, maxval, 0 );
}

pm_close( ifp );

exit( 0 );
}
3.1.cäv“
pcxtoppm.cv”
ppmtopcx.c3v• ppmtorgb3.cc.1v– ppmquantallt.cv— gouldtoppm.c1
v˜
ppmtoyuv.1 v™ pjtoppm.1.cvš ppmdither.1c.cvÇ ppmtopj.1opvÈ pjtoppm.cuwvÊ ppmdither.ciconvö ppmtopj.c
v÷
ppmtotga.c vø
ppmtotga.1 vù ppmtosixel.1 pbmplus05oct91/ppm/picttoppm.1 444 3010 34 2265 5023104050 11514 .TH picttoppm 1 "16 January 1990"
.IX picttoppm
.SH NAME
picttoppm - convert a Macintosh PICT file into a portable pixmap
.SH SYNOPSIS
.B picttoppm
.RB [ -verbose ]
.RI [ pictfile ]
.SH DESCRIPTION
Reads a PICT file (version 1 or 2) and outputs a portable pixmap.
.IX PICT
.IX Macintosh
Useful as the first step in converting a scanned image to something
that can be displayed on Unix.
.SH OPTIONS
.TP
.B -v
Turns on verbose mode which prints a
a whole bunch of information that only
.I picttoppm
hackers really care about.
.SH BUGS
The PICT file format is a general drawing format.
.I picttoppm
only supports a small subset of its operations but is still very useful for
files produced by scanning software. In particular, text added to a
scanned image will be silently ignored.
.SH SEE ALSO
Inside Macintosh volume 5,
ppmtopict(1),
ppm(5)
.SH AUTHOR
Copyright 1989 George Phillips
.\" Permission is granted to freely distribute this program in whole or in
.\" part provided you don't make money off it, you don't pretend that you
.\" wrote it and that this notice accompanies the code.
.\"
.\" George Phillips
.\" Department of Computer Science
.\" University of British Columbia
pmquantall.1Zu_ ppmmake.cZu`
ppmtoicr.1Nua ppmtopict.1»Ov~ ppmtopuzz.1Z“v
ximtoppm.1”v€
ximtoppm.c•v
ppmtoxpm.c–v‚
xpmtoppm.c®vƒ ppmtopuzz.c
v„
qrttoppm.1
v…
qrttoppm.cv†
tgatoppm.c
v‡
ppmtopi1.c vˆ
spctoppm.c v‰
sputoppm.c vŠpbmplus05oct91/ppm/ppm.5 444 3010 34 6317 5070567255 10325 .TH ppm 5 "27 September 1991"
.SH NAME
ppm - portable pixmap file format
.SH DESCRIPTION
The portable pixmap format is a lowest common denominator color image
file format.
.IX "PPM file format"
The definition is as follows:
.IP - 2
A "magic number" for identifying the file type.
A ppm file's magic number is the two characters "P3".
.IX "magic numbers"
.IP - 2
Whitespace (blanks, TABs, CRs, LFs).
.IP - 2
A width, formatted as ASCII characters in decimal.
.IP - 2
Whitespace.
.IP - 2
A height, again in ASCII decimal.
.IP - 2
Whitespace.
.IP - 2
The maximum color-component value, again in ASCII decimal.
.IP - 2
Whitespace.
.IP - 2
Width * height pixels, each three ASCII decimal values between 0 and the
specified maximum value, starting at the top-left
corner of the pixmap, proceeding in normal English reading order.
The three values for each pixel represent red, green, and blue, respectively;
a value of 0 means that color is off, and the maximum value means that color
is maxxed out.
.IP - 2
Characters from a "#" to the next end-of-line are ignored (comments).
.IP - 2
No line should be longer than 70 characters.
.PP
Here is an example of a small pixmap in this format:
.nf
P3
# feep.ppm
4 4
15
0 0 0 0 0 0 0 0 0 15 0 15
0 0 0 0 15 7 0 0 0 0 0 0
0 0 0 0 0 0 0 15 7 0 0 0
15 0 15 0 0 0 0 0 0 0 0 0
.fi
.PP
Programs that read this format should be as lenient as possible,
accepting anything that looks remotely like a pixmap.
.PP
There is also a variant on the format, available
by setting the RAWBITS option at compile time. This variant is
different in the following ways:
.IX RAWBITS
.IP - 2
The "magic number" is "P6" instead of "P3".
.IP - 2
The pixel values are stored as plain bytes, instead of ASCII decimal.
.IP - 2
Whitespace is not allowed in the pixels area, and only a single character
of whitespace (typically a newline) is allowed after the maxval.
.IP - 2
The files are smaller and many times faster to read and write.
.PP
Note that this raw format can only be used for maxvals less than
or equal to 255.
If you use the
.I ppm
library and try to write a file with a larger maxval,
it will automatically fall back on the slower but more general plain
format.
.SH "SEE ALSO"
giftoppm(1), gouldtoppm(1), ilbmtoppm(1), imgtoppm(1), mtvtoppm(1),
pcxtoppm(1), pgmtoppm(1), pi1toppm(1), picttoppm(1), pjtoppm(1), qrttoppm(1),
rawtoppm(1), rgb3toppm(1), spctoppm(1), sputoppm(1), tgatoppm(1),
ximtoppm(1), xpmtoppm(1), yuvtoppm(1),
ppmtogif(1), ppmtoicr(1), ppmtoilbm(1), ppmtopcx(1), ppmtopgm(1),
ppmtopi1(1), ppmtopict(1), ppmtopj(1), ppmtopuzz(1), ppmtorgb3(1),
ppmtosixel(1), ppmtotga(1), ppmtouil(1), ppmtoxpm(1), ppmtoyuv(1),
ppmdither(1), ppmhist(1), ppmmake(1), ppmpat(1), ppmquant(1), ppmquantall(1),
ppmrelief(1),
pnm(5), pgm(5), pbm(5)
.SH AUTHOR
Copyright (C) 1989, 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
aximum value, starting at the top-left
corner of the pixmap, proceeding in normal English reading order.
The three values for each pixel represent red, green, and blue, respectively;
a value of 0 means that color is off, and the maximum value means that color
is maxxed out.
.IP - 2
Characters from a "#" pbmplus05oct91/ppm/ppmtopi1.1 444 3010 34 1457 5023000335 11251 .TH ppmtopi1 1 "19 July 1990"
.IX ppmtopi1
.SH NAME
ppmtopi1 - convert a portable pixmap into an Atari Degas .pi1 file
.SH SYNOPSIS
.B ppmtopi1
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Produces an Atari Degas .pi1 file as output.
.IX Atari
.IX "Degas .pi1"
.SH "SEE ALSO"
pi1toppm(1), ppm(5), pbmtopi3(1), pi3topbm(1)
.SH AUTHOR
Copyright (C) 1991 by Steve Belczyk ([email protected]) and Jef Poskanzer.
.\" Permission to use, copy, modify and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/ppmmake.1 444 3010 34 2651 5070270647 11150 .TH ppmmake 1 "24 September 1991"
.IX ppmmake
.SH NAME
ppmmake - create a pixmap of a specified size
.SH SYNOPSIS
.B ppmmake
.I color width height
.SH DESCRIPTION
Produces a portable pixmap of the specified color, width, and height.
.IX "generating pixmaps"
.PP
The color can be specified in five ways:
.IX "specifying colors"
.TP
o
A name, assuming
that a pointer to an X11-style color names file was compiled in.
.TP
o
An X11-style hexadecimal specifier: rgb:r/g/b, where r g and b are
each 1- to 4-digit hexadecimal numbers.
.TP
o
An X11-style decimal specifier: rgbi:r/g/b, where r g and b are
floating point numbers between 0 and 1.
.TP
o
For backwards compatibility, an old-X11-style hexadecimal
number: #rgb, #rrggbb, #rrrgggbbb, or #rrrrggggbbbb.
.TP
o
For backwards compatibility, a triplet of numbers
separated by commas: r,g,b, where r g and b are
floating point numbers between 0 and 1.
(This style was added before MIT came up with the similar rgbi style.)
.SH "SEE ALSO"
ppm(5), pbmmake(1)
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
cv†
tgatoppm.c
v‡
ppmtopi1.c vˆ
spctoppm.c v‰
sputoppm.c vŠpbmplus05oct91/ppm/xim.h 444 3010 34 12636 4746227465 10437 /* xim.h - header file for Xim files
**
** Taken from the X.V11R4 version of XimHeader.h:
**
** Author: Philip R. Thompson
** Address: [email protected], 9-526
** Note: size of header should be 1024 (1K) bytes.
** $Header: /mit/phils/X/RCS/XimHeader.h,v 1.7 89/11/09 17:26:54 phils Exp Locker: phils $
** $Date: 89/11/09 17:26:54 $
** $Source: /mit/phils/X/RCS/XimHeader.h,v $
*/

#define IMAGE_VERSION 3
#ifndef _BYTE
typedef unsigned char byte;
#define _BYTE 1
#endif

/* External ascii file format. */
typedef struct ImageHeader {
char file_version[8]; /* header version */
char header_size[8]; /* Size of file header in bytes */
char image_width[8]; /* Width of the raster image */
char image_height[8]; /* Height of the raster imgage */
char num_colors[8]; /* Actual number of entries in c_map */
char num_channels[3]; /* 0 or 1 = pixmap, 3 = RG&B buffers */
char bytes_per_line[5]; /* bytes per scanline */
char num_pictures[4]; /* Number of pictures in file */
char bits_per_channel[4]; /* usually 1 or 8 */
char alpha_channel[4]; /* Alpha channel flag */
char runlength[4]; /* Runlength encoded flag */
char author[48]; /* Name of who made it */
char date[32]; /* Date and time image was made */
char program[16]; /* Program that created this file */
char comment[96]; /* other viewing info. for this image */
unsigned char c_map[256][3]; /* RGB values of the pixmap indices */
} ImageHeader, XimAsciiHeader;


/* Internal binary format. */
typedef struct Color {
byte pixel, red, grn, blu;
} Color;

typedef struct XimImage {
int width; /* width of the image in pixels */
int height; /* height of the image in pixels */
unsigned datasize; /* size of one channel of data */
short nchannels; /* number data channels in image */
short bits_channel; /* usually 1 or 8 */
short bytes_per_line; /* bytes to hold one scanline */
byte* data; /* pixmap or red channel data */
byte* grn_data; /* green channel data */
byte* blu_data; /* blue channel data */
byte* other; /* other (alpha) data */
unsigned alpha_flag :1; /* alpha channel flag */
unsigned packed_flag:1; /* data packed in one chunk of memory */
unsigned runlen_flag:1; /* runlength encoded data flag */
unsigned : 0; /* future flags, word alignment */
short tpics, npics; /* number of images, total & left in file */
short ncolors; /* " " colors in the color table */
Color* colors; /* colortable, one byte per r/g/b & pixel */
char* author; /* author credit, copyright, etc */
char* date; /* date image was made, grabbed, etc. */
char* program; /* program used to make this */
short ncomments; /* number of comments strings */
char** comments; /* pointers to null terminated strings */
char* offset; /* original offset in machine memory */
float chroma_red[2]; /* x, y image chromacity coords */
float chroma_grn[2];
float chroma_blu[2];
float chroma_wht[2];
float gamma; /* image storage gamma */
} XimImage;

/* Future external ascii variable length header - under review. */
#if (VERSION == 4)
typedef struct XimAsciiHeader {
char file_version[4]; /* header version */
char header_size[8]; /* Size of file header (fixed part only) */
char image_height[8]; /* Height of the raster imgage in pixels */
char image_width[8]; /* Width of the raster image in pixels */
char bytes_line[8]; /* Actual # of bytes separating scanlines */
char bits_channel[4]; /* Bits per channel (usually 1 or 8) */
char num_channels[4]; /* 1 = pixmap, 3 = RG&B buffers */
char alpha_channel[2]; /* Alpha channel flag */
char num_colors[4]; /* Number of entries in c_map (if any) */
char num_pictures[4]; /* Number of images in file */
char runlength_flag[2]; /* Runlength encoded flag */
char future_flags[8];
char author[48]; /* Name of who made it, from passwd entry */
char date[32]; /* Unix format date */
char program[32]; /* Program that created this */
char gamma[12]; /* image storage gamma */
char chroma_red[24]; /* image red primary chromaticity coords. */
char chroma_grn[24]; /* " green " " " */
char chroma_blu[24]; /* " blue " " " */
char chroma_wht[24]; /* " white point " " */
char comment_length[8] /* Total length of comments */
/* char* comment; Null separated comments */
/* unsigned char c_map[]; RGB Colortable, (ncolors * 3 bytes) */
} XimAsciiHeader;
#endif /*VERSION 4*/

#ifndef rnd
#define rnd(x) ((int)((float)(x) + 0.5)) /* round a float to an int */
#endif

/* Note:
* - All data is in char's in order to maintain easily portability
* across machines, and some human readibility.
* - Images may be stored as pixmaps (8 bits/pixel) or as seperate
* red, green, blue channel data (24+ bits/pixel).
* - An alpha channel is optional and is found after every num_channels
* of data.
* - Pixmaps or RGB (and alpha) channel data are stored respectively
* after the header.
* - If num_channels = 1, a pixmap is assumed and the colormap in the
* header is used.
* - Data size = image_width * image_height.
*/
, word alignment */
short tpics, npics; /* number of images, total & left in file */
shpbmplus05oct91/ppm/ppmrelief.1 444 3010 34 1701 5022777261 11475 .TH ppmrelief 1 "11 January 1991"
.IX ppmrelief
.SH NAME
ppmrelief - run a Laplacian relief filter on a portable pixmap
.SH SYNOPSIS
.B ppmrelief
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Does a Laplacian relief filter, and writes a portable pixmap as output.
.IX "Laplacian relief"
.PP
The Laplacian relief filter is described in "Beyond Photography" by Holzmann,
equation 3.19.
It's a sort of edge-detection.
.IX "edge detection"
.SH "SEE ALSO"
pgmbentley(1), pgmoil(1), ppm(5)
.SH AUTHOR
Copyright (C) 1990 by Wilson Bent ([email protected])
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
 ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/libppm.h 444 3010 34 433 4742173125 11042 /* libppm.h - internal header file for libppm portable pixmap library
*/

#ifndef _LIBPPM_H_
#define _LIBPPM_H_

/* Here are some routines internal to the ppm library. */

void ppm_readppminitrest ARGS(( FILE* file, int* colsP, int* rowsP, pixval* maxvalP ));

#endif /*_LIBPPM_H_*/
ZcsD ilbmtoppm.1SZdsE
ppmtogif.1esF
imgtoppm.1fsGtga.hn.sH ppmtoilbm.1c½ÉsI
mtvtoppm.1ÊsJ libppm4.c.csKlibppm.3go.sL ppmcmap.hcosM ppmhist.cuwsN
ppmquant.1 pbmplus05oct91/ppm/ppmtopgm.c 444 3010 34 16440 5032725217 11460 /* ppmtopgm.c - convert a portable pixmap to a portable graymap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "pgm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel* pixelrow;
register pixel* pP;
gray* grayrow;
register gray* gP;
int rows, cols, format, row;
register int col;
pixval maxval;

/* Lookup tables for fast RGB -> luminance calculation. */
static int times77[256] = {
0, 77, 154, 231, 308, 385, 462, 539,
616, 693, 770, 847, 924, 1001, 1078, 1155,
1232, 1309, 1386, 1463, 1540, 1617, 1694, 1771,
1848, 1925, 2002, 2079, 2156, 2233, 2310, 2387,
2464, 2541, 2618, 2695, 2772, 2849, 2926, 3003,
3080, 3157, 3234, 3311, 3388, 3465, 3542, 3619,
3696, 3773, 3850, 3927, 4004, 4081, 4158, 4235,
4312, 4389, 4466, 4543, 4620, 4697, 4774, 4851,
4928, 5005, 5082, 5159, 5236, 5313, 5390, 5467,
5544, 5621, 5698, 5775, 5852, 5929, 6006, 6083,
6160, 6237, 6314, 6391, 6468, 6545, 6622, 6699,
6776, 6853, 6930, 7007, 7084, 7161, 7238, 7315,
7392, 7469, 7546, 7623, 7700, 7777, 7854, 7931,
8008, 8085, 8162, 8239, 8316, 8393, 8470, 8547,
8624, 8701, 8778, 8855, 8932, 9009, 9086, 9163,
9240, 9317, 9394, 9471, 9548, 9625, 9702, 9779,
9856, 9933, 10010, 10087, 10164, 10241, 10318, 10395,
10472, 10549, 10626, 10703, 10780, 10857, 10934, 11011,
11088, 11165, 11242, 11319, 11396, 11473, 11550, 11627,
11704, 11781, 11858, 11935, 12012, 12089, 12166, 12243,
12320, 12397, 12474, 12551, 12628, 12705, 12782, 12859,
12936, 13013, 13090, 13167, 13244, 13321, 13398, 13475,
13552, 13629, 13706, 13783, 13860, 13937, 14014, 14091,
14168, 14245, 14322, 14399, 14476, 14553, 14630, 14707,
14784, 14861, 14938, 15015, 15092, 15169, 15246, 15323,
15400, 15477, 15554, 15631, 15708, 15785, 15862, 15939,
16016, 16093, 16170, 16247, 16324, 16401, 16478, 16555,
16632, 16709, 16786, 16863, 16940, 17017, 17094, 17171,
17248, 17325, 17402, 17479, 17556, 17633, 17710, 17787,
17864, 17941, 18018, 18095, 18172, 18249, 18326, 18403,
18480, 18557, 18634, 18711, 18788, 18865, 18942, 19019,
19096, 19173, 19250, 19327, 19404, 19481, 19558, 19635 };
static int times150[256] = {
0, 150, 300, 450, 600, 750, 900, 1050,
1200, 1350, 1500, 1650, 1800, 1950, 2100, 2250,
2400, 2550, 2700, 2850, 3000, 3150, 3300, 3450,
3600, 3750, 3900, 4050, 4200, 4350, 4500, 4650,
4800, 4950, 5100, 5250, 5400, 5550, 5700, 5850,
6000, 6150, 6300, 6450, 6600, 6750, 6900, 7050,
7200, 7350, 7500, 7650, 7800, 7950, 8100, 8250,
8400, 8550, 8700, 8850, 9000, 9150, 9300, 9450,
9600, 9750, 9900, 10050, 10200, 10350, 10500, 10650,
10800, 10950, 11100, 11250, 11400, 11550, 11700, 11850,
12000, 12150, 12300, 12450, 12600, 12750, 12900, 13050,
13200, 13350, 13500, 13650, 13800, 13950, 14100, 14250,
14400, 14550, 14700, 14850, 15000, 15150, 15300, 15450,
15600, 15750, 15900, 16050, 16200, 16350, 16500, 16650,
16800, 16950, 17100, 17250, 17400, 17550, 17700, 17850,
18000, 18150, 18300, 18450, 18600, 18750, 18900, 19050,
19200, 19350, 19500, 19650, 19800, 19950, 20100, 20250,
20400, 20550, 20700, 20850, 21000, 21150, 21300, 21450,
21600, 21750, 21900, 22050, 22200, 22350, 22500, 22650,
22800, 22950, 23100, 23250, 23400, 23550, 23700, 23850,
24000, 24150, 24300, 24450, 24600, 24750, 24900, 25050,
25200, 25350, 25500, 25650, 25800, 25950, 26100, 26250,
26400, 26550, 26700, 26850, 27000, 27150, 27300, 27450,
27600, 27750, 27900, 28050, 28200, 28350, 28500, 28650,
28800, 28950, 29100, 29250, 29400, 29550, 29700, 29850,
30000, 30150, 30300, 30450, 30600, 30750, 30900, 31050,
31200, 31350, 31500, 31650, 31800, 31950, 32100, 32250,
32400, 32550, 32700, 32850, 33000, 33150, 33300, 33450,
33600, 33750, 33900, 34050, 34200, 34350, 34500, 34650,
34800, 34950, 35100, 35250, 35400, 35550, 35700, 35850,
36000, 36150, 36300, 36450, 36600, 36750, 36900, 37050,
37200, 37350, 37500, 37650, 37800, 37950, 38100, 38250 };
static int times29[256] = {
0, 29, 58, 87, 116, 145, 174, 203,
232, 261, 290, 319, 348, 377, 406, 435,
464, 493, 522, 551, 580, 609, 638, 667,
696, 725, 754, 783, 812, 841, 870, 899,
928, 957, 986, 1015, 1044, 1073, 1102, 1131,
1160, 1189, 1218, 1247, 1276, 1305, 1334, 1363,
1392, 1421, 1450, 1479, 1508, 1537, 1566, 1595,
1624, 1653, 1682, 1711, 1740, 1769, 1798, 1827,
1856, 1885, 1914, 1943, 1972, 2001, 2030, 2059,
2088, 2117, 2146, 2175, 2204, 2233, 2262, 2291,
2320, 2349, 2378, 2407, 2436, 2465, 2494, 2523,
2552, 2581, 2610, 2639, 2668, 2697, 2726, 2755,
2784, 2813, 2842, 2871, 2900, 2929, 2958, 2987,
3016, 3045, 3074, 3103, 3132, 3161, 3190, 3219,
3248, 3277, 3306, 3335, 3364, 3393, 3422, 3451,
3480, 3509, 3538, 3567, 3596, 3625, 3654, 3683,
3712, 3741, 3770, 3799, 3828, 3857, 3886, 3915,
3944, 3973, 4002, 4031, 4060, 4089, 4118, 4147,
4176, 4205, 4234, 4263, 4292, 4321, 4350, 4379,
4408, 4437, 4466, 4495, 4524, 4553, 4582, 4611,
4640, 4669, 4698, 4727, 4756, 4785, 4814, 4843,
4872, 4901, 4930, 4959, 4988, 5017, 5046, 5075,
5104, 5133, 5162, 5191, 5220, 5249, 5278, 5307,
5336, 5365, 5394, 5423, 5452, 5481, 5510, 5539,
5568, 5597, 5626, 5655, 5684, 5713, 5742, 5771,
5800, 5829, 5858, 5887, 5916, 5945, 5974, 6003,
6032, 6061, 6090, 6119, 6148, 6177, 6206, 6235,
6264, 6293, 6322, 6351, 6380, 6409, 6438, 6467,
6496, 6525, 6554, 6583, 6612, 6641, 6670, 6699,
6728, 6757, 6786, 6815, 6844, 6873, 6902, 6931,
6960, 6989, 7018, 7047, 7076, 7105, 7134, 7163,
7192, 7221, 7250, 7279, 7308, 7337, 7366, 7395 };

ppm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[ppmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
pgm_writepgminit( stdout, cols, rows, maxval, 0 );
pixelrow = ppm_allocrow( cols );
grayrow = pgm_allocrow( cols );

for ( row = 0; row < rows; ++row )
{
ppm_readppmrow( ifp, pixelrow, cols, maxval, format );
if ( maxval <= 255 )
/* Use fast approximation to 0.299 r + 0.587 g + 0.114 b. */
for ( col = 0, pP = pixelrow, gP = grayrow;
col < cols;
++col, ++pP, ++gP )
*gP = (gray)
( ( times77[PPM_GETR( *pP )] + times150[PPM_GETG( *pP )] +
times29[PPM_GETB( *pP )] ) >> 8 );
else
/* Can't use fast approximation, so fall back on floats. */
for ( col = 0, pP = pixelrow, gP = grayrow;
col < cols;
++col, ++pP, ++gP )
*gP = (gray) ( PPM_LUMIN( *pP ) + 0.5 );
pgm_writepgmrow( stdout, grayrow, cols, maxval, 0 );
}

pm_close( ifp );

exit( 0 );
}
LE* g_outfile;

static int ClearCode;
static int EOFCode;

static void
compress( init_bits, outfile, ReadValue )
int init_bits;
FILE* outfile;
ifunptr ReadValue;
{
register long fcode;
register code_int i /* = 0 */;
pbmplus05oct91/ppm/ppmtopgm.1 444 3010 34 2463 5022777526 11367 .TH ppmtopgm 1 "23 December 1988"
.IX ppmtopgm
.SH NAME
ppmtopgm - convert a portable pixmap into a portable graymap
.SH SYNOPSIS
.B ppmtopgm
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Produces a portable graymap as output.
The quantization formula used is .299 r + .587 g + .114 b.
.PP
Note that although there is a
.I pgmtoppm
program, it is not necessary
for simple conversions from
.I pgm
to
.IR ppm ,
because any ppm program can
read
.I pgm
(and
.I pbm
) files automagically.
.I pgmtoppm
is for colorizing a
.I pgm
file. Also, see
.I ppmtorgb3
.IX ppmtorgb3
for a different way of converting color to gray.
.SH QUOTE
.nf
Cold-hearted orb that rules the night
Removes the colors from our sight
Red is gray, and yellow white
But we decide which is right
And which is a quantization error.
.fi
.SH "SEE ALSO"
pgmtoppm(1), ppmtorgb3(1), rgb3toppm(1), ppm(5), pgm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
€
ximtoppm.c•v
ppmtoxpm.c–v‚
xpmtoppm.c®vƒ ppmtopuzz.c
v„
qrttoppm.1
v…
qrttoppm.cv†
tgatoppm.c
v‡
ppmtopi1.c vˆ
spctoppm.c v‰
sputoppm.c vŠpbmplus05oct91/ppm/libppm1.c 444 3010 34 10557 5032735304 11162 /* libppm1.c - ppm utility library part 1
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "libppm.h"
#include "pgm.h"
#include "libpgm.h"
#include "pbm.h"
#include "libpbm.h"

void
ppm_init( argcP, argv )
int* argcP;
char* argv[];
{
pgm_init( argcP, argv );
}

void
ppm_readppminitrest( file, colsP, rowsP, maxvalP )
FILE* file;
int* colsP;
int* rowsP;
pixval* maxvalP;
{
int maxval;

/* Read size. */
*colsP = pbm_getint( file );
*rowsP = pbm_getint( file );

/* Read maxval. */
maxval = pbm_getint( file );
if ( maxval > PPM_MAXMAXVAL )
pm_error(
"maxval is too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS" );
*maxvalP = maxval;
}

pixval ppm_pbmmaxval = 1;

void
ppm_readppminit( file, colsP, rowsP, maxvalP, formatP )
FILE* file;
int* colsP;
int* rowsP;
int* formatP;
pixval* maxvalP;
{
/* Check magic number. */
*formatP = pbm_readmagicnumber( file );
switch ( PPM_FORMAT_TYPE(*formatP) )
{
case PPM_TYPE:
ppm_readppminitrest( file, colsP, rowsP, maxvalP );
break;

case PGM_TYPE:
pgm_readpgminitrest( file, colsP, rowsP, maxvalP );
break;

case PBM_TYPE:
pbm_readpbminitrest( file, colsP, rowsP );
*maxvalP = ppm_pbmmaxval;
break;

default:
pm_error( "bad magic number - not a ppm, pgm, or pbm file" );
}
}

#if __STDC__
void
ppm_readppmrow( FILE* file, pixel* pixelrow, int cols, pixval maxval, int format )
#else /*__STDC__*/
void
ppm_readppmrow( file, pixelrow, cols, maxval, format )
FILE* file;
pixel* pixelrow;
int cols, format;
pixval maxval;
#endif /*__STDC__*/
{
register int col;
register pixel* pP;
register pixval r, g, b;
gray* grayrow;
register gray* gP;
bit* bitrow;
register bit* bP;

switch ( format )
{
case PPM_FORMAT:
for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
{
r = pbm_getint( file );
#ifdef DEBUG
if ( r > maxval )
pm_error( "r value out of bounds (%u > %u)", r, maxval );
#endif /*DEBUG*/
g = pbm_getint( file );
#ifdef DEBUG
if ( g > maxval )
pm_error( "g value out of bounds (%u > %u)", g, maxval );
#endif /*DEBUG*/
b = pbm_getint( file );
#ifdef DEBUG
if ( b > maxval )
pm_error( "b value out of bounds (%u > %u)", b, maxval );
#endif /*DEBUG*/
PPM_ASSIGN( *pP, r, g, b );
}
break;

case RPPM_FORMAT:
for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
{
r = pbm_getrawbyte( file );
#ifdef DEBUG
if ( r > maxval )
pm_error( "r value out of bounds (%u > %u)", r, maxval );
#endif /*DEBUG*/
g = pbm_getrawbyte( file );
#ifdef DEBUG
if ( g > maxval )
pm_error( "g value out of bounds (%u > %u)", g, maxval );
#endif /*DEBUG*/
b = pbm_getrawbyte( file );
#ifdef DEBUG
if ( b > maxval )
pm_error( "b value out of bounds (%u > %u)", b, maxval );
#endif /*DEBUG*/
PPM_ASSIGN( *pP, r, g, b );
}
break;

case PGM_FORMAT:
case RPGM_FORMAT:
grayrow = pgm_allocrow( cols );
pgm_readpgmrow( file, grayrow, cols, maxval, format );
for ( col = 0, gP = grayrow, pP = pixelrow; col < cols; ++col, ++gP, ++pP )
{
r = *gP;
PPM_ASSIGN( *pP, r, r, r );
}
pgm_freerow( grayrow );
break;

case PBM_FORMAT:
case RPBM_FORMAT:
bitrow = pbm_allocrow( cols );
pbm_readpbmrow( file, bitrow, cols, format );
for ( col = 0, bP = bitrow, pP = pixelrow; col < cols; ++col, ++bP, ++pP )
{
r = ( *bP == PBM_WHITE ) ? maxval : 0;
PPM_ASSIGN( *pP, r, r, r );
}
pbm_freerow( bitrow );
break;

default:
pm_error( "can't happen" );
}
}

pixel**
ppm_readppm( file, colsP, rowsP, maxvalP )
FILE* file;
int* colsP;
int* rowsP;
pixval* maxvalP;
{
pixel** pixels;
int row;
int format;

ppm_readppminit( file, colsP, rowsP, maxvalP, &format );

pixels = ppm_allocarray( *colsP, *rowsP );

for ( row = 0; row < *rowsP; ++row )
ppm_readppmrow( file, pixels[row], *colsP, *maxvalP, format );

return pixels;
}
ifp = pm_openr( argv[1] );
else
ifp = stdin;

ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
pgm_writepgminit( stdout, colpbmplus05oct91/ppm/libppm2.c 444 3010 34 11533 5032725163 11160 /* libppm2.c - ppm utility library part 2
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "libppm.h"

#if __STDC__
void
ppm_writeppminit( FILE* file, int cols, int rows, pixval maxval, int forceplain )
#else /*__STDC__*/
void
ppm_writeppminit( file, cols, rows, maxval, forceplain )
FILE* file;
int cols, rows;
pixval maxval;
int forceplain;
#endif /*__STDC__*/
{
#ifdef PBMPLUS_RAWBITS
if ( maxval <= 255 && ! forceplain )
fprintf(
file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, RPPM_MAGIC2,
cols, rows, maxval );
else
fprintf(
file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, PPM_MAGIC2,
cols, rows, maxval );
#else /*PBMPLUS_RAWBITS*/
fprintf(
file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, PPM_MAGIC2,
cols, rows, maxval );
#endif /*PBMPLUS_RAWBITS*/
}

static int
putus( n, file )
unsigned short n;
FILE* file;
{
if ( n >= 10 )
if ( putus( n / 10, file ) == EOF )
return EOF;
return putc( n % 10 + '0', file );
}

#ifdef PBMPLUS_RAWBITS
static void
ppm_writeppmrowraw( file, pixelrow, cols, maxval )
FILE* file;
pixel* pixelrow;
int cols;
pixval maxval;
{
register int col;
register pixel* pP;
register pixval val;

for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
{
val = PPM_GETR( *pP );
#ifdef DEBUG
if ( val > maxval )
pm_error( "r value out of bounds (%u > %u)", val, maxval );
#endif /*DEBUG*/
if ( putc( val, file ) == EOF )
pm_error( "write error" );
val = PPM_GETG( *pP );
#ifdef DEBUG
if ( val > maxval )
pm_error( "g value out of bounds (%u > %u)", val, maxval );
#endif /*DEBUG*/
if ( putc( val, file ) == EOF )
pm_error( "write error" );
val = PPM_GETB( *pP );
#ifdef DEBUG
if ( val > maxval )
pm_error( "b value out of bounds (%u > %u)", val, maxval );
#endif /*DEBUG*/
if ( putc( val, file ) == EOF )
pm_error( "write error" );
}
}
#endif /*PBMPLUS_RAWBITS*/

static void
ppm_writeppmrowplain( file, pixelrow, cols, maxval )
FILE* file;
pixel* pixelrow;
int cols;
pixval maxval;
{
register int col, charcount;
register pixel* pP;
register pixval val;

charcount = 0;
for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
{
if ( charcount >= 65 )
{
if ( putc( '\n', file ) == EOF )
pm_error( "write error" );
charcount = 0;
}
else if ( charcount > 0 )
{
if ( putc( ' ', file ) == EOF )
pm_error( "write error" );
if ( putc( ' ', file ) == EOF )
pm_error( "write error" );
charcount += 2;
}
val = PPM_GETR( *pP );
#ifdef DEBUG
if ( val > maxval )
pm_error( "r value out of bounds (%u > %u)", val, maxval );
#endif /*DEBUG*/
if ( putus( val, file ) == EOF )
pm_error( "write error" );
if ( putc( ' ', file ) == EOF )
pm_error( "write error" );
val = PPM_GETG( *pP );
#ifdef DEBUG
if ( val > maxval )
pm_error( "g value out of bounds (%u > %u)", val, maxval );
#endif /*DEBUG*/
if ( putus( val, file ) == EOF )
pm_error( "write error" );
if ( putc( ' ', file ) == EOF )
pm_error( "write error" );
val = PPM_GETB( *pP );
#ifdef DEBUG
if ( val > maxval )
pm_error( "b value out of bounds (%u > %u)", val, maxval );
#endif /*DEBUG*/
if ( putus( val, file ) == EOF )
pm_error( "write error" );
charcount += 11;
}
if ( charcount > 0 )
if ( putc( '\n', file ) == EOF )
pm_error( "write error" );
}

#if __STDC__
void
ppm_writeppmrow( FILE* file, pixel* pixelrow, int cols, pixval maxval, int forceplain )
#else /*__STDC__*/
void
ppm_writeppmrow( file, pixelrow, cols, maxval, forceplain )
FILE* file;
pixel* pixelrow;
int cols;
pixval maxval;
int forceplain;
#endif /*__STDC__*/
{
#ifdef PBMPLUS_RAWBITS
if ( maxval <= 255 && ! forceplain )
ppm_writeppmrowraw( file, pixelrow, cols, maxval );
else
ppm_writeppmrowplain( file, pixelrow, cols, maxval );
#else /*PBMPLUS_RAWBITS*/
ppm_writeppmrowplain( file, pixelrow, cols, maxval );
#endif /*PBMPLUS_RAWBITS*/
}

#if __STDC__
void
ppm_writeppm( FILE* file, pixel** pixels, int cols, int rows, pixval maxval, int forceplain )
#else /*__STDC__*/
void
ppm_writeppm( file, pixels, cols, rows, maxval, forceplain )
FILE* file;
pixel** pixels;
int cols, rows;
pixval maxval;
int forceplain;
#endif /*__STDC__*/
{
int row;

ppm_writeppminit( file, cols, rows, maxval, forceplain );

for ( row = 0; row < rows; ++row )
ppm_writeppmrow( file, pixels[row], cols, maxval, forceplain );
}
10 + '0', file );
}

#ifdef PBMPLUS_RAWBITS
static void
ppm_writeppmrowraw( file, pixelrow, cols, maxval )
FILE* file;
pixel* pixelrow;
int cols;
pbmplus05oct91/ppm/libppm3.c 444 3010 34 14324 5032726532 11163 /* libppm3.c - ppm utility library part 3
**
** Colormap routines.
**
** Copyright (C) 1989, 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "ppmcmap.h"
#include "libppm.h"

#define HASH_SIZE 20023

#ifdef PPM_PACKCOLORS
#define ppm_hashpixel(p) ( ( (int) (p) & 0x7fffffff ) % HASH_SIZE )
#else /*PPM_PACKCOLORS*/
#define ppm_hashpixel(p) ( ( ( (long) PPM_GETR(p) * 33023 + (long) PPM_GETG(p) * 30013 + (long) PPM_GETB(p) * 27011 ) & 0x7fffffff ) % HASH_SIZE )
#endif /*PPM_PACKCOLORS*/

colorhist_vector
ppm_computecolorhist( pixels, cols, rows, maxcolors, colorsP )
pixel** pixels;
int cols, rows, maxcolors;
int* colorsP;
{
colorhash_table cht;
colorhist_vector chv;

cht = ppm_computecolorhash( pixels, cols, rows, maxcolors, colorsP );
if ( cht == (colorhash_table) 0 )
return (colorhist_vector) 0;
chv = ppm_colorhashtocolorhist( cht, maxcolors );
ppm_freecolorhash( cht );
return chv;
}

void
ppm_addtocolorhist( chv, colorsP, maxcolors, colorP, value, position )
colorhist_vector chv;
pixel* colorP;
int* colorsP;
int maxcolors, value, position;
{
int i, j;

/* Search colorhist for the color. */
for ( i = 0; i < *colorsP; ++i )
if ( PPM_EQUAL( chv[i].color, *colorP ) )
{
/* Found it - move to new slot. */
if ( position > i )
{
for ( j = i; j < position; ++j )
chv[j] = chv[j + 1];
}
else if ( position < i )
{
for ( j = i; j > position; --j )
chv[j] = chv[j - 1];
}
chv[position].color = *colorP;
chv[position].value = value;
return;
}
if ( *colorsP < maxcolors )
{
/* Didn't find it, but there's room to add it; so do so. */
for ( i = *colorsP; i > position; --i )
chv[i] = chv[i - 1];
chv[position].color = *colorP;
chv[position].value = value;
++(*colorsP);
}
}

colorhash_table
ppm_computecolorhash( pixels, cols, rows, maxcolors, colorsP )
pixel** pixels;
int cols, rows, maxcolors;
int* colorsP;
{
colorhash_table cht;
register pixel* pP;
colorhist_list chl;
int col, row, hash;

cht = ppm_alloccolorhash( );
*colorsP = 0;

/* Go through the entire image, building a hash table of colors. */
for ( row = 0; row < rows; ++row )
for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
{
hash = ppm_hashpixel( *pP );
for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
if ( PPM_EQUAL( chl->ch.color, *pP ) )
break;
if ( chl != (colorhist_list) 0 )
++(chl->ch.value);
else
{
if ( ++(*colorsP) > maxcolors )
{
ppm_freecolorhash( cht );
return (colorhash_table) 0;
}
chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
if ( chl == 0 )
pm_error( "out of memory computing hash table" );
chl->ch.color = *pP;
chl->ch.value = 1;
chl->next = cht[hash];
cht[hash] = chl;
}
}

return cht;
}

colorhash_table
ppm_alloccolorhash( )
{
colorhash_table cht;
int i;

cht = (colorhash_table) malloc( HASH_SIZE * sizeof(colorhist_list) );
if ( cht == 0 )
pm_error( "out of memory allocating hash table" );

for ( i = 0; i < HASH_SIZE; ++i )
cht[i] = (colorhist_list) 0;

return cht;
}

int
ppm_addtocolorhash( cht, colorP, value )
colorhash_table cht;
pixel* colorP;
int value;
{
register int hash;
register colorhist_list chl;

chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
if ( chl == 0 )
return -1;
hash = ppm_hashpixel( *colorP );
chl->ch.color = *colorP;
chl->ch.value = value;
chl->next = cht[hash];
cht[hash] = chl;
return 0;
}

colorhist_vector
ppm_colorhashtocolorhist( cht, maxcolors )
colorhash_table cht;
int maxcolors;
{
colorhist_vector chv;
colorhist_list chl;
int i, j;

/* Now collate the hash table into a simple colorhist array. */
chv = (colorhist_vector) malloc( maxcolors * sizeof(struct colorhist_item) );
/* (Leave room for expansion by caller.) */
if ( chv == (colorhist_vector) 0 )
pm_error( "out of memory generating histogram" );

/* Loop through the hash table. */
j = 0;
for ( i = 0; i < HASH_SIZE; ++i )
for ( chl = cht[i]; chl != (colorhist_list) 0; chl = chl->next )
{
/* Add the new entry. */
chv[j] = chl->ch;
++j;
}

/* All done. */
return chv;
}

colorhash_table
ppm_colorhisttocolorhash( chv, colors )
colorhist_vector chv;
int colors;
{
colorhash_table cht;
int i, hash;
pixel color;
colorhist_list chl;

cht = ppm_alloccolorhash( );

for ( i = 0; i < colors; ++i )
{
color = chv[i].color;
hash = ppm_hashpixel( color );
for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
if ( PPM_EQUAL( chl->ch.color, color ) )
pm_error(
"same color found twice - %d %d %d", PPM_GETR(color),
PPM_GETG(color), PPM_GETB(color) );
chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
if ( chl == (colorhist_list) 0 )
pm_error( "out of memory" );
chl->ch.color = color;
chl->ch.value = i;
chl->next = cht[hash];
cht[hash] = chl;
}

return cht;
}

int
ppm_lookupcolor( cht, colorP )
colorhash_table cht;
pixel* colorP;
{
int hash;
colorhist_list chl;

hash = ppm_hashpixel( *colorP );
for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
if ( PPM_EQUAL( chl->ch.color, *colorP ) )
return chl->ch.value;

return -1;
}

void
ppm_freecolorhist( chv )
colorhist_vector chv;
{
free( (char*) chv );
}

void
ppm_freecolorhash( cht )
colorhash_table cht;
{
int i;
colorhist_list chl, chlnext;

for ( i = 0; i < HASH_SIZE; ++i )
for ( chl = cht[i]; chl != (colorhist_list) 0; chl = chlnext )
{
chlnext = chl->next;
free( (char*) chl );
}
free( (char*) cht );
}
any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#inpbmplus05oct91/ppm/xpmtoppm.1 444 3010 34 1352 5023000247 11360 .TH xpmtoppm 1 "16 August 1990"
.IX xpmtoppm
.SH NAME
xpmtoppm - convert an X11 pixmap into a portable pixmap
.SH SYNOPSIS
.B xpmtoppm
.RI [ xpmfile ]
.SH DESCRIPTION
Reads an X11 pixmap (XPM) as input.
.IX XPM
.IX "X window system"
Produces a portable pixmap as output.
.SH "SEE ALSO"
ppmtoxpm(1), ppm(5)
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
pm.1ks[
giftoppm.cds\ gouldtoppm.1Z{s]
pi1toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/sputoppm.1 444 3010 34 1447 5023000170 11363 .TH sputoppm 1 "19 July 1990"
.IX sputoppm
.SH NAME
sputoppm - convert an Atari uncompressed Spectrum file into a portable pixmap
.SH SYNOPSIS
.B sputoppm
.RI [ spufile ]
.SH DESCRIPTION
Reads an Atari uncompressed Spectrum file as input.
.IX Atari
.IX Spectrum
Produces a portable pixmap as output.
.SH "SEE ALSO"
spctoppm(1), ppm(5)
.SH AUTHOR
Copyright (C) 1991 by Steve Belczyk ([email protected]) and Jef Poskanzer.
.\" Permission to use, copy, modify and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/spctoppm.1 444 3010 34 1443 5023000151 11334 .TH spctoppm 1 "19 July 1990"
.IX spctoppm
.SH NAME
spctoppm - convert an Atari compressed Spectrum file into a portable pixmap
.SH SYNOPSIS
.B spctoppm
.RI [ spcfile ]
.SH DESCRIPTION
Reads an Atari compressed Spectrum file as input.
.IX Atari
.IX Spectrum
Produces a portable pixmap as output.
.SH "SEE ALSO"
sputoppm(1), ppm(5)
.SH AUTHOR
Copyright (C) 1991 by Steve Belczyk ([email protected]) and Jef Poskanzer.
.\" Permission to use, copy, modify and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.

pi1toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/ppmquantall.1 444 3010 34 3316 5022777211 12047 .TH ppmquantall 1 "27 July 1990"
.IX ppmquantall
.SH NAME
ppmquantall - run ppmquant on a bunch of files all at once, so they share a common colormap
.SH SYNOPSIS
.B ppmquantall
.I ncolors ppmfile
.RI ...
.SH DESCRIPTION
Takes a bunch of portable pixmap as input.
Chooses
.I ncolors
colors to best represent all of the images, maps the
existing colors to the new ones, and
.B overwrites the input files
with the new quantized versions.
.IX "colormap reduction"
.PP
Verbose explanation: Let's say you've got a dozen pixmaps that you want
to display on the screen all at the same time. Your screen can only
display 256 different colors, but the pixmaps have a total of a thousand
or so different colors. For a single pixmap you solve this problem with
.IR ppmquant ;
.IX ppmquant
this script solves it for multiple pixmaps. All it does is
concatenate them together into one big pixmap, run
.I ppmquant
on that, and then split it up into little pixmaps again.
.PP
(Note that another way to solve this problem is to pre-select a set of
colors and then use
.IR ppmquant 's
.B -map
option to separately quantize each pixmap to that set.)
.SH "SEE ALSO"
ppmquant(1), ppm(5)
.SH BUGS
It's a csh script.
Csh scripts are not portable to System V.
Scripts in general are not portable to non-Unix environments.
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
v”
ppmtopcx.c3v• ppmtorgb3.cc.1v– ppmquantallt.cv— gouldtoppm.c1
v˜
ppmtoyuv.1 v™ pjtoppm.1.cvš ppmdither.1c.cvÇ ppmtopj.1opvÈ pjtoppm.cuwvÊ ppmdither.ciconvö ppmtopj.c
v÷
ppmtotga.c vø
ppmtotga.1 vù ppmtosixel.1 pbmplus05oct91/ppm/ppmmake.c 444 3010 34 2732 5032725203 11221 /* ppmmake.c - create a pixmap of a specified color and size
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
pixel color;
pixel* pixrow;
register pixel* pP;
int argn, rows, cols, row;
register int col;
char* usage = " ";

ppm_init( &argc, argv );

argn = 1;

if ( argn == argc )
pm_usage( usage );
color = ppm_parsecolor( argv[argn], PPM_MAXMAXVAL );
++argn;
if ( argn == argc )
pm_usage( usage );
if ( sscanf( argv[argn], "%d", &cols ) != 1 )
pm_usage( usage );
++argn;
if ( argn == argc )
pm_usage( usage );
if ( sscanf( argv[argn], "%d", &rows ) != 1 )
pm_usage( usage );
++argn;

if ( argn != argc )
pm_usage( usage );

ppm_writeppminit( stdout, cols, rows, PPM_MAXMAXVAL, 0 );
pixrow = ppm_allocrow( cols );

for ( row = 0; row < rows; ++row )
{
for ( col = 0, pP = pixrow; col < cols; ++col, ++pP )
*pP = color;
ppm_writeppmrow( stdout, pixrow, cols, PPM_MAXMAXVAL, 0 );
}

exit( 0 );
}

spctoppm.c v‰
sputoppm.c vŠpbmplus05oct91/ppm/ppmtoicr.1 444 3010 34 6157 5023104064 11343 .TH ppmtoicr 1 "30 July 1990"
.IX ppmtoicr
.SH NAME
ppmtoicr - convert a portable pixmap into NCSA ICR format
.SH SYNOPSIS
.B ppmtoicr
.RB [ -windowname
.IR name ]
.RB [ -expand
.IR expand ]
.RB [ -display
.IR display ]
.RB [ -rle ]
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap file as input.
Produces an NCSA Telnet Interactive Color Raster graphic file as output.
.IX "NCSA ICR"
If
.I ppmfile
is not supplied,
.I ppmtoicr
will read from standard input.
.PP
Interactive Color Raster (ICR) is a protocol for displaying raster
graphics on workstation screens. The protocol is implemented in NCSA
Telnet for the Macintosh version 2.3.
.IX Macintosh
The ICR protocol shares
characteristics of the Tektronix graphics terminal emulation protocol.
.IX Tektronix
For example, escape sequences are used to control the display.
.PP
.I ppmtoicr
will output the appropriate sequences to create a window of the
dimensions of the input pixmap,
create a colormap of up to 256
colors on the display, then load the picture data into the window.
.PP
Note that there is no icrtoppm tool - this transformation is one way.
.SH OPTIONS
.TP 14
.BI -windowname name
Output will be displayed in
.I name
(Default is to use
.I ppmfile
or "untitled" if standard input is read.)
.TP
.BI -expand expand
Output will be expanded on display by factor
.I expand
(For example, a value of 2 will cause four pixels to be displayed for
every input pixel.)
.TP
.BI -display display
Output will be displayed on screen numbered
.I display
.TP
.B -rle
Use run-length encoded format for display. (This will nearly always
result in a quicker display, but may skew the colormap.)
.SH EXAMPLES
To display a
.I ppm
file using the protocol:
.nf
ppmtoicr ppmfile
.fi
This will create a window named
.I ppmfile
on the display with the correct dimensions for
.I ppmfile,
create and download a colormap of up
to 256 colors, and download the picture into the window. The same effect
may be achieved by the following sequence:
.nf
ppmtoicr ppmfile > filename
cat filename
.fi
To display a GIF
file using the protocol in a window titled after the input file, zoom
the displayed image by a factor of 2, and
run-length encode the data:
.nf
giftoppm giffile | ppmtoicr -w giffile -r -e 2
.fi
.SH BUGS
.PP
The protocol uses frequent
.I fflush
calls to speed up display. If the
output is saved to a file for later display via
.I cat,
drawing will be
much slower. In either case, increasing the Blocksize limit on the
display will speed up transmission substantially.
.SH SEE ALSO
.BR ppm(5)
.LP
.IR "NCSA Telnet for the Macintosh" ,
University of Illinois at Urbana-Champaign (1989)
.SH AUTHOR
Copyright (C) 1990 by Kanthan Pillay ([email protected]),
Princeton University Computing and Information Technology.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
memory computing hash table" );
chl->ch.color = *pP;
chl->ch.value = 1;
chl->next = cht[hash];
cht[hash] = chl;
}
}

return cht;
}

colorhash_table
ppm_alloccolorhash( )
{
colorhash_table cht;
int i;

cht = (colorhash_table) malloc( HASH_SIZE * sizeof(colorhist_list) );
if ( cht == 0 )
pm_error( "out of memory allocating hash table" );

for ( i = pbmplus05oct91/ppm/ppmtopict.1 444 3010 34 2574 5023104070 11521 .TH ppmtopict 1 "15 April 1990"
.IX ppmtopict
.SH NAME
ppmtopict - convert a portable pixmap into a Macintosh PICT file
.SH SYNOPSIS
.B ppmtopict
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Produces a Macintosh PICT file as output.
.IX PICT
.IX Macintosh
.PP
The generated file is only the data fork of a picture.
You will need a program such as
.I mcvert
to generate a Macbinary or a BinHex file that contains the necessary
information to identify the file as a PICT file to MacOS.
.PP
Even though PICT supports 2 and 4 bits per pixel,
.I ppmtopict
always generates an 8 bits per pixel file.
.SH BUGS
The picture size field is only correct if the output is to a file
since writing into this field requires seeking backwards on a file.
However the PICT documentation seems to suggest that this field is
not critical anyway since it is only the lower 16 bits of the picture size.
.SH "SEE ALSO"
picttoppm(1), ppm(5), mcvert(1)
.SH AUTHOR
Copyright (C) 1990 by Ken Yap .
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
z.c
v„
qrttoppm.1
v…
qrttoppm.cv†
tgatoppm.c
v‡
ppmtopi1.c vˆ
spctoppm.c v‰
sputoppm.c vŠpbmplus05oct91/ppm/ppmtopuzz.1 444 3010 34 1620 5023003060 11556 .TH ppmtopuzz 1 "22 August 1990"
.IX ppmtopuzz
.SH NAME
ppmtopuzz - convert a portable pixmap into an X11 "puzzle" file
.SH SYNOPSIS
.B ppmtopuzz
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Produces an X11 "puzzle" file as output.
A "puzzle" file is for use with the
.I puzzle
.IX puzzle
.IX "X window system"
program included with the X11 distribution -
.IR puzzle 's
.B -picture
flag lets you specify an image file.
.SH "SEE ALSO"
ppm(5), puzzle(1)
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
m.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/ximtoppm.1 444 3010 34 1432 5023000234 11344 .TH ximtoppm 1 "25 March 1990"
.IX ximtoppm
.SH NAME
ximtoppm - convert an Xim file into a portable pixmap
.SH SYNOPSIS
.B ximtoppm
.RI [ ximfile ]
.SH DESCRIPTION
Reads an Xim file as input.
.IX Xim
.IX "X window system"
Produces a portable pixmap as output.
The Xim toolkit is included in the contrib tree of the X.V11R4 release.
.SH "SEE ALSO"
ppm(5)
.SH AUTHOR
Copyright (C) 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
Z{s]
pi1toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/ximtoppm.c 444 3010 34 26036 5032726563 11501 /* ximtoppm.c - read an Xim file and produce a portable pixmap
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "xim.h"

static int ReadXim ARGS(( FILE *in_fp, XimImage *xim ));
static int ReadXimHeader ARGS(( FILE *in_fp, XimImage *header ));
static int ReadXimImage ARGS(( FILE *in_fp, XimImage *xim ));
static int ReadImageChannel ARGS(( FILE *infp, byte *buf, unsigned int *bufsize, int encoded ));

void
main( argc, argv )
int argc;
char *argv[];
{
FILE *ifp;
XimImage xim;
pixel *pixelrow, colormap[256];
register pixel *pP;
int argn, rows, cols, row, mapped;
register int col;
pixval maxval;

ppm_init( &argc, argv );

argn = 1;

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( "[ximfile]" );

if ( ! ReadXim( ifp, &xim ) )
pm_error( "can't read Xim file" );
rows = xim.height;
cols = xim.width;
if ( xim.nchannels == 1 && xim.bits_channel == 8 )
{
int i;

mapped = 1;
maxval = 255;
for ( i = 0; i < xim.ncolors; ++i )
{
PPM_ASSIGN(
colormap[i], xim.colors[i].red,
xim.colors[i].grn, xim.colors[i].blu );
/* Should be colormap[xim.colors[i].pixel], but Xim is broken. */
}
}
else if ( xim.nchannels == 3 )
{
mapped = 0;
maxval = pm_bitstomaxval( xim.bits_channel );
}
else
pm_error(
"unknown Xim file type, nchannels == %d, bits_channel == %d",
xim.nchannels, xim.bits_channel );

ppm_writeppminit( stdout, cols, rows, maxval, 0 );
pixelrow = ppm_allocrow( cols );

for ( row = 0; row < rows; ++row )
{
if ( mapped )
{
register byte *xbp;

for ( col = 0, pP = pixelrow,
xbp = xim.data + row * xim.bytes_per_line;
col < cols;
++col, ++pP, ++xbp )
*pP = colormap[*xbp];
}
else
{
register byte *xrbp, *xgbp, *xbbp;

for ( col = 0, pP = pixelrow,
xrbp = xim.data + row * xim.bytes_per_line,
xgbp = xim.grn_data + row * xim.bytes_per_line,
xbbp = xim.blu_data + row * xim.bytes_per_line;
col < cols;
++col, ++pP, ++xrbp, ++xgbp, ++xbbp )
PPM_ASSIGN( *pP, *xrbp, *xgbp, *xbbp );
}
ppm_writeppmrow( stdout, pixelrow, cols, maxval, 0 );
}
pm_close( ifp );
exit( 0 );
}

/* The rest is excerpted and slightly modified from the X.V11R4 version
** of xim_io.c.
*/

/***********************************************************************
* File: xlib.c
* Author: Philip Thompson
* $Date: 89/11/01 10:14:23 $
* $Revision: 1.14 $
* Purpose: General xim libray of utililities
* Copyright (c) 1988 Philip R. Thompson
* Computer Resource Laboratory (CRL)
* Dept. of Architecture and Planning
* M.I.T., Rm 9-526
* Cambridge, MA 02139
* This software and its documentation may be used, copied, modified,
* and distributed for any purpose without fee, provided:
* -- The above copyright notice appears in all copies.
* -- This disclaimer appears in all source code copies.
* -- The names of M.I.T. and the CRL are not used in advertising
* or publicity pertaining to distribution of the software
* without prior specific written permission from me or CRL.
* I provide this software freely as a public service. It is NOT a
* commercial product, and therefore is not subject to an an implied
* warranty of merchantability or fitness for a particular purpose. I
* provide it as is, without warranty.
* This software is furnished only on the basis that any party who
* receives it indemnifies and holds harmless the parties who furnish
* it against any claims, demands, or liabilities connected with using
* it, furnishing it to others, or providing it to a third party.
*
* Philip R. Thompson ([email protected])
***********************************************************************/

static int
ReadXim(in_fp, xim)
FILE *in_fp;
XimImage *xim;
{
if (!ReadXimHeader(in_fp, xim)) {
pm_message("can't read xim header" );
return(0);
}
if (!ReadXimImage(in_fp, xim)) {
pm_message("can't read xim data" );
return(0);
}
return(1);
}

static int
ReadXimHeader(in_fp, header)
FILE *in_fp;
XimImage *header;
{
int i;
char *cp;
XimAsciiHeader a_head;

cp = (char *) header;
for (i = 0; i < sizeof(XimImage); ++i )
*cp++ = 0;
/* Read header and verify image file formats */
if (fread((char *)&a_head, sizeof(ImageHeader), 1, in_fp) != 1) {
pm_message("ReadXimHeader: unable to read file header" );
return(0);
}
if (atoi(a_head.header_size) != sizeof(ImageHeader)) {
pm_message("ReadXimHeader: header size mismatch" );
return(0);
}
if (atoi(a_head.file_version) != IMAGE_VERSION) {
pm_message("ReadXimHeader: incorrect Image_file version" );
return(0);
}
header->width = atoi(a_head.image_width);
header->height = atoi(a_head.image_height);
header->ncolors = atoi(a_head.num_colors);
header->nchannels = atoi(a_head.num_channels);
header->bytes_per_line = atoi(a_head.bytes_per_line);
/* header->npics = atoi(a_head.num_pictures);
*/
header->bits_channel = atoi(a_head.bits_per_channel);
header->alpha_flag = atoi(a_head.alpha_channel);
if (strlen(a_head.author)) {
if (!(header->author = calloc((unsigned int)strlen(a_head.author)+1,
1))) {
pm_message("ReadXimHeader: can't calloc author string" );
return(0);
}
header->width = atoi(a_head.image_width);
strncpy(header->author, a_head.author, strlen(a_head.author));
}
if (strlen(a_head.date)) {
if (!(header->date =calloc((unsigned int)strlen(a_head.date)+1,1))){
pm_message("ReadXimHeader: can't calloc date string" );
return(0);
}
header->width = atoi(a_head.image_width);
strncpy(header->date, a_head.date, strlen(a_head.date));
}
if (strlen(a_head.program)) {
if (!(header->program = calloc(
(unsigned int)strlen(a_head.program) + 1, 1))) {
pm_message("ReadXimHeader: can't calloc program string" );
return(0);
}
header->width = atoi(a_head.image_width);
strncpy(header->program, a_head.program,strlen(a_head.program));
}
/* Do double checking for bakwards compatibility */
if (header->npics == 0)
header->npics = 1;
if (header->bits_channel == 0)
header->bits_channel = 8;
else if (header->bits_channel == 24) {
header->nchannels = 3;
header->bits_channel = 8;
}
if ((int)header->bytes_per_line == 0)
if (header->bits_channel == 1 && header->nchannels == 1)
header->bytes_per_line = (header->width + 7) / 8;
else
header->bytes_per_line = header->width;
header->datasize =(unsigned int)header->bytes_per_line * header->height;
if (header->nchannels == 3 && header->bits_channel == 8)
header->ncolors = 0;
else if (header->nchannels == 1 && header->bits_channel == 8) {
header->colors = (Color *)calloc((unsigned int)header->ncolors,
sizeof(Color));
if (header->colors == NULL) {
pm_message("ReadXimHeader: can't calloc colors" );
return(0);
}
for (i=0; i < header->ncolors; i++) {
header->colors[i].red = a_head.c_map[i][0];
header->colors[i].grn = a_head.c_map[i][1];
header->colors[i].blu = a_head.c_map[i][2];
}
}
return(1);
}

static int
ReadXimImage(in_fp, xim)
FILE *in_fp;
XimImage *xim;
{
if (xim->data) {
free((char *)xim->data);
xim->data = (byte *)0;
}
if (xim->grn_data) {
free((char *)xim->grn_data);
xim->grn_data = (byte *)0;
}
if (xim->blu_data) {
free((char *)xim->blu_data);
xim->blu_data = (byte *)0;
}
if (xim->other) {
free((char *)xim->other);
xim->other = (byte *)0;
}
xim->npics = 0;
if (!(xim->data = (byte *)calloc(xim->datasize, 1))) {
pm_message("ReadXimImage: can't malloc pixmap data" );
return(0);
}
if (!ReadImageChannel(in_fp, xim->data, &xim->datasize, 0)) {
pm_message("ReadXimImage: end of the images" );
return(0);
}
if (xim->nchannels == 3) {
xim->grn_data = (byte *)malloc(xim->datasize);
xim->blu_data = (byte *)malloc(xim->datasize);
if (xim->grn_data == NULL || xim->blu_data == NULL) {
pm_message("ReadXimImage: can't malloc rgb channel data" );
free((char *)xim->data);
if (xim->grn_data) free((char *)xim->grn_data);
if (xim->blu_data) free((char *)xim->blu_data);
xim->data = xim->grn_data = xim->blu_data = (byte*)0;
return(0);
}
if (!ReadImageChannel(in_fp, xim->grn_data, &xim->datasize, 0))
return(0);
if (!ReadImageChannel(in_fp, xim->blu_data, &xim->datasize, 0))
return(0);
}
if (xim->alpha_flag) {
if ((xim->other = (byte *)malloc(xim->datasize)) == NULL) {
pm_message("ReadXimImage: can't malloc alpha data" );
return(0);
}
if (!ReadImageChannel(in_fp, xim->other, &xim->datasize, 0))
return(0);
}
xim->npics = 1;
return(1);
}

static int
ReadImageChannel(infp, buf, bufsize, encoded)
FILE *infp;
byte *buf;
unsigned int *bufsize;
int encoded;
{
register int i, runlen, nbytes;
register unsigned int j;
register byte *line;
long marker;

if (!encoded)
j = fread((char *)buf, 1, (int)*bufsize, infp);
else {
if ((line=(byte *)malloc((unsigned int)BUFSIZ)) == NULL) {
pm_message("ReadImageChannel: can't malloc() fread string" );
return(0);
}
/* Unrunlength encode data */
marker = ftell(infp);
j = 0;
while (((nbytes=fread((char *)line, 1, BUFSIZ, infp)) > 0) &&
(j < *bufsize)) {
for (i=0; (i < nbytes) && (j < *bufsize); i++) {
runlen = (int)line[i]+1;
i++;
while (runlen--)
buf[j++] = line[i];
}
marker += i;
}
/* return to the begining of the next image's bufffer */
if (fseek(infp, marker, 0) == -1) {
pm_message("ReadImageChannel: can't fseek to location in image buffer" );
return(0);
}
free((char *)line);
}
if (j != *bufsize) {
pm_message("unable to complete channel: %u / %u (%d%%)",
j, *bufsize, (int)(j*100.0 / *bufsize) );
*bufsize = j;
}
return(1);
}
lse /*SIGNED_COMPARE_SLOW*/
while ( (c = GIFNextPixel( ReadValue )) != EOF ) { /* } */
#endif /*SIGNED_COMPARE_SLOW*/

++in_count;

fcode = (long) (((long) c << maxbits) + ent);
i = (((code_int)c << hshift) ^ ent); /* xor hashing */

if ( HashTabOf (i) == fcode ) {
ent = CodeTabOf (i);
continue;
} else if ( (long)HashTabOf (i) < 0 ) /* empty slot */
goto nomatch;
disp = hsize_reg - ipbmplus05oct91/ppm/ppmtoxpm.c 444 3010 34 14754 5032726557 11517 /* ppmtoxpm.c - read a portable pixmap and produce a X11 pixmap
**
** Copyright (C) 1990 by Mark W. Snitily
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
**
** This tool was developed for Schlumberger Technologies, ATE Division, and
** with their permission is being made available to the public with the above
** copyright notice and permission notice.
*/

#include
#include "ppm.h"
#include "ppmcmap.h"

/* Max number of colors allowed in ppm input. */
#define MAXCOLORS 256

/* Lower bound and upper bound of character-pixels printed in XPM output. */
#define LOW_CHAR '`'
#define HIGH_CHAR '~'

typedef struct { /* character-pixel mapping */
char* cixel; /* character string printed for pixel */
char* rgbname; /* ascii rgb color, either mnemonic or #rgb value */
} cixel_map;

static char* gen_numstr ARGS(( int i, int base, char low_char, int digits ));
static void gen_cmap ARGS(( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel** pixels;
register pixel* pP;
int argn, rows, cols, ncolors, row, col, i;
pixval maxval;
colorhash_table cht;
colorhist_vector chv;
cixel_map cmap[MAXCOLORS];
int charspp;
char out_name[100];
char* cp;
char* usage = "[-name ] [ppmfile]";

ppm_init( &argc, argv );
out_name[0] = '\0';

argn = 1;

/* Check for command line options. */
while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-name", 2 ) )
{
++argn;
if ( argn == argc )
pm_usage( usage );
(void) strcpy( out_name, argv[argn] );
}
else
pm_usage( usage );
++argn;
}

if ( argn != argc )
{
/* Open the input file. */
ifp = pm_openr( argv[argn] );

/* If output filename not specified, use input filename as default. */
if ( out_name[0] == '\0' )
{
(void) strcpy( out_name, argv[argn] );
cp = index( out_name, '.' );
if ( cp != 0 )
*cp = '\0'; /* remove extension */
if ( strcmp( out_name, "-" ) == 0 )
(void) strcpy( out_name, "noname" );
}

++argn;
}
else
{
/* No input file specified. */
ifp = stdin;
if ( out_name[0] == '\0' )
(void) strcpy( out_name, "noname" );
}

if ( argn != argc )
pm_usage( usage );

/* Read in the ppm file. */
pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
pm_close( ifp );

/* Figure out the colormap. */
pm_message( "computing colormap..." );
chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &ncolors );
if ( chv == (colorhist_vector) 0 )
pm_error(
"too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
pm_message( "%d colors found", ncolors );

/* Make a hash table for fast color lookup. */
cht = ppm_colorhisttocolorhash( chv, ncolors );

/* Now generate the character-pixel colormap table. */
gen_cmap( chv, ncolors, maxval, cmap, &charspp );

/* Write out the XPM header. */
printf( "#define %s_format %d\n", out_name, 1 );
printf( "#define %s_width %d\n", out_name, cols );
printf( "#define %s_height %d\n", out_name, rows );
printf( "#define %s_ncolors %d\n", out_name, ncolors );
printf( "#define %s_chars_per_pixel %d\n", out_name, charspp );

/* Write out the ascii colormap. */
printf( "static char *%s_colors[] = {\n", out_name );
for ( i = 0; i < ncolors; ++i )
{
printf( " \"%s\", \"%s\"", cmap[i].cixel, cmap[i].rgbname );
if ( i != ncolors - 1 )
printf( ",\n" );
else
printf( "\n" );
}
printf( "};\n" );

/* Write out the ascii character-pixel image. */
printf( "static char *%s_pixels[] = {\n", out_name );
for ( row = 0; row < rows; ++row )
{
printf( "\"" );
for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
printf( "%s", cmap[ppm_lookupcolor(cht, pP)].cixel );
if ( row != rows - 1 )
printf( "\",\n" );
else
printf( "\"\n" );
}
printf( "};\n" );

exit( 0 );
}

/* Given a number and a base, this routine prints the number into a
** malloc'ed string and returns it. The length of the string is
** specified by "digits". The ascii characters of the printed
** number range from low_char to low_char + base. The string is
** low_char filled.
*/

#if __STDC__
static char*
gen_numstr( int i, int base, char low_char, int digits )
#else /*__STDC__*/
static char*
gen_numstr( i, base, low_char, digits )
int i, base, digits;
char low_char;
#endif /*__STDC__*/
{
char* str;
char* p;
int d;

/* Allocate memory for printed number. Abort if error. */
str = (char*) malloc( digits + 1 );
if ( str == 0 )
pm_error( "out of memory allocating number string" );

/* Generate characters starting with least significant digit. */
p = str + digits;
*p-- = '\0'; /* nul terminate string */
while ( p >= str )
{
d = i % base;
i /= base;
*p-- = low_char + d;
}

return str;
}

#if __STDC__
static void
gen_cmap( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP )
#else /*__STDC__*/
static void
gen_cmap( chv, ncolors, maxval, cmap, charsppP )
colorhist_vector chv;
int ncolors;
pixval maxval;
cixel_map cmap[MAXCOLORS];
int* charsppP;
#endif /*__STDC__*/
{
int i, j, base;
char* colorname;

/* Figure out how many characters per pixel we'll be using. Don't want
** to be forced to link with libm.a, so using a division loop rather than
** a log function.
*/
base = (int) HIGH_CHAR - (int) LOW_CHAR + 1;
for ( *charsppP = 0, j = ncolors; j > 0; ++(*charsppP) )
j /= base;

/* Generate the character-pixel string and the rgb name for each colormap
** entry.
*/
for ( i = 0; i < ncolors; ++i )
{
/* Generate color value characters. */
cmap[i].cixel = gen_numstr( i, base, LOW_CHAR, *charsppP );

/* Generate color name string. */
colorname = ppm_colorname( &(chv[i].color), maxval, 1 );

/* And copy it. */
cmap[i].rgbname = (char*) malloc( strlen( colorname ) + 1 );
if ( cmap[i].rgbname == 0 )
pm_error( "out of memory allocating color name" );
(void) strcpy( cmap[i].rgbname, colorname );
}
}
while (runlen--pbmplus05oct91/ppm/xpmtoppm.c 444 3010 34 14300 5032726565 11501 /* xpmtoppm.c - read an X11 pixmap file and produce a portable pixmap
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

static void ReadXPMFile ARGS((
FILE* stream, int* widthP, int* heightP, int* ncolorsP,
int* chars_per_pixelP, pixel** colorsP, int** dataP ));
static void getline ARGS(( char* line, int size, FILE* stream ));

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel* pixrow;
pixel* colors;
register pixel* pP;
int rows, cols, ncolors, chars_per_pixel, row;
register int col;
int* data;
register int* ptr;

ppm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[xpmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

ReadXPMFile(
ifp, &cols, &rows, &ncolors, &chars_per_pixel, &colors, &data );

pm_close( ifp );

ppm_writeppminit( stdout, cols, rows, (pixval) PPM_MAXMAXVAL, 0 );
pixrow = ppm_allocrow( cols );

for ( row = 0, ptr = data; row < rows; ++row )
{
for ( col = 0, pP = pixrow; col < cols; ++col, ++pP, ++ptr )
*pP = colors[*ptr];
ppm_writeppmrow( stdout, pixrow, cols, (pixval) PPM_MAXMAXVAL, 0 );
}

exit( 0 );
}

#define MAX_LINE 500

static void
ReadXPMFile( stream, widthP, heightP, ncolorsP, chars_per_pixelP, colorsP, dataP )
FILE* stream;
int* widthP;
int* heightP;
int* ncolorsP;
int* chars_per_pixelP;
pixel** colorsP;
int** dataP;
{
char line[MAX_LINE], str1[MAX_LINE], str2[MAX_LINE];
char* t1;
char* t2;
int format, v, datasize;
int* ptr;
int* ptab;
register int i, j;

*widthP = *heightP = *ncolorsP = *chars_per_pixelP = format = -1;

/* Read the initial defines. */
for ( ; ; )
{
getline( line, sizeof(line), stream );

if ( sscanf( line, "#define %s %d", str1, &v ) == 2 )
{
if ( ( t1 = rindex( str1, '_' ) ) == NULL )
t1 = str1;
else
++t1;
if ( ! strcmp( t1, "format" ) )
format = v;
else if ( ! strcmp( t1, "width" ) )
*widthP = v;
else if ( ! strcmp( t1, "height" ) )
*heightP = v;
else if ( ! strcmp( t1, "ncolors" ) )
*ncolorsP = v;
else if ( ! strcmp( t1, "pixel" ) )
*chars_per_pixelP = v;
}
else if ( ! strncmp( line, "static char", 11 ) )
{
if ( ( t1 = rindex( line, '_' ) ) == NULL )
t1 = line;
else
++t1;
break;
}
}
if ( format == -1 )
pm_error( "missing or invalid format" );
if ( format != 1 )
pm_error( "can't handle XPM version %d", format );
if ( *widthP == -1 )
pm_error( "missing or invalid width" );
if ( *heightP == -1 )
pm_error( "missing or invalid height" );
if ( *ncolorsP == -1 )
pm_error( "missing or invalid ncolors" );
if ( *chars_per_pixelP == -1 )
pm_error( "missing or invalid chars_per_pixel" );
if ( *chars_per_pixelP > 2 )
pm_message(
"warning, chars_per_pixel > 2 uses a lot of memory" );

/* If there's a monochrome color table, skip it. */
if ( ! strncmp( t1, "mono", 4 ) )
{
for ( ; ; )
{
getline( line, sizeof(line), stream );
if ( ! strncmp( line, "static char", 11 ) )
break;
}
}

/* Allocate space for color table. */
if ( *chars_per_pixelP <= 2 )
{
/* Up to two chars per pixel, we can use an indexed table. */
v = 1;
for ( i = 0; i < *chars_per_pixelP; ++i )
v *= 256;
*colorsP = ppm_allocrow( v );
}
else
{
/* Over two chars per pixel, we fall back on linear search. */
*colorsP = ppm_allocrow( *ncolorsP);
ptab = (int*) malloc( *ncolorsP * sizeof(int) );
}

/* Read color table. */
for ( i = 0; i < *ncolorsP; ++i )
{
getline( line, sizeof(line), stream );

if ( ( t1 = index( line, '"' ) ) == NULL )
pm_error( "error scanning color table" );
if ( ( t2 = index( t1 + 1, '"' ) ) == NULL )
pm_error( "error scanning color table" );
if ( t2 - t1 - 1 != *chars_per_pixelP )
pm_error(
"wrong number of chars per pixel in color table" );
strncpy( str1, t1 + 1, t2 - t1 - 1 );
str1[t2 - t1 - 1] = '\0';

if ( ( t1 = index( t2 + 1, '"' ) ) == NULL )
pm_error( "error scanning color table" );
if ( ( t2 = index( t1 + 1, '"' ) ) == NULL )
pm_error( "error scanning color table" );
strncpy( str2, t1 + 1, t2 - t1 - 1 );
str2[t2 - t1 - 1] = '\0';

v = 0;
for ( j = 0; j < *chars_per_pixelP; ++j )
v = ( v << 8 ) + str1[j];
if ( *chars_per_pixelP <= 2 )
/* Index into table. */
(*colorsP)[v] = ppm_parsecolor( str2, (pixval) PPM_MAXMAXVAL );
else
{
/* Set up linear search table. */
(*colorsP)[i] = ppm_parsecolor( str2, (pixval) PPM_MAXMAXVAL );
ptab[i] = v;
}
}

/* Read pixels. */
for ( ; ; )
{
getline( line, sizeof(line), stream );
if ( ! strncmp( line, "static char", 11 ) )
break;
}
datasize = *widthP * *heightP;
*dataP = (int*) malloc( datasize * sizeof(int) );
if ( *dataP == 0 )
pm_error( "out of memory" );
i = 0;
ptr = *dataP;
for ( ; ; )
{
getline( line, sizeof(line), stream );

/* Find the open quote. */
if ( ( t1 = index( line, '"' ) ) == NULL )
pm_error( "error scanning pixels" );
++t1;

/* Handle pixels until a close quote or the end of the image. */
while ( *t1 != '"' )
{
v = 0;
for ( j = 0; j < *chars_per_pixelP; ++j )
v = ( v << 8 ) + *t1++;
if ( *chars_per_pixelP <= 2 )
/* Index into table. */
*ptr++ = v;
else
{
/* Linear search into table. */
for ( j = 0; j < *ncolorsP; ++j )
if ( ptab[j] == v )
goto gotit;
pm_error( "unrecognized pixel in line \"%s\"", line );
gotit:
*ptr++ = j;
}
++i;
if ( i >= datasize )
return;
}
}
}

static void
getline( line, size, stream )
char* line;
int size;
FILE* stream;
{
if ( fgets( line, MAX_LINE, stream ) == NULL )
pm_error( "EOF / read error" );
if ( strlen( line ) == MAX_LINE - 1 )
pm_error( "line too long" );
}
= i % base;
i /= base;
*p-- = low_char + d;
}

return str;
}

#if __STDC__
static void
gen_cmap( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP )
#else /*__STDC__*/
static void
gen_cmap( chv, ncolors, maxval, cmap, charsppP )
colorhist_vector chv;
int ncolopbmplus05oct91/ppm/ppmtopuzz.c 444 3010 34 4731 5032734650 11666 /* ppmtopuzz.c - read a portable pixmap and write an X11 "puzzle" file
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "ppmcmap.h"

#define MAXVAL 255
#define MAXCOLORS 256

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel** pixels;
register pixel* pP;
colorhist_vector chv;
colorhash_table cht;
int rows, cols, row, colors, i;
register int col;
pixval maxval;

ppm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[ppmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
pm_close( ifp );

pm_message( "computing colormap..." );
chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
if ( chv == (colorhist_vector) 0 )
{
pm_message(
"too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
exit( 1 );
}
pm_message( "%d colors found", colors );

/* Write puzzle header. */
(void) pm_writebiglong( stdout, cols );
(void) pm_writebiglong( stdout, rows );
(void) putchar( (unsigned char) colors );
if ( maxval > MAXVAL )
pm_message(
"maxval is not %d - automatically rescaling colors", MAXVAL );
for ( i = 0; i < colors; ++i )
{
pixel p;

p = chv[i].color;
if ( maxval != MAXVAL )
PPM_DEPTH( p, p, maxval, MAXVAL );
(void) putchar( (unsigned char) PPM_GETR( p ) );
(void) putchar( (unsigned char) PPM_GETG( p ) );
(void) putchar( (unsigned char) PPM_GETB( p ) );
}

/* Convert color vector to color hash table, for fast lookup. */
cht = ppm_colorhisttocolorhash( chv, colors );
ppm_freecolorhist( chv );

/* And write out the data. */
for ( row = 0; row < rows; ++row )
{
for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
{
register int color;

color = ppm_lookupcolor( cht, pP );
if ( color == -1 )
pm_error(
"color not found?!? row=%d col=%d r=%d g=%d b=%d",
row, col, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP) );
(void) putchar( (unsigned char) color );
}
}

exit( 0 );
}
NULL )
pm_error( "error scanning pbmplus05oct91/ppm/qrttoppm.1 444 3010 34 1333 5022777756 11412 .TH qrttoppm 1 "25 August 1989"
.IX qrttoppm
.SH NAME
qrttoppm - convert output from the QRT ray tracer into a portable pixmap
.SH SYNOPSIS
.B qrttoppm
.RI [ qrtfile ]
.SH DESCRIPTION
Reads a QRT file as input.
.IX "QRT raytracer"
Produces a portable pixmap as output.
.SH "SEE ALSO"
ppm(5)
.SH AUTHOR
Copyright (C) 1989 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
esZ
tgatoppm.1ks[
giftoppm.cds\ gouldtoppm.1Z{s]
pi1toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/qrttoppm.c 444 3010 34 3344 5032725231 11456 /* qrttoppm.c - read a QRT ray-tracer output file and produce a portable pixmap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
register pixel* pixelrow;
int rows, cols, row, col;
pixval maxval;
unsigned char* buf;

ppm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[qrtfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

/* Read in the QRT file. First the header. */
cols = getc( ifp );
cols += getc( ifp ) << 8;
rows = getc( ifp );
rows += getc( ifp ) << 8;

if ( cols <= 0 || rows <= 0 )
pm_error( "invalid size: %d %d", cols, rows );
maxval = 255;

ppm_writeppminit( stdout, cols, rows, maxval, 0 );
pixelrow = ppm_allocrow( cols );
buf = (unsigned char *) malloc( 3 * cols );
if ( buf == (unsigned char *) 0 )
pm_error( "out of memory" );

for ( row = 0; row < rows; row++ )
{
(void) getc( ifp ); /* discard */
(void) getc( ifp ); /* linenum */
if ( fread( buf, 3 * cols, 1, ifp ) != 1 )
pm_error( "EOF / read error" );
for ( col = 0; col < cols; col++ )
PPM_ASSIGN(
pixelrow[col], buf[col], buf[cols + col], buf[2 * cols + col] );
ppm_writeppmrow( stdout, pixelrow, cols, maxval, 0 );
}

pm_close( ifp );

exit( 0 );
}
v• ppmtorgb3.cc.1v– ppmquantallt.cv— gouldtoppm.c1
v˜
ppmtoyuv.1 v™ pjtoppm.1.cvš ppmdither.1c.cvÇ ppmtopj.1opvÈ pjtoppm.cuwvÊ ppmdither.ciconvö ppmtopj.c
v÷
ppmtotga.c vø
ppmtotga.1 vù ppmtosixel.1 pbmplus05oct91/ppm/tgatoppm.c 444 3010 34 23357 5032735100 11445 /* tgatoppm.c - read a TrueVision Targa file and write a portable pixmap
**
** Partially based on tga2rast, version 1.0, by Ian MacPhedran.
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "tga.h"

#define MAXCOLORS 16384

static int mapped, rlencoded;

static pixel ColorMap[MAXCOLORS];
static int RLE_count = 0, RLE_flag = 0;

static void readtga ARGS(( FILE* ifp, struct ImageHeader* tgaP ));
static void get_map_entry ARGS(( FILE* ifp, pixel* Value, int Size ));
static void get_pixel ARGS(( FILE* ifp, pixel* dest, int Size ));
static unsigned char getbyte ARGS(( FILE* ifp ));

void
main( argc, argv )
int argc;
char* argv[];
{
struct ImageHeader tga_head;
int i;
unsigned int temp1, temp2;
FILE* ifp;
int argn, debug, rows, cols, row, col, realrow;
int maxval;
pixel** pixels;
char* usage = " [-debug] [tgafile]";

ppm_init( &argc, argv );

argn = 1;
debug = 0;

if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-debug", 2 ) )
debug = 1;
else
pm_usage( usage );
++argn;
}

if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

/* Read the Targa file header. */
readtga( ifp, &tga_head );
if ( debug )
{
pm_message( "IDLength = %d\n", (int) tga_head.IDLength );
pm_message( "CoMapType = %d\n", (int) tga_head.CoMapType );
pm_message( "ImgType = %d\n", (int) tga_head.ImgType );
pm_message( "Index_lo = %d\n", (int) tga_head.Index_lo );
pm_message( "Index_hi = %d\n", (int) tga_head.Index_hi );
pm_message( "Length_lo = %d\n", (int) tga_head.Length_lo );
pm_message( "Length_hi = %d\n", (int) tga_head.Length_hi );
pm_message( "CoSize = %d\n", (int) tga_head.CoSize );
pm_message( "X_org_lo = %d\n", (int) tga_head.X_org_lo );
pm_message( "X_org_hi = %d\n", (int) tga_head.X_org_hi );
pm_message( "Y_org_lo = %d\n", (int) tga_head.Y_org_lo );
pm_message( "Y_org_hi = %d\n", (int) tga_head.Y_org_hi );
pm_message( "Width_lo = %d\n", (int) tga_head.Width_lo );
pm_message( "Width_hi = %d\n", (int) tga_head.Width_hi );
pm_message( "Height_lo = %d\n", (int) tga_head.Height_lo );
pm_message( "Height_hi = %d\n", (int) tga_head.Height_hi );
pm_message( "PixelSize = %d\n", (int) tga_head.PixelSize );
pm_message( "AttBits = %d\n", (int) tga_head.AttBits );
pm_message( "Rsrvd = %d\n", (int) tga_head.Rsrvd );
pm_message( "OrgBit = %d\n", (int) tga_head.OrgBit );
pm_message( "IntrLve = %d\n", (int) tga_head.IntrLve );
}
rows = ( (int) tga_head.Height_lo ) + ( (int) tga_head.Height_hi ) * 256;
cols = ( (int) tga_head.Width_lo ) + ( (int) tga_head.Width_hi ) * 256;

switch ( tga_head.ImgType )
{
case TGA_Map:
case TGA_RGB:
case TGA_Mono:
case TGA_RLEMap:
case TGA_RLERGB:
case TGA_RLEMono:
break;

default:
pm_error( "unknown Targa image type %d", tga_head.ImgType );
}

if ( tga_head.ImgType == TGA_Map ||
tga_head.ImgType == TGA_RLEMap ||
tga_head.ImgType == TGA_CompMap ||
tga_head.ImgType == TGA_CompMap4 )
{ /* Color-mapped image */
if ( tga_head.CoMapType != 1 )
pm_error(
"mapped image (type %d) with color map type != 1",
tga_head.ImgType );
mapped = 1;
/* Figure maxval from CoSize. */
switch ( tga_head.CoSize )
{
case 8:
case 24:
case 32:
maxval = 255;
break;

case 15:
case 16:
maxval = 31;
break;

default:
pm_error(
"unknown colormap pixel size - %d", tga_head.CoSize );
}
if ( maxval > PPM_MAXMAXVAL )
pm_error(
"CoSize is too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS" );
}
else
{ /* Not colormap, so figure maxval from PixelSize. */
mapped = 0;
switch ( tga_head.PixelSize )
{
case 8:
case 24:
case 32:
maxval = 255;
break;

case 15:
case 16:
maxval = 31;
break;

default:
pm_error( "unknown pixel size - %d", tga_head.PixelSize );
}
if ( maxval > PPM_MAXMAXVAL )
pm_error(
"PixelSize is too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS" );
}

/* If required, read the color map information. */
if ( tga_head.CoMapType != 0 )
{
temp1 = tga_head.Index_lo + tga_head.Index_hi * 256;
temp2 = tga_head.Length_lo + tga_head.Length_hi * 256;
if ( ( temp1 + temp2 + 1 ) >= MAXCOLORS )
pm_error( "too many colors - %d", ( temp1 + temp2 + 1 ) );
for ( i = temp1; i < ( temp1 + temp2 ); i++ )
get_map_entry( ifp, &ColorMap[i], (int) tga_head.CoSize );
}

/* Check run-length encoding. */
if ( tga_head.ImgType == TGA_RLEMap ||
tga_head.ImgType == TGA_RLERGB ||
tga_head.ImgType == TGA_RLEMono )
rlencoded = 1;
else
rlencoded = 0;

/* Read the Targa file body and convert to portable format. */
pixels = ppm_allocarray( cols, rows );
for ( row = 0; row < rows; row++ )
{
if ( tga_head.IntrLve == TGA_IL_Four )
{
if ( 4 * row < rows )
realrow = 4 * row;
else if ( 2 * row < rows )
{
realrow = row - rows / 4;
realrow = 4 * realrow + 1;
}
else if ( 4 * row < 3 * rows )
{
realrow = row - rows / 2;
realrow = 4 * realrow + 2;
}
else
{
realrow = row - rows / 2 - rows / 4;
realrow = 4 * realrow + 3;
}
}
else if ( tga_head.IntrLve == TGA_IL_Two )
{
if ( 2 * row < rows )
realrow = 2 * row;
else
{
realrow = row - rows / 2;
realrow = 2 * realrow + 1;
}
}
else
realrow = row;

if ( tga_head.OrgBit == 0 )
realrow = rows - realrow - 1;

for ( col = 0; col < cols; col++ )
get_pixel( ifp, &(pixels[realrow][col]), (int) tga_head.PixelSize );
}

pm_close( ifp );

ppm_writeppm( stdout, pixels, cols, rows, (pixval) maxval, 0 );

exit( 0 );
}

static void
readtga( ifp, tgaP )
FILE* ifp;
struct ImageHeader* tgaP;
{
unsigned char flags;
ImageIDField junk;

tgaP->IDLength = getbyte( ifp );
tgaP->CoMapType = getbyte( ifp );
tgaP->ImgType = getbyte( ifp );
tgaP->Index_lo = getbyte( ifp );
tgaP->Index_hi = getbyte( ifp );
tgaP->Length_lo = getbyte( ifp );
tgaP->Length_hi = getbyte( ifp );
tgaP->CoSize = getbyte( ifp );
tgaP->X_org_lo = getbyte( ifp );
tgaP->X_org_hi = getbyte( ifp );
tgaP->Y_org_lo = getbyte( ifp );
tgaP->Y_org_hi = getbyte( ifp );
tgaP->Width_lo = getbyte( ifp );
tgaP->Width_hi = getbyte( ifp );
tgaP->Height_lo = getbyte( ifp );
tgaP->Height_hi = getbyte( ifp );
tgaP->PixelSize = getbyte( ifp );
flags = getbyte( ifp );
tgaP->AttBits = flags & 0xf;
tgaP->Rsrvd = ( flags & 0x10 ) >> 4;
tgaP->OrgBit = ( flags & 0x20 ) >> 5;
tgaP->IntrLve = ( flags & 0xc0 ) >> 6;

if ( tgaP->IDLength != 0 )
fread( junk, 1, (int) tgaP->IDLength, ifp );
}

static void
get_map_entry( ifp, Value, Size )
FILE* ifp;
pixel* Value;
int Size;
{
unsigned char j, k, r, g, b;

/* Read appropriate number of bytes, break into rgb & put in map. */
switch ( Size )
{
case 8: /* Grey scale, read and triplicate. */
r = g = b = getbyte( ifp );
break;

case 16: /* 5 bits each of red green and blue. */
case 15: /* Watch for byte order. */
j = getbyte( ifp );
k = getbyte( ifp );
r = ( k & 0x7C ) >> 2;
g = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
b = j & 0x1F;
break;

case 32:
case 24: /* 8 bits each of blue green and red. */
b = getbyte( ifp );
g = getbyte( ifp );
r = getbyte( ifp );
if ( Size == 32 )
(void) getbyte( ifp ); /* Read alpha byte & throw away. */
break;

default:
pm_error( "unknown colormap pixel size (#2) - %d", Size );
}
PPM_ASSIGN( *Value, r, g, b );
}

static void
get_pixel( ifp, dest, Size )
FILE* ifp;
pixel* dest;
int Size;
{
static pixval Red, Grn, Blu;
unsigned char j, k;
static unsigned int l;

/* Check if run length encoded. */
if ( rlencoded )
{
if ( RLE_count == 0 )
{ /* Have to restart run. */
unsigned char i;
i = getbyte( ifp );
RLE_flag = ( i & 0x80 ) >> 7;
if ( RLE_flag == 0 )
/* Stream of unencoded pixels. */
RLE_count = i + 1;
else
/* Single pixel replicated. */
RLE_count = i - 127;
/* Decrement count & get pixel. */
RLE_count--;
}
else
{ /* Have already read count & (at least) first pixel. */
RLE_count--;
if ( RLE_flag != 0 )
/* Replicated pixels. */
goto PixEncode;
}
}
/* Read appropriate number of bytes, break into RGB. */
switch ( Size )
{
case 8: /* Grey scale, read and triplicate. */
Red = Grn = Blu = l = getbyte( ifp );
break;

case 16: /* 5 bits each of red green and blue. */
case 15: /* Watch byte order. */
j = getbyte( ifp );
k = getbyte( ifp );
l = ( (unsigned int) k << 8 ) + j;
Red = ( k & 0x7C ) >> 2;
Grn = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
Blu = j & 0x1F;
break;

case 32:
case 24: /* 8 bits each of blue green and red. */
Blu = getbyte( ifp );
Grn = getbyte( ifp );
Red = getbyte( ifp );
if ( Size == 32 )
(void) getbyte( ifp ); /* Read alpha byte & throw away. */
l = 0;
break;

default:
pm_error( "unknown pixel size (#2) - %d", Size );
}

PixEncode:
if ( mapped )
*dest = ColorMap[l];
else
PPM_ASSIGN( *dest, Red, Grn, Blu );
}

static unsigned char
getbyte( ifp )
FILE* ifp;
{
unsigned char c;

if ( fread( (char*) &c, 1, 1, ifp ) != 1 )
pm_error( "EOF / read error" );

return c;
}
l: can't fseek to location in image buffer" );
return(0);
}
free((char *)line);
}
if (j != *bufsize) {
pm_message("unable to complete channel: %u / %u (%d%%)",
j, *bufsize, (int)(j*100.0 / *bufsize) );
*bufsizpbmplus05oct91/ppm/ppmtopi1.c 444 3010 34 6062 5070744606 11352 /* ppmtopi1.c - read a portable pixmap and write a Degas PI1 file
**
** Copyright (C) 1991 by Steve Belczyk and Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "ppmcmap.h"

#define COLS 320
#define ROWS 200
#define MAXVAL 7
#define MAXCOLORS 16

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel** pixels;
register pixel *pP;
colorhist_vector chv;
colorhash_table cht;
int rows, cols, row, colors, i;
register int col;
pixval maxval;
short screen[ROWS*COLS/4]; /* simulate the ST's video RAM */

ppm_init( &argc, argv );

if ( argc > 2 )
pm_usage( "[ppmfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
pm_close( ifp );
if ( (cols > COLS) || (rows > ROWS) )
pm_error( "image is larger than %dx%d - sorry", COLS, ROWS );

pm_message( "computing colormap..." );
chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
if ( chv == (colorhist_vector) 0 )
{
pm_message(
"too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
exit( 1 );
}
pm_message( "%d colors found", colors );

/* Write PI1 header - resolution and palette. */
(void) pm_writebigshort( stdout, (short) 0 ); /* low resolution */
for ( i = 0; i < 16; ++i )
{
short w;

if ( i < colors )
{
pixel p;

p = chv[i].color;
if ( maxval != MAXVAL )
PPM_DEPTH( p, p, maxval, MAXVAL );
w = ( (int) PPM_GETR( p ) ) << 8;
w |= ( (int) PPM_GETG( p ) ) << 4;
w |= ( (int) PPM_GETB( p ) );
}
else
w = 0;
(void) pm_writebigshort( stdout, w );
}
if ( maxval > MAXVAL )
pm_message(
"maxval is not %d - automatically rescaling colors", MAXVAL );

/* Convert color vector to color hash table, for fast lookup. */
cht = ppm_colorhisttocolorhash( chv, colors );
ppm_freecolorhist( chv );

/* Clear the screen buffer. */
for ( i = 0; i < ROWS*COLS/4; ++i )
screen[i] = 0;

/* Convert. */
for ( row = 0; row < rows; ++row )
{
for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
{
register int color, ind, b, plane;

color = ppm_lookupcolor( cht, pP );
if ( color == -1 )
pm_error(
"color not found?!? row=%d col=%d r=%d g=%d b=%d",
row, col, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP) );
ind = 80 * row + ( ( col >> 4 ) << 2 );
b = 0x8000 >> (col & 0xf);
for ( plane = 0; plane < 4; ++plane )
if ( color & (1 << plane) )
screen[ind+plane] |= b;
}
}

/* And write out the screen buffer. */
for ( i = 0; i < ROWS*COLS/4; ++i )
(void) pm_writebigshort( stdout, screen[i] );

exit( 0 );
}
ppm.c
v ImakefilevŽMakefilebmtv
ppmmerge.ctv
ppmtopcx.1tv‘ ppmtopict.copbmv’ ppmtorgb3.1.cäv“
pcxtoppm.cv”
ppmtopcx.c3v• ppmtorgb3.cc.1v– ppmquantallt.cv— gouldtoppm.c1
v˜
ppmtoyuv.1 v™ pjtoppm.1.cvš ppmdither.1c.cvÇ ppmtopj.1opvÈ pjtoppm.cuwvÊ ppmdither.ciconvö ppmtopj.c
v÷
ppmtotga.c vø
ppmtotga.1 vù ppmtosixel.1 pbmplus05oct91/ppm/spctoppm.c 444 3010 34 10407 5070745425 11464 /* spctoppm.c - read a compressed Spectrum file and produce a portable pixmap
**
** Copyright (C) 1991 by Steve Belczyk and Jef Poskanzer
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

#define ROWS 200
#define COLS 320
#define MAXVAL 7

static void DoBitmap ARGS(( FILE* ifp ));
static void DoChar ARGS(( int n, char c ));
static void DoColormap ARGS(( FILE* ifp ));

static char screen[ROWS*COLS/2];
static short sscreen[ROWS*COLS/4];
static pixel pal[ROWS][48];
static long colormap_length, bitmap_length;

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
char c1, c2;
pixel* pixelrow;
register pixel* pP;
int row, col;

ppm_init( &argc, argv );

/* Check args. */
if ( argc > 2 )
pm_usage( "[spcfile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

/* Check SPC file header. */
c1 = getc( ifp );
c2 = getc( ifp );

if ( ( c1 != 'S' ) || ( c2 != 'P' ) )
pm_error( "not a Spectrum picture" );

/* Skip reserved bytes. */
getc( ifp );
getc( ifp );

/* Get length of bitmap data. */
(void) pm_readbiglong( ifp, &bitmap_length );

/* and colormap */
(void) pm_readbiglong( ifp, &colormap_length );

/* Process bitmap. */
DoBitmap( ifp );

/* Process colormap. */
DoColormap( ifp );

pm_close( ifp );

/* Write the PPM file. */
ppm_writeppminit( stdout, COLS, ROWS, (pixval) MAXVAL, 0 );
pixelrow = ppm_allocrow( COLS );

for ( row = 0; row < ROWS; ++row )
{
for ( col = 0, pP = pixelrow; col < COLS; ++col, ++pP )
{
int c, ind, b, plane, x1;

/* Compute pixel value. */
ind = ( 80 * row ) + ( ( col >> 4 ) << 2 );
b = 0x8000 >> (col & 0xf);
c = 0;
for ( plane = 0; plane < 4; ++plane )
if ( b & sscreen[ind+plane] )
c |= (1 << plane);

/* Compute palette index. */
x1 = 10 * c;
if ( c & 1 )
x1 -= 5;
else
++x1;
if ( ( col >= x1 ) && ( col < ( x1 + 160 ) ) )
c += 16;
if ( col >= ( x1 + 160 ) )
c += 32;

/* Store the proper color. */
*pP = pal[row][c];
}
ppm_writeppmrow( stdout, pixelrow, COLS, (pixval) MAXVAL, 0 );
}

exit( 0 );
}

static void
DoBitmap( ifp )
FILE* ifp;
{
int i;
long count, data;
char h, c;

/* Zero out first scan line. */
for ( i = 0; i < 160; ++i )
screen[i] = 0;

/* 'count' counts number of input bytes. */
count = 0;

/* 'data' counts just data bytes. */
data = 0;

while ( count < bitmap_length )
{
/* Get next record header. */
h = getc( ifp );
++count;

if ( ( h >= 0 ) && ( count < bitmap_length ) )
{
for ( i = 0; i <= h; ++i )
{
c = getc( ifp );
++count;
DoChar( data, c );
++data;
}
}
else if ( ( h < 0 ) && ( count < bitmap_length ) )
{
c = getc( ifp );
++count;

for ( i = 0; i < ( 2 - h ); ++i )
{
DoChar( data, c );
++data;
}
}
}

/* Convert the char version of the screen to short. */
for ( i = 0; i < ROWS*COLS/4; ++i )
sscreen[i] = ( screen[i<<1] << 8 ) + ( 0xff & screen[(i<<1)+1] );
}

#if __STDC__
static void
DoChar( int n, char c )
#else /*__STDC__*/
static void
DoChar( n, c )
int n;
char c;
#endif /*__STDC__*/
{
int i;

/* Compute screen index. */
i = 160 + 2 * ( n / 7960 ) + 8 * ( ( n % 7960 ) / 2 ) + ( n & 1 );
screen[i] = c;
}

static void
DoColormap( ifp )
FILE* ifp;
{
int i, j, b;
short mask;

/* Clear first three palettes. */
for ( j = 0; j < 48; ++j )
PPM_ASSIGN( pal[0][j], 0, 0, 0 );

/* Read the palettes. */
for ( i = 1; i < ROWS; ++i )
for ( j = 0; j < 3; ++j )
{
(void) pm_readbigshort( ifp, &mask );
for ( b = 0; b < 15; ++b )
if ( mask & ( 1 << b ) )
{
short k;
(void) pm_readbigshort( ifp, &k );
PPM_ASSIGN( pal[i][(j*16)+b],
( k & 0x700 ) >> 8,
( k & 0x070 ) >> 4,
( k & 0x007 ) );
}
}
}
art run. */
unsigned char i;
i = getbyte( ifp );
RLE_flag = ( i & 0x80 ) >> 7;
if ( RLE_flag == 0 )
/* Stream of unencoded pixels. */
RLE_count = i + 1;
else
/* Single pixel replicated. */
RLE_count = i - 127;
/pbmplus05oct91/ppm/sputoppm.c 444 3010 34 4665 5070745635 11502 /* sputoppm.c - read an uncompressed Spectrum file and produce a portable pixmap
**
** Copyright (C) 1991 by Steve Belczyk and Jef Poskanzer
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

#define ROWS 200
#define COLS 320
#define MAXVAL 7

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
pixel pal[ROWS][48]; /* Spectrum palettes, three per row */
short screen[ROWS*COLS/4]; /* simulates the Atari's video RAM */
int i, j;
pixel* pixelrow;
register pixel* pP;
int row, col;

ppm_init( &argc, argv );

/* Check args. */
if ( argc > 2 )
pm_usage( "[spufile]" );

if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;

/* Read the SPU file */

/* Read the screen data. */
for ( i = 0; i < ROWS*COLS/4; ++i )
(void) pm_readbigshort( ifp, &screen[i] );

/* Clear the first palette line. */
for ( j = 0; j < 48; ++j )
PPM_ASSIGN( pal[0][j], 0, 0, 0 );

/* Read the palettes. */
for ( i = 1; i < ROWS; ++i )
for ( j = 0; j < 48; ++j )
{
short k;
(void) pm_readbigshort( ifp, &k );
PPM_ASSIGN( pal[i][j],
( k & 0x700 ) >> 8,
( k & 0x070 ) >> 4,
( k & 0x007 ) );
}

pm_close( ifp );

/* Ok, get set for writing PPM. */
ppm_writeppminit( stdout, COLS, ROWS, (pixval) MAXVAL, 0 );
pixelrow = ppm_allocrow( COLS );

/* Now do the conversion. */
for ( row = 0; row < ROWS; ++row )
{
for ( col = 0, pP = pixelrow; col < COLS; ++col, ++pP )
{
int c, ind, b, plane, x1;

/* Compute pixel value. */
ind = 80 * row + ( ( col >> 4 ) << 2 );
b = 0x8000 >> (col & 0xf);
c = 0;
for ( plane = 0; plane < 4; ++plane )
if ( b & screen[ind+plane] )
c |= (1 << plane);

/* Compute palette index. */
x1 = 10 * c;
if ( c & 1 )
x1 -= 5;
else
++x1;
if ( ( col >= x1 ) && ( col < ( x1 + 160 ) ) )
c += 16;
if ( col >= ( x1 + 160 ) )
c += 32;

/* Store the proper color. */
*pP = pal[row][c];
}
ppm_writeppmrow( stdout, pixelrow, COLS, (pixval) MAXVAL, 0 );
}

exit( 0 );
}
pmtopj.c
v÷
ppmtotga.c vø
ppmtotga.1 vù ppmtosixel.1 pbmplus05oct91/ppm/ppmtoicr.c 444 3010 34 15533 5032734360 11453 /* ppmtoicr.c - convert a portable pixmap to NCSA ICR protocol
**
** Copyright (C) 1990 by Kanthan Pillay ([email protected])
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "ppmcmap.h"

#define MAXCOLORS 256
#define CLUTCOLORS 768

static int colorstobpp ARGS(( int colors ));
static int GetPixel ARGS(( int x, int y ));
static int rleit ARGS(( char* buf, char* bufto, int len ));

static pixel** pixels;
static colorhash_table cht;
static char* testimage;

void
main(argc, argv)
int argc;
char* argv[];
{
FILE* ifp;
int argn, rows, cols, colors, i, j, BitsPerPixel, newxsize;
pixval maxval;
colorhist_vector chv;
char rgb[CLUTCOLORS];
char* windowname;
char* thischar;
char* thisline;
char* space;
register unsigned char c;
register char* p;
int display, expand;
int rleflag, winflag;
char* usage = "[-windowname windowname] [-expand expand] [-display display] [-rle] [ppmfile]";

ppm_init( &argc, argv );

argn = 1;
windowname = "untitled";
winflag = 0;
expand = 1;
display = 0;
rleflag = 0;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < argc )
{
++argn;
windowname = argv[argn];
winflag = 1;
}
else if ( pm_keymatch(argv[argn],"-expand",2) && argn + 1 < argc )
{
++argn;
if ( sscanf( argv[argn], "%d",&expand ) != 1 )
pm_usage( usage );
}
else if ( pm_keymatch(argv[argn],"-display",2) && argn + 1 < argc )
{
++argn;
if ( sscanf( argv[argn], "%d",&display ) != 1 )
pm_usage( usage );
}
else if ( pm_keymatch(argv[argn],"-rle",2) )
rleflag = 1;
else if ( pm_keymatch(argv[argn],"-norle",2) )
rleflag = 0;
else
pm_usage( usage );
}

if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
if ( ! winflag )
windowname = argv[argn];
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pixels = ppm_readppm( ifp, &cols, &rows, &maxval );

pm_close( ifp );

for (i = 0; i < CLUTCOLORS; i++)
rgb[i] = 0;

/* Figure out the colormap. */
pm_message("computing colormap..." );
chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
if (chv == (colorhist_vector) 0)
pm_error( "too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
pm_message("%d colors found", colors );

/* Turn the ppm colormap into an ICR colormap. */
if (maxval > 255)
pm_message(
"maxval is not 255 - automatically rescaling colors" );
for (i = 0; i < colors; i++)
{
j = (3 * i);
if (maxval == 255)
{
rgb[j] = PPM_GETR(chv[i].color) ;
j++;
rgb[j] = PPM_GETG(chv[i].color) ;
j++;
rgb[j] = PPM_GETB(chv[i].color) ;
}
else
{
rgb[j] = (int) PPM_GETR(chv[i].color) * 255 / maxval;
j++;
rgb[j] = (int) PPM_GETG(chv[i].color) * 255 / maxval;
j++;
rgb[j] = (int) PPM_GETB(chv[i].color) * 255 / maxval;
}
}
BitsPerPixel = colorstobpp(colors);

/* And make a hash table for fast lookup. */
cht = ppm_colorhisttocolorhash(chv, colors);
ppm_freecolorhist(chv);


/************** Create a new window using ICR protocol *********/
/* Format is "ESC^W;left;top;width;height;display;windowname" */

pm_message("creating window %s ...", windowname );
(void)printf("\033^W;%d;%d;%d;%d;%d;%s^",0,0,cols*expand,rows*expand,display,windowname);
fflush(stdout);


/****************** Download the colormap. ********************/
pm_message("downloading colormap for %s ...", windowname );

(void)printf("\033^M;%d;%d;%d;%s^",0,MAXCOLORS,CLUTCOLORS,windowname);
thischar = rgb;
for (j=0; j c = *thischar++;
if (c > 31 && c < 123 ) { /* printable ASCII */
putchar(c);
}
else {
putchar((c>>6)+123); /* non-printable, so encode it */
putchar((c & 0x3f) + 32);
}
}
fflush(stdout);

/**************** send out picture *************************/
/* Protocol's RLE scheme is quicker but buggy */

if (rleflag) {
pm_message("sending run-length encoded picture data ..." );
testimage = (char*) malloc(rows*cols);
p = testimage;
for (i=0; i for (j=0; j *p++ = GetPixel(j,i);
space = (char*) malloc(rows*3);
thisline = testimage;
for (i = 0; i < rows; i++) {
newxsize = rleit(thisline,space,cols);
thisline += cols; /* increment to next line */
(void)printf("\033^R;%d;%d;%d;%d;%s^",0,i*expand,expand,newxsize,windowname);
thischar = space;
for (j=0; j< newxsize; j++) {
c= *thischar++; /*get byte to send */
if (c>31 && c <123) {
putchar(c);
}
else {
putchar((c>>6) + 123);
putchar((c & 0x3f) + 32);
}
}
fflush(stdout);
}
free(space);
exit(0);
}

/* Otherwise, send out uncompressed pixel data via the slow method */

else {
pm_message("sending picture data ..." );
for (i = 0; i < rows; i++) {
(void)printf("\033^P;%d;%d;%d;%d;%s^",0,i*expand,expand,cols,windowname);
for (j = 0; j < cols; j++) {
c = GetPixel(j,i);
if (c > 31 && c < 123) {
putchar(c);
}
else {
putchar((c>>6)+123);
putchar((c & 0x3f) + 32);
}
}
}
fflush(stdout);
exit(0);
}
}

static int
colorstobpp(colors)
int colors;
{
int bpp;

if (colors <= 2)
bpp = 1;
else if (colors <= 4)
bpp = 2;
else if (colors <= 8)
bpp = 3;
else if (colors <= 16)
bpp = 4;
else if (colors <= 32)
bpp = 5;
else if (colors <= 64)
bpp = 6;
else if (colors <= 128)
bpp = 7;
else if (colors <= 256)
bpp = 8;
else
pm_error("can't happen" );
return bpp;
}

static int
GetPixel(x, y)
int x, y;
{
int color;

color = ppm_lookupcolor(cht, &pixels[y][x]);
return color;
}


/* rleit compress with run length encoding as per NCSA's documentation */

static int
rleit(buf,bufto,len)
char* buf;
char* bufto;
int len;
{
register char* p;
register char* q;
register char* cfoll;
register char* clead;
char* begp;
int i;

p = buf;
cfoll = bufto;
clead = cfoll + 1;

begp = p;
while (len > 0 ) { /* encode until gone */

q = p + 1;
i = len-1;
while (*p == *q && i+120 > len && i) {
q++;
i--;
}

if (q > p +2) { /* three in a row */
if (p > begp) {
*cfoll = p - begp;
cfoll = clead;
}
*cfoll++ = 128 | (q-p); /*len of seq*/
*cfoll++ = *p; /* char of seq */
len -= q-p; /* subtract len of seq */
p = q;
clead = cfoll+1;
begp = p;
}
else {
*clead++ = *p++; /* copy one char */
len--;
if (p>begp + 120) {
*cfoll = p - begp;
cfoll = clead++;
begp = p;
}
}
}

/* fillin last bytecount */

if (p>begp)
*cfoll = (p - begp);
else
clead--;

return((int) (clead-bufto)); /*how many stored as encoded */
}
y = 0;
rleflag = 0;

while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < pbmplus05oct91/ppm/pgmtoppm.c 444 3010 34 6517 5032725176 11450 /* pgmtoppm.c - colorize a portable graymap into a portable pixmap
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
gray* grayrow;
register gray* gP;
pixel p;
pixel* pixelrow;
register pixel* pP;
pixel** mappixels;
int argn, rows, cols, format, maprows, mapcols, mapmaxcolor, row;
register int col;
gray maxval;
pixval mapmaxval;
char* color0;
char* color1;
pixval red0, grn0, blu0, red1, grn1, blu1;
char* usage = " [pgmfile]\n , [pgmfile]\n -map mapfile [pgmfile]";

ppm_init( &argc, argv );

argn = 1;
mappixels = (pixel**) 0;

if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-map", 2 ) )
{
++argn;
if ( argn == argc )
pm_usage( usage );
ifp = pm_openr( argv[argn] );
mappixels = ppm_readppm( ifp, &mapcols, &maprows, &mapmaxval );
pm_close( ifp );
mapmaxcolor = maprows * mapcols - 1;
}
else
pm_usage( usage );
++argn;
}

if ( mappixels == (pixel**) 0 )
{
if ( argn == argc )
pm_usage( usage );
color0 = argv[argn];
++argn;
}

if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;

if ( argn != argc )
pm_usage( usage );

pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
grayrow = pgm_allocrow( cols );
if ( mappixels == (pixel**) 0 )
ppm_writeppminit( stdout, cols, rows, (pixval) maxval, 0 );
else
ppm_writeppminit( stdout, cols, rows, mapmaxval, 0 );
pixelrow = ppm_allocrow( cols );

if ( mappixels == (pixel**) 0 )
{
color1 = index( color0, '-' );
if ( color1 == 0 )
{
color1 = color0;
red0 = 0;
grn0 = 0;
blu0 = 0;
}
else
{
*color1 = '\0';
++color1;
p = ppm_parsecolor( color0, (pixval) maxval );
red0 = PPM_GETR( p );
grn0 = PPM_GETG( p );
blu0 = PPM_GETB( p );
}
p = ppm_parsecolor( color1, (pixval) maxval );
red1 = PPM_GETR( p );
grn1 = PPM_GETG( p );
blu1 = PPM_GETB( p );
}

for ( row = 0; row < rows; ++row )
{
pgm_readpgmrow( ifp, grayrow, cols, maxval, format );

if ( mappixels == (pixel**) 0 )
{
for ( col = 0, gP = grayrow, pP = pixelrow;
col < cols;
++col, ++gP, ++pP )
PPM_ASSIGN(
*pP,
( red0 * ( maxval - *gP ) + red1 * *gP ) / maxval,
( grn0 * ( maxval - *gP ) + grn1 * *gP ) / maxval,
( blu0 * ( maxval - *gP ) + blu1 * *gP ) / maxval );

}
else
{
register int c;

for ( col = 0, gP = grayrow, pP = pixelrow;
col < cols;
++col, ++gP, ++pP )
{
if ( maxval == mapmaxcolor )
c = *gP;
else
c = *gP * mapmaxcolor / maxval;
*pP = mappixels[c / mapcols][c % mapcols];
}
}

ppm_writeppmrow( stdout, pixelrow, cols, (pixval) maxval, 0 );
}

pm_close( ifp );

exit( 0 );
}
);


/************** Create a new window using ICR protocol *********/
/* Format is "ESC^W;left;top;width;height;display;windowname" */

pm_message("creating window %s ...",pbmplus05oct91/ppm/picttoppm.c 444 3010 34 75721 5070522502 11635 /*
* picttoppm.c -- convert a MacIntosh PICT file to PPM format.
*
* Copyright 1989 George Phillips
*
* Permission is granted to freely distribute this program in whole or in
* part provided you don't make money off it, you don't pretend that you
* wrote it and that this notice accompanies the code.
*
* George Phillips
* Department of Computer Science
* University of British Columbia
*/

#include "ppm.h"

/*
* Typical byte, 2 byte and 4 byte integers.
*/
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long longword;

/*
* Data structures for QuickDraw (and hence PICT) stuff.
*/

struct Rect {
word top;
word left;
word bottom;
word right;
};

struct pixMap {
struct Rect Bounds;
word version;
word packType;
longword packSize;
longword hRes;
longword vRes;
word pixelType;
word pixelSize;
word cmpCount;
word cmpSize;
longword planeBytes;
longword pmTable;
longword pmReserved;
};

struct ct_entry {
word red;
word green;
word blue;
};

static char* stage;
static struct Rect picFrame;
static word* red;
static word* green;
static word* blue;
static word rowlen;
static longword planelen;
static int verbose;

struct opdef {
char* name;
int len;
void (*impl)();
char* description;
};

#define WORD_LEN (-1)

static void interpret_pict ARGS(( void ));
static void compact_plane ARGS(( word* plane, int planelen ));
static void output_ppm ARGS(( int version ));
static void Opcode_9A ARGS(( void ));
static void BitsRect ARGS(( int version ));
static void BitsRegion ARGS(( int version ));
static void do_bitmap ARGS(( int version, int rowBytes, int is_region ));
static void do_pixmap ARGS(( int version, word rowBytes, int is_region ));
static void blit ARGS((
struct Rect* srcRect, struct Rect* srcBounds, int srcwid, byte* srcplane,
int pixSize, struct Rect* dstRect, struct Rect* dstBounds, int dstwid,
struct ct_entry* colour_map, int mode ));
static byte* unpackbits ARGS(( struct Rect* bounds, word rowBytes, int pixelSize ));
static byte* expand_buf ARGS(( byte* buf, int* len, int bits_per_pixel ));
static void Clip ARGS(( int version ));
static void read_pixmap ARGS(( struct pixMap* p, word* rowBytes ));
static struct ct_entry* read_colour_table ARGS(( void ));
static void BkPixPat ARGS(( int version ));
static void PnPixPat ARGS(( int version ));
static void FillPixPat ARGS(( int version ));
static void read_pattern ARGS(( void ));

static void skip_text ARGS(( void ));
static void LongText ARGS(( int version ));
static void DHText ARGS(( int version ));
static void DVText ARGS(( int version ));
static void DHDVText ARGS(( int version ));
static void skip_poly_or_region ARGS(( int version ));
static void LongComment ARGS(( void ));

static int rectsamesize ARGS(( struct Rect* r1, struct Rect* r2 ));
static void rectinter ARGS(( struct Rect* r1, struct Rect* r2, struct Rect* r3 ));

static void read_rect ARGS(( struct Rect* r ));
static void dump_rect ARGS(( char* s, struct Rect* r ));

static word get_op ARGS(( int version ));

static longword read_long ARGS(( void ));
static word read_word ARGS(( void ));
static byte read_byte ARGS(( void ));

static void skip ARGS(( int n ));
static void read_n ARGS(( int n, char* buf ));

/*
* a table of the first 194(?) opcodes. The table is too empty.
*
* Probably could use an entry specifying if the opcode is valid in version
* 1, etc.
*/

/* for reserved opcodes of known length */
#define res(length) \
{ "reserved", (length), NULL, "reserved for Apple use" }

/* for reserved opcodes of length determined by a function */
#define resf(skipfunction) \
{ "reserved", NA, (skipfunction), "reserved for Apple use" }

/* seems like RGB colours are 6 bytes, but Apple say's they're variable */
/* I'll use 6 for now as I don't care that much. */
#define RGB_LEN (6)

#define NA (0)

static struct opdef optable[] = {
/* 0x00 */ { "NOP", 0, NULL, "nop" },
/* 0x01 */ { "Clip", NA, Clip, "clip" },
/* 0x02 */ { "BkPat", 8, NULL, "background pattern" },
/* 0x03 */ { "TxFont", 2, NULL, "text font (word)" },
/* 0x04 */ { "TxFace", 1, NULL, "text face (byte)" },
/* 0x05 */ { "TxMode", 2, NULL, "text mode (word)" },
/* 0x06 */ { "SpExtra", 4, NULL, "space extra (fixed point)" },
/* 0x07 */ { "PnSize", 4, NULL, "pen size (point)" },
/* 0x08 */ { "PnMode", 2, NULL, "pen mode (word)" },
/* 0x09 */ { "PnPat", 8, NULL, "pen pattern" },
/* 0x0a */ { "FillPat", 8, NULL, "fill pattern" },
/* 0x0b */ { "OvSize", 4, NULL, "oval size (point)" },
/* 0x0c */ { "Origin", 4, NULL, "dh, dv (word)" },
/* 0x0d */ { "TxSize", 2, NULL, "text size (word)" },
/* 0x0e */ { "FgColor", 4, NULL, "foreground color (longword)" },
/* 0x0f */ { "BkColor", 4, NULL, "background color (longword)" },
/* 0x10 */ { "TxRatio", 8, NULL, "numer (point), denom (point)" },
/* 0x11 */ { "Version", 1, NULL, "version (byte)" },
/* 0x12 */ { "BkPixPat", NA, BkPixPat, "color background pattern" },
/* 0x13 */ { "PnPixPat", NA, PnPixPat, "color pen pattern" },
/* 0x14 */ { "FillPixPat", NA, FillPixPat, "color fill pattern" },
/* 0x15 */ { "PnLocHFrac", 2, NULL, "fractional pen position" },
/* 0x16 */ { "ChExtra", 2, NULL, "extra for each character" },
/* 0x17 */ res(0),
/* 0x18 */ res(0),
/* 0x19 */ res(0),
/* 0x1a */ { "RGBFgCol", RGB_LEN, NULL, "RGB foreColor" },
/* 0x1b */ { "RGBBkCol", RGB_LEN, NULL, "RGB backColor" },
/* 0x1c */ { "HiliteMode", 0, NULL, "hilite mode flag" },
/* 0x1d */ { "HiliteColor", RGB_LEN, NULL, "RGB hilite color" },
/* 0x1e */ { "DefHilite", 0, NULL, "Use default hilite color" },
/* 0x1f */ { "OpColor", RGB_LEN, NULL, "RGB OpColor for arithmetic modes" },
/* 0x20 */ { "Line", 8, NULL, "pnLoc (point), newPt (point)" },
/* 0x21 */ { "LineFrom", 4, NULL, "newPt (point)" },
/* 0x22 */ { "ShortLine", 6, NULL, "pnLoc (point, dh, dv (-128 .. 127))" },
/* 0x23 */ { "ShortLineFrom", 2, NULL, "dh, dv (-128 .. 127)" },
/* 0x24 */ res(WORD_LEN),
/* 0x25 */ res(WORD_LEN),
/* 0x26 */ res(WORD_LEN),
/* 0x27 */ res(WORD_LEN),
/* 0x28 */ { "LongText", NA, LongText, "txLoc (point), count (0..255), text" },
/* 0x29 */ { "DHText", NA, DHText, "dh (0..255), count (0..255), text" },
/* 0x2a */ { "DVText", NA, DVText, "dv (0..255), count (0..255), text" },
/* 0x2b */ { "DHDVText", NA, DHDVText, "dh, dv (0..255), count (0..255), text" },
/* 0x2c */ res(WORD_LEN),
/* 0x2d */ res(WORD_LEN),
/* 0x2e */ res(WORD_LEN),
/* 0x2f */ res(WORD_LEN),
/* 0x30 */ { "frameRect", 8, NULL, "rect" },
/* 0x31 */ { "paintRect", 8, NULL, "rect" },
/* 0x32 */ { "eraseRect", 8, NULL, "rect" },
/* 0x33 */ { "invertRect", 8, NULL, "rect" },
/* 0x34 */ { "fillRect", 8, NULL, "rect" },
/* 0x35 */ res(8),
/* 0x36 */ res(8),
/* 0x37 */ res(8),
/* 0x38 */ { "frameSameRect", 0, NULL, "rect" },
/* 0x39 */ { "paintSameRect", 0, NULL, "rect" },
/* 0x3a */ { "eraseSameRect", 0, NULL, "rect" },
/* 0x3b */ { "invertSameRect", 0, NULL, "rect" },
/* 0x3c */ { "fillSameRect", 0, NULL, "rect" },
/* 0x3d */ res(0),
/* 0x3e */ res(0),
/* 0x3f */ res(0),
/* 0x40 */ { "frameRRect", 8, NULL, "rect" },
/* 0x41 */ { "paintRRect", 8, NULL, "rect" },
/* 0x42 */ { "eraseRRect", 8, NULL, "rect" },
/* 0x43 */ { "invertRRect", 8, NULL, "rect" },
/* 0x44 */ { "fillRRrect", 8, NULL, "rect" },
/* 0x45 */ res(8),
/* 0x46 */ res(8),
/* 0x47 */ res(8),
/* 0x48 */ { "frameSameRRect", 0, NULL, "rect" },
/* 0x49 */ { "paintSameRRect", 0, NULL, "rect" },
/* 0x4a */ { "eraseSameRRect", 0, NULL, "rect" },
/* 0x4b */ { "invertSameRRect", 0, NULL, "rect" },
/* 0x4c */ { "fillSameRRect", 0, NULL, "rect" },
/* 0x4d */ res(0),
/* 0x4e */ res(0),
/* 0x4f */ res(0),
/* 0x50 */ { "frameOval", 8, NULL, "rect" },
/* 0x51 */ { "paintOval", 8, NULL, "rect" },
/* 0x52 */ { "eraseOval", 8, NULL, "rect" },
/* 0x53 */ { "invertOval", 8, NULL, "rect" },
/* 0x54 */ { "fillOval", 8, NULL, "rect" },
/* 0x55 */ res(8),
/* 0x56 */ res(8),
/* 0x57 */ res(8),
/* 0x58 */ { "frameSameOval", 0, NULL, "rect" },
/* 0x59 */ { "paintSameOval", 0, NULL, "rect" },
/* 0x5a */ { "eraseSameOval", 0, NULL, "rect" },
/* 0x5b */ { "invertSameOval", 0, NULL, "rect" },
/* 0x5c */ { "fillSameOval", 0, NULL, "rect" },
/* 0x5d */ res(0),
/* 0x5e */ res(0),
/* 0x5f */ res(0),
/* 0x60 */ { "frameArc", 12, NULL, "rect, startAngle, arcAngle" },
/* 0x61 */ { "paintArc", 12, NULL, "rect, startAngle, arcAngle" },
/* 0x62 */ { "eraseArc", 12, NULL, "rect, startAngle, arcAngle" },
/* 0x63 */ { "invertArc", 12, NULL, "rect, startAngle, arcAngle" },
/* 0x64 */ { "fillArc", 12, NULL, "rect, startAngle, arcAngle" },
/* 0x65 */ res(12),
/* 0x66 */ res(12),
/* 0x67 */ res(12),
/* 0x68 */ { "frameSameArc", 4, NULL, "rect, startAngle, arcAngle" },
/* 0x69 */ { "paintSameArc", 4, NULL, "rect, startAngle, arcAngle" },
/* 0x6a */ { "eraseSameArc", 4, NULL, "rect, startAngle, arcAngle" },
/* 0x6b */ { "invertSameArc", 4, NULL, "rect, startAngle, arcAngle" },
/* 0x6c */ { "fillSameArc", 4, NULL, "rect, startAngle, arcAngle" },
/* 0x6d */ res(4),
/* 0x6e */ res(4),
/* 0x6f */ res(4),
/* 0x70 */ { "framePoly", NA, skip_poly_or_region, "poly" },
/* 0x71 */ { "paintPoly", NA, skip_poly_or_region, "poly" },
/* 0x72 */ { "erasePoly", NA, skip_poly_or_region, "poly" },
/* 0x73 */ { "invertPoly", NA, skip_poly_or_region, "poly" },
/* 0x74 */ { "fillPoly", NA, skip_poly_or_region, "poly" },
/* 0x75 */ resf(skip_poly_or_region),
/* 0x76 */ resf(skip_poly_or_region),
/* 0x77 */ resf(skip_poly_or_region),
/* 0x78 */ { "frameSamePoly", 0, NULL, "poly (NYI)" },
/* 0x79 */ { "paintSamePoly", 0, NULL, "poly (NYI)" },
/* 0x7a */ { "eraseSamePoly", 0, NULL, "poly (NYI)" },
/* 0x7b */ { "invertSamePoly", 0, NULL, "poly (NYI)" },
/* 0x7c */ { "fillSamePoly", 0, NULL, "poly (NYI)" },
/* 0x7d */ res(0),
/* 0x7e */ res(0),
/* 0x7f */ res(0),
/* 0x80 */ { "frameRgn", NA, skip_poly_or_region, "region" },
/* 0x81 */ { "paintRgn", NA, skip_poly_or_region, "region" },
/* 0x82 */ { "eraseRgn", NA, skip_poly_or_region, "region" },
/* 0x83 */ { "invertRgn", NA, skip_poly_or_region, "region" },
/* 0x84 */ { "fillRgn", NA, skip_poly_or_region, "region" },
/* 0x85 */ resf(skip_poly_or_region),
/* 0x86 */ resf(skip_poly_or_region),
/* 0x87 */ resf(skip_poly_or_region),
/* 0x88 */ { "frameSameRgn", 0, NULL, "region (NYI)" },
/* 0x89 */ { "paintSameRgn", 0, NULL, "region (NYI)" },
/* 0x8a */ { "eraseSameRgn", 0, NULL, "region (NYI)" },
/* 0x8b */ { "invertSameRgn", 0, NULL, "region (NYI)" },
/* 0x8c */ { "fillSameRgn", 0, NULL, "region (NYI)" },
/* 0x8d */ res(0),
/* 0x8e */ res(0),
/* 0x8f */ res(0),
/* 0x90 */ { "BitsRect", NA, BitsRect, "copybits, rect clipped" },
/* 0x91 */ { "BitsRgn", NA, BitsRegion, "copybits, rgn clipped" },
/* 0x92 */ res(WORD_LEN),
/* 0x93 */ res(WORD_LEN),
/* 0x94 */ res(WORD_LEN),
/* 0x95 */ res(WORD_LEN),
/* 0x96 */ res(WORD_LEN),
/* 0x97 */ res(WORD_LEN),
/* 0x98 */ { "PackBitsRect", NA, BitsRect, "packed copybits, rect clipped" },
/* 0x99 */ { "PackBitsRgn", NA, BitsRegion, "packed copybits, rgn clipped" },
/* 0x9a */ { "Opcode_9A", NA, Opcode_9A, "the mysterious opcode 9A" },
/* 0x9b */ res(WORD_LEN),
/* 0x9c */ res(WORD_LEN),
/* 0x9d */ res(WORD_LEN),
/* 0x9e */ res(WORD_LEN),
/* 0x9f */ res(WORD_LEN),
/* 0xa0 */ { "ShortComment", 2, NULL, "kind (word)" },
/* 0xa1 */ { "LongComment", NA, LongComment, "kind (word), size (word), data" }
};

static int align = 0;
static FILE* ifp;

void
main(argc, argv)
int argc;
char* argv[];
{
int argn;
char* usage = "[-verbose] [pictfile]";

ppm_init( &argc, argv );

argn = 1;
verbose = 0;

if (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
if (pm_keymatch(argv[argn], "-verbose", 2))
verbose = 1;
else
pm_usage(usage);
++argn;
}

if (argn < argc) {
ifp = pm_openr(argv[argn]);
++argn;
} else
ifp = stdin;

if (argn != argc)
pm_usage(usage);

stage = "Reading 512 byte header";
skip(512);

interpret_pict();
exit(0);
}

static void
interpret_pict()
{
byte ch;
word picSize;
word opcode;
word len;
int version;

stage = "Reading picture size";
picSize = read_word();

if (verbose)
pm_message("picture size = %d (0x%x)", picSize, picSize);

stage = "reading picture frame";
read_rect(&picFrame);

if (verbose) {
dump_rect("Picture frame:", &picFrame);
pm_message("Picture size is %d x %d",
picFrame.right - picFrame.left,
picFrame.bottom - picFrame.top);
}

/* allocation is same for version 1 or version 2. We are super-duper
* wasteful of memory for version 1 picts. Someday, we'll separate
* things and only allocate a byte per pixel for version 1 (or heck,
* even only a bit, but that would require even more extra work).
*/

rowlen = picFrame.right - picFrame.left;
planelen = rowlen * (picFrame.bottom - picFrame.top);
if ((red = (word*)malloc(planelen * sizeof(word))) == NULL ||
(green = (word*)malloc(planelen * sizeof(word))) == NULL ||
(blue = (word*)malloc(planelen * sizeof(word))) == NULL)

pm_error("not enough memory to hold picture");

while ((ch = read_byte()) == 0)
;
if (ch != 0x11)
pm_error("No version number");

switch (read_byte()) {
case 1:
version = 1;
break;
case 2:
if (read_byte() != 0xff)
pm_error("can only do version 2, subcode 0xff");
version = 2;
break;
default:
pm_error("Unknown version");
}

if (verbose)
pm_message("PICT version %d", version);

while((opcode = get_op(version)) != 0xff) {
if (opcode < 0xa2) {
if (verbose) {
stage = optable[opcode].name;
if (!strcmp(stage, "reserved"))
pm_message("reserved opcode=0x%x", opcode);
else
pm_message("%s", stage = optable[opcode].name);
}

if (optable[opcode].impl != NULL)
(*optable[opcode].impl)(version);
else if (optable[opcode].len >= 0)
skip(optable[opcode].len);
else switch (optable[opcode].len) {
case WORD_LEN:
len = read_word();
skip(len);
break;
default:
pm_error("can't do length of %d",
optable[opcode].len);
}
}
else if (opcode == 0xc00) {
if (verbose)
pm_message("HeaderOp");
stage = "HeaderOp";
skip(24);
}
else if (opcode >= 0xa2 && opcode <= 0xaf) {
stage = "skipping reserved";
if (verbose)
pm_message("%s 0x%x", stage, opcode);
skip(read_word());
}
else if (opcode >= 0xb0 && opcode <= 0xcf) {
/* just a reserved opcode, no data */
if (verbose)
pm_message("reserved 0x%x", opcode);
}
else if (opcode >= 0xd0 && opcode <= 0xfe) {
stage = "skipping reserved";
if (verbose)
pm_message("%s 0x%x", stage, opcode);
skip(read_long());
}
else if (opcode >= 0x100 && opcode <= 0x7fff) {
stage = "skipping reserved";
if (verbose)
pm_message("%s 0x%x", stage, opcode);
skip((opcode >> 7) & 255);
}
else if (opcode >= 0x8000 && opcode <= 0x80ff) {
/* just a reserved opcode */
if (verbose)
pm_message("reserved 0x%x", opcode);
}
else if (opcode >= 8100 && opcode <= 0xffff) {
stage = "skipping reserved";
if (verbose)
pm_message("%s 0x%x", stage, opcode);
skip(read_long());
}
else
pm_error("can't handle opcode of %x", opcode);
}
output_ppm(version);
}

static void
compact_plane(plane, planelen)
register word* plane;
register int planelen;
{
register byte* p;

for (p = (byte*)plane; planelen-- > 0; )
*p++ = (*plane++ >> 8) & 255;
}

static void
output_ppm(version)
int version;
{
int width;
int height;
word test;
int offset1;
register char* r;
register char* g;
register char* b;
pixel* pixelrow;
register pixel* pP;
int row;
register int col;

/* determine byte order */
test = 0x0001;
offset1 = *((char*)&test);

stage = "writing PPM";

width = picFrame.right - picFrame.left;
height = picFrame.bottom - picFrame.top;
r = (char*) red;
compact_plane((word*) r, width * height);
g = (char*) green;
compact_plane((word*) g, width * height);
b = (char*) blue;
compact_plane((word*) b, width * height);

ppm_writeppminit(stdout, width, height, (pixval) 255, 0 );
pixelrow = ppm_allocrow(width);
for (row = 0; row < height; ++row) {
for (col = 0, pP = pixelrow; col < width;
++col, ++pP, ++r, ++g, ++b) {
PPM_ASSIGN(*pP, *r, *g, *b);
}

ppm_writeppmrow(stdout, pixelrow, width, (pixval) 255, 0 );
}
}

/*
* This could use read_pixmap, but I'm too lazy to hack read_pixmap.
*/

static void
Opcode_9A()
{
#ifdef DUMP
FILE *fp = fopen("data", "w");
int ch;
if (fp == NULL) exit(1);
while ((ch = fgetc(ifp)) != EOF) fputc(ch, fp);
exit(0);
#else
struct pixMap p;
struct Rect srcRect;
struct Rect dstRect;
byte* pm;
int pixwidth;
word mode;

/* skip fake len, and fake EOF */
skip(4);
read_word(); /* version */
read_rect(&p.Bounds);
pixwidth = p.Bounds.right - p.Bounds.left;
p.packType = read_word();
p.packSize = read_long();
p.hRes = read_long();
p.vRes = read_long();
p.pixelType = read_word();
p.pixelSize = read_word();
p.pixelSize = read_word();
p.cmpCount = read_word();
p.cmpSize = read_word();
p.planeBytes = read_long();
p.pmTable = read_long();
p.pmReserved = read_long();

if (p.pixelSize == 16)
pixwidth *= 2;
else if (p.pixelSize == 32)
pixwidth *= 3;

read_rect(&srcRect);
if (verbose)
dump_rect("source rectangle:", &srcRect);

read_rect(&dstRect);
if (verbose)
dump_rect("destination rectangle:", &dstRect);

mode = read_word();
if (verbose)
pm_message("mode = %x", mode);

pm = unpackbits(&p.Bounds, 0, p.pixelSize);

blit(&srcRect, &(p.Bounds), pixwidth, pm, p.pixelSize,
&dstRect, &picFrame, rowlen,
NULL,
mode);

free(pm);
#endif
}

static void
BitsRect(version)
int version;
{
word rowBytes;

stage = "Reading rowBytes for bitsrect";
rowBytes = read_word();

if (verbose)
pm_message("rowbytes = 0x%x (%d)", rowBytes, rowBytes & 0x7fff);

if (rowBytes & 0x8000)
do_pixmap(version, rowBytes, 0);
else
do_bitmap(version, rowBytes, 0);
}

static void
BitsRegion(version)
int version;
{
word rowBytes;

stage = "Reading rowBytes for bitsregion";
rowBytes = read_word();

if (rowBytes & 0x8000)
do_pixmap(version, rowBytes, 1);
else
do_bitmap(version, rowBytes, 1);
}

static void
do_bitmap(version, rowBytes, is_region)
int version;
int rowBytes;
int is_region;
{
struct Rect Bounds;
struct Rect srcRect;
struct Rect dstRect;
word mode;
byte* pm;
static struct ct_entry colour_table[] = { {65535L, 65535L, 65535L}, {0, 0, 0} };

read_rect(&Bounds);
read_rect(&srcRect);
read_rect(&dstRect);
mode = read_word();

if (is_region)
skip_poly_or_region(version);

stage = "unpacking rectangle";

pm = unpackbits(&Bounds, rowBytes, 1);

blit(&srcRect, &Bounds, Bounds.right - Bounds.left, pm, 8,
&dstRect, &picFrame, rowlen,
colour_table,
mode);

free(pm);
}

#if __STDC__
static void
do_pixmap( int version, word rowBytes, int is_region )
#else /*__STDC__*/
static void
do_pixmap(version, rowBytes, is_region)
int version;
word rowBytes;
int is_region;
#endif /*__STDC__*/
{
word mode;
struct pixMap p;
word pixwidth;
byte* pm;
struct ct_entry* colour_table;
struct Rect srcRect;
struct Rect dstRect;

read_pixmap(&p, NULL);

pixwidth = p.Bounds.right - p.Bounds.left;

if (verbose)
pm_message("%d x %d rectangle", pixwidth,
p.Bounds.bottom - p.Bounds.top);

colour_table = read_colour_table();

read_rect(&srcRect);

if (verbose)
dump_rect("source rectangle:", &srcRect);

read_rect(&dstRect);

if (verbose)
dump_rect("destination rectangle:", &dstRect);

mode = read_word();

if (verbose)
pm_message("mode = %x", mode);

if (is_region)
skip_poly_or_region(version);

stage = "unpacking rectangle";

pm = unpackbits(&p.Bounds, rowBytes, p.pixelSize);

blit(&srcRect, &(p.Bounds), pixwidth, pm, 8,
&dstRect, &picFrame, rowlen,
colour_table,
mode);

free(colour_table);
free(pm);
}

static void
blit(srcRect, srcBounds, srcwid, srcplane, pixSize, dstRect, dstBounds, dstwid, colour_map, mode)
struct Rect* srcRect;
struct Rect* srcBounds;
int srcwid;
byte* srcplane;
int pixSize;
struct Rect* dstRect;
struct Rect* dstBounds;
int dstwid;
struct ct_entry* colour_map;
int mode;
{
struct Rect clipsrc;
struct Rect clipdst;
register byte* src;
register word* reddst;
register word* greendst;
register word* bluedst;
register int i;
register int j;
int dstoff;
int xsize;
int ysize;
int srcadd;
int dstadd;
struct ct_entry* ct;
int pkpixsize;

/* almost got it. clip source rect with source bounds.
* clip dest rect with dest bounds.
* If they're not the same size - die!
* (it would require zeroing some area!)
* co-ordinate translations are actually done!
*/
rectinter(srcBounds, srcRect, &clipsrc);
rectinter(dstBounds, dstRect, &clipdst);

if (verbose) {
dump_rect("copying from:", &clipsrc);
dump_rect("to: ", &clipdst);
}

if (!rectsamesize(&clipsrc, &clipdst))
pm_message("warning, rectangles of different sizes after clipping!");


/* lots of assumptions about 8 bits per component, chunky bits, etc! */
/* 🙁 🙁 */

pkpixsize = 1;
if (pixSize == 16)
pkpixsize = 2;

src = srcplane + (clipsrc.top - srcBounds->top) * srcwid +
(clipsrc.left - srcBounds->left) * pkpixsize;
dstoff = (clipdst.top - dstBounds->top) * dstwid +
(clipdst.left - dstBounds->left);

reddst = red + dstoff;
greendst = green + dstoff;
bluedst = blue + dstoff;

xsize = clipsrc.right - clipsrc.left;
ysize = clipsrc.bottom - clipsrc.top;
srcadd = srcwid - xsize * pkpixsize;
dstadd = dstwid - xsize;

switch (pixSize) {
case 8:
for (i = 0; i < ysize; ++i) {
for (j = 0; j < xsize; ++j) {
ct = colour_map + *src++;
*reddst++ = ct->red;
*greendst++ = ct->green;
*bluedst++ = ct->blue;
}
src += srcadd;
reddst += dstadd;
greendst += dstadd;
bluedst += dstadd;
}
break;
case 16:
for (i = 0; i < ysize; ++i) {
for (j = 0; j < xsize; ++j) {
*reddst++ = (*src & 0x7c) << 9;
*greendst = (*src++ & 3) << 14;
*greendst++ |= (*src & 0xe0) << 6;
*bluedst++ = (*src++ & 0x1f) << 11;
}
src += srcadd;
reddst += dstadd;
greendst += dstadd;
bluedst += dstadd;
}
break;
case 32:
srcadd = (srcwid / 3) - xsize;
for (i = 0; i < ysize; ++i) {
for (j = 0; j < xsize; ++j)
*reddst++ = *src++ << 8;

reddst += dstadd;
src += srcadd;

for (j = 0; j < xsize; ++j)
*greendst++ = *src++ << 8;

greendst += dstadd;
src += srcadd;

for (j = 0; j < xsize; ++j)
*bluedst++ = *src++ << 8;

bluedst += dstadd;
src += srcadd;
}
}
}

#if __STDC__
static byte*
unpackbits( struct Rect* bounds, word rowBytes, int pixelSize )
#else /*__STDC__*/
static byte*
unpackbits(bounds, rowBytes, pixelSize)
struct Rect* bounds;
word rowBytes;
int pixelSize;
#endif /*__STDC__*/
{
byte* linebuf;
byte* pm;
byte* pm_ptr;
register int i,j,k,l;
word pixwidth;
int linelen;
int len;
byte* bytepixels;
int buflen;
int pkpixsize;

if (pixelSize <= 8)
rowBytes &= 0x7fff;

stage = "unpacking packbits";

pixwidth = bounds->right - bounds->left;

pkpixsize = 1;
if (pixelSize == 16) {
pkpixsize = 2;
pixwidth *= 2;
}
else if (pixelSize == 32)
pixwidth *= 3;

if (rowBytes == 0)
rowBytes = pixwidth;

/* we're sloppy and allocate some extra space because we can overshoot
* by as many as 8 bytes when we unpack the raster lines. Really, I
* should be checking to see if we go over the scan line (it is
* possbile) and complain of a corrupt file. That fix is more complex
* (and probably costly in CPU cycles) and will have to come later.
*/
if ((pm = (byte*)malloc((pixwidth * (bounds->bottom - bounds->top) + 8) * sizeof(byte))) == NULL)
pm_error("no mem for packbits rectangle");

/* Sometimes we get rows with length > rowBytes. I'll allocate some
* extra for slop and only die if the size is _way_ out of wack.
*/
if ((linebuf = (byte*)malloc(rowBytes + 100)) == NULL)
pm_error("can't allocate memory for line buffer");

if (rowBytes < 8) {
/* ah-ha! The bits aren't actually packed. This will be easy */
for (i = 0; i < bounds->bottom - bounds->top; i++) {
pm_ptr = pm + i * pixwidth;
read_n(buflen = rowBytes, (char*) linebuf);
bytepixels = expand_buf(linebuf, &buflen, pixelSize);
for (j = 0; j < buflen; j++)
*pm_ptr++ = *bytepixels++;
}
}
else {
for (i = 0; i < bounds->bottom - bounds->top; i++) {
pm_ptr = pm + i * pixwidth;
if (rowBytes > 250 || pixelSize > 8)
linelen = read_word();
else
linelen = read_byte();

if (verbose)
pm_message("linelen: %d", linelen);

if (linelen > rowBytes) {
pm_message("linelen > rowbytes! (%d > %d) at line %d",
linelen, rowBytes, i);
}

read_n(linelen, (char*) linebuf);

for (j = 0; j < linelen; ) {
if (linebuf[j] & 0x80) {
len = ((linebuf[j] ^ 255) & 255) + 2;
buflen = pkpixsize;
bytepixels = expand_buf(linebuf + j+1, &buflen, pixelSize);
for (k = 0; k < len; k++) {
for (l = 0; l < buflen; l++)
*pm_ptr++ = *bytepixels++;
bytepixels -= buflen;
}
j += 1 + pkpixsize;
}
else {
len = (linebuf[j] & 255) + 1;
buflen = len * pkpixsize;
bytepixels = expand_buf(linebuf + j+1, &buflen, pixelSize);
for (k = 0; k < buflen; k++)
*pm_ptr++ = *bytepixels++;
j += len * pkpixsize + 1;
}
}
}
}

free(linebuf);

return(pm);
}

static byte*
expand_buf(buf, len, bits_per_pixel)
byte* buf;
int* len;
int bits_per_pixel;
{
static byte pixbuf[256 * 8];
register byte* src;
register byte* dst;
register int i;

src = buf;
dst = pixbuf;

switch (bits_per_pixel) {
case 8:
case 16:
case 32:
return(buf);
case 4:
for (i = 0; i < *len; i++) {
*dst++ = (*src >> 4) & 15;
*dst++ = *src++ & 15;
}
*len *= 2;
break;
case 2:
for (i = 0; i < *len; i++) {
*dst++ = (*src >> 6) & 3;
*dst++ = (*src >> 4) & 3;
*dst++ = (*src >> 2) & 3;
*dst++ = *src++ & 3;
}
*len *= 4;
break;
case 1:
for (i = 0; i < *len; i++) {
*dst++ = (*src >> 7) & 1;
*dst++ = (*src >> 6) & 1;
*dst++ = (*src >> 5) & 1;
*dst++ = (*src >> 4) & 1;
*dst++ = (*src >> 3) & 1;
*dst++ = (*src >> 2) & 1;
*dst++ = (*src >> 1) & 1;
*dst++ = *src++ & 1;
}
*len *= 8;
break;
default:
pm_error("bad bits per pixel in expand_buf");
}
return(pixbuf);
}

static void
Clip(version)
int version;
{
skip(read_word() - 2);
}

static void
read_pixmap(p, rowBytes)
struct pixMap* p;
word* rowBytes;
{
stage = "getting pixMap header";

if (rowBytes != NULL)
*rowBytes = read_word();

read_rect(&p->Bounds);
p->version = read_word();
p->packType = read_word();
p->packSize = read_long();
p->hRes = read_long();
p->vRes = read_long();
p->pixelType = read_word();
p->pixelSize = read_word();
p->cmpCount = read_word();
p->cmpSize = read_word();
p->planeBytes = read_long();
p->pmTable = read_long();
p->pmReserved = read_long();

if (verbose) {
pm_message("pixelType: %d", p->pixelType);
pm_message("pixelSize: %d", p->pixelSize);
pm_message("cmpCount: %d", p->cmpCount);
pm_message("cmpSize: %d", p->cmpSize);
}

if (p->pixelType != 0)
pm_error("sorry, I only do chunky format");
if (p->cmpCount != 1)
pm_error("sorry, cmpCount != 1");
if (p->pixelSize != p->cmpSize)
pm_error("oops, pixelSize != cmpSize");
}

static struct ct_entry*
read_colour_table()
{
longword ctSeed;
word ctFlags;
word ctSize;
word val;
int i;
struct ct_entry* colour_table;

stage = "getting color table info";

ctSeed = read_long();
ctFlags = read_word();
ctSize = read_word();

if (verbose) {
pm_message("ctSeed: %d", ctSeed);
pm_message("ctFlags: %d", ctFlags);
pm_message("ctSize: %d", ctSize);
}

stage = "reading colour table";

if ((colour_table = (struct ct_entry*) malloc(sizeof(struct ct_entry) * (ctSize + 1))) == NULL)
pm_error("no memory for colour table");

for (i = 0; i <= ctSize; i++) {
if ((val = read_word()) > ctSize)
pm_error("pixel value greater than colour table size");
/* seems that if we have a device colour table, the val is
* always zero, so I assume we allocate up the list of colours.
*/
if (ctFlags & 0x8000)
val = i;
colour_table[val].red = read_word();
colour_table[val].green = read_word();
colour_table[val].blue = read_word();

if (verbose)
pm_message("%d: [%d,%d,%d]", val,
colour_table[val].red,
colour_table[val].green,
colour_table[val].blue, 0);
}

return(colour_table);
}

/* these 3 do nothing but skip over their data! */
static void
BkPixPat(version)
int version;
{
read_pattern();
}

static void
PnPixPat(version)
int version;
{
read_pattern();
}

static void
FillPixPat(version)
int version;
{
read_pattern();
}

/* this just skips over a version 2 pattern. Probabaly will return
* a pattern in the fabled complete version.
*/
static void
read_pattern()
{
word PatType;
word rowBytes;
struct pixMap p;
byte* pm;
struct ct_entry* ct;

stage = "Reading a pattern";

PatType = read_word();

switch (PatType) {
case 2:
skip(8); /* old pattern data */
skip(5); /* RGB for pattern */
break;
case 1:
skip(8); /* old pattern data */
read_pixmap(&p, &rowBytes);
ct = read_colour_table();
pm = unpackbits(&p.Bounds, rowBytes, p.pixelSize);
free(pm);
free(ct);
break;
default:
pm_error("unknown pattern type in read_pattern");
}
}

/* more stubs for text output */

static void
skip_text()
{
skip(read_byte());
}

static void
LongText(version)
int version;
{
skip(4);
skip_text();
}

static void
DHText(version)
int version;
{
skip(1);
skip_text();
}

static void
DVText(version)
int version;
{
skip(1);
skip_text();
}

static void
DHDVText(version)
int version;
{
skip(2);
skip_text();
}

static void
skip_poly_or_region(version)
int version;
{
stage = "skipping polygon or region";
skip(read_word() - 2);
}

static void
LongComment()
{
stage = "skipping longword comment";

skip(2);
skip(read_word());
}

static int
rectequal(r1, r2)
struct Rect* r1;
struct Rect* r2;
{
return(r1->top == r2->top &&
r1->bottom == r2->bottom &&
r1->left == r2->left &&
r1->right == r2->right);
}

static int
rectsamesize(r1, r2)
struct Rect* r1;
struct Rect* r2;
{
return(r1->right - r1->left == r2->right - r2->left &&
r1->bottom - r1->top == r2->bottom - r2->top);
}

static void
rectinter(r1, r2, r3)
struct Rect* r1;
struct Rect* r2;
struct Rect* r3;
{
r3->left = max(r1->left, r2->left);
r3->top = max(r1->top, r2->top);
r3->right = min(r1->right, r2->right);
r3->bottom = min(r1->bottom, r2->bottom);
}

static void
read_rect(r)
struct Rect* r;
{
r->top = read_word();
r->left = read_word();
r->bottom = read_word();
r->right = read_word();
}

static void
dump_rect(s, r)
char* s;
struct Rect* r;
{
pm_message("%s (%d,%d) (%d,%d)",
s, r->left, r->top, r->right, r->bottom);
}

/*
* All data in version 2 is 2-byte word aligned. Odd size data
* is padded with a null.
*/
static word
get_op(version)
int version;
{
if ((align & 1) && version == 2) {
stage = "aligning for opcode";
read_byte();
}

stage = "reading opcode";

if (version == 1)
return(read_byte());
else
return(read_word());
}

static longword
read_long()
{
word i;

i = read_word();
return((i << 16) | read_word());
}

static word
read_word()
{
byte b;

b = read_byte();

return((b << 8) | read_byte());
}

static byte
read_byte()
{
int c;

if ((c = fgetc(ifp)) == EOF)
pm_error("EOF / read error while %s", stage);

++align;
return(c & 255);
}

static void
skip(n)
int n;
{
static byte buf[1024];

align += n;

for (; n > 0; n -= 1024)
if (fread(buf, n > 1024 ? 1024 : n, 1, ifp) != 1)
pm_error("EOF / read error while %s", stage);
}

static void
read_n(n, buf)
int n;
char* buf;
{
align += n;

if (fread(buf, n, 1, ifp) != 1)
pm_error("EOF / read error while %s", stage);
}
) == NULL)
pm_error("no mem for packbits rectpbmplus05oct91/ppm/Imakefile 444 3010 34 6071 5070733327 11244 # Imakefile for ppm tools.
#
# Copyright (C) 1989, 1991 by Jef Poskanzer.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted, provided
# that the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation. This software is provided "as is" without express or
# implied warranty.

PGMDIR = ../pgm
INCLUDEPGM = -I$(PGMDIR)
LIBPGM = $(PGMDIR)/libpgm.a
DEFPGM = $(PGMDIR)/pgm.h
DEFLIBPGM = $(PGMDIR)/libpgm.h

PBMDIR = ../pbm
INCLUDEPBM = -I$(PBMDIR)
LIBPBM = $(PBMDIR)/libpbm.a
DEFPBM = $(PBMDIR)/pbm.h ../pbmplus.h
DEFLIBPBM = $(PBMDIR)/libpbm.h

INCLUDE = -I.. $(INCLUDEPGM) $(INCLUDEPBM)
RGBDEF = -DRGB_DB=\"DefaultRGBDatabase\"
ALLCFLAGS = $(CFLAGS) $(RGBDEF) $(INCLUDE)
LIBPPM = libppm.a

PORTBINARIES = giftoppm gouldtoppm ilbmtoppm imgtoppm mtvtoppm \
pcxtoppm pgmtoppm pi1toppm picttoppm \
pjtoppm ppmdither ppmhist ppmmake ppmquant \
ppmrelief ppmtogif ppmtoicr ppmtoilbm \
ppmtopcx ppmtopgm ppmtopi1 ppmtopict \
ppmtopj ppmtopuzz ppmtorgb3 ppmtosixel \
ppmtotga ppmtouil ppmtoxpm ppmtoyuv qrttoppm \
rawtoppm rgb3toppm spctoppm sputoppm \
tgatoppm ximtoppm xpmtoppm yuvtoppm
MATHBINARIES = ppmpat
BINARIES = $(PORTBINARIES) $(MATHBINARIES)
SCRIPTS = ppmquantall

MANUALS1 = giftoppm.1 gouldtoppm.1 ilbmtoppm.1 imgtoppm.1 mtvtoppm.1 \
pcxtoppm.1 pgmtoppm.1 pi1toppm.1 picttoppm.1 \
pjtoppm.1 ppmdither.1 ppmhist.1 ppmmake.1 ppmquant.1 \
ppmrelief.1 ppmtogif.1 ppmtoicr.1 ppmtoilbm.1 \
ppmtopcx.1 ppmtopgm.1 ppmtopi1.1 ppmtopict.1 \
ppmtopj.1 ppmtopuzz.1 ppmtorgb3.1 ppmtosixel.1 \
ppmtotga.1 ppmtouil.1 ppmtoxpm.1 ppmtoyuv.1 qrttoppm.1 \
rawtoppm.1 rgb3toppm.1 spctoppm.1 sputoppm.1 \
tgatoppm.1 ximtoppm.1 xpmtoppm.1 yuvtoppm.1 \
ppmpat.1 \
ppmquantall.1
MANUALS3 = libppm.3
MANUALS5 = ppm.5

all: $(BINARIES)

install:: all
cp $(BINARIES) $(BINDIR)
cp $(SCRIPTS) $(BINDIR)
cd $(BINDIR) ; chmod +x $(SCRIPTS)

install.man::
cp $(MANUALS1) $(MANUALS3) $(MANUALS5) $(MANDIR)

# Rule for plain programs.
$(PORTBINARIES): ppm.h $(DEFPGM) $(DEFPBM) $(LIBPPM) $(LIBPGM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] $(LIBPPM) $(LIBPGM) $(LIBPBM)

# Rule for math-dependent programs.
$(MATHBINARIES): ppm.h $(DEFPGM) $(DEFPBM) $(LIBPPM) $(LIBPGM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] -lm $(LIBPPM) $(LIBPGM) $(LIBPBM)

# And library.
$(LIBPPM): libppm1.o libppm2.o libppm3.o libppm4.o libppm5.o
-rm $(LIBPPM)
$(AR) $(LIBPPM) libppm1.o libppm2.o libppm3.o libppm4.o libppm5.o
-$(RANLIB) $(LIBPPM)

libppm1.o: ppm.h $(DEFPGM) $(DEFPBM) libppm.h libppm1.c
$(CC) $(ALLCFLAGS) -c libppm1.c
libppm2.o: ppm.h $(DEFPGM) $(DEFPBM) libppm.h libppm2.c $(DEFLIBPGM) $(DEFLIBPBM)
$(CC) $(ALLCFLAGS) -c libppm2.c
libppm3.o: ppm.h $(DEFPGM) $(DEFPBM) libppm.h libppm3.c
$(CC) $(ALLCFLAGS) -c libppm3.c
libppm4.o: ppm.h $(DEFPGM) $(DEFPBM) ppmcmap.h libppm4.c
$(CC) $(ALLCFLAGS) -c libppm4.c
libppm5.o: ppm.h $(DEFPGM) $(DEFPBM) ppmdraw.h libppm5.c
$(CC) $(ALLCFLAGS) -c libppm5.c

DependTarget()
IR)/libpgm.h

PBMDIR = ../pbm
INCLUDEPBM = -I$(PBMDIR)
LIBPBM = $(PBMDIR)/libpbm.a
DEFPBM = $(PBMDIR)/pbm.h ../pbmplus.h
DEFLIBPBM = $(PBMDIR)/libpbm.h

INCLUDE = -I.. $(INCLUDEPGM) $(INCLUDEPBM)
RGBDEF = -DRGB_DB=\"DefaultRGBDatabase\"
ALLCFLAGS = $(CFLAGS) $(RGBDEF) $(INCLUDE)
LIBPPM = libppm.a

PORTBINARIES = giftoppm gouldtoppm ilbmtoppm imgtoppm mtvtoppm \
pcxtoppm pgmtoppm pi1toppm picttoppm \
pjtoppm ppmdither ppmhist ppmmake ppmquant \
ppbmplus05oct91/ppm/Makefile 444 3010 34 14611 5070703751 11110 # Makefile for ppm tools.
#
# Copyright (C) 1989, 1991 by Jef Poskanzer.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted, provided
# that the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation. This software is provided "as is" without express or
# implied warranty.

# Default values, usually overridden by top-level Makefile.
#CC = cc
CC = gcc -ansi -pedantic -fcombine-regs -fpcc-struct-return
#CFLAGS = -O
CFLAGS = -g
#CFLAGS = -g -O
RGBDEF = -DRGB_DB=\"/usr/lib/X11/rgb.txt\"
#LDFLAGS = -s
LDFLAGS =
INSTALLBINARIES = /usr/new/pbm
INSTALLSCRIPTS = $(INSTALLBINARIES)
INSTALLMANUALS1 = /usr/man/mann
SUFFIXMANUALS1 = 1
INSTALLMANUALS3 = /usr/man/mann
SUFFIXMANUALS3 = 3
INSTALLMANUALS5 = /usr/man/mann
SUFFIXMANUALS5 = 5
MANCP = cp

PGMDIR = ../pgm
INCLUDEPGM = -I$(PGMDIR)
LIBPGM = $(PGMDIR)/libpgm.a
DEFPGM = $(PGMDIR)/pgm.h
DEFLIBPGM = $(PGMDIR)/libpgm.h

PBMDIR = ../pbm
INCLUDEPBM = -I$(PBMDIR)
LIBPBM = $(PBMDIR)/libpbm.a
DEFPBM = $(PBMDIR)/pbm.h ../pbmplus.h
DEFLIBPBM = $(PBMDIR)/libpbm.h

SHELL = /bin/sh
INCLUDE = -I.. $(INCLUDEPGM) $(INCLUDEPBM)
ALLCFLAGS = $(CFLAGS) $(RGBDEF) $(INCLUDE)
LIBPPM = libppm.a

PORTBINARIES = giftoppm gouldtoppm ilbmtoppm imgtoppm mtvtoppm \
pcxtoppm pgmtoppm pi1toppm picttoppm \
pjtoppm ppmdither ppmhist ppmmake ppmquant \
ppmrelief ppmtogif ppmtoicr ppmtoilbm \
ppmtopcx ppmtopgm ppmtopi1 ppmtopict \
ppmtopj ppmtopuzz ppmtorgb3 ppmtosixel \
ppmtotga ppmtouil ppmtoxpm ppmtoyuv qrttoppm \
rawtoppm rgb3toppm spctoppm sputoppm \
tgatoppm ximtoppm xpmtoppm yuvtoppm
MATHBINARIES = ppmpat
BINARIES = $(PORTBINARIES) $(MATHBINARIES)
SCRIPTS = ppmquantall

OBJECTS = giftoppm.o gouldtoppm.o ilbmtoppm.o imgtoppm.o mtvtoppm.o \
pcxtoppm.o pgmtoppm.o pi1toppm.o picttoppm.o \
pjtoppm.o ppmdither.o ppmhist.o ppmmake.o ppmquant.o \
ppmrelief.o ppmtogif.o ppmtoicr.o ppmtoilbm.o \
ppmtopcx.o ppmtopgm.o ppmtopi1.o ppmtopict.o \
ppmtopj.o ppmtopuzz.o ppmtorgb3.o ppmtosixel.o \
ppmtotga.o ppmtouil.o ppmtoxpm.o ppmtoyuv.o qrttoppm.o \
rawtoppm.o rgb3toppm.o spctoppm.o sputoppm.o \
tgatoppm.o ximtoppm.o xpmtoppm.o yuvtoppm.o \
ppmpat.o

MANUALS1 = $(BINARIES) $(SCRIPTS)
MANUALS3 = libppm
MANUALS5 = ppm


#all: binaries
all: merge
#install: install.bin
install: install.merge


binaries: $(BINARIES)

install.bin: binaries $(SCRIPTS)
cd $(INSTALLBINARIES) ; rm -f $(BINARIES)
cp $(BINARIES) $(INSTALLBINARIES)
cd $(INSTALLSCRIPTS) ; rm -f $(SCRIPTS)
cp $(SCRIPTS) $(INSTALLSCRIPTS)
cd $(INSTALLSCRIPTS) ; chmod +x $(SCRIPTS)


merge: ppmmerge
ppmmerge: ppmmerge.c $(OBJECTS) $(LIBPPM) $(LIBPGM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] $(OBJECTS) -lm $(LIBPPM) $(LIBPGM) $(LIBPBM)

install.merge: install.ppmmerge $(SCRIPTS)
install.ppmmerge: ppmmerge
cd $(INSTALLBINARIES) ; rm -f $(BINARIES)
cp ppmmerge $(INSTALLBINARIES)
cd $(INSTALLBINARIES) ; for i in $(BINARIES) ; do ln ppmmerge $$i ; done
rm $(INSTALLBINARIES)/ppmmerge
cd $(INSTALLSCRIPTS) ; rm -f $(SCRIPTS)
cp $(SCRIPTS) $(INSTALLSCRIPTS)
cd $(INSTALLSCRIPTS) ; chmod +x $(SCRIPTS)


install.man:
for i in $(MANUALS1) ; do \
rm -f $(INSTALLMANUALS1)/$$i.$(SUFFIXMANUALS1) ; \
$(MANCP) $$i.1 $(INSTALLMANUALS1)/$$i.$(SUFFIXMANUALS1) ; \
done
for i in $(MANUALS3) ; do \
rm -f $(INSTALLMANUALS3)/$$i.$(SUFFIXMANUALS3) ; \
$(MANCP) $$i.3 $(INSTALLMANUALS3)/$$i.$(SUFFIXMANUALS3) ; \
done
for i in $(MANUALS5) ; do \
rm -f $(INSTALLMANUALS5)/$$i.$(SUFFIXMANUALS5) ; \
$(MANCP) $$i.5 $(INSTALLMANUALS5)/$$i.$(SUFFIXMANUALS5) ; \
done


# Rule for plain programs.
$(PORTBINARIES): ppm.h $(DEFPGM) $(DEFPBM) $(LIBPPM) $(LIBPGM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] $(LIBPPM) $(LIBPGM) $(LIBPBM)

# Rule for math-dependent programs.
$(MATHBINARIES): ppm.h $(DEFPGM) $(DEFPBM) $(LIBPPM) $(LIBPGM) $(LIBPBM)
$(CC) $(ALLCFLAGS) $(LDFLAGS) -o [email protected] [email protected] -lm $(LIBPPM) $(LIBPGM) $(LIBPBM)

# Rule for objects.
$(OBJECTS): ppm.h $(DEFPGM) $(DEFPBM)
$(CC) $(ALLCFLAGS) "-Dmain=$*_main" -c $*.c

# And libraries.
$(LIBPBM):
cd $(PBMDIR) ; make lib
$(LIBPGM):
cd $(PGMDIR) ; make lib
lib: $(LIBPPM)
$(LIBPPM): libppm1.o libppm2.o libppm3.o libppm4.o libppm5.o
-rm $(LIBPPM)
ar rc $(LIBPPM) libppm1.o libppm2.o libppm3.o libppm4.o libppm5.o
-ranlib $(LIBPPM)

libppm1.o: ppm.h $(DEFPGM) $(DEFPBM) libppm.h libppm1.c
$(CC) $(ALLCFLAGS) -c libppm1.c
libppm2.o: ppm.h $(DEFPGM) $(DEFPBM) libppm.h libppm2.c $(DEFLIBPGM) \
$(DEFLIBPBM)
$(CC) $(ALLCFLAGS) -c libppm2.c
libppm3.o: ppm.h $(DEFPGM) $(DEFPBM) ppmcmap.h libppm.h libppm3.c
$(CC) $(ALLCFLAGS) -c libppm3.c
libppm4.o: ppm.h $(DEFPGM) $(DEFPBM) libppm4.c
$(CC) $(ALLCFLAGS) -c libppm4.c
libppm5.o: ppm.h $(DEFPGM) $(DEFPBM) ppmdraw.h libppm5.c
$(CC) $(ALLCFLAGS) -c libppm5.c

# Other dependencies.
giftoppm giftoppm.o: giftoppm.c
gouldtoppm gouldtoppm.o: gouldtoppm.c
ilbmtoppm ilbmtoppm.o: ilbmtoppm.c ilbm.h
imgtoppm imgtoppm.o: imgtoppm.c
mtvtoppm mtvtoppm.o: mtvtoppm.c
pcxtoppm pcxtoppm.o: pcxtoppm.c
pgmtoppm pgmtoppm.o: pgmtoppm.c
pi1toppm pi1toppm.o: pi1toppm.c
picttoppm picttoppm.o: picttoppm.c
pjtoppm pjtoppm.o: pjtoppm.c
ppmdither ppmdither.o: ppmdither.c
ppmhist ppmhist.o: ppmhist.c ppmcmap.h
ppmmake ppmmake.o: ppmmake.c
ppmpat ppmpat.o: ppmpat.c ppmdraw.h
ppmquant ppmquant.o: ppmquant.c $(PGMDIR)/dithers.h ppmcmap.h
ppmrelief ppmrelief.o: ppmrelief.c
ppmtogif ppmtogif.o: ppmtogif.c ppmcmap.h
ppmtoicr ppmtoicr.o: ppmtoicr.c ppmcmap.h
ppmtoilbm ppmtoilbm.o: ppmtoilbm.c ilbm.h ppmcmap.h
ppmtopcx ppmtopcx.o: ppmtopcx.c ppmcmap.h
ppmtopgm ppmtopgm.o: ppmtopgm.c
ppmtopi1 ppmtopi1.o: ppmtopi1.c ppmcmap.h
ppmtopict ppmtopict.o: ppmtopict.c ppmcmap.h
ppmtopj ppmtopj.o: ppmtopj.c
ppmtopuzz ppmtopuzz.o: ppmtopuzz.c ppmcmap.h
ppmtorgb3 ppmtorgb3.o: ppmtorgb3.c
ppmtosixel ppmtosixel.o: ppmtosixel.c ppmcmap.h
ppmtotga ppmtotga.o: ppmtotga.c ppmcmap.h
ppmtouil ppmtouil.o: ppmtouil.c ppmcmap.h
ppmtoxpm ppmtoxpm.o: ppmtoxpm.c ppmcmap.h
ppmtoyuv ppmtoyuv.o: ppmtoyuv.c
qrttoppm qrttoppm.o: qrttoppm.c
rawtoppm rawtoppm.o: rawtoppm.c
rgb3toppm rgb3toppm.o: rgb3toppm.c
spctoppm spctoppm.o: spctoppm.c
sputoppm sputoppm.o: sputoppm.c
tgatoppm tgatoppm.o: tgatoppm.c tga.h
ximtoppm ximtoppm.o: ximtoppm.c xim.h
xpmtoppm xpmtoppm.o: xpmtoppm.c
yuvtoppm yuvtoppm.o: yuvtoppm.c

clean:
-rm -f *.o *.a *.cat core $(BINARIES) ppmmerge
j] & 255) + 1;
buflen = len * pkpixsize;
bytepixels = expand_buf(linebuf + j+1, &buflen, pixelSize);
forpbmplus05oct91/ppm/ppmmerge.c 444 3010 34 4537 5070567277 11431 /* ppmmerge.c - wrapper program for PPM
**
** Copyright (C) 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include
#include "ppm.h"

void
main( argc, argv )
int argc;
char* argv[];
{
register char* cp;

again:
if ( ( cp = rindex( argv[0], '/' ) ) != (char*) 0 )
++cp;
else
cp = argv[0];
if ( strcmp( cp, "ppmmerge" ) == 0 )
{
++argv;
--argc;
goto again;
}

#define TRY(s,m) { if ( strcmp( cp, s ) == 0 ) m( argc, argv ); }

TRY("giftoppm", giftoppm_main);
TRY("gouldtoppm", gouldtoppm_main);
TRY("ilbmtoppm", ilbmtoppm_main);
TRY("imgtoppm", imgtoppm_main);
TRY("mtvtoppm", mtvtoppm_main);
TRY("pcxtoppm", pcxtoppm_main);
TRY("pgmtoppm", pgmtoppm_main);
TRY("pi1toppm", pi1toppm_main);
TRY("picttoppm", picttoppm_main);
TRY("pjtoppm", pjtoppm_main);
TRY("ppmdither", ppmdither_main);
TRY("ppmhist", ppmhist_main);
TRY("ppmmake", ppmmake_main);
TRY("ppmpat", ppmpat_main);
TRY("ppmquant", ppmquant_main);
TRY("ppmrelief", ppmrelief_main);
TRY("ppmtogif", ppmtogif_main);
TRY("ppmtoicr", ppmtoicr_main);
TRY("ppmtoilbm", ppmtoilbm_main);
TRY("ppmtopcx", ppmtopcx_main);
TRY("ppmtopgm", ppmtopgm_main);
TRY("ppmtopi1", ppmtopi1_main);
TRY("ppmtopict", ppmtopict_main);
TRY("ppmtopj", ppmtopj_main);
TRY("ppmtopuzz", ppmtopuzz_main);
TRY("ppmtorgb3", ppmtorgb3_main);
TRY("ppmtosixel", ppmtosixel_main);
TRY("ppmtotga", ppmtotga_main);
TRY("ppmtouil", ppmtouil_main);
TRY("ppmtoxpm", ppmtoxpm_main);
TRY("ppmtoyuv", ppmtoyuv_main);
TRY("qrttoppm", qrttoppm_main);
TRY("rawtoppm", rawtoppm_main);
TRY("rgb3toppm", rgb3toppm_main);
TRY("spctoppm", spctoppm_main);
TRY("sputoppm", sputoppm_main);
TRY("tgatoppm", tgatoppm_main);
TRY("ximtoppm", ximtoppm_main);
TRY("xpmtoppm", xpmtoppm_main);
TRY("yuvtoppm", yuvtoppm_main);

(void) fprintf(
stderr, "ppmmerge: \"%s\" is an unknown PPM program!\n", cp );
exit( 1 );
}
rge
#install: install.bin
install: install.merge


binaries: $(BINARIES)

install.bin: binaries $(SCRIPTS)
cd $(INSTALLBINARIES) ; rm -f $(BINARIES)
cp $(BINARpbmplus05oct91/ppm/ppmtopcx.1 444 3010 34 1312 5022777463 11366 .TH ppmtopcx 1 "09 April 1990"
.IX ppmtopcx
.SH NAME
ppmtopcx - convert a portable pixmap into a PCX file
.SH SYNOPSIS
.B ppmtopcx
.RI [ ppmfile ]
.SH DESCRIPTION
Reads a portable pixmap as input.
Produces a PCX file as output.
.IX PCX
.SH "SEE ALSO"
pcxtoppm(1), ppm(5)
.SH AUTHOR
Copyright (C) 1990 by Michael Davidson.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.
sY
pgmtoppm.1esZ
tgatoppm.1ks[
giftoppm.cds\ gouldtoppm.1Z{s]
pi1toppm.1 s^
ppmtogif.c}s_ ppmtoilbm.cs`ppm.hZsa
mtvtoppm.ccsb picttoppm.1Zscppm.5ctp
ppmtopi1.1.tê ppmmake.1uctëxim.h
tì ppmrelief.1pbmttípbmplus05oct91/ppm/ppmtopict.c 444 3010 34 25060 5032734555 11637 /*
** ppmtopict.c - read a portable pixmap and produce a Macintosh PICT2 file.
**
** Copyright (C) 1990 by Ken Yap .
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"
#include "ppmcmap.h"

#define HEADER_SIZE 512

#define RUN_THRESH 3
#define MAX_RUN 128 /* 0xff = 2, 0xfe = 3, etc */
#define MAX_COUNT 128 /* 0x00 = 1, 0x01 = 2, etc */

/* Opcodes */
#define PICT_NOP 0x00
#define PICT_clipRgn 0x01
#define PICT_bkPat 0x02
#define PICT_txFont 0x03
#define PICT_txFace 0x04
#define PICT_txMode 0x05
#define PICT_spExtra 0x06
#define PICT_pnSize 0x07
#define PICT_pnMode 0x08
#define PICT_pnPat 0x09
#define PICT_thePat 0x0A
#define PICT_ovSize 0x0B
#define PICT_origin 0x0C
#define PICT_txSize 0x0D
#define PICT_fgColor 0x0E
#define PICT_bkColor 0x0F
#define PICT_txRatio 0x10
#define PICT_picVersion 0x11
#define PICT_blPixPat 0x12
#define PICT_pnPixPat 0x13
#define PICT_fillPixPat 0x14
#define PICT_pnLocHFrac 0x15
#define PICT_chExtra 0x16
#define PICT_rgbFgCol 0x1A
#define PICT_rgbBkCol 0x1B
#define PICT_hiliteMode 0x1C
#define PICT_hiliteColor 0x1D
#define PICT_defHilite 0x1E
#define PICT_opColor 0x1F
#define PICT_line 0x20
#define PICT_line_from 0x21
#define PICT_short_line 0x22
#define PICT_short_line_from 0x23
#define PICT_long_text 0x28
#define PICT_DH_text 0x29
#define PICT_DV_text 0x2A
#define PICT_DHDV_text 0x2B
#define PICT_frameRect 0x30
#define PICT_paintRect 0x31
#define PICT_eraseRect 0x32
#define PICT_invertRect 0x33
#define PICT_fillRect 0x34
#define PICT_frameSameRect 0x38
#define PICT_paintSameRect 0x39
#define PICT_eraseSameRect 0x3A
#define PICT_invertSameRect 0x3B
#define PICT_fillSameRect 0x3C
#define PICT_frameRRect 0x40
#define PICT_paintRRect 0x41
#define PICT_eraseRRect 0x42
#define PICT_invertRRect 0x43
#define PICT_fillRRect 0x44
#define PICT_frameSameRRect 0x48
#define PICT_paintSameRRect 0x49
#define PICT_eraseSameRRect 0x4A
#define PICT_invertSameRRect 0x4B
#define PICT_fillSameRRect 0x4C
#define PICT_frameOval 0x50
#define PICT_paintOval 0x51
#define PICT_eraseOval 0x52
#define PICT_invertOval 0x53
#define PICT_fillOval 0x54
#define PICT_frameSameOval 0x58
#define PICT_paintSameOval 0x59
#define PICT_eraseSameOval 0x5A
#define PICT_invertSameOval 0x5B
#define PICT_fillSameOval 0x5C
#define PICT_frameArc 0x60
#define PICT_paintArc 0x61
#define PICT_eraseArc 0x62
#define PICT_invertArc 0x63
#define PICT_fillArc 0x64
#define PICT_frameSameArc 0x68
#define PICT_paintSameArc 0x69
#define PICT_eraseSameArc 0x6A
#define PICT_invertSameArc 0x6B
#define PICT_fillSameArc 0x6C
#define PICT_framePoly 0x70
#define PICT_paintPoly 0x71
#define PICT_erasePoly 0x72
#define PICT_invertPoly 0x73
#define PICT_fillPoly 0x74
#define PICT_frameSamePoly 0x78
#define PICT_paintSamePoly 0x79
#define PICT_eraseSamePoly 0x7A
#define PICT_invertSamePoly 0x7B
#define PICT_fillSamePoly 0x7C
#define PICT_frameRgn 0x80
#define PICT_paintRgn 0x81
#define PICT_eraseRgn 0x82
#define PICT_invertRgn 0x83
#define PICT_fillRgn 0x84
#define PICT_frameSameRgn 0x88
#define PICT_paintSameRgn 0x89
#define PICT_eraseSameRgn 0x8A
#define PICT_invertSameRgn 0x8B
#define PICT_fillSameRgn 0x8C
#define PICT_BitsRect 0x90
#define PICT_BitsRgn 0x91
#define PICT_PackBitsRect 0x98
#define PICT_PackBitsRgn 0x99
#define PICT_shortComment 0xA0
#define PICT_longComment 0xA1
#define PICT_EndOfPicture 0xFF
#define PICT_headerOp 0x0C00

static void putFill ARGS(( FILE *fd, int n ));
static void putShort ARGS(( FILE *fd, int i ));
static void putLong ARGS(( FILE *fd, long i ));
static void putFixed ARGS(( FILE *fd, int in, int frac ));
static void putRect ARGS(( FILE *fd, int x1, int x2, int y1, int y2 ));
static int putRow ARGS(( FILE *fd, int row, int cols, pixel *rowpixels, char *packed ));

#define MAXCOLORS 256
static colorhash_table cht;

void
main(argc, argv)
int argc;
char *argv[];
{
FILE *ifp;
int argn, rows, cols, colors, i, row, oc;
register pixel **pixels;
char *packed;
pixval maxval;
long lmaxval, rval, gval, bval;
colorhist_vector chv;

ppm_init( &argc, argv );

argn = 1;
if (argn < argc)
{
ifp = pm_openr(argv[1]);
argn++;
}
else
ifp = stdin;
if (argn != argc)
pm_usage("[ppmfile]");

pixels = ppm_readppm(ifp, &cols, &rows, &maxval);
if (cols < 8)
pm_error("ppm input too narrow, must be >= 8 pixels wide" );
lmaxval = (long)maxval;
pm_close(ifp);

/* Figure out the colormap. */
pm_message("computing colormap..." );
chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
if (chv == (colorhist_vector) 0)
pm_error("too many colors - try doing a 'ppmquant %d'", MAXCOLORS);
pm_message("%d colors found", colors );

/* Make a hash table for fast color lookup. */
cht = ppm_colorhisttocolorhash(chv, colors);

/* write the header */
putFill(stdout, HEADER_SIZE);

/* write picSize and picFrame */
putShort(stdout, 0);
putRect(stdout, 0, 0, rows, cols);

/* write version op and version */
putShort(stdout, PICT_picVersion);
putShort(stdout, 0x02FF);
putShort(stdout, PICT_headerOp);
putLong(stdout, -1L);
putFixed(stdout, 0, 0);
putFixed(stdout, 0, 0);
putFixed(stdout, cols, 0);
putFixed(stdout, rows, 0);
putFill(stdout, 4);

/* seems to be needed by many PICT2 programs */
putShort(stdout, PICT_clipRgn);
putShort(stdout, 10);
putRect(stdout, 0, 0, rows, cols);

/* write picture */
putShort(stdout, PICT_PackBitsRect);
putShort(stdout, cols | 0x8000);
putRect(stdout, 0, 0, rows, cols);
putShort(stdout, 0); /* pmVersion */
putShort(stdout, 0); /* packType */
putLong(stdout, 0L); /* packSize */
putFixed(stdout, 72, 0); /* hRes */
putFixed(stdout, 72, 0); /* vRes */
putShort(stdout, 0); /* pixelType */
putShort(stdout, 8); /* pixelSize */
putShort(stdout, 1); /* cmpCount */
putShort(stdout, 8); /* cmpSize */
putLong(stdout, 0L); /* planeBytes */
putLong(stdout, 0L); /* pmTable */
putLong(stdout, 0L); /* pmReserved */
putLong(stdout, 0L); /* ctSeed */
putShort(stdout, 0); /* ctFlags */
putShort(stdout, colors-1); /* ctSize */

/* Write out the colormap. */
for (i = 0; i < colors; i++)
{
putShort(stdout, i);
rval = PPM_GETR(chv[i].color);
gval = PPM_GETG(chv[i].color);
bval = PPM_GETB(chv[i].color);
if (lmaxval != 65535L)
{
rval = rval * 65535L / lmaxval;
gval = gval * 65535L / lmaxval;
bval = bval * 65535L / lmaxval;
}
putShort(stdout, (short)rval);
putShort(stdout, (short)gval);
putShort(stdout, (short)bval);
}

putRect(stdout, 0, 0, rows, cols); /* srcRect */
putRect(stdout, 0, 0, rows, cols); /* dstRect */
putShort(stdout, 0); /* mode */

/* Finally, write out the data. */
packed = (char*) malloc((unsigned)(cols+cols/MAX_COUNT+1));
oc = 0;
for (row = 0; row < rows; row++)
oc += putRow(stdout, row, cols, pixels[row], packed);

/* if we wrote an odd number of pixdata bytes, pad */
if (oc & 1)
putc(0, stdout);
putShort(stdout, PICT_EndOfPicture);

lmaxval = ftell(stdout) - HEADER_SIZE;
if (fseek(stdout, (long)HEADER_SIZE, 0) >= 0)
putShort(stdout, (short)(lmaxval & 0xffff));

exit(0);
}

static void
putFill(fd, n)
FILE *fd;
int n;
{
register int i;

for (i = 0; i < n; i++)
putc(0, fd);
}

static void
putShort(fd, i)
FILE *fd;
int i;
{
putc((i >> 8) & 0xff, fd);
putc(i & 0xff, fd);
}

#if __STDC__
static void
putLong( FILE *fd, long i )
#else /*__STDC__*/
static void
putLong(fd, i)
FILE *fd;
long i;
#endif /*__STDC__*/
{
putc((int)((i >> 24) & 0xff), fd);
putc(((int)(i >> 16) & 0xff), fd);
putc(((int)(i >> 8) & 0xff), fd);
putc((int)(i & 0xff), fd);
}

static void
putFixed(fd, in, frac)
FILE *fd;
int in, frac;
{
putShort(fd, in);
putShort(fd, frac);
}

static void
putRect(fd, x1, x2, y1, y2)
FILE *fd;
int x1, x2, y1, y2;
{
putShort(fd, x1);
putShort(fd, x2);
putShort(fd, y1);
putShort(fd, y2);
}

#define RUNLENGTH
#ifdef RUNLENGTH

#define runtochar(c) (257-(c))
#define counttochar(c) ((c)-1)

static int
putRow(fd, row, cols, rowpixels, packed)
FILE *fd;
int row, cols;
pixel *rowpixels;
char *packed;
{
register int i;
int packcols, count, run, rep, oc;
register pixel *pP;
pixel lastp;
register char *p;

run = count = 0;
for (cols--, i = cols, pP = rowpixels + cols, p = packed, lastp = *pP;
i >= 0; i--, lastp = *pP, pP--)
{
if (PPM_EQUAL(lastp, *pP))
run++;
else if (run < RUN_THRESH)
{
while (run > 0)
{
*p++ = ppm_lookupcolor(cht, &lastp);
run--;
count++;
if (count == MAX_COUNT)
{
*p++ = counttochar(MAX_COUNT);
count -= MAX_COUNT;
}
}
run = 1;
}
else
{
if (count > 0)
*p++ = counttochar(count);
count = 0;
while (run > 0)
{
rep = run > MAX_RUN ? MAX_RUN : run;
*p++ = ppm_lookupcolor(cht, &lastp);
*p++ = runtochar(rep);
run -= rep;
}
run = 1;
}
}
if (run < RUN_THRESH)
{
while (run > 0)
{
*p++ = ppm_lookupcolor(cht, &lastp);
run--;
count++;
if (count == MAX_COUNT)
{
*p++ = counttochar(MAX_COUNT);
count -= MAX_COUNT;
}
}
}
else
{
if (count > 0)
*p++ = counttochar(count);
count = 0;
while (run > 0)
{
rep = run > MAX_RUN ? MAX_RUN : run;
*p++ = ppm_lookupcolor(cht, &lastp);
*p++ = runtochar(rep);
run -= rep;
}
run = 1;
}
if (count > 0)
*p++ = counttochar(count);

packcols = p - packed; /* how many did we write? */
if (cols > 250)
{
putShort(fd, packcols);
oc = packcols + 2;
}
else
{
putc(packcols, fd);
oc = packcols + 1;
}

/* now write out the packed row */
while(p != packed)
{
--p;
putc(*p, fd);
}

return (oc);
}

#else /* RUNLENGTH */

/* real dumb putRow with no compression */
static int
putRow(fd, row, cols, rowpixels, packed)
FILE *fd;
int row, cols;
pixel *rowpixels;
char *packed;
{
register int i, j, bc, oc;
register pixel *pP;

#if notdef
bzero(aux, cols); /* aux?? */
#endif /*notdef*/
bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT;
if (bc > 250)
{
putShort(fd, bc);
oc = bc + 2;
}
else
{
putc(bc, fd);
oc = bc + 1;
}
for (i = 0, pP = rowpixels; i < cols;)
{
if (cols - i > MAX_COUNT)
{
putc(MAX_COUNT - 1, fd);
for (j = 0; j < MAX_COUNT; j++)
{
putc(ppm_lookupcolor(cht, pP), fd);
pP++;
}
i += MAX_COUNT;
}
else
{
putc(cols - i - 1, fd);
for (j = 0; j < cols - i; j++)
{
putc(ppm_lookupcolor(cht, pP), fd);
pP++;
}
i = cols;
}
}
return (oc);
}
#endif /* RUNLENGTH */

}
return(pixbuf);
}

static void
Clip(version)
int version;
{
skip(read_word() - 2);
}

static void
read_pixmap(p, rowBytes)
struct pixMap* p;
word* rowBytes;
{
stage = "getting pixMap header";

if (rowBytes != NULL)
*rowBytes = read_word();

read_rect(&p->Bounds);
p->version = read_word();
p->packType = read_word();
p->packSize = read_long();
p->hRes = read_long();
p->vRes = read_long();
p->pixelType = read_word();
p->pixelSize = read_word();
pbmplus05oct91/ppm/ppmtorgb3.1 444 3010 34 2165 5022777635 11441