peps-2.0

peps-2.0 will preprocess encapsulated Postscript
files and allow you to convert them into bitmaps.
Note the word allow: peps does not do the conversion for you.
Rather, it prepares the Postscript input for a bitmap conversion by
Ghostscript,
which must already be installed on your system.

peps reads its input either from a file or from stdin
and sends its output either to a file or to stdout. You can use it
as a stand-alone Postscript-to-bitmap conversion program, or as a Unix
filter. And you can use it on line to create bitmaps on the fly and send
them out to a web browser, even compressing them if the browser supports
gzip compression (most browsers do, but peps will check first,
unless you tell it otherwise).

Because peps uses Ghostscript to do the actual conversion,
you can use it to convert Postscript into any type of bitmap supported
by your particular installation of Ghostscript. While in
version 1.0 the default was to create pnm
bitmaps, in version 2.0 the default is to
produce PNG bitmaps with 16 million colors. The reason why
version 1.0 defaulted to pnm was that at the time version 1.0
was written, most Unix installations of Ghostscript could only
anti-alias pnm bitmaps. Recent versions of Ghostscript do not
have this limitation.

Please take a look at this picture:

It suffers from a serious case of aliasing. To see it, compare the connectors
on the FreeBSD Box and on Windows 95 with those on the Router. They are
different even though their original Postscript code is identical. Which one
is correct?

Actually, neither.

Now, take a look at this picture:

It was produced from the same EPS original, but using 4-bit anti-aliasing.
To produce them, version 1.0 had to use Ghostscript to create a pnm
file, then use
pnmtopng
to convert it into a PNG file. With version 2.0
peps uses Ghostscript to create the PNG bitmap directly.

The simplest way to use peps is by typing the program name (peps)
followed by the name of the input file. For example:

% peps tiger.ps

This will convert the file tiger.ps (which comes as part of the
Ghostscript distribution) into a PNG bitmap, using peps
defaults, which means vertical and horizontal resolution of 100, 4-bit
anti-aliasing, using the safe mode, sending the output to stdout.

Usually, defaults are not good enough. For example, for the above images,
the resolution of 100 was correct. But in the case of tiger.ps, that
resolution would result in a very huge bitmap.

The -r switch followed by a number defines the resolution of the
image. The larger the number, the larger the resultant bitmap.

You can also set the vertical and horizontal resolution separately, using
the -h and the -v switches.

The -p switch will make sure the output comes as a
PNG bitmap. That is the default anyway. Thus,

% peps -r 36 -p tiger.ps

will produce this image:

% peps -v 36 -h 18 -p tiger.ps

results in:

While the -r, -v and -h
switches tell peps what resolution in dots per inch to use, you have the option
to instead decide how many pixels wide and high, or wide or high the image should be.
The -w and -q switches determine the width
and height respectively.

% peps -w 250 -q 100 -p tiger.ps

produces:

Use the -W or the -Q switch to decide the width
or the height, while keeping the original width/height ratio. Note that
these switches are capital letters.

% peps -W 250 -p tiger.ps

gets:

Use the -m switch instead of the -p
switch to produce monochrome (grayscale) PNG bitmaps:

% peps -Q 300 -m tiger.ps

The -x, -X, -y,
and -Y switches allow you to add extra space to the left
(-x), right (-X), bottom (-y), and the top (-Y) of the image. This is the same
as creating a frame for the image. You can also use negative numbers, which
will crop the image instead:

% peps -r 36 -x -100 -X -100 -Y 20 -p tiger.ps

results in:

Please note that these numbers are in Postscript points, not in the number
of pixels to add (or cut). That means that when you change the resolution
of the output, the frame/crop will keep its relative size: The result
will look exactly the same, but will be resized as necessary.

The -a switch defines the angle of rotation of the image in
degrees, about the center of the image. By default the angle is 0. A positive
angle rotates counter-clockwise, a negative one clockwise.

Rotation almost always results in parts of the image being cut off.
This can be prevented by adding some extra borders as described above.

% peps -r 36 -p -x 60 -y 40 -Y 50 -a 30 tiger.ps

produces:

In all of the above examples, peps read the input file. It checked
that it started with %!PS-Adobe- to make sure the file had a
valid Postscript header. It then looked for the standard %%BoundingBox:
line to find the proper image bounding box. Without this information
peps would not know what to ask Ghostscript to do.

You can override the bounding box with the -b switch followed by
the left, bottom, right, and top coordinates in Postscript points. When you
do that, peps does not look for the header, so your input does not
even need to have it. This allows you to use any Postscript file for
peps input, not just the encapsulated ones.

