[comp.lang.postscript] SUN Rasterfile -> Postscript followup

keves@net1.ucsd.edu (Brian Keves) (01/23/88)

This is the followup I promised concerning SUN raster file to Postscript
conversions. The first letter gives some information, and the last two
give source code. The first source, called suntops, is, in my opinion,
superior to the second. This is because it is written with unix in mind,
and I was able to integrate it into my Transcript software without any
problems.

I hope you enjoy, and I wish to thank all of the people who sent me replies.
                           -----------------
Brian Keves			ARPA:	keves@sdcsvax.ucsd.edu
P.O. Box 12238			UUCP:	sdcsvax!keves
La Jolla, CA  92037-0620 	BITNET:	keves@ucsd
				PHONE:	619-534-3839 Please leave a message

ORGANIZATION: Lab for Mathematics and Statistics @ UCSD

Any opinions expressed are strictly my own and do not necessarily reflect the
opinions of my employer or UC Regents.
                           -----------------
From: lou@aramis.rutgers.edu (Lou Steinberg)
Subject: Re: Request for raster to Postscript program (SUN)

In article <4483@sdcsvax.UCSD.EDU> keves@net1.ucsd.edu (Brian Keves) writes:
> I need a program to convert SUN raster output to Postscript. 
On my sun3, at least, man pssun gives:

NAME
     pssun - convert a Sun raster-format  file  to  a  POSTSCRIPT
     file.

... etc. 

I -think- this is a standard sun program.
     [Quite a few people said this, but in fact it is actually an add on from
      Adobe Systems. BWK]
--
					Lou Steinberg

uucp:   {pretty much any major site}!rutgers!aramis.rutgers.edu!lou 
arpa:   lou@aramis.rutgers.edu
                           -----------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	Makefile
#	suntops.1
#	suntops.h
#	error.c
#	main.c
#	suntops.c
# This archive created: Sun Jan 17 12:51:43 1988
# By:	(super-user) ()
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Makefile'" '(680 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
XPGM	= suntops
XSRCS	= error.c main.c suntops.c
XHDRS	= suntops.h
XOBJS	= error.o main.o suntops.o
XMAN	= suntops.1
X
XCFLAGS	= -O
XLDFLAGS	=
XLIBS	=
XBINDIR	= /usr/local/bin
XBINMODE	= 755
XMANDIR	= /usr/local/man/man1
XMANMODE	= 444
XLINTFLAGS = -chab
XSHARFLAGS = -cvpX
X
X$(PGM): $(OBJS)
X	$(CC) $(LDFLAGS) -o $(PGM) $(OBJS) $(LIBS)
X
Xinstall: $(PGM) $(MAN)
X	strip $(PGM)
X	mv $(PGM) $(BINDIR)
X	chmod $(BINMODE) $(BINDIR)/$(PGM)
X	cp $(MAN) $(MANDIR)
X	chmod $(MANMODE) $(MANDIR)/$(MAN)
X
Xclean:
X	rm -f $(PGM) $(OBJS)
X
Xlint:
X	lint $(LINTFLAGS) $(SRCS)
X
Xshar: $(PGM).shar
X
X$(PGM).shar: Makefile $(MAN) $(HDRS) $(SRCS)
X	shar $(SHARFLAGS) Makefile $(MAN) $(HDRS) $(SRCS) >$(PGM).shar
X
X$(OBJS): $(HDRS)
SHAR_EOF
if test 680 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 680 characters)'
fi
chmod +x 'Makefile'
fi # end of overwriting check
echo shar: extracting "'suntops.1'" '(1835 characters)'
if test -f 'suntops.1'
then
	echo shar: will not over-write existing file "'suntops.1'"
