[comp.lang.perl] Sun rasterfile to HP LaserJet filter

poage@sunny.ucdavis.edu (Tom Poage) (01/22/91)

Here's an almost-quick-and-dirty perl script to convert
Sun mono raster file format to HP LaserJet raster format.
Comes in handy for those 'Calvin and Hobbs' files you
find in the graphics archives. :-)

Do with it what you will.

Tom.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  ras2lj
# Wrapped by poage@sunny on Mon Jan 21 18:04:18 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ras2lj' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ras2lj'\"
else
echo shar: Extracting \"'ras2lj'\" \(3346 characters\)
sed "s/^X//" >'ras2lj' <<'END_OF_FILE'
X#!/bin/perl
X# ras2lj: Convert Sun rasterfile format to HP LaserJet raster format.
X# Sure, you can have it.
X# Tom Poage, Mon Jan 21 17:18:54 PST 1991
X
X# Look for optional resolution argument (dots/inch); 150 looks best.
X($resolution) = $ARGV[0] =~ /^-(.+)/ unless $#ARGV < $[;
if (defined $resolution) {
X	shift;
X	{
X		last if $resolution eq '300';
X		last if $resolution eq '150';
X		last if $resolution eq '100';
X		last if $resolution eq '75';
X		die "Invalid dots/inch argument.\n";
X	}
X} else {
X	$resolution = '150';
X}
X
X$rasterfile_t = 'i8';
X$rasterfile_t_len = length(pack($rasterfile_t,undef));
X
X# Read either STDIN or a single command line file name.
unshift(@ARGV, '-') if $#ARGV < $[; # Thanks, Larry.
X$ARGV = shift;
open(RASTER, $ARGV) || die "File not found.\n";
if (read(RASTER,$_,$rasterfile_t_len) != $rasterfile_t_len) {
X	die 'Read error, stopped';
X}
X($ras_magic,$ras_width,$ras_height,$ras_depth,$ras_length,$ras_type,
X$ras_maptype,$ras_maplength) = unpack($rasterfile_t,$_);
X
die "'$ARGV' is not a raster file.\n" if $ras_magic != 0x59a66a95;
X
X# I suppose one could run a color image through rasfilter8to1.
X# This is left as an exercise for the reader.  :-)
die "Sorry, can't do color.\n" if $ras_depth != 1;
X
if ($ras_type == 2) {
X	# Found byte-encoded (compressed) raster file.
X	# There's already a program to unencode this, so let's use
X	# that one instead and pipe it to another copy of this script.
X	close(RASTER);
X	pipe(R,W) || die "Can't make pipe";
X	if ($pid = fork) { # parent
X		close(R);
X		open(STDOUT, ">&W");
X		close(W);
X		open(STDIN, $ARGV);
X		exec '/usr/lib/rasfilters/convert.2';
X	} else { # child
X		die "Couldn't fork" unless defined $pid;
X		close(W);
X		open(STDIN, "<&R");
X		close(R);
X		exec $0; # Start over.  Use a goto if you want.
X	}
X}
X
X# $ras_width is the length of the image line, and $width is $ras_width
X# rounded up to the next 16 bit boundary (see <rasterfile.h>).
X# $ras_height * $width should equal $ras_length if the data is not
X# compressed and the depth is one bit.  It appears that the bits
X# between the image line end and the data line end may contain garbage;
X# a mask is constructed to zero those bits.
X
X$width = ($ras_width + 15) >> 4 << 4; # Round up to 16 bit boundary.
X$width >>= 3; # Convert bits to bytes.
X
X# Create mask.
vec($mask,0,0); # Force vec interpretation.
X$mask = "\377" x $width;
for ($ras_width .. ($width<<3)-1) { vec($mask,$_,1) = 0; }
X
X$ESC = "\33";
X$null = "\0" x $width;
X$printbuf = '';
for ($i = 0; $i < $ras_height; ++$i) {
X	$nchars = read(RASTER,$data,$width);
X	if ($nchars != $width) {
X		die "Line ${i} is short, stopped";
X	}
X	# Probably faster if I just did the $data &= ~$mask
X	# instead of testing for it.  I left it in so warn()
X	# could be noisy.
X	if (($data & ~$mask) ne $null) {
X		warn "Garbage bits found in the raster tail, line ${i}.\n";
X		$data &= $mask;
X	}
X	$printbuf .= "${ESC}*b${width}W" . $data;
X}
X
X# Start HP LaserJet emulation: Kyocera laser printer specific (PRESCRIBE).
X# The BANG is factored out so I can print this file without the printer
X# thinking I gave it a command.  Take it out if you don't have a Kyocera.
X$BANG = '!';
print "${BANG}R${BANG}SEM6;EXIT;";
X
print "${ESC}*t${resolution}R"; # Set resolution.
X
print "${ESC}*r0A"; # Start raster graphics mode.
print $printbuf; # Actual raster data.
print "${ESC}*rB"; # End raster graphics mode.
END_OF_FILE
if test 3346 -ne `wc -c <'ras2lj'`; then
    echo shar: \"'ras2lj'\" unpacked with wrong size!
fi
chmod +x 'ras2lj'
# end of 'ras2lj'
fi
echo shar: End of shell archive.
exit 0
-- 
Tom Poage, Clinical Engineering
Universiy of California, Davis, Medical Center, Sacramento, CA
poage@sunny.ucdavis.edu  {...,ucbvax,uunet}!ucdavis!sunny!poage