% peps -b 120 345 250 400 -Q 300 -p tiger.ps

zooms in:

PostScript is not just an image description language. It is a true
programming language which allows you to read and write files on the
system. By default, peps tells Ghostscript to ignore
any commands to write to files. This is a safety feature. Without it,
you might download an EPS file from the web, and be surprised that some
of your data was mysteriously wiped out.

If, however, you want to disable this safeguard, use the -s
switch. If, on the other hand, you want to enable it explicitly,
use the -S (capital letter) switch.

The -g, -t and -l
switches control anti-aliasing. The -g switch controls
the anti-aliasing of graphics, the -t switch controls
the anti-aliasing of text, and the -l switch controls
the anti-aliasing of both, graphics and text.

These two switches must be followed by the number of bits to use
for anti-aliasing. The valid values are 1
(no anti-aliasing), 2 (some anti-aliasing), and
4 (full anti-aliasing).

The default value is 4 for both.

The -o switch allows you to declare an output file.
By default, the output goes to stdout, but you can send it to a
file using this option. For example,

% peps -p -o tiger.png tiger.ps

will send the output to tiger.png.

The -i switch tells peps to read the input from
stdin. This was added after much soul searching in version
2.0. Why much soul searching? Because stdin cannot be
rewound. And because the Postscript specification allows you to
create Postscript files, encapsulated or not, which defers the
%%BoundingBox: comment to the trailer. When that happens and
the input is coming from stdin, well, whatever Postscript
code appears before the %%BoundingBox: comment, it is lost and
peps cannot send it to Ghostscript.

So, in version 1.0, I decided not to accept input from stdin
at all. But that limits the usefulness of peps. As of
version 2.0, peps will read its input from stdin
under the condition that either the input starts with
the %!PS-Adobe- and has a %%BoundingBox:
comment before any actual Postscript code appears, or you use
the -b switch.

The -c switch tells peps it is used either from
a CGI script or as a CGI script. The -C and -M
switches may also be used with CGI scripts. More about
that later.

The -n switch will result in producing a pnm bitmap,
while the -f switch followed by a Ghostscript device name
instructs peps that the bitmap should be produced by
that device. Of course, Ghostscript has to know about
such a device. For example, we could create a jpeg bitmap:

% peps -Q 250 -f jpeg tiger.ps

Note: When using the -f switch, please be mindful
that the purpose of peps is to convert Postscript code
into bitmaps. And while Ghostscript treats bitmaps as special-purpose
devices, not all of Ghostscript devices are bitmaps. If you use the
-f switch to select a non-bitmap device, chances are
it will either not work at all or not work as you were hoping.
For example, if you opt for -f x11, one of two
things will happen: If you are running X Window, Ghostscript will paint
the output to a window but the window will then disappear. And if you are
not running on X Window, you will just get an error message. This is because
the x11 device sends its output to a graphical
window, not to a file.

The -z switch tells peps to pipe its output
through gzip which will compress it. peps will
ignore the switch if the output goes to a file. But if you want
the output in a .gz file, just redirect it to one, like this:

% peps -z -p tiger.ps > tiger.png.gz

The -Z (capital letter) does the opposite: It tells
peps not to compress the output.

System administrators may choose to compile peps with
a different set of defaults than discussed here. You can find
out what defaults are on your system by entering:

% peps -d

You can find what version of peps is installed on your
system by typing:

% peps -v

If it tells you the version, that is the version installed.
If it shows you the list of options instead, it is version 1.0
(in that case you should upgrade—or ask your system
administrator to upgrade—to the current version).

You can get a quick list of options by typing:

% peps -h

For a more detailed list, type:

% man peps

All switches can be listed in any order. If a switch contradicts another
switch, whichever switch is listed later will win.

Under Unix it is possible to run files as scripts by starting
the files with a #! followed by the full path of the program
that can interpret the files. That only works if that program
treats the # character as the start of a comment.

The Postscript language does not treat the # character as
the start of a comment, but peps will ignore the first line
of its input if it starts with a #. It must be the very first
letter of the very first line. Any other line that contains it,
will not be treated as a comment, only the first one.

CGI stands for Common Gateway Interface. It allows
webmasters to create web content on the fly. If you are not familiar
with how CGI works, you may want to read my
CGI
Programming Is Simple! tutorial.

