Return to Floodgap Software
ppmascii
Once again everything retro
is cool, and so is ASCII art, the once maligned practice of drawing cartoon
figures, cute icons and conspicuous bits of the female anatomy
in a humble assortment of printable
7-bit ASCII characters. Despite this, however, there are good reasons for
still being able to render images in printable ASCII:
- Viewing graphics on dumb terminals (more common than you think) or other
systems that do not have bitmapped graphics
- Sending images over non-8-bit-safe connections, or where MIME is not
available
- Anonymous browsing, such as ssh to a remote host, using console
tools to feed images and multimedia data to a remote viewer
- Impressing your l33t friends and getting g33k MOTASes
ppmascii (intentionally not named "ppm to ascii" or "ppm 2 ascii"
due to similar sounding tools) is an attempt to rectify some of the problems
of the existing bitmap-to-ASCII renderers, namely, poor output and
difficulty with
modification or improvement. Being 100% Perl, requiring no modules,
ppmascii is slower than a compiled approach, but barely
perceptably so on modern hardware; moreover, being a script, you can hack it up
for your
particular terminal's features and customize it for better local function.
You can also change the characters used for "pixels" (ppmascii was
calibrated against as wide a range of monospaced fonts that I had available,
but it may not match your tastes, so it's easy to change).
Furthermore, ppmascii includes many features that other renderers
and converters do not, such as built-in Floyd-Steinberg dithering, input-stage
image controls and simple aspect scaling. This allows you to get very nice
image output with hardly any work, but with the flexibility
of built-in tinkering to taste.
Finally, you can use any image toolkit such as netpbm or ImageMagick
to generate portable anymaps for ppmascii's consumption; this is a
trivial file format to process and is generated by a tremendous number of
tools. Although the name implies only PPMs are supported, ppmascii
will actually read and process P1, P2, P3, P5 and P6-type files.
Here are the major options (or you can say ppmascii -help):
- Debugging:
- -showheader
- Shows PNM header information, namely width, height, colour depth and
PNM type.
- Input-stage adjustments:
- -bright=n
- Use image brightness factor of n (1.0=identity and
default), where 0<n<infinity. This
is not gamma and is strictly linear.
- -contrast=n
- Adjust image contrast by n (0.0=identity and
default), where -infinity<n<infinity. Unlike Photoshop,
negative values yield higher contrast.
-photo and -lineart are two preset options that set
suggested default brights and contrasts for continuous-tone images and
high contrast images, respectively. Dithering may still apply on the output
stage.
- Distortions and transformations:
- -x2
- Doubles the width of the displayed image. This is useful for displays where
characters are taller than they are wide (which is
the majority), better approximating
the original aspect ratio but possibly making the image too wide to view
without clipping. Pixels are averaged together for a smoother display
unless you also specify -nosmooth.
- -y2
- Double-prints lines, effectively making the output twice as tall. In my
usage this is not frequently needed, so it only uses a simple reduplication
and no averaging. If you want averaging in a future version, please
shamelessly grovel.
- -winx=n and -winy=n
- Sets the upper left corner of the rendering window to (winx,winy)
of the original image.
If either is not specified, that value is 0 (thus default (0,0) if
neither are specified). All pixels in the original
image above and left of this point are
not rendered (however, the skipping is not especially efficient in this
version and a wide clip may slow down rendering). Values are relative to the
original image. If you roll too far, you will get a blank or distorted image
as ppmascii does no bounds checking (maybe it should?).
- -width=n and -height=n
- Sets the maximum width and height of the render window. The width defaults
to the value of the environment variable COLUMNS if set, or 79 if not.
The height defaults to infinite (i.e., render until there is no more data).
Output will be clipped to the render window (note that this means that if you
use -x2 or -y2, each pixel is twice as large -- or 4x if
both -- and thus will
be clipped over a smaller area of the original
if you do not similarly change the width and height
[though this is usually what you actually want]).
- Output-stage and rendering adjustments:
By default ppmascii uses RGB perceptual luminance coefficients and
Floyd-Steinberg dithering, with characters selected for displays with dark
backgrounds and light text.
- -invert
- Inverts display for light background and dark text.
- -norgb
- Compute the luminance of a pixel using a simple arithmetic sum, not
standard RGB perceptual luminance
coefficients. Slightly faster but may be less perceptually
accurate since it is not weighted for green. Irrelevant if the image
is greyscale.
- -nodither
- Do not use Floyd-Steinberg dithering. This is moderately faster but
with occasionally noticible
banding on typical images. However, if you have a better quantizer/ditherer
and want to use that to feed to
ppmascii, then pass this option so that ppmascii won't
mess with its output.
- -nosmooth
- Do not antialias or smooth. This is mildly faster but obviously blocky.
Only makes a difference for those options where antialiasing or smoothing is
offered (i.e., -x2). Smoothing/antialiasing occurs after
dithering.
Most people may want to play with the "palette." This can be done by changing
the @elements list. Although I have tried to make a "spectrum" that
works on as wide a range of monospace/non-proportional terminal fonts (under
X, Mac OS X and Windows) as possible,
I imagine people will have their own preferences and thus you
can specify them there, or completely warp the list to render something
totally crazy. By default, the list is 16 elements long, so the default
rendering is in "16 shades of grey."
To give you an idea of the output,
here are a few sample renderings using the de facto image processing
standard portrait of Lenna (this is a
PNG conversion of the original
TIFF; the
TIFF and PNG are scaled to 80 pixels wide for purposes of
terminal width). The command lines I used for each example are stated.
As with all such optical illusions, they are best appreciated from a distance.
;-)
ppmascii is distributed under the
Floodgap Free Software License. Originally
it was written for Perl 4.036 and may even still run under Perl 4, but this
most current version is only supported on 5.005 or better. It should run on
any system where Perl is supported.
This version 1.2 corrects a math error that can sometimes cause a
divide-by-zero condition, and improves compatibility on Perl 5.8 and
later. Last modified 5/19/2010.
Please send me your comments. One day I might also release my old
pnmtotek utility for Tektronix terminals if there is enough
interest.
Cameron Kaiser