|The PNG Guide is an eBook based on Greg Roelofs' book, originally published by O'Reilly.|
|Home Applications Applications: Image Converters pnmtopng|
Currently, the latest version of pnmtopng is 2.37.2, released in March 1999; it can be found on the PNG home site, http://www.libpng.org/pub/png/apps/pnmtopng.html, along with pointers to the libraries on which it depends.
Written and maintained by Alexander Lehmann and Willem van Schaik with contributions and fixes from others, pnmtopng is primarily a Unix-based tool, which unfortunately limits its usefulness to a minority of computer users. But other parts of the NetPBM suite have been ported to OS/2 and Windows, and it is likely that a future release of both pnmtopng and NetPBM will be more portable and may even include ready-to-go executables.
PBMplus/NetPBM is that intermediate format. It was originally designed by
Jef Poskanzer and released as the PBMplus suite, with later ``interim''
released as NetPBM by Bill Davidsen. Since there has never been another PBMplus
release, I will henceforth refer to the format as NetPBM, the name by which it
is now most commonly known. The format is quite simple: three lines of text
header--which may additionally include one or more comment lines--followed
by the uncompressed image data. The image data may be stored as either text
or binary values; the latter is more efficient and far more commonly used, but
the existence of the text format means that one can actually create images or
color palettes in an ordinary text editor. There are also three basic NetPBM
image flavors: bilevel (or black and white), which is referred to as a
One notable feature missing from the NetPBM format is provision for alpha channels; this is a known limitation with implications for converting between formats that support transparency, such as PNG, GIF, and TIFF. pnmtopng gets around this to some extent by the simple expedient of storing transparency information in a separate grayscale file. Before we get into that, let's look at some simpler cases.
pnmtopng is a command-line program, and, thanks to its Unix heritage, it is
designed to operate as part of a multicommand pipeline. Unix pipes are a
slick method of connecting the output of one program into the input of another;
in principle there is no limit to how long such a chain can be, although in
practice the amount of system resources that are available may constrain
things. Here is a simple example that converts a GIF image into PNG:
giftopnm foo.gif | pnmtopng > foo.png
The file foo.gif is read by giftopnm (part of the NetPBM suite) and converted to NetPBM format, then piped into the input of pnmtopng, which converts the image to PNG format. Since there are no more programs to be run, pnmtopng's output is redirected into a file--in this case, foo.png.
Observant readers will recall that GIF images are always palette-based, yet I didn't say anything about palettes in describing the NetPBM format. In fact, NetPBM has no concept of palettes; giftopnm usually converts GIF images into PPM format (the RGB flavor). Fortunately, pnmtopng is smart enough to count the colors in an image and automatically write a palette-based PNG image if there are 256 or fewer colors. It will likewise detect if a color image is actually composed only of gray values; in that case, it will write either a grayscale PNG or a palette-based one, depending on which can be written with the fewest bits. This automatic checking comes at a cost, however: because it requires inspection of every pixel, it can be quite slow for large images. pnmtopng therefore includes a -force option to skip the checking. With this option, the previous example would result in a 24-bit truecolor PNG:
giftopnm foo.gif | pnmtopng -force > foo24.png
Here are examples for two other popular image formats, TIFF and JPEG:
tifftopnm foo.tiff | pnmtopng > foo-was-tiff.png djpeg foo.jpg | pnmtopng > foo-was-jpeg.png
But these are all trivial conversions. Suppose I would like to convert an existing NetPBM image into an interlaced PNG, including gamma information, a timestamp, and some text--say, the author's name, the title of the image, its copyright, and perhaps the date on which the original photograph was taken. The first thing we need to do is create a small text file containing the text information. pnmtopng treats the first word on any line that does not begin with a blank (either a space or a tab character) as the keyword, with the actual text following. The text may stretch over several lines, and keywords with spaces in them must be quoted. Thus the following text file, containing four keywords and their corresponding values, would suffice:
Title The Incredible and Rarely Seen Foo Author Greg Roelofs Copyright This image is hereby placed in the public domain by its author. "Creation Time" 4 July 1976 is the date on which this particular Foo was photographed.
Note that leading blanks (or ``white space''), including any between the keywords and subsequent text, will not be included in the PNG text chunks. But any newlines (or ``carriage returns,'' loosely speaking) will be included exactly as typed; thus, there will be one in the Copyright text chunk, right before the word ``public,'' and another in the Creation Time text chunk, immediately after ``1976.'' In addition, there is currently a bug in pnmtopng: when all of the text corresponding to a keyword appears on a line following the keyword--that is, the keyword is immediately followed by a carriage return--the program will sometimes crash. The problem will almost certainly be fixed by the time this book reaches print, but in the meantime, it can be avoided by adding a space after the keyword.
So assuming the text file were named comments.txt (and contains no keywords followed immediately by newlines), the following command would create the PNG image with the specified text and other information:
pnmtopng -interlace -gamma 0.65909 -text comments.txt \ -time 1998-10-25 21:00:00 foo.ppm > foo.png
The first option is self-explanatory: the PNG image will be interlaced. For the -gamma option, we've used a value that corresponds to a typical Macintosh; we're imagining that the original image was scanned and tweaked on a Mac before being converted to PPM format (foo.ppm) on some other system. The -time option requires a little more explanation. First, note that it is distinct from the ``Creation Time'' text chunk we included; the -time option will write the special PNG tIME chunk, which represents the time the image was last modified. But the last modification time is clearly the time the image was converted into PNG format, so pnmtopng really should not require the user to specify the time information explicitly. This is particularly true, given that PNG's time chunk is supposed to be in Coordinated Universal Time, and most users are unlikely to know how to convert to that. With luck, this oversight will also be corrected in the next release of the program.
pnmtopng -alpha ovalmask.pgm foo.ppm > foo.png
This will ordinarily create a 32-bit RGBA image--in other words, truecolor with a full alpha channel. But if it happens that the combination of the original RGB image and the mask produces at most 256 RGBA combinations, pnmtopng is smart enough to detect that and write a palette-based image with transparency information instead. Moreover, it will automatically arrange the palette and transparency entries so that all of the completely opaque colors are at the end of the palette; the corresponding transparency entries may then be omitted, resulting in a smaller file.
In some cases, the transparency mask contains only fully opaque and fully transparent values, and it may happen (usually by design) that the parts of the underlying image that correspond to the transparent region are all one color, even though there may be thousands of colors in the opaque part. pnmtopng will again detect this, creating a palette-based image with just one transparency entry if possible; if there are too many colors, it will instead write a full grayscale or RGB image with a single color marked transparent. This results in a PNG file that's much more compact than one with a full alpha channel.
Transparent images intended for display only on web browsers will always have some sort of background specified as part of the web page, but for images that may be rendered by a standalone viewer, it is often desirable to include an explicit background color in the image. The -background option provides that capability; it accepts a color argument in almost any format allowed by MIT's X Window System, including English text (assuming the X color database file can be found). Thus, the following three commands are equivalent (the -alpha ovalmask.pgm option has been omitted for brevity):
pnmtopng -background rgbi:1.0/0.855/0.726 foo.ppm > foo.png pnmtopng -background "peach puff" foo.ppm > foo.png pnmtopng -background "#ffdab9" foo.ppm > foo.png
For most users, the second form is probably the most easily understood but the least precise. Making it precise requires the finely honed ability to find the X color-database file, which can be difficult when it exists and impossible when it doesn't (it is also explicitly platform-dependent; that is, the same color name is allowed to have different RGB values on different machines). Therefore, the first form is likely to be the most useful. It specifies the RGB values of the background color as decimal fractions between 0.0 and 1.0. The values are separated by forward slashes (/) and prefixed by rgbi:. The third form is the old-style hexadecimal format that is favored by programmers but almost no one else. (It also happens to be the format used in the demo programs I present in Chapter 13, "Reading PNG Images" and Chapter 14, "Reading PNG Images Progressively" on reading PNG images. Oh, the embarrassment.) The hex value need not be placed in quotation marks on a command line, but within a shell script it should be quoted, or the hash character (#) will be treated as the beginning of a comment.
pnmtopng also potentially supports the creation of 16-bit-per-sample images (that is, 16-bit grayscale, 32-bit gray+alpha, 48-bit RGB or 64-bit RGBA), but only with text (ASCII) NetPBM files, and only if the underlying NetPBM library supports 16-bit images, which is not the default behavior. The requirement to use ASCII format for the 16-bit NetPBM image files is a current limitation of the NetPBM suite. As with transparency and palettes, pnmtopng detects if 16-bit samples are really just scaled 8-bit samples; if so, it will automatically convert the image back to 8-bit samples unless the -force option is given. It can also be instructed to convert true 16-bit samples to 8-bit with the -downsample option.
Other supported features include chromaticity information, histograms, compressed
text, explicit single-color transparency, physical pixel dimensions, and
special compression options. Quantization of truecolor images to 256 or
fewer colors is not supported by pnmtopng itself, but it is a straightforward
part of the standard NetPBM package. For example, to quantize a 24-bit TIFF
image to the 256 best colors, dither the result, and save it as a palette-based
PNG, one can use:
tifftopnm foo.tiff | ppmquant -fs 256 | pnmtopng > foo.png
The -fs option to ppmquant instructs it to use Floyd-Steinberg dithering, which generally looks very nice but does require a fair amount of computation. The 256 parameter indicates the number of colors to be used in the final version; any value may be used (web-savvy designers might wish to use a smaller number of colors), but only values of 256 or less will result in a palette-based PNG image. What about images with an alpha channel? Unfortunately, those who wish to quantize 32-bit RGBA images down to a 256-entry ``RGBA palette'' are stuck for now. The ppmquant algorithm can easily be modified to support RGBA values in addition to ordinary RGB, but until NetPBM itself is updated, there is no way to pipe transparency information from one NetPBM utility into another.
For users of very large images, one other point is worth mentioning: pnmtopng
currently reads the entire image into memory buffers before doing anything
with it, which means that a 4000 × 4000 RGBA image would require 64 megabytes
of real and/or virtual memory just for the uncompressed image itself. But
all is not lost; in Chapter 15, "Writing PNG Images", I present a very
simple-minded NetPBM-to-PNG converter, and one of its design goals was the
ability to convert images on the fly, requiring only a very small memory
footprint. (Of course, this only works if the PNG image is not
interlaced.) The demo program also has a -time option that
automatically records the current time in the proper format, as well as one
or two other potentially handy features.
|Home Applications Applications: Image Converters pnmtopng|