It is quite easy and simple to create images on the fly with
peps and have a web server send them to a web browser.
For that, we use the -c flag, and send the output to
stdout. When we do that, peps will first write the
appropriate Content-Type header to stdout. It will
then check to see if the browser accepts gzip compression.
If so, it will also write the correct Content-Encoding
header. It will then print two new-line characters, indicating
that the header is finished and contents follow. Only then will
it send the bitmap (compressed by gzip if applicable)
to stdout. And, of course, as discussed above,
it will ignore the first input line if it starts with a #.

To execute your scripts, the web server needs to know that
they are CGI executables. Depending on your web server configuration,
you may have to place your scripts into a /cgi-bin/
directory. Or you may have to end the script name with the .cgi
extension. Or, you may configure your we server to recognize some
other extension as a script. For example, on the Apache server
you just need to add the following line the .htaccess
file:

AddHandler cgi-script png

This will work in the directory in which the .htaccess
file is located and all of its subdirectories. And as you
probably have regular PNG files on your web site, you need
to create a separate directory just for the dynamically
created bitmaps.

Enough talk, let's see a simple example. Let's create a file,
name it line.png and store it in the directory with that
.htaccess file. Now assuming that your copy of peps
is installed in /usr/bin, let's edit the file with these
contents:

We have started the file with #!/usr/bin/peps -p -c -b 10 10 20 20
-r3600. Remember, we have named the file line.png.
Now, assuming that your Unix user name is bobby and the file
is located in /usr/www/bobby/images, that first line will cause
the system to execute the following:

That means peps will read its input from /usr/www/bobby/images/line.png
and write its output to stdout. It will produce a PNG bitmap
with a resolution of 3600 dpi, both vertically and horizontally. It
will expect the Postscript code bounding box to be 10 10 20 20.
And it will produce all the necessary CGI headers, as well as check
whether the browser can accept gzip compression.

When reading the file, peps will discard the first line
and pass everything else on to Ghostscript with all the
necessary instructions on what kind of bitmap to produce.

The Postscript code is very simple in this example: Draw a magenta
colored line from 10 10 to 20 20. Now because the
bounding box also goes from 10 10 to 20 20, the line
will go from the lower left corner to the upper right coner. It will be a very
tiny line. But because we are using the resolution of 3600 dpi, while our computer
monitor is set up for maybe 100 dpi, the magenta line should seem as if
we were looking at it through a microscope.

Naturally, on a web site you would use Postscript to do
more than draw a magenta line.

There still is much more that you can do. Since peps
can accept its input from stdin, you can use it to
create images that are different for every person, or different
on different occasions. You can use peps in a shell
script that changes the Postscript code as necessary, or you
can pipe the output of some program to peps.

In our next example, we are going to write a shell script
that produces Postscript code to display the IP address
of the visitor to your web site. We will use a font that
is not distributed with Ghostscript because it is a font
we paid for. We are allowed to use it in our creations, but not to
give the font itself away. So, we upload the font to some directory
that is not accessible from the web. We must let Ghostcript
know where the font is. We do so by setting the GS_FONTPATH
environmental variable. We could do that from our shell script.
But then we'd need to do it from every shell script we use
with fonts. So, the better solution (at least with the
Apache web server) is to do it in the .htaccess
file. Assuming the fonts are in /usr/home/bobby/myfonts,
this is what we add to .htaccess:

The Apache server sets the REMOTE_ADDR environmental
variable to the caller's IP address. And the sh shell
replaces $REMOTE_ADDR in our script with the value
of REMOTE_ADDR. Note that we started the script
with echo Cache-Control: private. This
tells the web browser that it can cache the image, but it also
tells any gateways the image may be passing through not to cache
it because the image only makes sense to the one person we made
it for.

By the way, the OsF in the name of the font used to
display the IP address stands for Old-style Figures.
That means that no, the numbers are not misaligned, as inevitably
some people will complain, but that they are perfectly
aligned according to classical typography which aligns
numbers with lower-case letters and gives them descenders (as in the p)
and ascenders (as in the h).

If you prefer, you can create your HTTP header and simply run
peps without the -c switch. In that case,
you may want to use the -C (capital letter)
switch, which will simply print the HTTP Content-Type
line and exit. In that case, you can also use the -z
switch to turn the gzip compression on, or the -Z
(capital letter) to turn it off.

In the scripts we have seen, we used peps to print the correct
HTTP Content-Type. Let us see how peps
figures out what to print: It looks for the type in several places. If it finds
the correct type, it quits looking and prints it. If it does not find
it anywhere, it prints:

Cotent-Type: image/x-device

The device part is the name of the Ghostscript
output device specified with the -f switch.

So, what are the places peps searches for an answer? They are
several files, which may or may not exist (if they do not exist,
they just do not exist, peps will continue to work). If they do
exist, peps expects them to contain a list of Ghostscript devices
and their corresponding content types, one per line. Also, peps
will treat the # character as the start of a comment
extending to the end of the line. An example of the list might be:

The file peps.mime located in the home directory.
Whose home directory? If the PEPSUSER environmental
variable is defined, it will look in the home directory of the user
specified by it. Or, in Unix speak: ~$PEPSUSER/peps.mime.
If the PEPSUSER environmental variable is not defined,
it will look in the home directory of the effective user that invoked
peps. Or in Unix speak: ~/peps.mime.

The file /etc/peps.mime, unless the system
administrator compiled peps with a different directory to look
in.

A list hard-coded inside peps. That means that any of the
above files are only necessary if your system uses Ghostscript with
devices that peps does not know about. These could be custom
bitmap formats, or formats added to future versions of Ghostscript.

Since CGI scripts are normally invoked by a web server, under most
circumstances, the effective user will be nobody,
or a similar special user. If you need to define your own content
types, you can use the -M switch. But a better
choice is to define the PEPSUSER environmental
variable (better because you only need to do it once). Assuming again
that your user name is bobby and that
you are using the Apache web server, you just need to enter the
following into the .htaccess file:

Developing CGI scripts would be rather tedious if you had to debug them
by uploading them on your web server and seeing if they work as desired,
then editing them at home or work and again upload them, and so on. To
make their development much easier, a special version of peps, called
xpeps will print the bitmap into a window instead of sending it to
stdout or to a file.

Here is an example of what it looks like under X window:

Xpeps is not an X window program. It simply calls
Ghostscript and tells it to process the EPS source and display it
using its x11 device. We could actually accomplish the same
with peps -f x11, but if we did, we would encounter
a problem: As soon as Ghostscript is done processing the EPS input,
it would exit. The bitmap would flash on the display and promptly
vanish.

To overcome this problem, xpeps waits for you to press ENTER
before quitting Ghostscript. This works well when its input comes
from a file, but what is xpeps to do when the input comes from
stdin? A default solution is to fork and wait until, well, until you
kill it:

Doing that would allow you to test your CGI scripts, like this:

But, while it would work, it would leave a lot of zombies behind.
Therefore, xpeps introduces two new command line options,
-e [time] and -E [time].
The time parameter tells xpeps
how many seconds after sending its data to Ghostscript it should
evaporate. Additionally, with the -E
option, xpeps will print out the pid of its background
process, so you can kill it explicitly. If you do
not specify the time parameter, xpeps
will wait for its evaporation delay, which is forever by default,
but you can (and probably should) compile it with a finite value.

You can use these switches whether the input comes from stdin
or from a file. Here is an example of running xpeps three times
in a row, the first two time specifying the evaporation delay of
600 seconds, the third time running it without a delay, so xpeps
waits for us to press ENTER:

You can use the -e and -E switches with
peps as well. They will simply do nothing. But that allows you to debug
your scripts with xpeps and once they are debugged, you just need
to change /usr/X11R6/bin/xpeps to
/usr/bin/peps and install the script on your web server.

To install peps you need a computer computer operating Unix. You also
need Ghostscript on your
path (its full path will be hardcoded into peps and xpeps
at compilation time. Similarly, you will need gzip.

Additionally, if you want to install xpeps, you will also need
X Window, and your copy of Ghostscript will need to support the x11
and devices.

You need all of the above before installing peps and xpeps.
Please read the README file for further installation information.
Assuming you already have the above requirements, installing peps
alone on most systems is as simple as typing:

$ make install clean

Or, to install both, peps and xpeps:

$ make install xinstall clean

If you do not have Unix, the best thing to do is to get it. You can
get FreeBSD and install it
right off the Internet. If, however, you absolutely must use
MS Windows, all is not lost. You will need to install Cygwin. Then you will either need
to get the Cygwin version of Ghostscript and X Window, and
install peps and xpeps like this:

$ env BINEXT=.exe make install xinstall clean

Or you will need to install Ghostscript for Windows (you
will still need Cygwin), and note where its file gswin32c.exe
is located, then convert its path into the Cygwin path, such as
/cygdrive/c/gs/gs-8.15/bin, and then type
all of the following: