This is pnmtops.c in view mode; [Download] [Up]
/* pnmtops.c - read a portable anymap and produce a PostScript 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.
**
**
** -nocenter option added November 1993 by Wolfgang Stuerzlinger,
** wrzl@gup.uni-linz.ac.at.
**
*/
#include "pnm.h"
#define MARGIN 0.95
static void putinit ARGS(( char* name, int cols, int rows, int padright, int bps, float scale, int dpi, int pagewid, int pagehgt, int format, int turnflag, int turnokflag, int rleflag, int center ));
static void putitem ARGS(( void ));
static void putxelval ARGS(( xelval xv ));
static void putrest ARGS(( void ));
static void rleputbuffer ARGS(( void ));
static void rleputitem ARGS(( void ));
static void rleputxelval ARGS(( xelval xv ));
static void rleflush ARGS(( void ));
static void rleputrest ARGS(( void ));
int
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
xel* xelrow;
register xel* xP;
int argn, turnflag, turnokflag, rleflag, center;
int rows, cols, format, bps, padright, row, col;
xelval maxval, nmaxval;
float scale, f;
int dpi, pagewid, pagehgt;
char name[100];
char* cp;
char* usage = "[-scale <x>] [-turn|-noturn] [-rle|-runlength] [-dpi <n>] [-width <n>] [-height <n>] [-rle|-runlength] [-center|-nocenter] [pnmfile]";
pnm_init( &argc, argv );
argn = 1;
scale = 1.0;
turnflag = 0;
center = 1;
turnokflag = 1;
rleflag = 0;
/* LaserWriter defaults. */
dpi = 300;
pagewid = 612;
pagehgt = 762;
/* Check for flags. */
while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-scale", 2 ) )
{
++argn;
if ( argn == argc || sscanf( argv[argn], "%f", &scale ) != 1 )
pm_usage( usage );
}
else if ( pm_keymatch( argv[argn], "-turn", 2 ) )
turnflag = 1;
else if ( pm_keymatch( argv[argn], "-noturn", 4 ) )
turnokflag = 0;
else if ( pm_keymatch( argv[argn], "-center", 2 ) )
center = 1;
else if ( pm_keymatch( argv[argn], "-nocenter", 4 ) )
center = 0;
else if ( pm_keymatch( argv[argn], "-rle", 2 ) ||
pm_keymatch( argv[argn], "-runlength", 2 ) )
rleflag = 1;
else if ( pm_keymatch( argv[argn], "-dpi", 2 ) )
{
++argn;
if ( argn == argc || sscanf( argv[argn], "%d", &dpi ) != 1 )
pm_usage( usage );
}
else if ( pm_keymatch( argv[argn], "-width", 2 ) )
{
++argn;
if ( argn == argc || sscanf( argv[argn], "%f", &f ) != 1 )
pm_usage( usage );
pagewid = f * 72.0;
}
else if ( pm_keymatch( argv[argn], "-height", 2 ) )
{
++argn;
if ( argn == argc || sscanf( argv[argn], "%f", &f ) != 1 )
pm_usage( usage );
pagehgt = f * 72.0;
}
else
pm_usage( usage );
++argn;
}
if ( argn < argc )
{
ifp = pm_openr( argv[argn] );
strcpy( name, argv[argn] );
if ( strcmp( name, "-" ) == 0 )
strcpy( name, "noname" );
if ( ( cp = index( name, '.' ) ) != 0 )
*cp = '\0';
++argn;
}
else
{
ifp = stdin;
strcpy( name, "noname" );
}
if ( argn != argc )
pm_usage( usage );
pnm_readpnminit( ifp, &cols, &rows, &maxval, &format );
xelrow = pnm_allocrow( cols );
/* 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 PostScript", 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 ) / bps;
putinit(name, cols, rows, padright, bps, scale, dpi, pagewid, pagehgt,
format, turnflag, turnokflag, rleflag, center );
for ( row = 0; row < rows; ++row )
{
pnm_readpnmrow( ifp, xelrow, cols, maxval, format );
switch ( PNM_FORMAT_TYPE( format ) )
{
case PPM_TYPE:
/* Color. */
for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
if ( maxval != nmaxval )
PPM_DEPTH( *xP, *xP, maxval, nmaxval );
/* First red. */
for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
if ( rleflag )
rleputxelval( PPM_GETR( *xP ) );
else
putxelval( PPM_GETR( *xP ) );
for ( col = 0; col < padright; ++col )
if ( rleflag )
rleputxelval( 0 );
else
putxelval( 0 );
if ( rleflag )
rleflush();
/* Then green. */
for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
if ( rleflag )
rleputxelval( PPM_GETG( *xP ) );
else
putxelval( PPM_GETG( *xP ) );
for ( col = 0; col < padright; ++col )
if ( rleflag )
rleputxelval( 0 );
else
putxelval( 0 );
if ( rleflag )
rleflush();
/* And blue. */
for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
if ( rleflag )
rleputxelval( PPM_GETB( *xP ) );
else
putxelval( PPM_GETB( *xP ) );
for ( col = 0; col < padright; ++col )
if ( rleflag )
rleputxelval( 0 );
else
putxelval( 0 );
if ( rleflag )
rleflush();
break;
default:
/* Grayscale. */
for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
{
if ( maxval != nmaxval )
PNM_ASSIGN1( *xP, (int) PNM_GET1(*xP) * nmaxval / maxval );
if ( rleflag )
rleputxelval( PNM_GET1( *xP ) );
else
putxelval( PNM_GET1( *xP ) );
}
for ( col = 0; col < padright; ++col )
if ( rleflag )
rleputxelval( 0 );
else
putxelval( 0 );
if ( rleflag )
rleflush();
break;
}
}
pm_close( ifp );
if ( rleflag )
rleputrest();
else
putrest();
exit( 0 );
}
static int bitspersample, item, bitsperitem, bitshift, itemsperline, items;
static int rleitem, rlebitsperitem, rlebitshift;
static int repeat, itembuf[128], count, repeatitem, repeatcount;
#if __STDC__
static void
putinit( char* name, int cols, int rows, int padright, int bps, float scale,
int dpi, int pagewid, int pagehgt, int format, int turnflag,
int turnokflag, int rleflag, int center )
#else /*__STDC__*/
static void
putinit( name, cols, rows, padright, bps, scale, dpi, pagewid, pagehgt, format,
turnflag, turnokflag, rleflag, center )
char* name;
int cols, rows, padright, bps;
float scale;
int dpi, pagewid, pagehgt, format, turnflag, turnokflag, rleflag, center;
#endif /*__STDC__*/
{
int icols, irows, devpix;
float pixfac, scols, srows, llx, lly;
/* Turn? */
icols = cols;
irows = rows;
if ( turnflag || ( turnokflag && cols > rows ) )
{
turnflag = 1;
cols = irows;
rows = icols;
}
/* Figure out size. */
devpix = dpi / 72.0 + 0.5; /* device pixels per unit, approx. */
pixfac = 72.0 / dpi * devpix; /* 1, approx. */
scols = scale * cols * pixfac;
srows = scale * rows * pixfac;
if ( scols > pagewid * MARGIN || srows > pagehgt * MARGIN )
{
if ( scols > pagewid * MARGIN )
{
scale *= pagewid / scols * MARGIN;
scols = scale * cols * pixfac;
srows = scale * rows * pixfac;
}
if ( srows > pagehgt * MARGIN )
{
scale *= pagehgt / srows * MARGIN;
scols = scale * cols * pixfac;
srows = scale * rows * pixfac;
}
pm_message(
"warning, image too large for page, rescaling to %g", scale );
}
llx = (center) ? ( pagewid - scols ) / 2 : 0;
lly = (center) ? ( pagehgt - srows ) / 2 : 0;
printf( "%%!PS-Adobe-2.0 EPSF-2.0\n" );
printf( "%%%%Creator: pnmtops\n" );
printf( "%%%%Title: %s.ps\n", name );
printf( "%%%%Pages: 1\n" );
printf(
"%%%%BoundingBox: %d %d %d %d\n",
(int) llx, (int) lly,
(int) ( llx + scols + 0.5 ), (int) ( lly + srows + 0.5 ) );
printf( "%%%%EndComments\n" );
if ( rleflag )
{
printf( "/rlestr1 1 string def\n" );
printf( "/readrlestring {\n" ); /* s -- nr */
printf( " /rlestr exch def\n" ); /* - */
printf( " currentfile rlestr1 readhexstring pop\n" ); /* s1 */
printf( " 0 get\n" ); /* c */
printf( " dup 127 le {\n" ); /* c */
printf( " currentfile rlestr 0\n" ); /* c f s 0 */
printf( " 4 3 roll\n" ); /* f s 0 c */
printf( " 1 add getinterval\n" ); /* f s */
printf( " readhexstring pop\n" ); /* s */
printf( " length\n" ); /* nr */
printf( " } {\n" ); /* c */
printf( " 256 exch sub dup\n" ); /* n n */
printf( " currentfile rlestr1 readhexstring pop\n" );/* n n s1 */
printf( " 0 get\n" ); /* n n c */
printf( " exch 0 exch 1 exch 1 sub {\n" ); /* n c 0 1 n-1*/
printf( " rlestr exch 2 index put\n" );
printf( " } for\n" ); /* n c */
printf( " pop\n" ); /* nr */
printf( " } ifelse\n" ); /* nr */
printf( "} bind def\n" );
printf( "/readstring {\n" ); /* s -- s */
printf( " dup length 0 {\n" ); /* s l 0 */
printf( " 3 copy exch\n" ); /* s l n s n l*/
printf( " 1 index sub\n" ); /* s l n s n r*/
printf( " getinterval\n" ); /* s l n ss */
printf( " readrlestring\n" ); /* s l n nr */
printf( " add\n" ); /* s l n */
printf( " 2 copy le { exit } if\n" ); /* s l n */
printf( " } loop\n" ); /* s l l */
printf( " pop pop\n" ); /* s */
printf( "} bind def\n" );
}
else
{
printf( "/readstring {\n" ); /* s -- s */
printf( " currentfile exch readhexstring pop\n" );
printf( "} bind def\n" );
}
if ( PNM_FORMAT_TYPE( format ) == PPM_TYPE )
{
printf( "/rpicstr %d string def\n", ( icols + padright ) * bps / 8 );
printf( "/gpicstr %d string def\n", ( icols + padright ) * bps / 8 );
printf( "/bpicstr %d string def\n", ( icols + padright ) * bps / 8 );
}
else
printf( "/picstr %d string def\n", ( icols + padright ) * bps / 8 );
printf( "%%%%EndProlog\n" );
printf( "%%%%Page: 1 1\n" );
printf( "gsave\n" );
printf( "%g %g translate\n", llx, lly );
printf( "%g %g scale\n", scols, srows );
if ( turnflag )
printf( "0.5 0.5 translate 90 rotate -0.5 -0.5 translate\n" );
printf( "%d %d %d\n", icols, irows, bps );
printf( "[ %d 0 0 -%d 0 %d ]\n", icols, irows, irows );
if ( PNM_FORMAT_TYPE( format ) == PPM_TYPE )
{
printf( "{ rpicstr readstring }\n" );
printf( "{ gpicstr readstring }\n" );
printf( "{ bpicstr readstring }\n" );
printf( "true 3\n" );
printf( "colorimage\n" );
pm_message( "writing color PostScript..." );
}
else
{
printf( "{ picstr readstring }\n" );
printf( "image\n" );
}
bitspersample = bps;
itemsperline = items = 0;
if ( rleflag )
{
rleitem = 0;
rlebitsperitem = 0;
rlebitshift = 8 - bitspersample;
repeat = 1;
count = 0;
}
else
{
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 putxelval( xelval xv )
#else /*__STDC__*/
static void
putxelval( xv )
xelval xv;
#endif /*__STDC__*/
{
if ( bitsperitem == 8 )
putitem();
item += xv << bitshift;
bitsperitem += bitspersample;
bitshift -= bitspersample;
}
static void
putrest()
{
if ( bitsperitem > 0 )
putitem();
printf( "\n" );
printf( "grestore\n" );
printf( "showpage\n" );
printf( "%%%%Trailer\n" );
}
static void
rleputbuffer()
{
int i;
if ( repeat )
{
item = 256 - count;
putitem();
item = repeatitem;
putitem();
}
else
{
item = count - 1;
putitem();
for ( i = 0; i < count; ++i )
{
item = itembuf[i];
putitem();
}
}
repeat = 1;
count = 0;
}
static void
rleputitem()
{
int i;
if ( count == 128 )
rleputbuffer();
if ( repeat && count == 0 )
{ /* Still initializing a repeat buf. */
itembuf[count] = repeatitem = rleitem;
++count;
}
else if ( repeat )
{ /* Repeating - watch for end of run. */
if ( rleitem == repeatitem )
{ /* Run continues. */
itembuf[count] = rleitem;
++count;
}
else
{ /* Run ended - is it long enough to dump? */
if ( count > 2 )
{ /* Yes, dump a repeat-mode buffer and start a new one. */
rleputbuffer();
itembuf[count] = repeatitem = rleitem;
++count;
}
else
{ /* Not long enough - convert to non-repeat mode. */
repeat = 0;
itembuf[count] = repeatitem = rleitem;
++count;
repeatcount = 1;
}
}
}
else
{ /* Not repeating - watch for a run worth repeating. */
if ( rleitem == repeatitem )
{ /* Possible run continues. */
++repeatcount;
if ( repeatcount > 3 )
{ /* Long enough - dump non-repeat part and start repeat. */
count = count - ( repeatcount - 1 );
rleputbuffer();
count = repeatcount;
for ( i = 0; i < count; ++i )
itembuf[i] = rleitem;
}
else
{ /* Not long enough yet - continue as non-repeat buf. */
itembuf[count] = rleitem;
++count;
}
}
else
{ /* Broken run. */
itembuf[count] = repeatitem = rleitem;
++count;
repeatcount = 1;
}
}
rleitem = 0;
rlebitsperitem = 0;
rlebitshift = 8 - bitspersample;
}
#if __STDC__
static void rleputxelval( xelval xv )
#else /*__STDC__*/
static void
rleputxelval( xv )
xelval xv;
#endif /*__STDC__*/
{
if ( rlebitsperitem == 8 )
rleputitem();
rleitem += xv << rlebitshift;
rlebitsperitem += bitspersample;
rlebitshift -= bitspersample;
}
static void
rleflush()
{
if ( rlebitsperitem > 0 )
rleputitem();
if ( count > 0 )
rleputbuffer();
}
static void
rleputrest()
{
rleflush();
printf( "\n" );
printf( "grestore\n" );
printf( "showpage\n" );
printf( "%%%%Trailer\n" );
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.