else
sed 's/^X//' << \SHAR_EOF > 'suntops.1'
X.\" $Header: suntops.1,v 1.3 87/11/05 09:41:51 frew Exp $
X.TH SUNTOPS 1 "05 November 1987"
X.SH NAME
Xsuntops \- convert Sun rasterfile to PostScript
X.SH SYNOPSIS
X.B suntops
X.RB [ \-ir ]
X.RB [ \-h
X.IR height ]
X.RB [ \-w
X.IR width ]
X.RI [ file ]
X.SH DESCRIPTION
X.I Suntops
Xconverts a Sun rasterfile to a PostScript image.
XThe rasterfile is read from either the standard input or the specified
X.IR file .
XThe PostScript image is written to the standard output.
X.SH OPTIONS
X.TP
X.B \-i
XInvert the quantization of the printed image (i.e.,
Xreverse the output gray scale).
X.TP
X.B \-r
XRotate the PostScript output 90 degrees.
XUseful for printing landscape-mode rasterfiles (e.g. Sun
X.IR screendump s)
Xon portrait-mode printers (e.g. Apple LaserWriters).
X.TP
X.B \-h
XSet the maximum output image height to
X.I height
Xinches (default 9).
X.TP
X.B \-w
XSet the maximum output image width to
X.I width
Xinches (default 7.5).
X.SH EXAMPLES
XTo print the current Sun screen:
X.IP
Xscreendump\ |\ suntops \-r\ |\ lpr \-PPostScript
X.SH DIAGNOSTICS
X\*(lqself-explanatory\*(rq
X.SH RESTRICTIONS
XInput rasterfiles must be either 1 bit or 8 bits deep.
X.SH FUTURE DIRECTIONS
XSpecify page size on the command line.
X.PP
XAllow a \*(lqraw\*(rq output mode whereby the PostScript output is scaled to
Xexactly match the resolution of a specific printer.
XThis is supposed to print significantly faster.
X.PP
XProvide an alternative driver routine so that
X.I suntops
Xmay be invoked as
Xa line printer filter,
Xe.g.:
X.IP
Xlpr \-PPostScript \-v
X.SH AUTHOR
XJames Frew.
X.PP
X.B \-i
Xoption suggested by Philippe Schnoebelen.
X.PP
XPlease send bug reports,
Xfixes,
Xor enhancements to frew@hub.ucsb.edu
Xor
Xucbvax!ucsbcsl!frew.
X.SH BUGS
XThe
X.B \-r
Xoption is VERY slow
X(e.g.,
Xup to 45 MINUTES!).
XThis appears to be the fault of the LaserWriter's
X.B rotate
Xoperator,
Xwhen applied to large bitmaps.
SHAR_EOF
if test 1835 -ne "`wc -c < 'suntops.1'`"
then
	echo shar: error transmitting "'suntops.1'" '(should have been 1835 characters)'
fi
chmod +x 'suntops.1'
fi # end of overwriting check
echo shar: extracting "'suntops.h'" '(417 characters)'
if test -f 'suntops.h'
then
	echo shar: will not over-write existing file "'suntops.h'"
else
sed 's/^X//' << \SHAR_EOF > 'suntops.h'
X/*
X * suntops.h -- header file for suntops program
X */
X
X#define	PAGE_HEIGHT	11.0
X#define	PAGE_WIDTH	8.5
X
X#define	IMG_HEIGHT	9.0
X#define	IMG_WIDTH	7.5
X
X#define	ITOP(in)	( (int)((in) * 72.0) )
X
X#define	XTRANS_FUDGE	(1.0 / 16.0)	/* LaserWriter X bias		 */
X
X#define	HI_NYBBLE(i)	( ((i) >> 4) & 0xF )
X#define	LO_NYBBLE(i)	( (i) & 0xF )
X
X#define	FALSE		0
X#define	TRUE		(~FALSE)
X
Xextern void	error();
Xextern void	suntops();
SHAR_EOF
if test 417 -ne "`wc -c < 'suntops.h'`"
then
	echo shar: error transmitting "'suntops.h'" '(should have been 417 characters)'
fi
chmod +x 'suntops.h'
fi # end of overwriting check
echo shar: extracting "'error.c'" '(225 characters)'
if test -f 'error.c'
then
	echo shar: will not over-write existing file "'error.c'"
else
sed 's/^X//' << \SHAR_EOF > 'error.c'
X/*
X * error -- print error message and exit
X */
X
X#include <stdio.h>
X
Xextern int      errno;
X
Xvoid
Xerror(s)
X	char           *s;
X{
X	if (errno != 0) {
X		perror(s);
X	}
X	else {
X		(void) fprintf(stderr, "%s\n", s);
X	}
X
X	exit(1);
X}
SHAR_EOF
if test 225 -ne "`wc -c < 'error.c'`"
then
	echo shar: error transmitting "'error.c'" '(should have been 225 characters)'
fi
chmod +x 'error.c'
fi # end of overwriting check
echo shar: extracting "'main.c'" '(1186 characters)'
if test -f 'main.c'
then
	echo shar: will not over-write existing file "'main.c'"
else
sed 's/^X//' << \SHAR_EOF > 'main.c'
X/*
X * main -- driver for suntops
X */
X
X#include <stdio.h>
X
Xextern double   atof();
Xextern char    *optarg;
Xextern int      optind;
X
X#include "suntops.h"
X
Xmain(argc, argv)
X	int             argc;
X	char          **argv;
X{
X	FILE           *fpi;
X	int             opt;
X	double          height;
X	int             inverse;
X	int             rotate;
X	double          width;
X
X	inverse = FALSE;
X	rotate = FALSE;
X	height = IMG_HEIGHT;
X	width = IMG_WIDTH;
X
X	while ((opt = getopt(argc, argv, "h:irw:")) != EOF) {
X		switch (opt) {
X
X		case 'i':
X			inverse = TRUE;
X			break;
X
X		case 'r':
X			rotate = TRUE;
X			break;
X
X		case 'h':
X			height = atof(optarg);
X			if (height <= 0.0 || height > PAGE_HEIGHT) {
X				error("-h: bad height");
X			}
X
X			break;
X
X		case 'w':
X			width = atof(optarg);
X			if (width <= 0.0 || width > PAGE_WIDTH) {
X				error("-w: bad width");
X			}
X
X			break;
X
X		default:
X			error(
X			 "Usage: suntops [-ir] [-h height] [-w width] [file]"
X				);
X		}
X	}
X
X	if (argv[optind] == NULL) {
X		fpi = stdin;
X	}
X	else {
X		fpi = fopen(argv[optind], "r");
X		if (fpi == NULL) {
X			error(argv[optind]);
X		}
X	}
X
X	suntops(fpi, PAGE_HEIGHT, PAGE_WIDTH, height, width, inverse, rotate,
X		stdout);
X
X	exit(0);
X}
SHAR_EOF
if test 1186 -ne "`wc -c < 'main.c'`"
then
	echo shar: error transmitting "'main.c'" '(should have been 1186 characters)'
fi
chmod +x 'main.c'
fi # end of overwriting check
echo shar: extracting "'suntops.c'" '(4402 characters)'
if test -f 'suntops.c'
then
	echo shar: will not over-write existing file "'suntops.c'"
else
sed 's/^X//' << \SHAR_EOF > 'suntops.c'
X/*
X * suntops -- convert Sun rasterfile to PostScript image
X */
X
X#include <assert.h>
X#include <rasterfile.h>
X#include <stdio.h>
X
X#include "suntops.h"
X
Xstatic void
Xxch(a, b)
X	double         *a;
X	double         *b;
X{
X	double          temp;
X
X	temp = *a;
X	*a = *b;
X	*b = temp;
X}
X
Xvoid
Xsuntops(fpi, h_page, w_page, h_img, w_img, inverse, rotate, fpo)
X	register FILE  *fpi;		/* rasterfile stdio pointer	 */
X	double          h_page;		/* PostScript page height	 */
X	double          w_page;		/* PostScript page width	 */
X	double          h_img;		/* PostScript image height	 */
X	double          w_img;		/* PostScript image width	 */
X	int             inverse;	/* ? inverse : forward hex map	 */
X	int             rotate;		/* ? rotate output image 90 deg	 */
X	register FILE  *fpo;		/* PostScript stdio pointer	 */
X{
X	int             hexdig[16];	/* hexadecimal digit map	 */
X	double          aspect;		/* rasterfile aspect ratio	 */
X	register int    byte;		/* current rasterfile data byte	 */
X	register int   *hexp;		/* fast pointer to hexdig array	 */
X	struct rasterfile ras;		/* rasterfile header		 */
X
X /*
X  * read rasterfile header
X  */
X /* NOSTRICT */
X	if (fread((char *) (&ras), sizeof(ras), 1, fpi) != 1) {
X		error("can't read rasterfile header");
X	}
X
X	if (ras.ras_magic != RAS_MAGIC) {
X		error("input is not a Sun rasterfile");
X	}
X /*
X  * compute rasterfile aspect ratio
X  */
X	if (rotate) {
X		xch(&h_img, &w_img);
X		xch(&h_page, &w_page);
X	}
X
X	aspect = ras.ras_width;
X	aspect /= ras.ras_height;
X /*
X  * adjust PostScript image size to preserve aspect ratio
X  */
X	if (aspect >= w_img / h_img) {
X		h_img = w_img / aspect;
X	}
X	else {
X		w_img = h_img * aspect;
X	}
X
X	assert(h_page >= h_img);
X	assert(w_page >= w_img);
X /*
X  * rasterfile lines are padded to a multiple of 16 bits (see rasterfile(5));
X  * adjust rasterfile line length accordingly
X  */
X	switch (ras.ras_depth) {
X
X	case 1:
X		if (ras.ras_width % 16 != 0) {
X			ras.ras_width += 16 - ras.ras_width % 16;
X		}
X /*
X  * Sun black/white bitmap convention is opposite of PostScript, so inverse
X  * int->hex map
X  */
X		inverse = ~inverse;
X		break;
X
X	case 8:
X		ras.ras_width += ras.ras_width & 1;
X		break;
X
X	default:
X		error("bad rasterfile depth");
X	}
X /*
X  * initialize int->hex map
X  */
X	if (inverse) {
X /*
X  * inverse int->hex map
X  */
X		hexdig[0] = 'f';
X		hexdig[1] = 'e';
X		hexdig[2] = 'd';
X		hexdig[3] = 'c';
X		hexdig[4] = 'b';
X		hexdig[5] = 'a';
X		hexdig[6] = '9';
X		hexdig[7] = '8';
X		hexdig[8] = '7';
X		hexdig[9] = '6';
X		hexdig[10] = '5';
X		hexdig[11] = '4';
X		hexdig[12] = '3';
X		hexdig[13] = '2';
X		hexdig[14] = '1';
X		hexdig[15] = '0';
X	}
X	else {
X /*
X  * normal int->hex map
X  */
X		hexdig[0] = '0';
X		hexdig[1] = '1';
X		hexdig[2] = '2';
X		hexdig[3] = '3';
X		hexdig[4] = '4';
X		hexdig[5] = '5';
X		hexdig[6] = '6';
X		hexdig[7] = '7';
X		hexdig[8] = '8';
X		hexdig[9] = '9';
X		hexdig[10] = 'a';
X		hexdig[11] = 'b';
X		hexdig[12] = 'c';
X		hexdig[13] = 'd';
X		hexdig[14] = 'e';
X		hexdig[15] = 'f';
X	}
X /*
X  * PostScript header
X  */
X	(void) printf("%%!\n");
X /*
X  * if "rotate" set then rotate PostScript image 90 degrees
X  */
X	if (rotate) {
X		(void) printf("90 rotate\n");
X		(void) printf("0 -%d translate\n", ITOP(h_page));
X	}
X /*
X  * center the PostScript image on the output page
X  */
X	(void) printf("%d %d translate\n",
X		      ITOP(((w_page - w_img) / 2.0) + XTRANS_FUDGE),
X		      ITOP((h_page - h_img) / 2.0));
X	(void) printf("%d %d scale\n", ITOP(w_img), ITOP(h_img));
X /*
X  * I/O buffer for readhexstring
X  */
X	(void) printf("/linebuf %d string def\n",
X		      ras.ras_width / (8 / ras.ras_depth));
X /*
X  * set PostScript image parameters
X  */
X	(void) printf("%ld %ld %d\n",
X		      ras.ras_width, ras.ras_height, ras.ras_depth);
X	(void) printf("[%ld 0 0 -%ld 0 %ld]\n",
X		      ras.ras_width, ras.ras_height, ras.ras_height);
X	(void) printf("{currentfile linebuf readhexstring pop}\n");
X /*
X  * image data follows
X  */
X	(void) printf("image\n");
X /*
X  * convert rasterfile bytes to pairs of ASCII hexadecimal digits
X  */
X	hexp = hexdig;
X
X	while ((byte = getc(fpi)) != EOF) {
X		putc(hexp[HI_NYBBLE(byte)], fpo);
X		putc(hexp[LO_NYBBLE(byte)], fpo);
X	}
X
X	if (ferror(fpi)) {
X		error("input error");
X	}
X
X	if (ferror(fpo)) {
X		error("output error");
X	}
X /*
X  * display PostScript image on output device
X  */
X	(void) fprintf(fpo, "showpage\n");
X}
X
X#ifndef	lint
Xstatic char     rcsid[] = "$Header: suntops.c,v 1.2 87/09/14 12:41:52 frew Exp $";
X
X#endif
SHAR_EOF
if test 4402 -ne "`wc -c < 'suntops.c'`"
then
	echo shar: error transmitting "'suntops.c'" '(should have been 4402 characters)'
fi
chmod +x 'suntops.c'
fi # end of overwriting check
#	End of shell archive
exit 0
# ----------------------------------------------------------------------------
# James Frew	(805)961-8413		frew@hub.ucsb.edu
# CSL, UCSB, Santa Barbara, CA 93106	ucbvax!ucsbcsl!frew
                           -----------------
From: Lap@UDEL.EDU
Subject:  Re:  Raster to PS

Brian,

The source code for rf2ps follows.  I and my colleages have found it
useful, but it hasn't been too extensively tested, and is basically a
hack.  If you find it worthy, feel free to post it to the net (I don't
seem to have access).  If you have problems with it, please let me know,
also please contact me if you'd like to see any modifications or
extensions.  Good luck... (just compile with 'cc'):
--- cut here -----
/* RF2PS -- By 
   Larry Pearlstein
   University of Delaware

Non-commercial use and distribution is allowed. */
/* Usage: rf2ps filename > PSfile

Converts filename from SUN rasterfile format to PostScript suitable for
printing. */

#define TRUE -1
#define FALSE 0
#define PlotScale 4096.0

#include <stdio.h>

FILE *fp;
double AppleScaleX,AppleScaleY;
int invertFlag;

double scalex(x)
int x;
{
double y;
return( ((double) x / PlotScale) * AppleScaleX);
}

double scaley(y)
int y;
{
return( ((double) y / PlotScale) * AppleScaleY);
}

getint()
{
int x;
char c1,c2,c3,c4;

fscanf(fp,"%c%c%c%c",&c1,&c2,&c3,&c4);
x = ( (((unsigned) c1) & 0xff) << 24) + ( (((unsigned) c2) & 0xff) << 16) +
    ( (((unsigned) c3) & 0xff) <<  8) + (((unsigned) c4) & 0xff);
/* printf("%02x %02x %02x %02x %08x\n",c1,c2,c3,c4,x); */
return(x);
}


Parse()
{
struct {
   int ras_magic;
   int ras_width;
   int ras_height;
   int ras_depth;
   int ras_length;
   int ras_type;
   int ras_maptype;
   int ras_maplength;
   } rasterfile;
char c;
int i,count;
char dummy;
unsigned size;
char *malloc();
char *myPointer,*bufPtr;
int lines,chars;
int pixperbyte,hres,vres;
int nbytes;


rasterfile.ras_magic = getint();
rasterfile.ras_width = getint();
rasterfile.ras_height = getint();
rasterfile.ras_depth = getint();
rasterfile.ras_length = getint();
rasterfile.ras_type = getint();
rasterfile.ras_maptype = getint();
rasterfile.ras_maplength = getint();

pixperbyte = rasterfile.ras_depth;
hres = rasterfile.ras_width;
vres = rasterfile.ras_height;
nbytes = (hres * vres * pixperbyte)/8;

for (i=0; i<rasterfile.ras_maplength; ++i)
   fscanf(fp,"%c",&dummy);

myPointer = malloc((unsigned) (nbytes));
bufPtr = myPointer;

for (i=0; i < nbytes; ++i) {
   fscanf(fp,"%c",&c);
   if (invertFlag == TRUE) *bufPtr++ = c;
   else *bufPtr++ = ~c;
   }

printf("save\n");
printf("/picstr 2 string def\n");
printf("1 72 mul 2.25 72 mul translate\n");
printf("%f %f scale\n",AppleScaleX,AppleScaleY);
printf("/doimage {\n");
printf("%d %d %d\n",rasterfile.ras_width,rasterfile.ras_height,rasterfile.ras_depth);
printf("[ %d 0 0 %d 0 0 ]\n",rasterfile.ras_width,rasterfile.ras_height);
printf("{ currentfile picstr readhexstring pop }\n");
printf("image showpage restore } def\n");
printf("doimage\n");
/* Print out hex numbers, 32 to a line */
count = 0;
for (lines = 0; lines < vres; ++lines) {
   for (chars = 0; chars < (hres * pixperbyte)/8; ++chars) {
      printf("%02x",0xff &
         (int) *(myPointer + ((vres - 1) - lines) * ((hres * pixperbyte)/8) +
         chars) );
      if (++count == 32) {
         count = 0;
         printf("\n");
         }
      }
   }
if (count != 0) printf("\n");
}
      

main(argc,argv)
int argc;
char *argv[];
{
double Xin,Yin;
extern int optind;
extern char *optarg;
int I;

AppleScaleX = (72.0 * 6.5);
AppleScaleY = (72.0 * 6.5);
invertFlag = FALSE;
while ( (I = getopt(argc,argv,"x:y:i") ) != EOF) {
   switch (I) {
      case 'x':
         sscanf(optarg,"%lf",&Xin);
         AppleScaleX = 72.0 * Xin;
         break;
      case 'y':
         sscanf(optarg,"%lf",&Yin);
         AppleScaleY = 72.0 * Yin;
         break;
      case 'i':
         invertFlag = TRUE;
         break;
      default:
         break;
      }
   }   

/* See if any file name given */
if (optind == argc) fp = stdin;
else fp = fopen(argv[optind],"r");

Parse();
}
                           -----------------
Brian Keves			ARPA:	keves@sdcsvax.ucsd.edu
P.O. Box 12238			UUCP:	sdcsvax!keves
La Jolla, CA  92037-0620 	BITNET:	keves@ucsd