[comp.org.usenix] PostScript to interpolate facesaver pictures

gmp@rayssd.ray.com (Gregory M. Paris) (07/15/89)

Below is a PostScript program that I cobbled up to take facesaver data,
interpolate between pixels, and produce a page-sized, much-less-blocky
image.  Sure, it looks a little blurry (fixed in next release), but I
think you'll be surprised how much nicer these images look.

To use, you'll have to append the appropriate hexdata to the end of the
program then blast it off to your PostScript device.  Be warned, this
program can take a while to run!  (Doing it in PostScript was just for
fun.)  Also, I've made no attempt to account for the pecularities of
various printers -- you may need to fiddle with the translate command
and/or fiddle with graylevels.

Have fun.  Let me know if you have any improvements for this program.

-- 
Greg Paris <gmp@ray.com>
{decuac,necntc,uiucdcs,uunet}!rayssd!gmp
"Escalation is automatic!"

######################### Cut Here ###############################
#! /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:
#	interp.post
# This archive created: Fri Jul 14 22:13:43 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'interp.post'" '(3624 characters)'
if test -f 'interp.post'
then
	echo shar: will not over-write existing file "'interp.post'"
else
sed 's/^X//' << \SHAR_EOF > 'interp.post'
X% vi:set sw=4 ts=8:
X%
X% prints facesaver images to fill 8.5" x 11" pages
X% uses interpolation to increase pixel count for smoother images
X% warning: this takes a few minutes to run on our printer
X% author: Greg Paris <gmp@rayssd.ray.com>
X%
X
X/pikwid 108 def					% original picture width
X/pikhgt 128 def					% original picture length
X/horint 2 def					% horizontal interpolation rate
X/verint 2 def					% vertical interpolation rate
X
X/lineno 0 def					% current line number
X/horsiz pikwid 1 sub horint mul 1 add def	% interpolated picture width
X/versiz pikhgt 1 sub verint mul 1 add def	% interpolated picture height
X
X/pikstr pikwid string def			% input image lines
X/prvstr horsiz string def			% previous image line
X/curstr horsiz string def			% current image line
X/nxtstr horsiz string def			% next image line
X
X%
X% horiz: read in image line, interpolate into nxtstr
X%	leaves nothing new on the stack
X%
X/horiz {					% read then horiz interpolate
X    currentfile pikstr readhexstring pop pop	% read inline data
X    /pi 0 def					% index into pikstr
X    /ii 0 def					% index into nxtstr
X    {
X	/pv pikstr pi get def			% current picstr value
X	/pi pi 1 add def			% increment picstr index
X	nxtstr ii pv put			% put current value
X	/ii ii 1 add def			% increment nxtstr index
X	pi pikwid lt {				% to end of picstr
X	    /nv pikstr pi get def		% next picstr value
X	    /pwgt horint def			% previous pixel weight
X	    /nwgt 0 def				% next pixel weight
X	    horint 1 sub {			% repeat horint - 1 times
X		/pwgt pwgt 1 sub def		% decrement previous weight
X		/nwgt nwgt 1 add def		% increment next weight
X		nxtstr ii
X		    pv pwgt mul nv nwgt mul add	% weighted sum
X		    horint div round cvi	% weighted average
X		    put				% put at next position
X		/ii ii 1 add def		% increment nxtstr index
X	    } repeat
X	} { exit } ifelse
X    } loop
X} def
X
X%
X% vert: interpolates between prvstr and newstr to produce curstr
X%	leaves nothing new on the stack
X%
X/vert {						% interpolate vertically
X    /pwgt lineno verint mod def			% previous pixel weight
X    /nwgt verint pwgt sub def			% next pixel weight
X    /ii 0 def					% set index into line
X    horsiz {					% over line length
X	/pv prvstr ii get def			% previous pixel
X	/nv nxtstr ii get def			% next pixel
X	curstr ii
X	    pv pwgt mul nv nwgt mul add		% weighted sum
X	    verint div round cvi		% weighted average
X	    put					% put at next position
X	/ii ii 1 add def			% increment index into line
X    } repeat
X} def
X
X%
X% getnext: use interpolation when necessary to produce the next line
X%	modifies prvstr and nxtstr ; increments lineno
X%	leaves curstr on the stack
X%
X/getnext {					% produce next image line
X    lineno verint mod 0 eq {			% at an original line?
X	lineno 0 eq { horiz } if		% get first line
X	nxtstr prvstr copy pop			% copy nxtstr to prvstr
X	lineno versiz 1 sub lt { horiz } if	% get next line
X	prvstr curstr copy pop			% previous is current
X    } { vert } ifelse				% interpolate line
X    /lineno lineno 1 add def			% increment line count
X    curstr					% leave curstr on stack
X} def
X
X%
X% face: print a facesaver image on an 8.5" x 11" page
X%
X/face {						% main routine
X    0.5 72 mul dup translate			% image corner indented 0.5"
X    7.5 72 mul dup scale			% scale for 0.5" side borders
X    1 128 96 div scale				% correct non-squareness
X    /lineno 0 def				% reset line number
X    horsiz versiz 8				% dimensions of source image
X    [horsiz 0 0 versiz 0 0]			% map to unit square
X    { getnext } image				% build image, line by line
X    showpage					% display the image
X} def
X
X%
X%  run the program
X%  it's up to you, the user, to append the face data after the next line
Xface
SHAR_EOF
if test 3624 -ne "`wc -c < 'interp.post'`"
then
	echo shar: error transmitting "'interp.post'" '(should have been 3624 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0


-- 
Greg Paris <gmp@ray.com>
{decuac,necntc,uiucdcs,uunet}!rayssd!gmp
"Escalation is automatic!"