about summary refs log tree commit diff
path: root/converter
diff options
context:
space:
mode:
Diffstat (limited to 'converter')
-rw-r--r--converter/other/Makefile5
-rw-r--r--converter/other/cameratopam/camera.c2
-rw-r--r--converter/other/cameratopam/cameratopam.c2
-rw-r--r--converter/other/cameratopam/foveon.c4
-rw-r--r--converter/other/cameratopam/foveon.h4
-rw-r--r--converter/other/ipdb.c1
-rw-r--r--converter/other/pamtogif.c4
-rw-r--r--converter/other/pamtooctaveimg.c4
-rw-r--r--converter/other/pamtopam.c2
-rw-r--r--converter/other/pamtopnm.c2
-rw-r--r--converter/other/pamtosrf.c4
-rw-r--r--converter/other/pamtosvg/pamtosvg.c2
-rw-r--r--converter/other/pamtotiff.c2
-rw-r--r--converter/other/pamtowinicon.c1177
-rw-r--r--converter/other/pamtoxvmini.c4
-rw-r--r--converter/other/pnmtopclxl.c2
-rw-r--r--converter/other/pnmtopng.c534
-rw-r--r--converter/other/pnmtops.c82
-rw-r--r--converter/other/pstopnm.c378
-rw-r--r--converter/other/winicon.h82
-rw-r--r--converter/other/winicontopam.c1282
-rw-r--r--converter/pbm/pbmtolj.c2
-rw-r--r--converter/pbm/pbmtopsg3.c2
-rw-r--r--converter/ppm/411toppm.c10
-rw-r--r--converter/ppm/ppmtompeg/bframe.c2
-rw-r--r--converter/ppm/ppmtompeg/frame.c2
-rw-r--r--converter/ppm/ppmtompeg/headers/frames.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/param.h17
-rw-r--r--converter/ppm/ppmtompeg/parallel.c2
-rw-r--r--converter/ppm/ppmtompeg/param.c65
-rw-r--r--converter/ppm/ppmtompeg/ppmtompeg.c5
-rw-r--r--converter/ppm/ppmtompeg/readframe.c7
-rw-r--r--converter/ppm/ppmtompeg/specifics.c4
-rw-r--r--converter/ppm/ppmtopjxl.c229
-rw-r--r--converter/ppm/ppmtoyuv.c141
-rw-r--r--converter/ppm/sldtoppm.c137
-rw-r--r--converter/ppm/winicontoppm.c813
-rw-r--r--converter/ppm/yuvtoppm.c255
38 files changed, 4069 insertions, 1204 deletions
diff --git a/converter/other/Makefile b/converter/other/Makefile
index 746db87c..35f420f2 100644
--- a/converter/other/Makefile
+++ b/converter/other/Makefile
@@ -118,12 +118,13 @@ PORTBINARIES =  avstopam bmptopnm fitstopnm \
 		pamtoavs pamtodjvurle pamtofits pamtogif \
 		pamtohdiff pamtohtmltbl pamtompfont pamtooctaveimg \
 		pamtopam pamtopfm pamtopnm pamtouil \
-		pamtoxvmini \
+		pamtowinicon pamtoxvmini \
 		pbmtopgm pfmtopam \
 	        pgmtopbm pgmtoppm ppmtopgm pnmtoddif \
 		pnmtopclxl \
 		pnmtosgi pnmtosir pamtotga pnmtoxwd \
-		rlatopam sgitopnm sirtopnm sunicontopnm xwdtopnm zeisstopnm
+		rlatopam sgitopnm sirtopnm sunicontopnm \
+		winicontopam xwdtopnm zeisstopnm
 
 BINARIES = \
   $(PORTBINARIES) \
diff --git a/converter/other/cameratopam/camera.c b/converter/other/cameratopam/camera.c
index ea5eec39..254b6710 100644
--- a/converter/other/cameratopam/camera.c
+++ b/converter/other/cameratopam/camera.c
@@ -761,7 +761,7 @@ kodak_radc_load_raw()
 void kodak_jpeg_load_raw() {}
 #else
 
-static boolean
+static bool
 fill_input_buffer (j_decompress_ptr cinfo)
 {
   static char jpeg_buffer[4096];
diff --git a/converter/other/cameratopam/cameratopam.c b/converter/other/cameratopam/cameratopam.c
index 54b68a23..71c9c7af 100644
--- a/converter/other/cameratopam/cameratopam.c
+++ b/converter/other/cameratopam/cameratopam.c
@@ -69,7 +69,7 @@ int fuji_secondary;
 float cam_mul[4], pre_mul[4], coeff[3][4];
 int histogram[3][0x2000];
 jmp_buf failure;
-bool use_secondary;
+int use_secondary;
 bool verbose;
 
 #ifdef USE_LCMS
diff --git a/converter/other/cameratopam/foveon.c b/converter/other/cameratopam/foveon.c
index 0198940c..78e40baf 100644
--- a/converter/other/cameratopam/foveon.c
+++ b/converter/other/cameratopam/foveon.c
@@ -141,8 +141,8 @@ parse_foveon(FILE * const ifp) {
 
 
 void  
-foveon_coeff(bool * const useCoeffP,
-             float        coeff[3][4]) {
+foveon_coeff(int * const useCoeffP,
+             float       coeff[3][4]) {
 
     static const float foveon[3][3] =
     { {  1.4032, -0.2231, -0.1016 },
diff --git a/converter/other/cameratopam/foveon.h b/converter/other/cameratopam/foveon.h
index 57be2244..f3177e50 100644
--- a/converter/other/cameratopam/foveon.h
+++ b/converter/other/cameratopam/foveon.h
@@ -10,5 +10,5 @@ void
 foveon_load_raw(void);
 
 void  
-foveon_coeff(bool * const useCoeffP,
-             float        coeff[3][4]);
+foveon_coeff(int * const useCoeffP,
+             float       coeff[3][4]);
diff --git a/converter/other/ipdb.c b/converter/other/ipdb.c
index 5c1fc314..eec4495a 100644
--- a/converter/other/ipdb.c
+++ b/converter/other/ipdb.c
@@ -19,6 +19,7 @@
  *   Authors:  Eric A. Howe (mu@trends.net)
  *             Bryan Henderson, 2010
  */
+#define _BSD_SOURCE   /* Ensure strdup() is in <string.h> */
 #include <assert.h>
 #include <time.h>
 #include <string.h>
diff --git a/converter/other/pamtogif.c b/converter/other/pamtogif.c
index 4dac8923..5b9c219c 100644
--- a/converter/other/pamtogif.c
+++ b/converter/other/pamtogif.c
@@ -220,7 +220,7 @@ closestColor(tuple         const color,
     
     unsigned int i;
     unsigned int imin, dmin;
-    bool fits;
+    int fits;
 
     dmin = UINT_MAX;
     imin = 0;
@@ -1544,7 +1544,7 @@ computeTransparent(char          const colorarg[],
         const char * colorspec;
         bool exact;
         tuple transcolor;
-        bool found;
+        int found;
         int colorindex;
         
         if (colorarg[0] == '=') {
diff --git a/converter/other/pamtooctaveimg.c b/converter/other/pamtooctaveimg.c
index b090281d..28bc4cd4 100644
--- a/converter/other/pamtooctaveimg.c
+++ b/converter/other/pamtooctaveimg.c
@@ -75,13 +75,13 @@ findOrAddColor(tuple          const color,
   colormap *cmapP.  If the color isn't in the map, give it a new
   colormap index, put it in the colormap, and return that.
 -----------------------------------------------------------------------------*/
-    bool found;
+    int found;
     int colorIndex;
 
     pnm_lookuptuple(&cmapP->pam, cmapP->hash, color, &found, &colorIndex);
 
     if (!found) {
-        bool fits;
+        int fits;
         unsigned int plane;
 
         colorIndex = cmapP->nColors++;
diff --git a/converter/other/pamtopam.c b/converter/other/pamtopam.c
index cae54060..9cb82f7a 100644
--- a/converter/other/pamtopam.c
+++ b/converter/other/pamtopam.c
@@ -17,7 +17,7 @@
 int
 main(int argc, const char * argv[]) {
 
-    bool       eof;     /* no more images in input stream */
+    int        eof;     /* no more images in input stream */
     struct pam inpam;   /* Input PAM image */
     struct pam outpam;  /* Output PAM image */
 
diff --git a/converter/other/pamtopnm.c b/converter/other/pamtopnm.c
index ba655b1e..9bb662b7 100644
--- a/converter/other/pamtopnm.c
+++ b/converter/other/pamtopnm.c
@@ -109,7 +109,7 @@ main(int argc, char *argv[]) {
 
     struct cmdlineInfo cmdline;
     FILE* ifP;
-    bool eof;   /* no more images in input stream */
+    int eof;   /* no more images in input stream */
     struct pam inpam;   /* Input PAM image */
     struct pam outpam;  /* Output PNM image */
 
diff --git a/converter/other/pamtosrf.c b/converter/other/pamtosrf.c
index 19328073..3800d77c 100644
--- a/converter/other/pamtosrf.c
+++ b/converter/other/pamtosrf.c
@@ -112,7 +112,7 @@ srfAlphaFromTuple(tuple              const t,
                   const struct pam * const pamP) {
 
     uint8_t retval;
-    bool haveOpacity;
+    int haveOpacity;
     unsigned int opacityPlane;
 
     pnm_getopacity(pamP, &haveOpacity, &opacityPlane);
@@ -181,7 +181,7 @@ main(int argc, const char * argv[]) {
   struct cmdlineInfo cmdline;
   FILE *             ifP;
   struct srf         srf;
-  bool               eof;   /* No more images in input */
+  int                eof;   /* No more images in input */
   unsigned int       imageSeq;
       /* Sequence of current image in input file.  First = 0 */
 
diff --git a/converter/other/pamtosvg/pamtosvg.c b/converter/other/pamtosvg/pamtosvg.c
index 72aa4151..adf76801 100644
--- a/converter/other/pamtosvg/pamtosvg.c
+++ b/converter/other/pamtosvg/pamtosvg.c
@@ -134,7 +134,7 @@ parseCommandLine(int argc,
    Note that the strings we return are stored in the storage that
    was passed to us as the argv array.  We also trash *argv.
 --------------------------------------------------------------------------*/
-    optEntry *option_def;
+    optEntry * option_def;
     /* Instructions to pm_optParseOptions3 on how to parse our options. */
     optStruct3 opt;
 
diff --git a/converter/other/pamtotiff.c b/converter/other/pamtotiff.c
index 551909a0..0206678d 100644
--- a/converter/other/pamtotiff.c
+++ b/converter/other/pamtotiff.c
@@ -1055,7 +1055,7 @@ main(int argc, char *argv[]) {
     const char * inputFileDescription;
     FILE* ifP;
     TIFF* tifP;
-    bool eof;
+    int eof;
     unsigned int imageSeq;
 
     pnm_init(&argc, argv);
diff --git a/converter/other/pamtowinicon.c b/converter/other/pamtowinicon.c
new file mode 100644
index 00000000..c67267e4
--- /dev/null
+++ b/converter/other/pamtowinicon.c
@@ -0,0 +1,1177 @@
+#define _POSIX_SOURCE   /* Make sure fdopen() is in <stdio.h> */
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "netpbm/pm_config.h"
+#include "netpbm/pm_c_util.h"
+#include "netpbm/mallocvar.h"
+#include "netpbm/nstring.h"
+#include "netpbm/shhopt.h"
+#include "netpbm/pm_system.h"
+#include "netpbm/pam.h"
+#include "winicon.h"
+
+
+
+struct CmdlineInfo {
+    const char * inputFileName;
+    unsigned int verbose;
+    int          pngthreshold;
+    unsigned int truetransparent;
+};
+
+
+
+static void
+parseCommandLine(int argc, const char **argv,
+                 struct CmdlineInfo * const cmdlineP) {
+
+    optEntry *   option_def;
+    unsigned int option_def_index;
+    optStruct3   opt3;
+    unsigned int pngthresholdSpec;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;
+
+    OPTENT3 (0, "verbose",         OPT_FLAG, NULL,
+             &cmdlineP->verbose,         0);
+    OPTENT3 (0, "pngthreshold",    OPT_UINT, &cmdlineP->pngthreshold,
+             &pngthresholdSpec,          0);
+    OPTENT3 (0, "truetransparent", OPT_FLAG, NULL,
+             &cmdlineP->truetransparent, 0);
+
+    opt3.opt_table     = option_def;
+    opt3.short_allowed = false;
+    opt3.allowNegNum   = false;
+
+    pm_optParseOptions3(&argc, (char **)argv, opt3, sizeof(opt3), 0);
+
+    if (pngthresholdSpec) {
+        if (UINT_MAX / cmdlineP->pngthreshold < cmdlineP->pngthreshold)
+            pm_error("-pngthreshold is too large: %u", cmdlineP->pngthreshold);
+    } else
+        cmdlineP->pngthreshold = 128;
+
+    if (argc-1 > 0) {
+        cmdlineP->inputFileName = argv[1];
+
+        if (argc-1 > 1)
+            pm_error("Too many arguments: %u.  The only non-option "
+                     "argument is the optional input file name", argc-1);
+    } else
+        cmdlineP->inputFileName = "-";
+
+    free(option_def);
+}
+
+
+
+static bool verbose;
+
+static unsigned char const pngHeader[] = PNG_HEADER;
+
+
+
+struct Palette {
+    sample color[256][3];
+    unsigned int colorCt;
+        /* Number of colors in color[][] */
+    bool tooManyColors;
+        /* There are too many colors for a BMP palette (more than 256); only
+           the first 256 are in color[][]
+        */
+};
+
+
+
+static struct IconDir *
+newIconDir() {
+
+    struct IconDir * dirP;
+
+    MALLOCVAR_NOFAIL(dirP);
+
+    dirP->zero           = 0;
+    dirP->type           = ICONDIR_TYPE_ICO;
+    dirP->count          = 0;
+
+    dirP->entriesAllocCt = 0;
+    dirP->entries        = NULL;
+
+    return dirP;
+}
+
+
+
+static void
+freeIconDir(struct IconDir * const dirP) {
+    if (dirP->entries)
+        free(dirP->entries);
+
+    free(dirP);
+}
+
+
+
+static void
+addToDirectory(struct IconDirEntry * const dirEntryP,
+               struct IconDir *      const dirP) {
+/*----------------------------------------------------------------------------
+  Add an icon to the icon directory.
+-----------------------------------------------------------------------------*/
+    if (dirP->count + 1 > dirP->entriesAllocCt) {
+        /* Out of space in dirP->entries[].  Expand. */
+
+        dirP->entriesAllocCt += 8;
+
+        REALLOCARRAY(dirP->entries, dirP->entriesAllocCt);
+
+        if (!dirP->entries)
+            pm_error("Unable to get memory for %u entries "
+                     "in the Icon directory.", dirP->entriesAllocCt);
+    }
+
+    dirP->entries[dirP->count++] = *dirEntryP;
+}
+
+
+
+typedef void (GetPixelFn) (tuple **     const tuples,
+                           unsigned int const col,
+                           unsigned int const row,
+                           sample *     const pixel);
+
+
+
+static GetPixelFn get_grayscalePixel;
+
+static void
+get_grayscalePixel(tuple **     const tuples,
+                   unsigned int const col,
+                   unsigned int const row,
+                   sample *     const pixel) {
+/*----------------------------------------------------------------------------
+   Get a pixel from a grayscale PAM
+-----------------------------------------------------------------------------*/
+    pixel[0] = tuples[row][col][0];
+    pixel[1] = tuples[row][col][0];
+    pixel[2] = tuples[row][col][0];
+}
+
+
+
+static GetPixelFn get_rgbPixel;
+
+static void
+get_rgbPixel(tuple **     const tuples,
+             unsigned int const col,
+             unsigned int const row,
+             sample *     const pixel) {
+/*----------------------------------------------------------------------------
+   Get a pixel from an RGB PAM
+-----------------------------------------------------------------------------*/
+    pixel [0] = tuples [row][col][0];
+    pixel [1] = tuples [row][col][1];
+    pixel [2] = tuples [row][col][2];
+}
+
+
+static bool
+andMakesOpaque(const struct pam * const pamP,
+               tuple **           const tuples,
+               unsigned int       const row,
+               unsigned int       const col,
+               bool               const haveAlpha,
+               unsigned int       const alphaPlane,
+               bool               const haveAnd,
+               unsigned int       const andPlane) {
+/*----------------------------------------------------------------------------
+   The AND mask makes a pixel opaque
+-----------------------------------------------------------------------------*/
+    if (haveAnd)
+        return (pamP->maxval <= tuples[row][col][andPlane]);
+    else if (haveAlpha)
+        return (pamP->maxval <= tuples[row][col][alphaPlane]);
+    else
+        /* neither alpha channel nor AND mask: full opacity */
+        return true;
+}
+
+
+
+static void
+getPalette(struct pam *     const pamP,
+           tuple **         const tuples,
+           GetPixelFn *     const getPixel,
+           struct Palette * const paletteP) {
+/*----------------------------------------------------------------------------
+  Create the palette for all the colors in 'tuples'.
+-----------------------------------------------------------------------------*/
+    unsigned int row;
+
+    paletteP->colorCt = 0;  /* initial value */
+    paletteP->tooManyColors = false;  /* initial value */
+
+    for (row = 0; pamP->height > row && !paletteP->tooManyColors; ++row) {
+        unsigned int col;
+        for (col = 0; pamP->width > col && !paletteP->tooManyColors; ++col) {
+            sample pixel[3];
+            unsigned int i;
+
+            getPixel(tuples, col, row, pixel);
+
+            for (i = 0; i < paletteP->colorCt; ++i) {
+                if ((paletteP->color[i][0] == pixel[0])
+                    && (paletteP->color[i][1] == pixel[1])
+                    && (paletteP->color[i][2] == pixel[2]))
+                    break;
+            }
+            if (i == paletteP->colorCt) {
+                /* We didn't find the color. */
+                if (paletteP->colorCt >= 256) {
+                    /* Image exceeds the palette capacity */
+                    paletteP->tooManyColors = true;
+                } else {
+                    /* Add the color to the palette */
+                    paletteP->color[paletteP->colorCt][0] = pixel[0];
+                    paletteP->color[paletteP->colorCt][1] = pixel[1];
+                    paletteP->color[paletteP->colorCt][2] = pixel[2];
+
+                    ++paletteP->colorCt;
+                }
+            }
+        }
+    }
+}
+
+
+
+static bool
+realAlphaNeeded(const struct pam * const pamP,
+                tuple **           const tuples,
+                unsigned int       const alphaPlane) {
+/*----------------------------------------------------------------------------
+  A real alpha channel (in contrast to an AND mask) is needed to represent the
+  image in 'tuples', given that 'alphaPlane' is the alpha plane.
+
+  A real alpha channel is needed if any pixel is translucent (neither opaque
+  nor transparent).
+-----------------------------------------------------------------------------*/
+    unsigned int row;
+
+    for (row = 0; row < pamP->height; ++row) {
+        unsigned int col;
+        for (col = 0; col < pamP->width; ++col) {
+            sample const opacity = tuples[row][col][alphaPlane];
+
+            if (opacity != 0 && opacity != pamP->maxval)
+                return true;
+        }
+    }
+    return false;
+}
+
+
+
+static void
+writeBmpImageHeader(unsigned int const width,
+                    unsigned int const height,
+                    unsigned int const bpp,
+                    unsigned int const rasterSize,
+                    FILE *       const ofP) {
+/*----------------------------------------------------------------------------
+
+  Write BMP image header
+    
+  Note: bm_height is sum of rows in XOR mask and AND mask, while
+  image_size is the size of the AND mask only.
+    
+  image_size does not include the sizes of the (optional) palette
+  and the (mandatory) AND mask.
+-----------------------------------------------------------------------------*/
+    pm_writelittlelongu  (ofP, 40);              /* header_size          */
+    pm_writelittlelongu  (ofP, width);           /* bm_width             */
+    pm_writelittlelongu  (ofP, height *2);       /* bm_height            */
+    pm_writelittleshortu (ofP, 1);               /* color_planes         */
+    pm_writelittleshortu (ofP, bpp);             /* bits_per_pixel       */
+    pm_writelittlelongu  (ofP, BI_RGB);          /* compression_method   */
+    pm_writelittlelongu  (ofP, rasterSize);      /* image_size           */
+    pm_writelittlelongu  (ofP, 0);               /* horizontal_resolution*/
+    pm_writelittlelongu  (ofP, 0);               /* vertical_resolution  */
+    pm_writelittlelongu  (ofP, 0);               /* colors_in_palette    */
+    pm_writelittlelongu  (ofP, 0);               /* important_colors     */
+}
+
+
+
+static void
+write32BitBmp(const struct pam *   const pamP,
+              tuple     **         const tuples,
+              GetPixelFn *         const getPixel,
+              bool                 const haveAlpha,
+              unsigned int         const alphaPlane,
+              FILE *               const ofP,
+              uint32_t *           const sizeP) {
+/*----------------------------------------------------------------------------
+  Write a 32-bit BMP encoded image to file *ofP.
+-----------------------------------------------------------------------------*/
+    int row;
+    
+    writeBmpImageHeader(pamP->width, pamP->height, 32, 
+                        pamP->width * 4 * pamP->height, ofP);
+
+    /*  write "XOR mask" */
+    for (row = pamP->height - 1; row >= 0; --row) {
+        unsigned int col;
+        for (col = 0; col < pamP->width; ++col) {
+            sample   pixel[3];
+            uint32_t val;
+
+            getPixel(tuples, col, row, pixel);
+
+            val = ((uint32_t) pixel[PAM_RED_PLANE] << 16)
+                + ((uint32_t) pixel[PAM_GRN_PLANE] <<  8)
+                + ((uint32_t) pixel[PAM_BLU_PLANE] <<  0)
+                ;
+            
+            if (haveAlpha)
+                val += (uint32_t) tuples[row][col][alphaPlane] << 24;
+
+            pm_writelittlelongu(ofP, val);
+       }
+    }
+    *sizeP = 40 + pamP->height * pamP->width * 4;
+}
+
+
+
+static void
+writeBmpPalette(const struct Palette * const paletteP,
+                unsigned int           const maxColors,
+                FILE *                 const ofP) {
+/*----------------------------------------------------------------------------
+   Write the palette of a BMP image.
+-----------------------------------------------------------------------------*/
+    unsigned int i;
+
+    for (i = 0; i < paletteP->colorCt; ++i)
+        pm_writelittlelongu(ofP, 0
+                            +(paletteP->color[i][PAM_RED_PLANE] << 16)
+                            +(paletteP->color[i][PAM_GRN_PLANE] <<  8)
+                            +(paletteP->color[i][PAM_BLU_PLANE] <<  0));
+    
+    for (; i < maxColors; ++i)
+        pm_writelittlelongu(ofP, 0);
+}
+
+
+
+static void
+writeXorMask(const struct pam *     const pamP,
+             tuple **               const tuples,
+             GetPixelFn *           const getPixel,
+             const struct Palette * const paletteP,
+             unsigned int           const bpp,
+             FILE *                 const ofP) {
+/*----------------------------------------------------------------------------
+   Write the "XOR mask" part of a BMP image.
+
+   This is what one normally thinks of as the foreground image raster.
+-----------------------------------------------------------------------------*/
+    unsigned int const maxCol = ((pamP->width * bpp + 31) & ~31) / bpp;
+
+    int row;
+                 
+    for (row = pamP->height - 1; row >= 0; --row) {
+        uint8_t  val;
+        uint16_t mask;
+        unsigned int col;
+
+        mask = 0x1;
+        val  = 0x0;
+
+        for (col = 0; col < pamP->width; ++col) {
+            sample pixel[3];
+            unsigned int i;
+
+            mask <<= bpp;
+            val  <<= bpp;
+
+            getPixel(tuples, col, row, pixel);
+
+            for (i = 0; i < paletteP->colorCt; ++i)
+                if (true
+                    && (pixel[0] == paletteP->color[i][0])
+                    && (pixel[1] == paletteP->color[i][1])
+                    && (pixel[2] == paletteP->color[i][2]))
+                    break;
+
+            assert(i < paletteP->colorCt);
+
+            val |= i;
+
+            if (mask > 0xFF) {
+                pm_writecharu(ofP, val);
+                mask = 0x1;
+                val  = 0x0;
+            }
+        }
+        for (; col < maxCol; ++col) {
+            mask <<= bpp;
+            val  <<= bpp;
+
+            if (mask > 0xFF) {
+                pm_writecharu(ofP, val);
+                mask = 0x1;
+            }
+        }
+    }
+}
+
+
+
+static void
+writePaletteBmp(unsigned int           const bpp,
+                const struct pam   *   const pamP,
+                tuple **               const tuples,
+                GetPixelFn *           const getPixel,
+                const struct Palette * const paletteP,
+                FILE *                 const ofP,
+                uint32_t *             const sizeP) {
+/*----------------------------------------------------------------------------
+  Write a `BMP with palette' encoded image to file *ofP.
+
+  Unless it would be smaller as a 32-bit direct image, in which case
+  write that instead.
+-----------------------------------------------------------------------------*/
+    unsigned int const maxColors = 1 << bpp;
+
+    unsigned int const rasterSize =
+        pamP->height *((pamP->width * bpp + 31) & ~31) / 8;
+
+    if (pamP->height * pamP->width * 4 <= maxColors * 4 + rasterSize)
+        write32BitBmp(pamP, tuples, getPixel, false /*haveAlpha*/, 0,
+                      ofP, sizeP);
+    else {
+        unsigned int const headerSize = 40;
+        unsigned int const paletteSize = maxColors * 4;
+
+        writeBmpImageHeader(pamP->width, pamP->height, bpp, rasterSize, ofP);
+
+        writeBmpPalette(paletteP, maxColors, ofP);
+
+        writeXorMask(pamP, tuples, getPixel, paletteP, bpp, ofP);
+
+        *sizeP = headerSize + paletteSize + rasterSize;
+    }
+}
+
+
+
+static void
+writeAndMask(const struct pam * const pamP,
+             tuple     **       const tuples,
+             bool               const haveAlpha,
+             unsigned int       const alphaPlane,
+             bool               const haveAnd,
+             unsigned int       const andPlane,
+             FILE *             const ofP,
+             uint32_t *         const sizeP) {
+/*----------------------------------------------------------------------------
+  Write the AND mask to file *ofP.
+-----------------------------------------------------------------------------*/
+    unsigned int const maxCol =((pamP->width * 1 + 31) & ~31) / 1;
+
+    int row;
+    unsigned int sizeSoFar;
+
+    sizeSoFar = 0;
+
+    for (row = pamP->height - 1; row >= 0; --row) {
+        uint8_t  val;
+        uint16_t mask;
+        unsigned int col;
+
+        mask = 0x1;
+        val  = 0x0;
+
+        for (col = 0; col < pamP->width; ++col) {
+            mask <<= 1;
+            val  <<= 1;
+
+            if (!andMakesOpaque(pamP, tuples, row, col, 
+                                haveAlpha, alphaPlane, haveAnd, andPlane))
+                val |= 0x1;
+
+            if (mask > 0xFF) {
+                pm_writecharu(ofP, val);
+                sizeSoFar += 1;
+                mask = 0x1;
+                val  = 0x0;
+            }
+        }
+        for (; col < maxCol; ++col) {
+            mask <<= 1;
+            val  <<= 1;
+
+            if (mask > 0xFF){
+                pm_writecharu(ofP, val);
+                sizeSoFar += 1;
+                mask = 0x1;
+            }
+        }
+    }
+    *sizeP = sizeSoFar;
+}
+
+
+
+static void
+makeAlphaFile(const struct pam * const imagePamP,
+              tuple **           const imageTuples,
+              unsigned int       const alphaPlane,
+              const char **      const alphaFileNameP) {
+
+    FILE * alphaFileP;
+    struct pam alphaPam;
+    tuple ** alphaTuples;
+    unsigned int row;
+    
+    pm_make_tmpfile(&alphaFileP, alphaFileNameP);
+
+    alphaPam.size   = sizeof(alphaPam);
+    alphaPam.len    = PAM_STRUCT_SIZE(tuple_type);
+    alphaPam.file   = alphaFileP;
+    alphaPam.format = PAM_FORMAT;
+    alphaPam.width  = imagePamP->width;
+    alphaPam.height = imagePamP->height;
+    alphaPam.depth  = 1;
+    alphaPam.maxval = imagePamP->maxval;
+    strcpy(alphaPam.tuple_type, PAM_PGM_TUPLETYPE);
+
+    alphaTuples = pnm_allocpamarray(&alphaPam);
+
+    assert(alphaPlane < imagePamP->depth);
+
+    for (row = 0; row < alphaPam.height; ++row) {
+        unsigned int col;
+        for (col = 0; col < alphaPam.width; ++col)
+            alphaTuples[row][col][0] = imageTuples[row][col][alphaPlane];
+    }
+
+    pnm_writepam(&alphaPam, alphaTuples);
+
+    pnm_freepamarray(alphaTuples, &alphaPam);
+
+    pm_close(alphaFileP);
+}
+
+
+
+struct AcceptToFileParm {
+    FILE *   ofP;
+    size_t * writeCtP;
+};
+
+static void
+acceptToFile(int    const pipeToSuckFd,
+             void * const accepterParm) {
+
+    struct AcceptToFileParm * const parmP = accepterParm;
+
+    FILE * const inFileP = fdopen(pipeToSuckFd, "r");
+
+    bool eof;
+    size_t copyCt;
+
+    for (eof = false, copyCt = 0; !eof; ) {
+        size_t readCt;
+        unsigned char buffer[1024];
+
+        readCt = fread(buffer, 1, sizeof(buffer), inFileP);
+
+        if (readCt == 0)
+            eof = true;
+        else {
+            size_t writeCt;
+
+            writeCt = fwrite(buffer, 1, readCt, parmP->ofP);
+
+            if (writeCt != readCt)
+                pm_error("Write to images file failed.  errno=%d (%s)",
+                         errno, strerror(errno));
+
+            copyCt += writeCt;
+        }
+    }
+    *parmP->writeCtP = copyCt;
+}
+
+
+
+static void
+writePng(const struct pam * const pamP,
+         tuple **           const tuples,
+         bool               const haveAlpha,
+         unsigned int       const alphaPlane,
+         bool               const haveAnd,
+         unsigned int       const andPlane,
+         uint32_t *         const sizeP,
+         FILE *             const ofP) {
+
+    struct pamtuples pamTuples;
+    size_t pngSize;
+    struct AcceptToFileParm acceptParm;
+    struct pam pam;
+
+    pam = *pamP;
+    pam.depth = pamP->depth - (haveAlpha ? 1 : 0) - (haveAnd ? 1 : 0);
+
+    pamTuples.pamP    = &pam;
+    pamTuples.tuplesP = (tuple ***)&tuples;
+
+    /* We're going to fork a process to add stuff to *ofP, so we flush
+       out this process' previous writes to that file first:
+    */
+    fflush(ofP);
+
+    acceptParm.ofP = ofP;
+    acceptParm.writeCtP = &pngSize;
+    
+    if (haveAlpha || haveAnd) {
+        const char * alphaFileName;
+        const char * command;
+
+        if (haveAlpha)
+            makeAlphaFile(pamP, tuples, alphaPlane, &alphaFileName);
+        else
+            makeAlphaFile(pamP, tuples, andPlane, &alphaFileName);
+
+        strcpy (pam.tuple_type,
+                pam.depth == 3 ? PAM_PPM_TUPLETYPE: PAM_PGM_TUPLETYPE);
+        
+        pm_asprintf(&command, "pnmtopng -alpha=\"%s\"", alphaFileName);
+
+        pm_system(pm_feed_from_pamtuples, &pamTuples,
+                  acceptToFile, &acceptParm,
+                  command);
+    
+        pm_strfree(command);
+    
+        unlink(alphaFileName);
+    } else {
+        pm_system(pm_feed_from_pamtuples, &pamTuples,
+                  acceptToFile, &acceptParm,
+                  "pnmtopng");
+    }
+
+    *sizeP = pngSize;
+}
+
+
+
+static void
+blackenXor(const struct pam * const pamP,
+           tuple     **       const tuples,
+           bool               const haveAlpha,
+           unsigned int       const alphaPlane,
+           bool               const haveAnd,
+           unsigned int       const andPlane) {
+/*----------------------------------------------------------------------------
+  Set all pixels marked as transparent in AND mask to black.
+-----------------------------------------------------------------------------*/
+    unsigned int row;
+
+    for (row = 0; row < pamP->height; ++row) {
+        unsigned int col;
+        for (col = 0; col < pamP->width; ++col) {
+            if (!andMakesOpaque(pamP, tuples, row, col,
+                                haveAlpha, alphaPlane, haveAnd, andPlane)) {
+                tuples[row][col][0] = PAM_BLACK;
+
+                if (pamP->depth >= 3) {
+                    tuples[row][col][1] = PAM_BLACK;
+                    tuples[row][col][2] = PAM_BLACK;
+                }
+            }
+        }
+    }
+}
+
+
+
+
+static void
+readAndScalePam(struct pam * const pamP,
+                bool         const doingPng,
+                tuple **     const tuples) {
+
+    if (doingPng) {
+        /* Read the image with its native maxval */
+        unsigned int row;
+        for (row = 0; row < pamP->height; ++row)
+            pnm_readpamrow(pamP, tuples[row]);
+    } else {
+        /* Read the image and scale to maxval 255 */
+        tuple * tuplerow;
+        unsigned int row;
+        tuplerow = pnm_allocpamrow(pamP);
+
+        for (row = 0; row < pamP->height; ++row) {
+            pnm_readpamrow(pamP, tuplerow);
+            pnm_scaletuplerow(pamP, tuples[row], tuplerow, 255);
+        }
+        pnm_freepamrow(tuplerow);
+        pamP->maxval = 255;
+    }
+}
+
+
+
+static void
+determineImageType(const struct pam * const pamP,
+                   tuple **           const tuples,
+                   GetPixelFn **      const getPixelP,
+                   bool *             const haveAlphaP,
+                   unsigned int *     const alphaPlaneP,
+                   bool *             const haveAndP,
+                   unsigned int *     const andPlaneP) {
+
+    /*  PAM input channels:
+     *
+     *  1-channel PAM: Grayscale
+     *  2-channel PAM: Grayscale +Alpha
+     *  3-channel PAM: RGB
+     *  4-channel PAM: RGB +Alpha
+     *  5-channel PAM: RGB +Alpha +AND mask
+     */
+    switch (pamP->depth) {
+    case 1:
+        *getPixelP  = get_grayscalePixel;
+        *haveAlphaP = false;
+        *haveAndP   = false;
+        break;
+
+    case 2:
+        *getPixelP = get_grayscalePixel;
+        if (realAlphaNeeded(pamP, tuples, 1)) {
+            *haveAlphaP  = true;
+            *alphaPlaneP = 1;
+            *haveAndP    = false;
+        } else {
+            *haveAlphaP = false;
+            *haveAndP   = true;
+            *andPlaneP  = 1;
+        }
+        break;
+
+    case 3:
+        *getPixelP  = get_rgbPixel;
+        *haveAlphaP = false;
+        *haveAndP   = false;
+        break;
+
+    case 4:
+        *getPixelP = get_rgbPixel;
+        if (realAlphaNeeded(pamP, tuples, 3)) {
+            *haveAlphaP  = true;
+            *alphaPlaneP = 3;
+            *haveAndP    = false;
+        } else {
+            *haveAlphaP = false;
+            *haveAndP    = true;
+            *andPlaneP  = 3;
+        }
+        break;
+
+    case 5:
+        *getPixelP   = get_rgbPixel;
+        *haveAlphaP  = true;
+        *alphaPlaneP = 3;
+        *haveAndP    = true;
+        *andPlaneP   = 4;
+        break;
+
+    default:
+        pm_error("unexpected PAM depth %u.  "
+                 "We understand depths 1-5", pamP->depth);
+        break;
+    }
+}
+
+
+
+static void
+reportImageInfo(unsigned int           const imageNum,
+                const struct pam *     const pamP,
+                const struct Palette * const paletteP,
+                bool                   const haveAlpha,
+                bool                   const haveAnd) {
+
+    const char * colorCt;
+
+    if (paletteP->tooManyColors)
+        pm_asprintf(&colorCt, "> 256");
+    else
+        pm_asprintf(&colorCt, "%u", paletteP->colorCt);
+
+    pm_message("Image %2u:"
+               " %3u x %3u x %u, %s colors%s%s",
+               imageNum,
+               pamP->width, pamP->height, pamP->depth,
+               colorCt,
+               haveAlpha ? ", alpha channel": "",
+               haveAnd ? ", AND mask": "");
+
+    pm_strfree(colorCt);
+}
+
+
+
+static void
+writeIconAndCreateDirEntry(const struct pam *     const pamP,
+                           tuple **               const tuples,
+                           GetPixelFn *           const getPixel,
+                           bool                   const doingPng,
+                           bool                   const haveAlpha,
+                           unsigned int           const alphaPlane,
+                           bool                   const haveAnd,
+                           unsigned int           const andPlane,
+                           bool                   const mustBlackenXor,
+                           const struct Palette * const paletteP,
+                           FILE *                 const ofP,
+                           struct IconDirEntry *  const dirEntryP) {
+/*----------------------------------------------------------------------------
+   Write to *ofP the icon image for the image represented by *pamP and
+   'tuples'.
+
+   Generate the information for an icon directory entry for this image
+   and return it as *dirEntryP.  ==>BUT: the 'offset' member of this
+   structure will not be meaningful. <==
+
+   Make a PNG image if 'doingPng' is true; BMP otherwise.
+
+   'haveAlpha' means that there is an alpha plane in 'tuples' and it is
+   Plane 'alphaPlane'.
+
+   'haveAnd' means that there is an AND plane in 'tuples' and it is Plane
+   'andPlane'.
+
+   *paletteP is the color palette for the icon; it contains an entry for each
+   color in 'tuples'.  Except: it may simply indicate that there are too many
+   colors in 'tuples' to have a palette.
+
+   The 'bits_per_pixel' member of the directory entry is supposed to tell the
+   color resolution of the image so the user can decide which of many versions
+   of the icon in the file to use.  But we just call it 32 bits in every case
+   except paletted BMP, where it actually relates to how many colors are in
+   the image.
+-----------------------------------------------------------------------------*/
+    dirEntryP->width          = pamP->width;
+    dirEntryP->height         = pamP->height;
+    dirEntryP->color_planes   = 1;
+    dirEntryP->zero           = 0;
+
+    if (doingPng) {
+        dirEntryP->color_count    = 0;
+        dirEntryP->bits_per_pixel = 32;
+
+        writePng(pamP, tuples, haveAlpha, alphaPlane, haveAnd, andPlane,
+                 &dirEntryP->size, ofP);
+    } else {
+        uint32_t bmpSize;
+        uint32_t andMaskSize;
+
+        if (mustBlackenXor)
+            blackenXor(pamP, tuples,
+                       haveAlpha, alphaPlane, haveAnd, andPlane);
+
+        if (haveAlpha) {
+            dirEntryP->color_count    = 0;
+            dirEntryP->bits_per_pixel = 32;
+
+            write32BitBmp(pamP, tuples, getPixel, haveAlpha, alphaPlane,
+                          ofP, &bmpSize);
+        } else if (paletteP->tooManyColors) {
+            /* Do a truecolor image */
+            dirEntryP->color_count    = 0;
+            dirEntryP->bits_per_pixel = 32;
+
+            write32BitBmp(pamP, tuples, getPixel, false /*haveAlpha*/, 0,
+                          ofP, &bmpSize);
+        } else {
+            /* Do a paletted image */
+
+            if (paletteP->colorCt <= 2) {
+                dirEntryP->color_count    = paletteP->colorCt;
+                dirEntryP->bits_per_pixel = 1;
+                    
+                writePaletteBmp(1, pamP, tuples, getPixel, paletteP,
+                                ofP, &bmpSize);
+            } else if (paletteP->colorCt <= 16) {
+                dirEntryP->color_count    = paletteP->colorCt;
+                dirEntryP->bits_per_pixel = 4;
+                    
+                writePaletteBmp(4, pamP, tuples, getPixel,paletteP,
+                                ofP, &bmpSize);
+            } else {
+                dirEntryP->color_count    = 0;
+                dirEntryP->bits_per_pixel = 8;
+                    
+                writePaletteBmp(8, pamP, tuples, getPixel, paletteP,
+                                ofP, &bmpSize);
+            }
+        }
+        writeAndMask(pamP, tuples, haveAlpha, alphaPlane, haveAnd, andPlane,
+                     ofP, &andMaskSize);
+
+        dirEntryP->size = bmpSize + andMaskSize;
+    }
+}
+
+
+
+static void
+convertOneImage(unsigned int     const imageNum,
+                FILE *           const ifP,
+                unsigned int     const pngThreshold,
+                bool             const mustBlackenXor,
+                FILE *           const ofP,
+                struct IconDir * const dirP) {
+
+    struct IconDirEntry dirEntry;
+    struct pam          pam;
+    tuple **            tuples;
+    bool                haveAlpha;
+    unsigned int        alphaPlane;
+    bool                haveAnd;
+    unsigned int        andPlane;
+    GetPixelFn *        getPixel;
+    struct Palette      palette;
+    bool                doingPng;
+        
+    /*  Output:
+     *
+     *  threshold^2 pixels or more:
+     *      no alpha channel:        PNG (RGB)
+     *      alpha channel:           PNG (RGBA)
+     *      alpha channel +AND mask: PNG (RGBA), AND mask dropped
+     *  alpha values other than 0 and maxval: 32bit +alpha BMP
+     *  no more than   2 colors:  1bit or 32bit BMP
+     *  no more than  16 colors:  4bit or 32bit BMP
+     *  no more than 256 colors:  8bit or 32bit BMP
+     *  more than    256 colors: 32bit BMP
+     */
+    pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type));
+
+    if (pam.width > 256 || pam.height > 256)
+        pm_error("Image %u: too large as a windows icon (%u x %u).  "
+                 "Maximum allowed dimension is 256",
+                 imageNum, pam.width, pam.height);
+
+    tuples = pnm_allocpamarray(&pam);
+
+    doingPng = pam.width * pam.height >= pngThreshold;
+
+    readAndScalePam(&pam, doingPng, tuples);
+
+    determineImageType(&pam, tuples, &getPixel,
+                       &haveAlpha, &alphaPlane, &haveAnd, &andPlane);
+
+    getPalette(&pam, tuples, getPixel, &palette);
+
+    if (verbose)
+        reportImageInfo(imageNum, &pam, &palette, haveAlpha, haveAnd);
+
+    writeIconAndCreateDirEntry(&pam, tuples, getPixel, doingPng,
+                               haveAlpha, alphaPlane,
+                               haveAnd, andPlane,
+                               mustBlackenXor,
+                               &palette,
+                               ofP, &dirEntry);
+
+    if (verbose)
+        pm_message("Image %2u: %u bytes", imageNum, dirEntry.size);
+
+    pnm_freepamarray(tuples, &pam);
+
+    addToDirectory(&dirEntry, dirP);
+}
+
+
+
+static void
+convert(FILE *           const ifP,
+        unsigned int     const pngThreshold,
+        bool             const mustBlackenXor,
+        struct IconDir * const dirP,
+        FILE *           const ofP) {
+/*----------------------------------------------------------------------------
+  Read a (multi-image) PAM file from *ifP and convert the individual images
+  to the proper format for a Windows icon file and write those to *ofP.
+
+  Where the number of pixels in an image is at least 'pngThreshold', use
+  a PNG image.  Otherwise, use a BMP.
+-----------------------------------------------------------------------------*/
+    unsigned int imageNum;
+    int eof;
+    
+    for (imageNum = 0, eof = false; !eof; ++imageNum) {
+        convertOneImage(imageNum, ifP, pngThreshold, mustBlackenXor,
+                        ofP, dirP);
+
+        pnm_nextimage(ifP, &eof);
+    }
+}
+
+
+
+static void
+writeIconDirEntry(const struct IconDirEntry * const dirEntryP,
+                  FILE *                      const ofP) {
+        
+    pm_writecharu        (ofP, dirEntryP->width);
+    pm_writecharu        (ofP, dirEntryP->height);
+    pm_writecharu        (ofP, dirEntryP->color_count);
+    pm_writecharu        (ofP, dirEntryP->zero);
+    pm_writelittleshortu (ofP, dirEntryP->color_planes);
+    pm_writelittleshortu (ofP, dirEntryP->bits_per_pixel);
+    pm_writelittlelongu  (ofP, dirEntryP->size); 
+    pm_writelittlelongu  (ofP, dirEntryP->offset);
+}
+
+
+
+static void
+writeIconDirectory(const struct IconDir * const dirP,
+                   FILE *                 const ofP) {
+/*----------------------------------------------------------------------------
+  Write to file *ofP the icon directory described by *dirP.
+
+  *dirP's image offset members are meaningless as input.  We fill them in.
+-----------------------------------------------------------------------------*/
+    uint32_t const hsize = 6 + dirP->count * 16;
+
+    unsigned int imageNum;
+    unsigned int imageOffset;
+
+    pm_writelittleshortu(ofP, dirP->zero);
+    pm_writelittleshortu(ofP, dirP->type);
+    pm_writelittleshortu(ofP, dirP->count);
+
+    for (imageNum = 0, imageOffset = hsize;
+         imageNum < dirP->count;
+         ++imageNum) {
+
+        struct IconDirEntry * const dirEntryP = &dirP->entries[imageNum];
+        
+        pm_message("image %2u: %3u x %3u x %2u",
+                   imageNum,
+                   dirEntryP->width,
+                   dirEntryP->height,
+                   dirEntryP->bits_per_pixel);
+
+        dirEntryP->offset = imageOffset;
+
+        writeIconDirEntry(dirEntryP, ofP);
+
+        imageOffset += dirEntryP->size;
+    }
+}
+
+
+
+static void
+copyFile(FILE * const ifP,
+         FILE * const ofP) {
+
+    bool eof;
+    
+    for (eof = false; !eof; ) {
+        unsigned char buffer[1024];
+        size_t bytesRead;
+
+        bytesRead = fread(buffer, 1, sizeof(buffer), ifP);
+
+        if (bytesRead == 0)
+            eof = true;
+        else {
+            size_t bytesWritten;
+
+            bytesWritten = fwrite(buffer, 1, bytesRead, ofP);
+
+            if (bytesWritten < bytesRead)
+                pm_error("Error writing to output file.");
+        }
+    }
+}
+
+
+
+static void
+writeIconFile(const struct IconDir * const dirP,
+              FILE *                 const imagesFileP,
+              FILE *                 const ofP) {
+/*----------------------------------------------------------------------------
+  Write a windows icon file.
+
+  *dirP is the icon directory to put in it.
+
+  *imagesFileP contains all the text of the icon images.  The contents of
+  this file go verbatim into the output.
+-----------------------------------------------------------------------------*/
+    writeIconDirectory(dirP, ofP);
+
+    copyFile(imagesFileP, ofP);
+}
+
+
+
+int
+main(int argc, const char *argv []) {
+
+    struct CmdlineInfo cmdline;
+    FILE * ifP;
+    FILE * imagesFileP;
+        /* This is the file in which we collect the individual icon
+           images to be copied later to the output.
+        */
+    struct IconDir * dirP;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    verbose = cmdline.verbose;
+
+    /* The output icon file has directory information at the top that we
+       can't know until we have looked at the input images.  So as we pass
+       through the input, we collect the directory information and generate
+       the individual icon images and store them in *imageFileP.  When we've
+       been through all of the input, we write out the directory and then
+       copy the images from *imageFileP to the output.
+    */
+
+    dirP = newIconDir();
+
+    imagesFileP = pm_tmpfile();
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    convert(ifP, SQR(cmdline.pngthreshold), cmdline.truetransparent,
+            dirP, imagesFileP);
+
+    rewind(imagesFileP);
+
+    writeIconFile(dirP, imagesFileP, stdout);
+
+    freeIconDir(dirP);
+
+    return 0;
+}
+
+
+
diff --git a/converter/other/pamtoxvmini.c b/converter/other/pamtoxvmini.c
index e1aa9b52..b57bcc74 100644
--- a/converter/other/pamtoxvmini.c
+++ b/converter/other/pamtoxvmini.c
@@ -152,14 +152,14 @@ getPaletteIndexThroughCache(struct pam *      const pamP,
    If the tuple-index association is in *paletteIndexP, use it.  If not,
    find it the hard way and add it to *palettedIndexP for the next guy.
 -----------------------------------------------------------------------------*/
-    bool found;
+    int found;
     int paletteIndex;
 
     pnm_lookuptuple(pamP, paletteHash, tuple, &found, &paletteIndex);
     if (found)
         *paletteIndexP = paletteIndex;
     else {
-        bool fits;
+        int fits;
         findClosestColor(pamP, tuple, xvPaletteP, paletteIndexP);
         
         pnm_addtotuplehash(pamP, paletteHash, tuple, *paletteIndexP, &fits);
diff --git a/converter/other/pnmtopclxl.c b/converter/other/pnmtopclxl.c
index 83fdf7bf..4cd7c4d0 100644
--- a/converter/other/pnmtopclxl.c
+++ b/converter/other/pnmtopclxl.c
@@ -1177,7 +1177,7 @@ printPages(int                 const outFd,
     while (sourceP) {
         FILE * ifP;
         struct pam pam;
-        bool eof;
+        int eof;
         unsigned int pageNum;
 
         ifP = pm_openr(sourceP->name);
diff --git a/converter/other/pnmtopng.c b/converter/other/pnmtopng.c
index edbe57f5..bcb94612 100644
--- a/converter/other/pnmtopng.c
+++ b/converter/other/pnmtopng.c
@@ -128,7 +128,6 @@ struct cmdlineInfo {
     int           filterSet;
     unsigned int  force;
     unsigned int  libversion;
-    unsigned int  compressionSpec;
     struct zlibCompression zlibCompression;
 };
 
@@ -480,6 +479,27 @@ parseCommandLine(int argc, const char ** argv,
 
 
 
+static void
+reportInputType(int    const format,
+                xelval const maxval) {
+
+    switch (PNM_FORMAT_TYPE(format)) {
+    case PBM_TYPE:
+        pm_message ("reading a PBM file");
+        break;
+    case PGM_TYPE:
+        pm_message ("reading a PGM file (maxval=%d)", maxval);
+        break;
+    case PPM_TYPE:
+        pm_message ("reading a PPM file (maxval=%d)", maxval);
+        break;
+    default:
+        assert(false);
+    }
+}
+
+
+
 static png_color_16
 xelToPngColor_16(xel    const input, 
                  xelval const maxval, 
@@ -857,7 +877,7 @@ tryTransparentColor(FILE *     const ifp,
                     pixel      const transcolor,
                     bool *     const singleColorIsTransP) {
 
-    int const pnm_type = PNM_FORMAT_TYPE(format);
+    int const pnmType = PNM_FORMAT_TYPE(format);
 
     xel * xelrow;
     bool singleColorIsTrans;
@@ -878,7 +898,7 @@ tryTransparentColor(FILE *     const ifp,
                 /* If we have a second transparent color, we're
                    disqualified
                 */
-                if (pnm_type == PPM_TYPE) {
+                if (pnmType == PPM_TYPE) {
                     if (!PPM_EQUAL(xelrow[col], transcolor))
                         singleColorIsTrans = FALSE;
                 } else {
@@ -895,7 +915,7 @@ tryTransparentColor(FILE *     const ifp,
                    the same color as our candidate transparent color,
                    that disqualifies us.
                 */
-                if (pnm_type == PPM_TYPE) {
+                if (pnmType == PPM_TYPE) {
                     if (PPM_EQUAL(xelrow[col], transcolor))
                         singleColorIsTrans = FALSE;
                 } else {
@@ -1118,6 +1138,51 @@ determineBackground(struct cmdlineInfo const cmdline,
 
 
 
+static bool
+hasColor(FILE *       const ifP,
+         unsigned int const cols,
+         unsigned int const rows,
+         xelval       const maxval,
+         int          const format,
+         pm_filepos   const rasterPos) {
+/*----------------------------------------------------------------------------
+   The image contains colors other than black, white, and gray.
+-----------------------------------------------------------------------------*/
+    bool retval;
+
+    if (PNM_FORMAT_TYPE(format) == PPM_TYPE) {
+        unsigned int row;
+        xel * xelrow;    /* malloc'ed */
+            /* The row of the input image currently being analyzed */
+        bool isGray;
+
+        xelrow = pnm_allocrow(cols);
+
+        pm_seek2(ifP, &rasterPos, sizeof(rasterPos));
+
+        for (row = 0, isGray = true; row < rows && isGray; ++row) {
+            unsigned int col;
+
+            pnm_readpnmrow(ifP, xelrow, cols, maxval, format);
+
+            for (col = 0; col < cols && isGray; ++col) {
+                    xel const p = xelrow[col];
+                if (PPM_GETR(p) != PPM_GETG(p) || PPM_GETG(p) != PPM_GETB(p))
+                    isGray = FALSE;
+            }
+        }
+
+        pnm_freerow(xelrow);
+
+        retval = !isGray;
+    } else
+        retval = false;
+
+    return retval;
+}
+
+
+
 static void
 findRedundantBits(FILE *         const ifp, 
                   int            const rasterPos, 
@@ -1819,19 +1884,19 @@ tryAlphaPalette(FILE *         const ifP,
 
 
 static void
-computePixelWidth(int            const pnm_type,
-                  unsigned int   const pnm_meaningful_bits,
+computePixelWidth(bool           const colorPng,
+                  unsigned int   const pnmMeaningfulBitCt,
                   bool           const alpha,
                   unsigned int * const bitsPerSampleP,
                   unsigned int * const bitsPerPixelP) {
 
     unsigned int bitsPerSample, bitsPerPixel;
 
-    if (pnm_type == PPM_TYPE || alpha) {
+    if (colorPng || alpha) {
         /* PNG allows only depths of 8 and 16 for a truecolor image 
            and for a grayscale image with an alpha channel.
           */
-        if (pnm_meaningful_bits > 8)
+        if (pnmMeaningfulBitCt > 8)
             bitsPerSample = 16;
         else 
             bitsPerSample = 8;
@@ -1839,24 +1904,24 @@ computePixelWidth(int            const pnm_type,
         /* A grayscale, non-colormapped, no-alpha PNG may have any 
              bit depth from 1 to 16
           */
-        if (pnm_meaningful_bits > 8)
+        if (pnmMeaningfulBitCt > 8)
             bitsPerSample = 16;
-        else if (pnm_meaningful_bits > 4)
+        else if (pnmMeaningfulBitCt > 4)
             bitsPerSample = 8;
-        else if (pnm_meaningful_bits > 2)
+        else if (pnmMeaningfulBitCt > 2)
             bitsPerSample = 4;
-        else if (pnm_meaningful_bits > 1)
+        else if (pnmMeaningfulBitCt > 1)
             bitsPerSample = 2;
         else
             bitsPerSample = 1;
     }
     if (alpha) {
-        if (pnm_type == PPM_TYPE)
+        if (colorPng)
             bitsPerPixel = 4 * bitsPerSample;
         else
             bitsPerPixel = 2 * bitsPerSample;
     } else {
-        if (pnm_type == PPM_TYPE)
+        if (colorPng)
             bitsPerPixel = 3 * bitsPerSample;
         else
             bitsPerPixel = bitsPerSample;
@@ -1904,7 +1969,7 @@ computeColorMap(FILE *         const ifP,
                 int            const cols,
                 int            const rows,
                 xelval         const maxval,
-                int            const pnmType,
+                bool           const colorPng,
                 int            const format,
                 bool           const force,
                 FILE *         const pfP,
@@ -1947,6 +2012,8 @@ computeColorMap(FILE *         const ifP,
 
   If the image is to have a background color, we return the palette index
   of that color as *backgroundIndexP.
+
+  'colorPng' means the PNG will be of the RGB variety.
 -------------------------------------------------------------------------- */
     if (force)
         pm_asprintf(noColormapReasonP, "You requested no color map");
@@ -1956,7 +2023,7 @@ computeColorMap(FILE *         const ifP,
                     maxval, PALETTEMAXVAL);
     else {
         unsigned int bitsPerPixel;
-        computePixelWidth(pnmType, pnm_meaningful_bits, alpha,
+        computePixelWidth(colorPng, pnm_meaningful_bits, alpha,
                           NULL, &bitsPerPixel);
 
         if (!pfP && bitsPerPixel == 1)
@@ -2069,9 +2136,9 @@ static void computeColorMapLookupTable(
 
 static void
 computeRasterWidth(bool           const colorMapped,
-                   unsigned int   const palette_size,
-                   int            const pnm_type,
-                   unsigned int   const pnm_meaningful_bits,
+                   unsigned int   const paletteSize,
+                   bool           const colorPng,
+                   unsigned int   const pnmMeaningfulBitCt,
                    bool           const alpha,
                    unsigned int * const bitsPerSampleP,
                    unsigned int * const bitsPerPixelP) {
@@ -2082,24 +2149,24 @@ computeRasterWidth(bool           const colorMapped,
 -----------------------------------------------------------------------------*/
     if (colorMapped) {
         /* The raster element is a palette index */
-        if (palette_size <= 2)
+        if (paletteSize <= 2)
             *bitsPerSampleP = 1;
-        else if (palette_size <= 4)
+        else if (paletteSize <= 4)
             *bitsPerSampleP = 2;
-        else if (palette_size <= 16)
+        else if (paletteSize <= 16)
             *bitsPerSampleP = 4;
         else
             *bitsPerSampleP = 8;
         *bitsPerPixelP = *bitsPerSampleP;
         if (verbose)
-            pm_message("Writing %d-bit color indexes", *bitsPerSampleP);
+            pm_message("Writing %u-bit color indexes", *bitsPerSampleP);
     } else {
         /* The raster element is an explicit pixel -- color and transparency */
-        computePixelWidth(pnm_type, pnm_meaningful_bits, alpha,
+        computePixelWidth(colorPng, pnmMeaningfulBitCt, alpha,
                           bitsPerSampleP, bitsPerPixelP);
 
         if (verbose)
-            pm_message("Writing %d bits per component per pixel", 
+            pm_message("Writing %u bits per component per pixel", 
                        *bitsPerSampleP);
     }
 }
@@ -2339,14 +2406,14 @@ doIhdrChunk(struct pngx * const pngxP,
             unsigned int  const height,
             unsigned int  const depth,
             bool          const colorMapped,
-            int           const pnmType,
+            bool          const colorPng,
             bool          const alpha) {
 
     int colorType;
 
     if (colorMapped)
         colorType = PNG_COLOR_TYPE_PALETTE;
-    else if (pnmType == PPM_TYPE)
+    else if (colorPng)
         colorType = PNG_COLOR_TYPE_RGB;
     else
         colorType = PNG_COLOR_TYPE_GRAY;
@@ -2552,252 +2619,235 @@ convertpnm(struct cmdlineInfo const cmdline,
    lazy -- it takes a great deal of work to carry all that information as
    separate arguments -- and it's only a very small violation.
 -----------------------------------------------------------------------------*/
-  xel p;
-  int rows, cols, format;
-  xelval maxval;
-      /* The maxval of the input image */
-  xelval png_maxval;
-      /* The maxval of the samples in the PNG output 
-         (must be 1, 3, 7, 15, 255, or 65535)
-      */
-  pixel transcolor;
-      /* The color that is to be transparent, with maxval equal to that
-         of the input image.
-      */
-  int transexact;  
-      /* boolean: the user wants only the exact color he specified to be
-         transparent; not just something close to it.
-      */
-  int transparent;
-  bool alpha;
-      /* There will be an alpha mask */
-  unsigned int pnm_meaningful_bits;
-  pixel backcolor;
-      /* The background color, with maxval equal to that of the input
-         image.
-      */
-  jmp_buf jmpbuf;
-  struct pngx * pngxP;
-
-  bool colorMapped;
-  pixel palettePnm[MAXCOLORS];
-  png_color palette[MAXCOLORS];
-      /* The color part of the color/alpha palette passed to the PNG
-         compressor 
-      */
-  unsigned int paletteSize;
-
-  gray transPnm[MAXCOLORS];
-  png_byte  trans[MAXCOLORS];
-      /* The alpha part of the color/alpha palette passed to the PNG
-         compressor 
-      */
-  unsigned int transSize;
-
-  colorhash_table cht;
-  coloralphahash_table caht;
-
-  unsigned int background_index;
-      /* Index into palette[] of the background color. */
-
-  gray alphaMaxval;
-  const char * noColormapReason;
-      /* The reason that we shouldn't make a colormapped PNG, or NULL if
-         we should.  malloc'ed null-terminated string.
-      */
-  unsigned int depth;
-      /* The number of bits per sample in the (uncompressed) png 
-         raster -- if the raster contains palette indices, this is the
-         number of bits in the index.
-      */
-  unsigned int fulldepth;
-      /* The total number of bits per pixel in the (uncompressed) png
-         raster, including all channels.
-      */
-  pm_filepos rasterPos;  
-      /* file position in input image file of start of image (i.e. after
-         the header)
-      */
-  xel *xelrow;    /* malloc'ed */
-      /* The row of the input image currently being processed */
-
-  int pnmType;
-  gray ** alpha_mask;
-
-  /* We initialize these guys to quiet compiler warnings: */
-  depth = 0;
-
-  errorlevel = 0;
-
-  if (setjmp(jmpbuf))
-      pm_error ("setjmp returns error condition");
-
-  pngx_create(&pngxP, PNGX_WRITE, &jmpbuf);
-
-  pnm_readpnminit(ifP, &cols, &rows, &maxval, &format);
-  pm_tell2(ifP, &rasterPos, sizeof(rasterPos));
-  pnmType = PNM_FORMAT_TYPE(format);
-
-  xelrow = pnm_allocrow(cols);
-
-  if (verbose) {
-      if (pnmType == PBM_TYPE)    
-          pm_message ("reading a PBM file");
-      else if (pnmType == PGM_TYPE)    
-          pm_message ("reading a PGM file (maxval=%d)", maxval);
-      else if (pnmType == PPM_TYPE)    
-          pm_message ("reading a PPM file (maxval=%d)", maxval);
-  }
-
-  determineTransparency(cmdline, ifP, rasterPos, cols, rows, maxval, format,
-                        afP,
-                        &alpha, &transparent, &transcolor, &transexact,
-                        &alpha_mask, &alphaMaxval);
-
-  determineBackground(cmdline, maxval, &backcolor);
-
-  /* first of all, check if we have a grayscale image written as PPM */
-
-  if (pnmType == PPM_TYPE && !cmdline.force) {
-      unsigned int row;
-      bool isgray;
-
-      isgray = TRUE;  /* initial assumption */
-      pm_seek2(ifP, &rasterPos, sizeof(rasterPos));
-      for (row = 0; row < rows && isgray; ++row) {
-          unsigned int col;
-          pnm_readpnmrow(ifP, xelrow, cols, maxval, format);
-          for (col = 0; col < cols && isgray; ++col) {
-              p = xelrow[col];
-              if (PPM_GETR(p) != PPM_GETG(p) || PPM_GETG(p) != PPM_GETB(p))
-                  isgray = FALSE;
-          }
-      }
-      if (isgray)
-          pnmType = PGM_TYPE;
-  }
-
-  /* handle `odd' maxvalues */
-
-  if (maxval > 65535 && !cmdline.downscale) {
-      pm_error("can only handle files up to 16-bit "
-               "(use -downscale to override");
-  }
-
-  findRedundantBits(ifP, rasterPos, cols, rows, maxval, format, alpha,
-                    cmdline.force, &pnm_meaningful_bits);
+    int rows, cols, format;
+    xelval maxval;
+    /* The maxval of the input image */
+    xelval pngMaxval;
+        /* The maxval of the samples in the PNG output 
+           (must be 1, 3, 7, 15, 255, or 65535)
+        */
+    pixel transcolor;
+        /* The color that is to be transparent, with maxval equal to that
+           of the input image.
+        */
+    bool transExact;  
+        /* boolean: the user wants only the exact color he specified to be
+           transparent; not just something close to it.
+        */
+    int transparent;
+    bool alpha;
+        /* There will be an alpha mask */
+    unsigned int pnmMeaningfulBitCt;
+    pixel backColor;
+        /* The background color, with maxval equal to that of the input
+           image.
+        */
+    jmp_buf jmpbuf;
+    struct pngx * pngxP;
+
+    bool colorMapped;
+    pixel palettePnm[MAXCOLORS];
+    png_color palette[MAXCOLORS];
+        /* The color part of the color/alpha palette passed to the PNG
+           compressor 
+        */
+    unsigned int paletteSize;
+
+    gray transPnm[MAXCOLORS];
+    png_byte  trans[MAXCOLORS];
+        /* The alpha part of the color/alpha palette passed to the PNG
+           compressor 
+        */
+    unsigned int transSize;
+
+    colorhash_table cht;
+    coloralphahash_table caht;
+
+    unsigned int backgroundIndex;
+        /* Index into palette[] of the background color. */
+
+    gray alphaMaxval;
+    const char * noColormapReason;
+        /* The reason that we shouldn't make a colormapped PNG, or NULL if
+           we should.  malloc'ed null-terminated string.
+        */
+    unsigned int depth;
+        /* The number of bits per sample in the (uncompressed) png 
+           raster -- if the raster contains palette indices, this is the
+           number of bits in the index.
+        */
+    unsigned int fulldepth;
+        /* The total number of bits per pixel in the (uncompressed) png
+           raster, including all channels.
+        */
+    pm_filepos rasterPos;  
+        /* file position in input image file of start of image (i.e. after
+           the header)
+        */
+    xel * xelrow;    /* malloc'ed */
+        /* The row of the input image currently being processed */
+
+    gray ** alpha_mask;
+
+    bool colorPng;
+        /* The PNG shall be of the color (RGB) variety */
+
+    /* We initialize these guys to quiet compiler warnings: */
+    depth = 0;
+
+    errorlevel = 0;
+
+    if (setjmp(jmpbuf))
+        pm_error ("setjmp returns error condition");
+
+    pngx_create(&pngxP, PNGX_WRITE, &jmpbuf);
+
+    pnm_readpnminit(ifP, &cols, &rows, &maxval, &format);
+    pm_tell2(ifP, &rasterPos, sizeof(rasterPos));
+
+    xelrow = pnm_allocrow(cols);
+
+    if (verbose)
+        reportInputType(format, maxval);
+
+    determineTransparency(cmdline, ifP, rasterPos, cols, rows, maxval, format,
+                          afP,
+                          &alpha, &transparent, &transcolor, &transExact,
+                          &alpha_mask, &alphaMaxval);
+
+    determineBackground(cmdline, maxval, &backColor);
+
+    if (cmdline.force)
+        colorPng = (PNM_FORMAT_TYPE(format) == PPM_TYPE);
+    else {
+        if (PNM_FORMAT_TYPE(format) == PPM_TYPE) {
+            colorPng = hasColor(ifP, cols, rows, maxval, format, rasterPos); 
+        } else
+            colorPng = false;
+    }
+
+
+    /* handle `odd' maxvalues */
+
+    if (maxval > 65535 && !cmdline.downscale) {
+        pm_error("can only handle files up to 16-bit "
+                 "(use -downscale to override");
+    }
+
+    findRedundantBits(ifP, rasterPos, cols, rows, maxval, format, alpha,
+                      cmdline.force, &pnmMeaningfulBitCt);
   
-  computeColorMap(ifP, rasterPos, cols, rows, maxval, pnmType, format,
-                  cmdline.force, pfP,
-                  alpha, transparent >= 0, transcolor, transexact, 
-                  !!cmdline.background, backcolor,
-                  alpha_mask, alphaMaxval, pnm_meaningful_bits,
-                  palettePnm, &paletteSize, transPnm, &transSize,
-                  &background_index, &noColormapReason);
-
-  if (noColormapReason) {
-      if (pfP)
-          pm_error("You specified a particular palette, but this image "
-                   "cannot be represented by any palette.  %s",
-                   noColormapReason);
-      if (verbose)
-          pm_message("Not using color map.  %s", noColormapReason);
-      pm_strfree(noColormapReason);
-      colorMapped = FALSE;
-  } else
-      colorMapped = TRUE;
+    computeColorMap(ifP, rasterPos, cols, rows, maxval, colorPng, format,
+                    cmdline.force, pfP,
+                    alpha, transparent >= 0, transcolor, transExact, 
+                    !!cmdline.background, backColor,
+                    alpha_mask, alphaMaxval, pnmMeaningfulBitCt,
+                    palettePnm, &paletteSize, transPnm, &transSize,
+                    &backgroundIndex, &noColormapReason);
+
+    if (noColormapReason) {
+        if (pfP)
+            pm_error("You specified a particular palette, but this image "
+                     "cannot be represented by any palette.  %s",
+                     noColormapReason);
+        if (verbose)
+            pm_message("Not using color map.  %s", noColormapReason);
+        pm_strfree(noColormapReason);
+        colorMapped = FALSE;
+    } else
+        colorMapped = TRUE;
   
-  computeColorMapLookupTable(colorMapped, palettePnm, paletteSize,
-                             transPnm, transSize, alpha, alphaMaxval,
-                             &cht, &caht);
+    computeColorMapLookupTable(colorMapped, palettePnm, paletteSize,
+                               transPnm, transSize, alpha, alphaMaxval,
+                               &cht, &caht);
 
-  computeRasterWidth(colorMapped, paletteSize, pnmType, 
-                     pnm_meaningful_bits, alpha,
-                     &depth, &fulldepth);
-  if (verbose)
-    pm_message ("writing a%s %d-bit %s%s file%s",
-                fulldepth == 8 ? "n" : "", fulldepth,
-                colorMapped ? "palette": 
-                (pnmType == PPM_TYPE ? "RGB" : "gray"),
-                alpha ? (colorMapped ? "+transparency" : "+alpha") : "",
-                cmdline.interlace ? " (interlaced)" : "");
+    computeRasterWidth(colorMapped, paletteSize, colorPng,
+                       pnmMeaningfulBitCt, alpha,
+                       &depth, &fulldepth);
+    if (verbose)
+        pm_message ("writing a%s %d-bit %s%s file%s",
+                    fulldepth == 8 ? "n" : "", fulldepth,
+                    colorMapped ? "palette": 
+                    colorPng ? "RGB" : "gray",
+                    alpha ? (colorMapped ? "+transparency" : "+alpha") : "",
+                    cmdline.interlace ? " (interlaced)" : "");
 
-  /* now write the file */
+    /* now write the file */
 
-  png_maxval = pm_bitstomaxval(depth);
+    pngMaxval = pm_bitstomaxval(depth);
 
-  if (setjmp (pnmtopng_jmpbuf_struct.jmpbuf)) {
-    pm_error ("setjmp returns error condition (2)");
-  }
+    if (setjmp (pnmtopng_jmpbuf_struct.jmpbuf)) {
+        pm_error ("setjmp returns error condition (2)");
+    }
 
-  doIhdrChunk(pngxP, cols, rows, depth, colorMapped, pnmType, alpha);
+    doIhdrChunk(pngxP, cols, rows, depth, colorMapped, colorPng, alpha);
 
-  if (cmdline.interlace)
-      pngx_setInterlaceHandling(pngxP);
+    if (cmdline.interlace)
+        pngx_setInterlaceHandling(pngxP);
 
-  doGamaChunk(cmdline, pngxP);
+    doGamaChunk(cmdline, pngxP);
 
-  doChrmChunk(cmdline, pngxP);
+    doChrmChunk(cmdline, pngxP);
 
-  doPhysChunk(cmdline, pngxP);
+    doPhysChunk(cmdline, pngxP);
 
-  if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_PALETTE) {
+    if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_PALETTE) {
 
-      /* creating PNG palette (Not counting the transparency palette) */
+        /* creating PNG palette (Not counting the transparency palette) */
 
-      createPngPalette(palettePnm, paletteSize, maxval,
-                       transPnm, transSize, alphaMaxval, 
-                       palette, trans);
-      pngx_setPlte(pngxP, palette, paletteSize);
+        createPngPalette(palettePnm, paletteSize, maxval,
+                         transPnm, transSize, alphaMaxval, 
+                         palette, trans);
+        pngx_setPlte(pngxP, palette, paletteSize);
 
-      doHistChunk(pngxP, cmdline.hist, palettePnm, ifP, rasterPos,
-                  cols, rows, maxval, format, cmdline.verbose);
-  }
+        doHistChunk(pngxP, cmdline.hist, palettePnm, ifP, rasterPos,
+                    cols, rows, maxval, format, cmdline.verbose);
+    }
 
-  doTrnsChunk(pngxP, trans, transSize,
-              transparent, transcolor, maxval, png_maxval);
+    doTrnsChunk(pngxP, trans, transSize,
+                transparent, transcolor, maxval, pngMaxval);
 
-  doBkgdChunk(pngxP, !!cmdline.background,
-              background_index, backcolor,
-              maxval, png_maxval, cmdline.verbose);
+    doBkgdChunk(pngxP, !!cmdline.background,
+                backgroundIndex, backColor,
+                maxval, pngMaxval, cmdline.verbose);
 
-  doSbitChunk(pngxP, png_maxval, maxval, alpha, alphaMaxval);
+    doSbitChunk(pngxP, pngMaxval, maxval, alpha, alphaMaxval);
 
-  /* tEXT and zTXT chunks */
-  if (cmdline.text || cmdline.ztxt)
-      pngtxt_read(pngxP, tfP, !!cmdline.ztxt, cmdline.verbose);
+    /* tEXT and zTXT chunks */
+    if (cmdline.text || cmdline.ztxt)
+        pngtxt_read(pngxP, tfP, !!cmdline.ztxt, cmdline.verbose);
 
-  doTimeChunk(cmdline, pngxP);
+    doTimeChunk(cmdline, pngxP);
 
-  if (cmdline.filterSet != 0)
-      pngx_setFilter(pngxP, cmdline.filterSet);
+    if (cmdline.filterSet != 0)
+        pngx_setFilter(pngxP, cmdline.filterSet);
 
-  setZlibCompression(pngxP, cmdline.zlibCompression);
+    setZlibCompression(pngxP, cmdline.zlibCompression);
 
-  png_init_io(pngxP->png_ptr, ofP);
+    png_init_io(pngxP->png_ptr, ofP);
 
-  /* write the png-info struct */
-  pngx_writeInfo(pngxP);
+    /* write the png-info struct */
+    pngx_writeInfo(pngxP);
 
-  /* let libpng take care of, e.g., bit-depth conversions */
-  pngx_setPacking(pngxP);
+    /* let libpng take care of, e.g., bit-depth conversions */
+    pngx_setPacking(pngxP);
 
-  writeRaster(pngxP, ifP, rasterPos,
-              cols, rows, maxval, format,
-              png_maxval, depth, alpha, alpha_mask, cht, caht);
+    writeRaster(pngxP, ifP, rasterPos,
+                cols, rows, maxval, format,
+                pngMaxval, depth, alpha, alpha_mask, cht, caht);
 
-  pngx_writeEnd(pngxP);
+    pngx_writeEnd(pngxP);
 
-  pngx_destroy(pngxP);
+    pngx_destroy(pngxP);
 
-  pnm_freerow(xelrow);
+    pnm_freerow(xelrow);
 
-  if (cht)
-      ppm_freecolorhash(cht);
-  if (caht)
-      freecoloralphahash(caht);
+    if (cht)
+        ppm_freecolorhash(cht);
+    if (caht)
+        freecoloralphahash(caht);
 
-  *errorLevelP = errorlevel;
+    *errorLevelP = errorlevel;
 }
 
 
diff --git a/converter/other/pnmtops.c b/converter/other/pnmtops.c
index dc55a7e3..1cf23be7 100644
--- a/converter/other/pnmtops.c
+++ b/converter/other/pnmtops.c
@@ -335,6 +335,22 @@ basebasename(const char * const filespec) {
 
 
 
+static void
+writeFile(const unsigned char * const buffer,
+          size_t                const writeCt,
+          const char *          const name,
+          FILE *                const ofP) {
+
+    size_t writtenCt;
+
+    writtenCt = fwrite(buffer, 1, writeCt, ofP);
+
+    if (writtenCt != writeCt)
+        pm_error("Error writing to %s output file", name);
+}
+
+
+
 #define MAX_FILTER_CT 10
     /* The maximum number of filters this code is capable of applying */
 
@@ -494,18 +510,12 @@ flateFilter(FILE *          const ifP,
         */
         do {
             unsigned int have;
-            size_t bytesWritten;
 
             strm.avail_out = chunkSz;
             strm.next_out = out;
             deflate(&strm, flush);
             have = chunkSz - strm.avail_out;
-            bytesWritten = fwrite(out, 1, have, ofP);
-            if (ferror(ofP) || bytesWritten != have) {
-                deflateEnd(&strm);
-                pm_error("Error writing to internal pipe during "
-                         "flate compression.");
-            }
+            writeFile(out, have, "flate filter", ofP);
         } while (strm.avail_out == 0);
         assert(strm.avail_in == 0);     /* all input is used */
 
@@ -548,10 +558,8 @@ rlePutBuffer (unsigned int    const repeat,
     if (repeat) {
         fputc(257 - count,  fP);
         fputc(repeatitem, fP);
-    } else {
-        fputc(count - 1, fP);
-        fwrite(itembuf, 1, count, fP);
-    }
+    } else
+        writeFile(itembuf, count, "rlePutBuffer", fP);
 }
 
 
@@ -673,23 +681,24 @@ asciiHexFilter(FILE *          const ifP,
     unsigned char inbuff[40], outbuff[81];
 
     for (eof = false; !eof; ) {
-        size_t bytesRead;
+        size_t readCt;
 
-        bytesRead = fread(inbuff, 1, 40, ifP);
+        readCt = fread(inbuff, 1, 40, ifP);
 
-        if (bytesRead == 0)
+        if (readCt == 0)
             eof = true;
         else {
             unsigned int i;
 
-            for (i = 0; i < bytesRead; ++i) {
+            for (i = 0; i < readCt; ++i) {
                 int const item = inbuff[i]; 
                 outbuff[i*2]   = hexits[item >> 4];
                 outbuff[i*2+1] = hexits[item & 15];
             }
         }
-        outbuff[bytesRead * 2] = '\n';
-        fwrite(outbuff, 1, bytesRead*2 + 1, ofP);
+        outbuff[readCt * 2] = '\n';
+
+        writeFile(outbuff, readCt * 2 + 1, "asciiHex filter", ofP);
     }
 
     fclose(ifP);
@@ -737,7 +746,9 @@ ascii85Filter(FILE *          const ifP,
                 outbuff[1] = value % 85 + 33;
                 outbuff[0] = value / 85 + 33;
 
-                fwrite(outbuff, 1, count + 1, ofP);
+                writeFile((const unsigned char *)outbuff, count + 1,
+                          "ASCII 85 filter", ofP);
+
                 count = value = 0;
                 outcount += 5; 
             }
@@ -759,7 +770,8 @@ ascii85Filter(FILE *          const ifP,
         outbuff[0] = value / 85 + 33;
         outbuff[count + 1] = '\n';
 
-        fwrite(outbuff, 1, count + 2, ofP);
+        writeFile((const unsigned char *)outbuff, count + 2,
+                  "ASCII 85 filter", ofP);
     }
 
     fclose(ifP);
@@ -869,13 +881,22 @@ addFilter(const char *    const description,
           OutputEncoder * const oeP,
           FILE **         const feedFilePP,
           pid_t *         const pidList) {
+/*----------------------------------------------------------------------------
+   Add a filter to the front of the chain.
 
-    pid_t pid;
+   Spawn a process to do the filtering, by running function 'filter'.
 
+   *feedFilePP is the present head of the chain.  We make the new filter
+   process write its output to that and get its input from a new pipe.
+   We update *feedFilePP to the sending end of the new pipe.
+
+   Add to the list pidList[] the PID of the process we spawn.
+-----------------------------------------------------------------------------*/
     FILE * const oldFeedFileP = *feedFilePP;
 
     FILE * newFeedFileP;
-        
+    pid_t pid;
+
     spawnFilter(oldFeedFileP, filter, oeP, &newFeedFileP, &pid);
             
     if (verbose)
@@ -883,7 +904,7 @@ addFilter(const char *    const description,
                    description, (unsigned)pid);
     
     fclose(oldFeedFileP);  /* Child keeps this open now */
-    
+
     addToPidList(pidList, pid);
 
     *feedFilePP = newFeedFileP;
@@ -1720,7 +1741,7 @@ convertRowPbm(struct pam *     const pamP,
         bitrow[colChars-1] <<= padRight;  /* right edge */
     }
 
-    fwrite(bitrow, 1, colChars, fP); 
+    writeFile(bitrow, colChars, "PBM reader", fP);
 }
 
 
@@ -1863,6 +1884,21 @@ convertRaster(struct pam * const inpamP,
 
 
 
+/* FILE MANAGEMENT: File management is pretty hairy here.  A filter, which
+   runs in its own process, needs to be able to cause its output file to
+   close because it might be an internal pipe and the next stage needs to
+   know output is done.  So the forking process must close its copy of the
+   file descriptor.  BUT: if the output of the filter is not an internal
+   pipe but this program's output, then we don't want it closed when the
+   filter terminates because we'll need it to be open for the next image
+   the program converts (with a whole new chain of filters).
+   
+   To prevent the progam output file from getting closed, we pass a
+   duplicate of it to spawnFilters() and keep the original open.
+*/
+
+
+
 static void
 convertPage(FILE *       const ifP, 
             int          const turnflag, 
diff --git a/converter/other/pstopnm.c b/converter/other/pstopnm.c
index 1dd27140..3704841b 100644
--- a/converter/other/pstopnm.c
+++ b/converter/other/pstopnm.c
@@ -18,6 +18,7 @@
 #define _XOPEN_SOURCE 500  
     /* Make sure fdopen() is in stdio.h and strdup() is in string.h */
 
+#include <assert.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -32,8 +33,8 @@
 #include "shhopt.h"
 #include "nstring.h"
 
-enum orientation {PORTRAIT, LANDSCAPE, UNSPECIFIED};
-struct box {
+enum Orientation {PORTRAIT, LANDSCAPE, UNSPECIFIED};
+struct Box {
     /* Description of a rectangle within an image; all coordinates 
        measured in points (1/72") with lower left corner of page being the 
        origin.
@@ -45,15 +46,15 @@ struct box {
     int ury;  /* upper right Y coord */
 };
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
     const char * inputFileName;  /* Names of input files */
     unsigned int forceplain;
-    struct box extract_box;
+    struct Box extractBox;
     unsigned int nocrop;
-    unsigned int format_type;
+    unsigned int formatType;
     unsigned int verbose;
     float xborder;
     unsigned int xmax;
@@ -62,15 +63,15 @@ struct cmdlineInfo {
     unsigned int ymax;
     unsigned int ysize;  /* zero means unspecified */
     unsigned int dpi;    /* zero means unspecified */
-    enum orientation orientation;
-    unsigned int goto_stdout;
+    enum Orientation orientation;
+    unsigned int stdout;
     unsigned int textalphabits;
 };
 
 
 static void
 parseCommandLine(int argc, char ** argv,
-                 struct cmdlineInfo * const cmdlineP) {
+                 struct CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that the file spec array we return is stored in the storage that
    was passed to us as the argv array.
@@ -82,8 +83,8 @@ parseCommandLine(int argc, char ** argv,
 
     unsigned int option_def_index;
 
-    unsigned int pbm_opt, pgm_opt, ppm_opt;
-    unsigned int portrait_opt, landscape_opt;
+    unsigned int pbmOpt, pgmOpt, ppmOpt;
+    unsigned int portraitOpt, landscapeOpt;
     float llx, lly, urx, ury;
     unsigned int llxSpec, llySpec, urxSpec, urySpec;
     unsigned int xmaxSpec, ymaxSpec, xsizeSpec, ysizeSpec, dpiSpec;
@@ -98,9 +99,9 @@ parseCommandLine(int argc, char ** argv,
     OPTENT3(0, "urx",        OPT_FLOAT, &urx, &urxSpec,                  0);
     OPTENT3(0, "ury",        OPT_FLOAT, &ury, &urySpec,                  0);
     OPTENT3(0, "nocrop",     OPT_FLAG,  NULL, &cmdlineP->nocrop,         0);
-    OPTENT3(0, "pbm",        OPT_FLAG,  NULL, &pbm_opt,                  0);
-    OPTENT3(0, "pgm",        OPT_FLAG,  NULL, &pgm_opt,                  0);
-    OPTENT3(0, "ppm",        OPT_FLAG,  NULL, &ppm_opt,                  0);
+    OPTENT3(0, "pbm",        OPT_FLAG,  NULL, &pbmOpt ,                  0);
+    OPTENT3(0, "pgm",        OPT_FLAG,  NULL, &pgmOpt,                   0);
+    OPTENT3(0, "ppm",        OPT_FLAG,  NULL, &ppmOpt,                  0);
     OPTENT3(0, "verbose",    OPT_FLAG,  NULL, &cmdlineP->verbose,        0);
     OPTENT3(0, "xborder",    OPT_FLOAT, &cmdlineP->xborder, NULL,        0);
     OPTENT3(0, "xmax",       OPT_UINT,  &cmdlineP->xmax, &xmaxSpec,      0);
@@ -109,9 +110,9 @@ parseCommandLine(int argc, char ** argv,
     OPTENT3(0, "ymax",       OPT_UINT,  &cmdlineP->ymax, &ymaxSpec,      0);
     OPTENT3(0, "ysize",      OPT_UINT,  &cmdlineP->ysize, &ysizeSpec,    0);
     OPTENT3(0, "dpi",        OPT_UINT,  &cmdlineP->dpi, &dpiSpec,        0);
-    OPTENT3(0, "portrait",   OPT_FLAG,  NULL, &portrait_opt,             0);
-    OPTENT3(0, "landscape",  OPT_FLAG,  NULL, &landscape_opt,            0);
-    OPTENT3(0, "stdout",     OPT_FLAG,  NULL, &cmdlineP->goto_stdout,    0);
+    OPTENT3(0, "portrait",   OPT_FLAG,  NULL, &portraitOpt,             0);
+    OPTENT3(0, "landscape",  OPT_FLAG,  NULL, &landscapeOpt,            0);
+    OPTENT3(0, "stdout",     OPT_FLAG,  NULL, &cmdlineP->stdout,         0);
     OPTENT3(0, "textalphabits", OPT_UINT,
             &cmdlineP->textalphabits,  &textalphabitsSpec, 0);
 
@@ -149,38 +150,38 @@ parseCommandLine(int argc, char ** argv,
     } else 
         cmdlineP->ysize = 0;
 
-    if (portrait_opt && !landscape_opt)
+    if (portraitOpt && !landscapeOpt)
         cmdlineP->orientation = PORTRAIT;
-    else if (!portrait_opt && landscape_opt)
+    else if (!portraitOpt && landscapeOpt)
         cmdlineP->orientation = LANDSCAPE;
-    else if (!portrait_opt && !landscape_opt)
+    else if (!portraitOpt && !landscapeOpt)
         cmdlineP->orientation = UNSPECIFIED;
     else
         pm_error("Cannot specify both -portrait and -landscape options");
 
-    if (pbm_opt)
-        cmdlineP->format_type = PBM_TYPE;
-    else if (pgm_opt)
-        cmdlineP->format_type = PGM_TYPE;
-    else if (ppm_opt)
-        cmdlineP->format_type = PPM_TYPE;
+    if (pbmOpt)
+        cmdlineP->formatType = PBM_TYPE;
+    else if (pgmOpt)
+        cmdlineP->formatType = PGM_TYPE;
+    else if (ppmOpt)
+        cmdlineP->formatType = PPM_TYPE;
     else
-        cmdlineP->format_type = PPM_TYPE;
+        cmdlineP->formatType = PPM_TYPE;
 
     /* If any one of the 4 bounding box coordinates is given on the
        command line, we default any of the 4 that aren't.  
     */
     if (llxSpec || llySpec || urxSpec || urySpec) {
-        if (!llxSpec) cmdlineP->extract_box.llx = 72;
-        else cmdlineP->extract_box.llx = llx * 72;
-        if (!llySpec) cmdlineP->extract_box.lly = 72;
-        else cmdlineP->extract_box.lly = lly * 72;
-        if (!urxSpec) cmdlineP->extract_box.urx = 540;
-        else cmdlineP->extract_box.urx = urx * 72;
-        if (!urySpec) cmdlineP->extract_box.ury = 720;
-        else cmdlineP->extract_box.ury = ury * 72;
+        if (!llxSpec) cmdlineP->extractBox.llx = 72;
+        else cmdlineP->extractBox.llx = llx * 72;
+        if (!llySpec) cmdlineP->extractBox.lly = 72;
+        else cmdlineP->extractBox.lly = lly * 72;
+        if (!urxSpec) cmdlineP->extractBox.urx = 540;
+        else cmdlineP->extractBox.urx = urx * 72;
+        if (!urySpec) cmdlineP->extractBox.ury = 720;
+        else cmdlineP->extractBox.ury = ury * 72;
     } else {
-        cmdlineP->extract_box.llx = -1;
+        cmdlineP->extractBox.llx = -1;
     }
 
     if (dpiSpec) {
@@ -230,19 +231,19 @@ addPsToFileName(char          const origFileName[],
    *newFileNameP.
 -----------------------------------------------------------------------------*/
     struct stat statbuf;
-    int stat_rc;
+    int statRc;
 
-    stat_rc = lstat(origFileName, &statbuf);
+    statRc = lstat(origFileName, &statbuf);
     
-    if (stat_rc == 0)
+    if (statRc == 0)
         *newFileNameP = strdup(origFileName);
     else {
         const char * fileNamePlusPs;
 
         pm_asprintf(&fileNamePlusPs, "%s.ps", origFileName);
 
-        stat_rc = lstat(fileNamePlusPs, &statbuf);
-        if (stat_rc == 0)
+        statRc = lstat(fileNamePlusPs, &statbuf);
+        if (statRc == 0)
             *newFileNameP = strdup(fileNamePlusPs);
         else
             *newFileNameP = strdup(origFileName);
@@ -311,9 +312,9 @@ computeSizeResBlind(unsigned int   const xmax,
 
 
 static void
-computeSizeRes(struct cmdlineInfo const cmdline, 
-               enum orientation   const orientation, 
-               struct box         const bordered_box,
+computeSizeRes(struct CmdlineInfo const cmdline, 
+               enum Orientation   const orientation, 
+               struct Box         const borderedBox,
                unsigned int *     const xsizeP, 
                unsigned int *     const ysizeP,
                unsigned int *     const xresP, 
@@ -344,11 +345,11 @@ computeSizeRes(struct cmdlineInfo const cmdline,
         */
 
     if (orientation == LANDSCAPE) {
-        sx = bordered_box.ury - bordered_box.lly;
-        sy = bordered_box.urx - bordered_box.llx;
+        sx = borderedBox.ury - borderedBox.lly;
+        sy = borderedBox.urx - borderedBox.llx;
     } else {
-        sx = bordered_box.urx - bordered_box.llx;
-        sy = bordered_box.ury - bordered_box.lly;
+        sx = borderedBox.urx - borderedBox.llx;
+        sy = borderedBox.ury - borderedBox.lly;
     }
 
     if (cmdline.dpi) {
@@ -373,9 +374,9 @@ computeSizeRes(struct cmdlineInfo const cmdline,
 
 
 
-enum postscript_language {COMMON_POSTSCRIPT, ENCAPSULATED_POSTSCRIPT};
+enum PostscriptLanguage {COMMON_POSTSCRIPT, ENCAPSULATED_POSTSCRIPT};
 
-static enum postscript_language
+static enum PostscriptLanguage
 languageDeclaration(char const inputFileName[],
                     bool const verbose) {
 /*----------------------------------------------------------------------------
@@ -383,7 +384,7 @@ languageDeclaration(char const inputFileName[],
   (Except that if the file is on Standard Input or doesn't validly declare
   a languages, just say it is Common Postscript).
 -----------------------------------------------------------------------------*/
-    enum postscript_language language;
+    enum PostscriptLanguage language;
 
     if (streq(inputFileName, "-"))
         /* Can't read stdin, because we need it to remain positioned for the 
@@ -399,9 +400,9 @@ languageDeclaration(char const inputFileName[],
         if (fgets(line, sizeof(line), infile) == NULL)
             language = COMMON_POSTSCRIPT;
         else {
-            const char eps_header[] = " EPSF-";
+            const char epsHeader[] = " EPSF-";
 
-            if (strstr(line, eps_header))
+            if (strstr(line, epsHeader))
                 language = ENCAPSULATED_POSTSCRIPT;
             else
                 language = COMMON_POSTSCRIPT;
@@ -418,61 +419,64 @@ languageDeclaration(char const inputFileName[],
 
 
 
-static struct box
-computeBoxToExtract(struct box const cmdline_extract_box,
+static struct Box
+computeBoxToExtract(struct Box const cmdlineExtractBox,
                     char       const inputFileName[],
                     bool       const verbose) {
 
-    struct box retval;
+    struct Box retval;
 
-    if (cmdline_extract_box.llx != -1)
+    if (cmdlineExtractBox.llx != -1)
         /* User told us what box to extract, so that's what we'll do */
-        retval = cmdline_extract_box;
+        retval = cmdlineExtractBox;
     else {
         /* Try to get the bounding box from the DSC %%BoundingBox
            statement (A Postscript comment) in the input.
         */
-        struct box ps_bb;  /* Box described by %%BoundingBox stmt in input */
+        struct Box psBb;  /* Box described by %%BoundingBox stmt in input */
 
         if (streq(inputFileName, "-"))
             /* Can't read stdin, because we need it to remain
                positioned for the Ghostscript interpreter to read it.  
             */
-            ps_bb.llx = -1;
+            psBb.llx = -1;
         else {
-            FILE *infile;
-            int found_BB, eof;  /* logical */
-            infile = pm_openr(inputFileName);
+            FILE * ifP;
+            bool foundBb;
+            bool eof;
+
+            ifP = pm_openr(inputFileName);
             
-            found_BB = FALSE;
-            eof = FALSE;
-            while (!eof && !found_BB) {
+            for (foundBb = FALSE, eof = FALSE; !foundBb && !eof; ) {
                 char line[200];
-                
-                if (fgets(line, sizeof(line), infile) == NULL)
+                char * fgetsRc;
+
+                fgetsRc = fgets(line, sizeof(line), ifP);
+
+                if (fgetsRc == NULL)
                     eof = TRUE;
                 else {
                     int rc;
                     rc = sscanf(line, "%%%%BoundingBox: %d %d %d %d",
-                                &ps_bb.llx, &ps_bb.lly, 
-                                &ps_bb.urx, &ps_bb.ury);
+                                &psBb.llx, &psBb.lly, 
+                                &psBb.urx, &psBb.ury);
                     if (rc == 4) 
-                        found_BB = TRUE;
+                        foundBb = TRUE;
                 }
             }
-            fclose(infile);
+            fclose(ifP);
 
-            if (!found_BB) {
-                ps_bb.llx = -1;
+            if (!foundBb) {
+                psBb.llx = -1;
                 pm_message("Warning: no %%%%BoundingBox statement "
-                           "in the input or command line.\n"
+                           "in the input or command line.  "
                            "Will use defaults");
             }
         }
-        if (ps_bb.llx != -1) {
+        if (psBb.llx != -1) {
             if (verbose)
                 pm_message("Using %%%%BoundingBox statement from input.");
-            retval = ps_bb;
+            retval = psBb;
         } else { 
             /* Use the center of an 8.5" x 11" page with 1" border all around*/
             retval.llx = 72;
@@ -489,13 +493,14 @@ computeBoxToExtract(struct box const cmdline_extract_box,
 
 
 
-static enum orientation
-computeOrientation(struct cmdlineInfo const cmdline, 
-                   struct box         const extract_box) {
+static enum Orientation
+computeOrientation(struct CmdlineInfo const cmdline, 
+                   struct Box         const extractBox) {
 
-    enum orientation retval;
-    unsigned int const input_width  = extract_box.urx - extract_box.llx;
-    unsigned int const input_height = extract_box.ury - extract_box.lly;
+    unsigned int const inputWidth  = extractBox.urx - extractBox.llx;
+    unsigned int const inputHeight = extractBox.ury - extractBox.lly;
+
+    enum Orientation retval;
 
     if (cmdline.orientation != UNSPECIFIED)
         retval = cmdline.orientation;
@@ -506,24 +511,24 @@ computeOrientation(struct cmdlineInfo const cmdline,
                so we can't use output dimensions to make the decision.  So
                just use the input dimensions.
             */
-            if (input_height > input_width) retval = PORTRAIT;
+            if (inputHeight > inputWidth) retval = PORTRAIT;
             else retval = LANDSCAPE;
         } else {
-            int output_width, output_height;
+            unsigned int outputWidth, outputHeight;
             if (cmdline.xsize) {
                 /* He gave xsize and ysize, so that's the output size */
-                output_width = cmdline.xsize;
-                output_height = cmdline.ysize;
+                outputWidth  = cmdline.xsize;
+                outputHeight = cmdline.ysize;
             } else {
                 /* Well then we'll just use his (or default) xmax, ymax */
-                output_width = cmdline.xmax;
-                output_height = cmdline.ymax;
+                outputWidth  = cmdline.xmax;
+                outputHeight = cmdline.ymax;
             }
 
-            if (input_height > input_width && output_height > output_width)
+            if (inputHeight > inputWidth && outputHeight > outputWidth)
                 retval = PORTRAIT;
-            else if (input_height < input_width && 
-                     output_height < output_width)
+            else if (inputHeight < inputWidth && 
+                     outputHeight < outputWidth)
                 retval = PORTRAIT;
             else 
                 retval = LANDSCAPE;
@@ -534,32 +539,39 @@ computeOrientation(struct cmdlineInfo const cmdline,
 
 
 
-static struct box
-addBorders(struct box const input_box, 
-           float      const xborder_scale,
-           float      const yborder_scale,
+static struct Box
+addBorders(struct Box const inputBox, 
+           float      const xborderScale,
+           float      const yborderScale,
            bool       const verbose) {
 /*----------------------------------------------------------------------------
-   Return a box which is 'input_box' plus some borders.
+   Return a box which is 'inputBox' plus some borders.
 
-   Add left and right borders that are the fraction 'xborder_scale' of the
+   Add left and right borders that are the fraction 'xborderScale' of the
    width of the input box; likewise for top and bottom borders with 
-   'yborder_scale'.
+   'yborderScale'.
 -----------------------------------------------------------------------------*/
-    struct box retval;
+    unsigned int const leftRightBorderSize = 
+        ROUNDU((inputBox.urx - inputBox.llx) * xborderScale);
+    unsigned int const topBottomBorderSize = 
+        ROUNDU((inputBox.ury - inputBox.lly) * yborderScale);
+
+    struct Box retval;
+
 
-    const int left_right_border_size = 
-        (int) ((input_box.urx - input_box.llx) * xborder_scale + 0.5);
-    const int top_bottom_border_size = 
-        (int) ((input_box.ury - input_box.lly) * yborder_scale + 0.5);
+    assert(inputBox.urx >= inputBox.llx);
+    assert(inputBox.ury >= inputBox.lly);
 
-    retval.llx = input_box.llx - left_right_border_size;
-    retval.lly = input_box.lly - top_bottom_border_size;
-    retval.urx = input_box.urx + left_right_border_size;
-    retval.ury = input_box.ury + top_bottom_border_size;
+    assert(inputBox.llx >= leftRightBorderSize);
+    assert(inputBox.lly >= topBottomBorderSize);
+
+    retval.llx = inputBox.llx - leftRightBorderSize;
+    retval.lly = inputBox.lly - topBottomBorderSize;
+    retval.urx = inputBox.urx + leftRightBorderSize;
+    retval.ury = inputBox.ury + topBottomBorderSize;
 
     if (verbose)
-        pm_message("With borders, extracted box is ((%d,%d),(%d,%d))",
+        pm_message("With borders, extracted box is ((%u,%u),(%u,%u))",
                    retval.llx, retval.lly, retval.urx, retval.ury);
 
     return retval;
@@ -568,8 +580,8 @@ addBorders(struct box const input_box,
 
 
 static const char *
-computePstrans(struct box       const box,
-               enum orientation const orientation,
+computePstrans(struct Box       const box,
+               enum Orientation const orientation,
                int              const xsize,
                int              const ysize, 
                int              const xres,
@@ -598,11 +610,20 @@ computePstrans(struct box       const box,
 
 
 static const char *
-computeOutfileArg(struct cmdlineInfo const cmdline) {
-
+computeOutfileArg(struct CmdlineInfo const cmdline) {
+/*----------------------------------------------------------------------------
+   Determine the value for the "OutputFile" variable to pass to Ghostscript,
+   which is what tells Ghostscript where to put its output.  This is either
+   a pattern such as "foo%03d.ppm" or "-" to indicate Standard Output.
+
+   We go with "-" if, according to 'cmdline', the user asked for
+   Standard Output or is giving his input on Standard Input.  Otherwise,
+   we go with the pattern, based on the name of the input file and output
+   format type the user requested.
+-----------------------------------------------------------------------------*/
     const char * retval;  /* malloc'ed */
 
-    if (cmdline.goto_stdout)
+    if (cmdline.stdout)
         retval = strdup("-");
     else if (streq(cmdline.inputFileName, "-"))
         retval = strdup("-");
@@ -616,12 +637,12 @@ computeOutfileArg(struct cmdlineInfo const cmdline) {
             /* The input file name ends in ".ps".  Chop it off. */
             basename[strlen(basename)-3] = '\0';
 
-        switch (cmdline.format_type) {
+        switch (cmdline.formatType) {
         case PBM_TYPE: suffix = "pbm"; break;
         case PGM_TYPE: suffix = "pgm"; break;
         case PPM_TYPE: suffix = "ppm"; break;
-        default: pm_error("Internal error: invalid value for format_type: %d",
-                          cmdline.format_type);
+        default: pm_error("Internal error: invalid value for formatType: %d",
+                          cmdline.formatType);
         }
         pm_asprintf(&retval, "%s%%03d.%s", basename, suffix);
 
@@ -633,17 +654,17 @@ computeOutfileArg(struct cmdlineInfo const cmdline) {
 
 
 static const char *
-computeGsDevice(int  const format_type,
+computeGsDevice(int  const formatType,
                 bool const forceplain) {
 
     const char * basetype;
     const char * retval;
 
-    switch (format_type) {
+    switch (formatType) {
     case PBM_TYPE: basetype = "pbm"; break;
     case PGM_TYPE: basetype = "pgm"; break;
     case PPM_TYPE: basetype = "ppm"; break;
-    default: pm_error("Internal error: invalid value format_type");
+    default: pm_error("Internal error: invalid value formatType");
     }
     if (forceplain)
         retval = strdup(basetype);
@@ -703,14 +724,13 @@ findGhostscriptProg(const char ** const retvalP) {
 
 static void
 execGhostscript(int          const inputPipeFd,
-                char         const ghostscript_device[],
-                char         const outfile_arg[], 
+                char         const ghostscriptDevice[],
+                char         const outfileArg[], 
                 int          const xsize,
                 int          const ysize, 
                 int          const xres,
                 int          const yres,
                 unsigned int const textalphabits,
-                char         const inputFileName[],
                 bool         const verbose) {
     
     const char * arg0;
@@ -729,8 +749,8 @@ execGhostscript(int          const inputPipeFd,
     close(inputPipeFd);
 
     pm_asprintf(&arg0, "gs");
-    pm_asprintf(&deviceopt, "-sDEVICE=%s", ghostscript_device);
-    pm_asprintf(&outfileopt, "-sOutputFile=%s", outfile_arg);
+    pm_asprintf(&deviceopt, "-sDEVICE=%s", ghostscriptDevice);
+    pm_asprintf(&outfileopt, "-sOutputFile=%s", outfileArg);
     pm_asprintf(&gopt, "-g%dx%d", xsize, ysize);
     pm_asprintf(&ropt, "-r%dx%d", xres, yres);
     pm_asprintf(&textalphabitsopt, "-dTextAlphaBits=%u", textalphabits);
@@ -760,26 +780,26 @@ execGhostscript(int          const inputPipeFd,
 
 
 static void
-executeGhostscript(char                     const pstrans[],
-                   char                     const ghostscript_device[],
-                   char                     const outfile_arg[], 
-                   int                      const xsize,
-                   int                      const ysize, 
-                   int                      const xres,
-                   int                      const yres,
-                   unsigned int             const textalphabits,
-                   char                     const inputFileName[], 
-                   enum postscript_language const language,
-                   bool                     const verbose) {
-
-    int gs_exit;  /* wait4 exit code from Ghostscript */
-    FILE *gs;  /* Pipe to Ghostscript's standard input */
-    FILE *infile;
+executeGhostscript(char                    const pstrans[],
+                   char                    const ghostscriptDevice[],
+                   char                    const outfileArg[], 
+                   int                     const xsize,
+                   int                     const ysize, 
+                   int                     const xres,
+                   int                     const yres,
+                   unsigned int            const textalphabits,
+                   char                    const inputFileName[], 
+                   enum PostscriptLanguage const language,
+                   bool                    const verbose) {
+
+    int gsTermStatus;  /* termination status of Ghostscript process */
+    FILE * pipeToGsP;  /* Pipe to Ghostscript's standard input */
+    FILE * ifP;
     int rc;
     int eof;  /* End of file on input */
     int pipefd[2];
 
-    if (strlen(outfile_arg) > 80)
+    if (strlen(outfileArg) > 80)
         pm_error("output file spec too long.");
     
     rc = pm_pipe(pipefd);
@@ -794,20 +814,20 @@ executeGhostscript(char                     const pstrans[],
     else if (rc == 0) {
         /* Child process */
         close(pipefd[1]);
-        execGhostscript(pipefd[0], ghostscript_device, outfile_arg,
+        execGhostscript(pipefd[0], ghostscriptDevice, outfileArg,
                         xsize, ysize, xres, yres, textalphabits,
-                        inputFileName, verbose);
+                        verbose);
     } else {
         pid_t const ghostscriptPid = rc;
         int const pipeToGhostscriptFd = pipefd[1];
         /* parent process */
         close(pipefd[0]);
 
-        gs = fdopen(pipeToGhostscriptFd, "w");
-        if (gs == NULL) 
+        pipeToGsP = fdopen(pipeToGhostscriptFd, "w");
+        if (pipeToGsP == NULL) 
             pm_error("Unable to open stream on pipe to Ghostscript process.");
     
-        infile = pm_openr(inputFileName);
+        ifP = pm_openr(inputFileName);
         /*
           In encapsulated Postscript, we the encapsulator are supposed to
           handle showing the page (which we do by passing a showpage
@@ -822,12 +842,12 @@ executeGhostscript(char                     const pstrans[],
           here, I think, so I boiled it down a bit.  JM 
         */
         if (language == ENCAPSULATED_POSTSCRIPT)
-            fprintf(gs, "\n/b4_Inc_state save def /showpage { } def\n");
+            fprintf(pipeToGsP, "\n/b4_Inc_state save def /showpage { } def\n");
  
         if (verbose) 
             pm_message("Postscript prefix command: '%s'", pstrans);
 
-        fprintf(gs, "%s\n", pstrans);
+        fprintf(pipeToGsP, "%s\n", pstrans);
 
         /* If our child dies, it closes the pipe and when we next write to it,
            we get a SIGPIPE.  We must survive that signal in order to report
@@ -840,34 +860,34 @@ executeGhostscript(char                     const pstrans[],
             char buffer[4096];
             int bytes_read;
             
-            bytes_read = fread(buffer, 1, sizeof(buffer), infile);
+            bytes_read = fread(buffer, 1, sizeof(buffer), ifP);
             if (bytes_read == 0) 
                 eof = TRUE;
             else 
-                fwrite(buffer, 1, bytes_read, gs);
+                fwrite(buffer, 1, bytes_read, pipeToGsP);
         }
-        pm_close(infile);
+        pm_close(ifP);
 
         if (language == ENCAPSULATED_POSTSCRIPT)
-            fprintf(gs, "\nb4_Inc_state restore showpage\n");
+            fprintf(pipeToGsP, "\nb4_Inc_state restore showpage\n");
 
-        fclose(gs);
+        fclose(pipeToGsP);
         
-        waitpid(ghostscriptPid, &gs_exit, 0);
+        waitpid(ghostscriptPid, &gsTermStatus, 0);
         if (rc < 0)
             pm_error("Wait for Ghostscript process to terminated failed.  "
                      "errno = %d (%s)", errno, strerror(errno));
 
-        if (gs_exit != 0) {
-            if (WIFEXITED(gs_exit))
+        if (gsTermStatus != 0) {
+            if (WIFEXITED(gsTermStatus))
                 pm_error("Ghostscript failed.  Exit code=%d\n", 
-                         WEXITSTATUS(gs_exit));
-            else if (WIFSIGNALED(gs_exit))
+                         WEXITSTATUS(gsTermStatus));
+            else if (WIFSIGNALED(gsTermStatus))
                 pm_error("Ghostscript process died due to a signal %d.",
-                         WTERMSIG(gs_exit));
+                         WTERMSIG(gsTermStatus));
             else 
                 pm_error("Ghostscript process died with exit code %d", 
-                         gs_exit);
+                         gsTermStatus);
         }
     }
 }
@@ -877,22 +897,22 @@ executeGhostscript(char                     const pstrans[],
 int
 main(int argc, char ** argv) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     const char * inputFileName;  /* malloc'ed */
         /* The file specification of our Postscript input file */
     unsigned int xres, yres;    /* Resolution in pixels per inch */
     unsigned int xsize, ysize;  /* output image size in pixels */
-    struct box extract_box;
+    struct Box extractBox;
         /* coordinates of the box within the input we are to extract; i.e.
            that will become the output. 
            */
-    struct box bordered_box;
+    struct Box borderedBox;
         /* Same as above, but expanded to include borders */
 
-    enum postscript_language language;
-    enum orientation orientation;
-    const char * ghostscript_device;
-    const char * outfile_arg;
+    enum PostscriptLanguage language;
+    enum Orientation orientation;
+    const char * ghostscriptDevice;
+    const char * outfileArg;
     const char * pstrans;
 
     pnm_init(&argc, argv);
@@ -901,36 +921,36 @@ main(int argc, char ** argv) {
 
     addPsToFileName(cmdline.inputFileName, &inputFileName, cmdline.verbose);
 
-    extract_box = computeBoxToExtract(cmdline.extract_box, inputFileName, 
+    extractBox = computeBoxToExtract(cmdline.extractBox, inputFileName, 
                                       cmdline.verbose);
 
     language = languageDeclaration(inputFileName, cmdline.verbose);
     
-    orientation = computeOrientation(cmdline, extract_box);
+    orientation = computeOrientation(cmdline, extractBox);
 
-    bordered_box = addBorders(extract_box, cmdline.xborder, cmdline.yborder,
-                              cmdline.verbose);
+    borderedBox = addBorders(extractBox, cmdline.xborder, cmdline.yborder,
+                             cmdline.verbose);
 
-    computeSizeRes(cmdline, orientation, bordered_box, 
+    computeSizeRes(cmdline, orientation, borderedBox, 
                    &xsize, &ysize, &xres, &yres);
     
-    pstrans = computePstrans(bordered_box, orientation,
+    pstrans = computePstrans(borderedBox, orientation,
                              xsize, ysize, xres, yres);
 
-    outfile_arg = computeOutfileArg(cmdline);
+    outfileArg = computeOutfileArg(cmdline);
 
-    ghostscript_device = 
-        computeGsDevice(cmdline.format_type, cmdline.forceplain);
+    ghostscriptDevice = 
+        computeGsDevice(cmdline.formatType, cmdline.forceplain);
     
-    pm_message("Writing %s file", ghostscript_device);
+    pm_message("Writing %s format", ghostscriptDevice);
     
-    executeGhostscript(pstrans, ghostscript_device, outfile_arg, 
+    executeGhostscript(pstrans, ghostscriptDevice, outfileArg, 
                        xsize, ysize, xres, yres, cmdline.textalphabits,
                        inputFileName,
                        language, cmdline.verbose);
 
-    pm_strfree(ghostscript_device);
-    pm_strfree(outfile_arg);
+    pm_strfree(ghostscriptDevice);
+    pm_strfree(outfileArg);
     pm_strfree(pstrans);
     
     return 0;
diff --git a/converter/other/winicon.h b/converter/other/winicon.h
new file mode 100644
index 00000000..9ede01f5
--- /dev/null
+++ b/converter/other/winicon.h
@@ -0,0 +1,82 @@
+#include "pm_c_util.h"
+
+#define ICONDIR_TYPE_ICO (1)
+
+/*  windows icon structures  */
+struct IconDirEntry {
+    uint16_t width;               /* image width in pixels 0 == 256 */
+    uint16_t height;              /* image height in pixels 0 == 256 */
+    uint8_t  color_count;         /* 0 if bits_per_pixel >= 8 */
+    uint8_t  zero;                /* 0 */
+    uint16_t color_planes;        /* 1 */
+    uint16_t bits_per_pixel;      /* allowed values: 1, 4, 8, 16 or 32 (1) */
+    uint32_t size;                /* size of image */
+    uint32_t offset;              /* file offset of image */
+
+    uint16_t index;               /* extra field (not in file) */
+};
+
+/*  (1) This is from
+ *  http://blogs.msdn.com/b/oldnewthing/archive/2010/10/19/10077610.aspx.
+ *
+ *  However, the bpp value in the icon directory is used as a hint for
+ *  image selection only.  It seems to be legal to set this value to
+ *  zero, and e.g. in SHELL32.DLL of Win98SE, there are many 8bpp
+ *  images described as 24 bit images in the icon directory.
+ *
+ *  The bpp value of image 1 in icon 150 in SHELL32.DLL of WinXP is 24
+ *  (in header and BMP).  This may be a bug, as the 32 x 32 x 8 image
+ *  is missing, but it shows the Windows icon rendering engine is able
+ *  to cope with 24 bit images).
+ *
+ *  16bpp icons are at least rare in the wild.
+ */
+struct IconDir {
+    uint16_t zero;                /* 0 */
+    uint16_t type;                /* 1 */
+    uint16_t count;               /* number of images in icon */
+
+    unsigned int entriesAllocCt;     /* # of allocated slots in 'entries'*/
+    struct IconDirEntry * entries;   /* one entry for each image */
+};
+
+/*  BMP image structures  */
+
+struct BitmapInfoHeader {
+    uint32_t header_size;         /* >= 40 */
+    int32_t  bm_width;
+    int32_t  bm_height;
+    uint16_t color_planes;
+    uint16_t bits_per_pixel;
+    uint32_t compression_method;
+    uint32_t image_size;
+    int32_t  horizontal_resolution; /* pixels per meter (!) */
+    int32_t  vertical_resolution;   /* pixels per meter (!) */
+    uint32_t colors_in_palette;
+    uint32_t important_colors;
+
+    bool top_down;                /* extra field (not in file) */
+
+};
+
+typedef enum {
+    BI_RGB       = 0,
+    BI_BITFIELDS = 3
+
+} BiCompression;
+
+/*  PNG image structures  */
+#define PNG_HEADER { 0x89, 'P', 'N', 'G', '\r', '\n', 0x1A /* ^Z */, '\n' }
+
+struct PngIhdr {
+    uint32_t length;              /* 13 */
+    uint32_t signature;           /* "IHDR" */
+    uint32_t width;               /* image width in pixels */
+    uint32_t height;              /* image height in pixels */
+    uint8_t  bit_depth;           /* depth per channel */
+    uint8_t  color_type;          /* recognized values: 0, 2, 3, 4 and 6 */
+    uint8_t  compression;
+    uint8_t  filter;
+    uint8_t  interlace;
+    uint32_t crc;
+};
diff --git a/converter/other/winicontopam.c b/converter/other/winicontopam.c
new file mode 100644
index 00000000..9bee8b3c
--- /dev/null
+++ b/converter/other/winicontopam.c
@@ -0,0 +1,1282 @@
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "netpbm/pm_config.h"
+#include "netpbm/pm_c_util.h"
+#include "netpbm/mallocvar.h"
+#include "netpbm/nstring.h"
+#include "netpbm/shhopt.h"
+#include "netpbm/pam.h"
+#include "netpbm/pm_system.h"
+
+#include "winicon.h"
+
+#define RED   0
+#define GRN   1
+#define BLU   2
+#define ALPHA 3
+#define CHANNEL_CHARS "RGBA"
+
+
+
+static bool verbose;
+
+
+
+struct CmdlineInfo {
+    
+    const char * inputFileName;
+    unsigned int allimages;
+    unsigned int imageSpec;
+    unsigned int image;
+    unsigned int andmasks;
+    unsigned int headerdump;
+    unsigned int verbose;
+};
+
+
+
+static void
+parseCommandLine(int argc, const char **argv,
+                 struct CmdlineInfo * const cmdlineP) {
+
+    optEntry *   option_def;
+    unsigned int option_def_index;
+    optStruct3   opt3;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;
+
+    OPTENT3 (0, "allimages",   OPT_FLAG,   NULL,
+             &cmdlineP->allimages,         0);
+    OPTENT3 (0, "image",     OPT_UINT,   &cmdlineP->image,
+             &cmdlineP->imageSpec,         0);
+    OPTENT3 (0, "andmasks",  OPT_FLAG,   NULL,
+             &cmdlineP->andmasks,          0);
+    OPTENT3 (0, "headerdump",   OPT_FLAG,   NULL,
+             &cmdlineP->headerdump,        0);
+    OPTENT3 (0, "verbose",   OPT_FLAG,   NULL,
+             &cmdlineP->verbose,           0);
+
+    opt3.opt_table     = option_def;
+    opt3.short_allowed = false;
+    opt3.allowNegNum   = false;
+
+    pm_optParseOptions3(&argc, (char **)argv, opt3, sizeof(opt3), 0);
+
+    if (cmdlineP->allimages && cmdlineP->imageSpec)
+        pm_error("You cannot specify both -allimages and -image");
+
+    if (argc-1 < 1)
+        cmdlineP->inputFileName = "-";
+    else {
+        cmdlineP->inputFileName = argv[1];
+
+        if (argc-1 > 1)
+            pm_error("Too many arguments.  The only possible "
+                     "non-option argument is the input file name");
+    }
+        
+    free(option_def);
+}
+
+
+
+static unsigned char const pngHeader[] = PNG_HEADER;
+
+
+
+struct File {
+
+    FILE *       fileP;
+    const char * name;
+    pm_filepos   pos;
+    
+};
+
+
+
+static uint32_t
+u8_le(const unsigned char * const buf,
+      size_t                const offset) {
+
+    return buf[offset + 0];
+}
+
+
+
+static uint32_t
+u16_le(const unsigned char * const buf,
+       size_t                const offset) {
+
+    return
+        ((uint32_t)buf[offset + 0] << 0) +
+        ((uint32_t)buf[offset + 1] << 8);
+}
+
+
+
+static uint32_t
+u32_le(const unsigned char * const buf,
+       size_t                const offset) {
+
+    return 
+        ((uint32_t)buf[offset + 0] <<  0) +
+        ((uint32_t)buf[offset + 1] <<  8) +
+        ((uint32_t)buf[offset + 2] << 16) +
+        ((uint32_t)buf[offset + 3] << 24);
+}
+
+
+
+static uint32_t
+s32_le(const unsigned char * const buf,
+       size_t                const offset) {
+
+    return 
+        ((uint32_t)buf[offset + 0] <<  0) +
+        ((uint32_t)buf[offset + 1] <<  8) +
+        ((uint32_t)buf[offset + 2] << 16) +
+        ((uint32_t)buf[offset + 3] << 24);
+}
+
+
+
+static uint32_t
+u8_be(const unsigned char * const buf,
+      size_t                const offset) {
+
+    return buf[offset + 0];
+}
+
+
+
+static uint32_t
+u32_be(const unsigned char * const buf,
+       size_t                const offset) {
+    
+    return 
+        ((uint32_t)buf[offset + 0] << 24) +
+        ((uint32_t)buf[offset + 1] << 16) +
+        ((uint32_t)buf[offset + 2] <<  8) +
+        ((uint32_t)buf[offset + 3] <<  0);
+}
+
+
+
+static uint32_t
+u32_xx(const unsigned char * const buf,
+       size_t                const offset) {
+
+    uint32_t u32;
+
+    ((uint8_t*) &u32)[0] = buf[offset + 0];
+    ((uint8_t*) &u32)[1] = buf[offset + 1];
+    ((uint8_t*) &u32)[2] = buf[offset + 2];
+    ((uint8_t*) &u32)[3] = buf[offset + 3];
+
+    return (u32);
+}
+
+
+
+static int
+cmpfn(const void * const aP,
+      const void * const bP) {
+
+    const struct IconDirEntry * const dirEntryAP = aP;
+    const struct IconDirEntry * const dirEntryBP = bP;
+
+    if (dirEntryAP->offset < dirEntryBP->offset)
+        return -1;
+    else if (dirEntryAP->offset > dirEntryBP->offset)
+        return +1;
+    else
+        return 0;
+}
+
+
+
+static void
+dumpIconDir(const struct IconDir * const dirP) {
+
+    unsigned int i;
+
+    pm_message("Type: %u", dirP->type);
+    pm_message("Icon directory has %u images:", dirP->count);
+
+    for (i = 0; i < dirP->count; ++i) {
+        const struct IconDirEntry * const dirEntryP = &dirP->entries[i];
+
+        pm_message("width: %u", dirEntryP->width);
+        pm_message("height: %u", dirEntryP->height);
+        pm_message("color count: %u", dirEntryP->color_count);
+        pm_message("# color planes: %u", dirEntryP->color_planes);
+        pm_message("bits per pixel: %u", dirEntryP->bits_per_pixel);
+        pm_message("offset in file of image: %u", dirEntryP->offset);
+        pm_message("size of image: %u", dirEntryP->size);
+        pm_message("zero field: %u", dirEntryP->zero);
+    }
+}
+
+            
+
+static struct IconDir *
+readIconDir(struct File * const fP,
+            bool          const needHeaderDump) {
+
+    struct IconDir head;
+    struct IconDir * dirP;
+    uint32_t  imageIndex; /* more bits than dir.count */
+
+    pm_readlittleshortu(fP->fileP, &head.zero);
+    pm_readlittleshortu(fP->fileP, &head.type);
+    pm_readlittleshortu(fP->fileP, &head.count);
+    fP->pos += 6;
+
+    if (head.zero != 0 || head.type != ICONDIR_TYPE_ICO)
+        pm_error("Not a valid windows icon file");
+
+    MALLOCVAR(dirP);
+
+    if (dirP == NULL)
+        pm_error("Could't allocate memory for Icon directory");
+
+    MALLOCARRAY(dirP->entries, head.count);
+
+    if (dirP->entries == NULL)
+        pm_error("Could not allocate memory for %u entries in icon directory",
+                 head.count);
+
+    dirP->zero           = head.zero;
+    dirP->type           = head.type;
+    dirP->count          = head.count;
+    dirP->entriesAllocCt = head.count;
+
+    for (imageIndex = 0; imageIndex < head.count; ++imageIndex) {
+        struct IconDirEntry * const dirEntryP = &dirP->entries[imageIndex];
+
+        unsigned char widthField, heightField;
+
+        unsigned long ul;
+
+        pm_readcharu(fP->fileP, &widthField);
+        dirEntryP->width  = (widthField == 0 ? 256 : widthField);
+
+        pm_readcharu(fP->fileP, &heightField);
+        dirEntryP->height = (heightField == 0 ? 256 : heightField);
+        
+        pm_readcharu(fP->fileP, &dirEntryP->color_count);
+
+        pm_readcharu(fP->fileP, &dirEntryP->zero);
+
+        pm_readlittleshortu(fP->fileP, &dirEntryP->color_planes);
+
+        pm_readlittleshortu(fP->fileP, &dirEntryP->bits_per_pixel);
+
+        pm_readlittlelongu(fP->fileP, &ul); dirEntryP->size = ul;
+
+        pm_readlittlelongu(fP->fileP, &ul); dirEntryP->offset = ul;
+
+        fP->pos += 16;
+
+        dirEntryP->index = imageIndex;
+    }
+
+    /* The following is paranoia code only:
+     
+       I've never seen a windows icon file in the wild with having the entries
+       in the directory stored in a different order than the images
+       themselves.  However, the file format allows for it ...
+     */
+    qsort(dirP->entries, dirP->count, sizeof(struct IconDirEntry), cmpfn);
+
+    if (verbose) {
+        pm_message("%s icon directory (%u image%s):",
+                   fP->name,
+                   dirP->count, dirP->count == 1 ? "" : "s");
+        
+        for (imageIndex = 0; imageIndex < dirP->count; ++imageIndex) {
+            const struct IconDirEntry * const dirEntryP =
+                &dirP->entries[imageIndex];
+
+            uint32_t colorCt;
+
+            if (dirEntryP->bits_per_pixel == 0)
+                colorCt = 0;
+            else if (dirEntryP->bits_per_pixel >= 32)
+                colorCt = 1u << 24;
+            else
+                colorCt = 1u << dirEntryP->bits_per_pixel;
+
+            if (dirEntryP->color_count != 0 &&
+                colorCt > dirEntryP->color_count) {
+                colorCt = dirEntryP->color_count;
+            }
+            pm_message ("%5u: %3u x %3u, %8u colors, %5u bytes",
+                        dirEntryP->index,
+                        dirEntryP->width,
+                        dirEntryP->height,
+                        colorCt,
+                        dirEntryP->size);
+        }
+    }
+
+    if (needHeaderDump)
+        dumpIconDir(dirP);
+
+    return dirP;
+}
+
+
+
+static void
+freeIconDir(struct IconDir * const dirP) {
+
+    free(dirP->entries);
+    free(dirP);
+}
+
+
+
+static const unsigned char *
+readImage(struct File *         const fP,
+          struct IconDirEntry * const dirEntryP) {
+
+    size_t rc;
+    unsigned char * image;
+    uint32_t skippedCt;
+
+    /*  Don't try to read an image that is smaller than the
+        BITMAPINFOHEADER of BMP images (40 bytes).
+     
+        PNG compressed images can't be smaller than that either, as the
+        PNG header plus the mandantory IHDR and IEND chunks already take
+        8 + 25 + 12 = 35 bytes, and there is to be a IDAT chunk too.
+     */
+    if (dirEntryP->size < 40) {
+        pm_error("image %2u: format violation: too small as an image.",
+                  dirEntryP->index);
+    }
+    if ((pm_filepos) dirEntryP->offset < fP->pos)
+        pm_error("image %2u: format violation: invalid offset.",
+                 dirEntryP->index);
+
+    /* The following is paranoia code only:
+     
+       I've never seen a windows icon file in the wild with gaps between
+       the images, but the file format allows for it, and Microsoft
+       expects the user to fseek() to the start of each image.
+     */
+    skippedCt = 0;
+
+    while ((pm_filepos) dirEntryP->offset > fP->pos) {
+        if (getc(fP->fileP) == EOF) {
+            pm_error("seeking to image %u: unexpected EOF", dirEntryP->index);
+        }
+        ++fP->pos;
+        ++skippedCt;
+    }
+
+    /*  The additional four bytes are for purify and friends, as the
+        routines reading BMP XOR and AND masks might read (but not
+        evaluate) some bytes beyond the image data.
+     */
+    image = malloc(dirEntryP->size + sizeof(uint32_t));
+    if (image == NULL)
+        pm_error("out of memory.");
+
+    rc = fread (image, 1, dirEntryP->size, fP->fileP);
+    if (rc != dirEntryP->size) {
+        pm_error("reading image %2u: unexpected EOF", dirEntryP->index);
+    }
+    fP->pos += dirEntryP->size;
+
+    return image;
+}
+
+
+
+static uint8_t
+getIdx1(const unsigned char * const bitmap,
+        uint32_t              const offset,
+        int16_t               const col) {
+
+    return u8_le(bitmap, offset + (col >> 3)) >> (7 - (col & 0x07)) & 0x1;
+}
+
+
+
+static uint8_t
+getIdx4(const unsigned char * const bitmap,
+        uint32_t              const offset,
+        int16_t               const col) {
+
+    if ((col & 1) == 0x0000)
+        return u8_le(bitmap, offset + (col >> 1)) >> 4 & 0x0F;
+    else
+        return u8_le(bitmap, offset + (col >> 1)) >> 0 & 0x0F;
+}
+
+
+
+static uint8_t
+getIdx8(const unsigned char * const bitmap,
+        uint32_t              const offset,
+        int16_t               const col) {
+
+    return u8_le(bitmap, offset + col);
+}
+
+
+
+typedef unsigned char PaletteEntry[4];
+
+
+
+static void
+dumpPalette(const PaletteEntry * const palette,
+            unsigned int         const colorCt) {
+
+    unsigned int i;
+
+    for (i = 0; i < colorCt; ++i) {
+        pm_message("Color %u: (%u, %u, %u)",
+                   i, palette[i][2], palette[i][1], palette[i][0]);
+    }
+}
+
+
+
+static void
+readXorPalette(struct BitmapInfoHeader * const hdrP,
+               const unsigned char *     const bitmap,
+               uint32_t                  const maxSize,
+               tuple **                  const tuples,
+               uint16_t                  const index,
+               bool                      const needHeaderDump,
+               uint32_t *                const bytesConsumedP) {
+
+    uint32_t paletteSize;
+
+    int16_t     row;
+    const PaletteEntry * palette;
+    uint32_t    truncatedXorSize;
+    uint32_t    bytesConsumed;
+    uint32_t    bytesPerRow;
+    const unsigned char * bitmapCursor;
+    uint32_t sizeRemaining;
+  
+    uint8_t (*getIdx) (const unsigned char * bitmap,
+                       uint32_t rowOffset,
+                       int16_t col);
+  
+    if (hdrP->compression_method != BI_RGB)
+        pm_error("image %2u: invalid compression method %u.",
+                 index, hdrP->compression_method);
+
+    assert(hdrP->bits_per_pixel < 16);
+
+    switch (hdrP->bits_per_pixel) {
+    case 1:
+        if (hdrP->colors_in_palette == 0)
+            hdrP->colors_in_palette = 2;
+        getIdx = getIdx1;
+        break;
+
+    case 4:
+        if (hdrP->colors_in_palette == 0)
+            hdrP->colors_in_palette = 16;
+        getIdx = getIdx4;
+        break;
+
+    case 8:
+        if (hdrP->colors_in_palette == 0)
+            hdrP->colors_in_palette = 256;
+        getIdx = getIdx8;
+        break;
+
+    default:
+        pm_error("image %2u: "
+                 "bits per pixel is a value we don't understand: %u",
+                  index, hdrP->bits_per_pixel);
+        getIdx = NULL;
+    }
+
+    bitmapCursor = &bitmap[0];  /* initial value */
+    sizeRemaining = maxSize;    /* initial value */
+    bytesConsumed = 0;          /* initial value */
+
+    paletteSize = hdrP->colors_in_palette * 4;
+
+    if (sizeRemaining < paletteSize)
+        pm_error("image %2u: "
+                 "reading palette: image truncated.", index);
+    
+    palette = (const PaletteEntry *) bitmapCursor;
+
+    if (needHeaderDump)
+        dumpPalette(palette, hdrP->colors_in_palette);
+
+    bitmapCursor  += paletteSize;
+    sizeRemaining -= paletteSize;
+    bytesConsumed += paletteSize;
+
+    {
+        uint32_t const xorSize = (uint32_t)
+            (((hdrP->bits_per_pixel * hdrP->bm_width + 31) / 32)
+             * 4 * hdrP->bm_height / 2);
+
+        if (sizeRemaining < xorSize) {
+            pm_message("image %2u: "
+                       "reading XOR mask: image truncated.", index);
+            truncatedXorSize = sizeRemaining;
+        } else
+            truncatedXorSize = xorSize;
+    }
+
+    bytesPerRow = ((hdrP->bits_per_pixel * hdrP->bm_width + 31) / 32) * 4;
+
+    for (row = 0; hdrP->bm_height / 2 > row; ++row) {
+        uint32_t rowOffset;
+
+        if (hdrP->top_down)
+            rowOffset = row * bytesPerRow;
+        else
+            rowOffset = (hdrP->bm_height / 2 - row - 1) * bytesPerRow;
+
+        if (rowOffset + bytesPerRow <= truncatedXorSize) {
+            int16_t col;
+            for (col = 0; hdrP->bm_width > col; ++col) {
+                uint8_t const idx = getIdx(bitmapCursor, rowOffset, col);
+
+                if (idx > hdrP->colors_in_palette)
+                    pm_error("invalid palette index in row %u, column %u.",
+                             row, col);
+
+                /*  The palette is an array of little-endian 32-bit values,
+                    where the RGB value is encoded as follows:
+                 
+                    red:   bits 2^16..2^23
+                    green: bits 2^8 ..2^15
+                    blue:  bits 2^0 ..2^7
+                 */
+                tuples[row][col][PAM_RED_PLANE] = palette[idx][2];
+                tuples[row][col][PAM_GRN_PLANE] = palette[idx][1];
+                tuples[row][col][PAM_BLU_PLANE] = palette[idx][0];
+            }
+        }
+    }
+
+    bitmapCursor  += truncatedXorSize;
+    sizeRemaining -= truncatedXorSize;
+    bytesConsumed += truncatedXorSize;
+
+    *bytesConsumedP = bytesConsumed;
+}
+
+
+
+static void
+readXorBitfields(struct BitmapInfoHeader * const hdrP,
+                 const unsigned char *     const bitmap,
+                 uint32_t                  const maxSize,
+                 tuple **                  const tuples,
+                 uint16_t                  const index,
+                 bool *                    const haveAlphaP,
+                 uint32_t *                const bytesConsumedP) {
+
+    uint32_t   bitfields[4];
+    uint8_t    shift    [4];
+    sample     maxval   [4];
+
+    int16_t      row;
+    uint32_t     bytesConsumed;
+    uint32_t     bytesPerSample;
+    uint32_t     bytesPerRow;
+    const unsigned char * bitmapCursor;
+    uint32_t     sizeRemaining;
+    uint32_t     truncatedXorSize;
+
+    static uint8_t alphas [256];
+    bool         allOpaque;
+    bool         allTransparent;
+
+    bytesConsumed = 0;
+
+    if (hdrP->compression_method != BI_RGB
+        && hdrP->compression_method != BI_BITFIELDS)
+        pm_error("image %2u: invalid compression method %u.",
+                 index, hdrP->compression_method);
+
+    assert(hdrP->bits_per_pixel >= 16);
+
+    switch (hdrP->bits_per_pixel) {
+    case 16:
+        bytesPerSample = 2;
+        bitfields[RED]   = 0x7C00;
+        bitfields[GRN]   = 0x03E0;
+        bitfields[BLU]   = 0x001F;
+        bitfields[ALPHA] = 0x0000;
+        break;
+
+    case 24:
+        bytesPerSample = 3;
+        bitfields[RED]   = 0xFF0000;
+        bitfields[GRN]   = 0x00FF00;
+        bitfields[BLU]   = 0x0000FF;
+        bitfields[ALPHA] = 0x000000;
+        break;
+
+    case 32:
+        bytesPerSample = 4;
+        bitfields[RED]   = 0x00FF0000;
+        bitfields[GRN]   = 0x0000FF00;
+        bitfields[BLU]   = 0x000000FF;
+        bitfields[ALPHA] = 0xFF000000;
+        break;
+
+    default:
+        pm_error("image %2u: bits per pixel is one we don't understand: %u.",
+                 index, hdrP->bits_per_pixel);
+        bytesPerSample = 0;
+    }
+
+    bitmapCursor = &bitmap[0]; /* initial value */
+    sizeRemaining = maxSize;  /* initial value */
+
+    /*  read bit fields from image data  */
+    if (hdrP->compression_method == BI_BITFIELDS) {
+        if (sizeRemaining < 12)
+            pm_error("image %2u: "
+                     "reading bit fields: image truncated.", index);
+
+        bitfields[RED]   = u32_le(bitmapCursor, 0);
+        bitfields[GRN]   = u32_le(bitmapCursor, 4);
+        bitfields[BLU]   = u32_le(bitmapCursor, 8);
+        bitfields[ALPHA] = 0;
+
+        bitmapCursor  += 12;
+        sizeRemaining -= 12;
+        bytesConsumed += 12;
+    }
+
+    /*  determine shift and maxval from bit field for each channel */
+    {
+        unsigned int i;
+
+        for (i = 0; 4 > i; ++i) {
+            if (bitfields[i] == 0) {
+                maxval[i] = 1;
+                shift [i] = 0;
+            } else {
+                unsigned int j;
+
+                maxval[i] = bitfields[i];
+
+                for (j = 0; 32 > j; ++j) {
+                    if ((maxval[i] & 0x1) != 0)
+                        break;
+                    maxval[i] >>= 1;
+                }
+                shift[i] = j;
+            }
+
+        }
+    }
+
+    /*  read the XOR mask */
+    {
+        uint32_t const xorSize = (uint32_t)
+            (((hdrP->bits_per_pixel * hdrP->bm_width + 31) / 32)
+             * 4 * hdrP->bm_height / 2);
+
+        if (sizeRemaining < xorSize) {
+            pm_message("image %2u: "
+                       "reading XOR mask: image truncated.", index);
+            truncatedXorSize = sizeRemaining;
+        } else
+            truncatedXorSize = xorSize;
+    }
+
+    bytesPerRow = ((hdrP->bits_per_pixel * hdrP->bm_width + 31) / 32) * 4;
+    MEMSZERO(alphas);
+
+    for (row = 0, allOpaque = true, allTransparent = true;
+         hdrP->bm_height / 2 > row;
+         ++row) {
+
+        uint32_t offset;
+
+        if (hdrP->top_down)
+            offset = row * bytesPerRow;
+        else
+            offset = (hdrP->bm_height / 2 - row - 1) * bytesPerRow;
+
+        if (offset + bytesPerRow <= truncatedXorSize) {
+            unsigned int col;
+            for (col = 0; col < hdrP->bm_width; ++col) {
+                uint32_t const pixel = u32_le(bitmapCursor, offset);
+                offset += bytesPerSample;
+
+                tuples[row][col][PAM_RED_PLANE] =
+                    pnm_scalesample((pixel & bitfields[RED]) >> shift[RED],
+                                    maxval[RED], 255);
+                tuples[row][col][PAM_GRN_PLANE] =
+                    pnm_scalesample((pixel & bitfields[GRN]) >> shift[GRN],
+                                    maxval[GRN], 255);
+                tuples [row][col][PAM_BLU_PLANE]
+                    = pnm_scalesample((pixel & bitfields[BLU]) >> shift[BLU],
+                                      maxval[BLU], 255);
+
+                if (bitfields [ALPHA] != 0) {
+                    tuples[row][col][PAM_TRN_PLANE]
+                        = pnm_scalesample(
+                            (pixel & bitfields[ALPHA]) >> shift[ALPHA],
+                            maxval[ALPHA], 255);
+
+                    if (tuples[row][col][PAM_TRN_PLANE] != 0)
+                        allTransparent = false;
+
+                    if (tuples [row][col][PAM_TRN_PLANE] != 255)
+                        allOpaque = false;
+
+                    alphas[tuples[row][col][PAM_TRN_PLANE]] = !0;
+                }
+            }
+        }
+    }
+
+    bitmapCursor  += truncatedXorSize;
+    sizeRemaining -= truncatedXorSize;
+    bytesConsumed += truncatedXorSize;
+
+    /*  A fully transparent alpha channel (all zero) in XOR mask is
+        defined to be void by Microsoft, and a fully opaque alpha
+        channel (all maxval) is trivial and will be dropped.
+    */
+    *haveAlphaP = !allTransparent && !allOpaque;
+
+    if (!allTransparent && verbose) {
+        unsigned int i;
+        unsigned int c;
+
+        for (i = 0, c = 0; 256 > i; ++i) {
+            if (alphas[i] != 0)
+                ++c;
+        }
+        pm_message("image %2u: %u distinct transparency value%s",
+                   index, c, (c == 1) ? "": "s");
+    }
+    *bytesConsumedP = bytesConsumed;
+}
+
+
+
+static void
+readAnd(struct BitmapInfoHeader * const hdrP,
+        const unsigned char *     const bitmap,
+        uint32_t                  const maxSize,
+        tuple **                  const tuples,
+        uint16_t                  const index,
+        unsigned int              const plane,
+        sample                    const maxval) {
+
+    int16_t  row;
+    uint32_t bytesConsumed;
+    uint32_t bytesPerRow;
+    uint32_t sizeRemaining;
+    uint32_t truncatedAndSize;
+
+    sizeRemaining = maxSize;  /* initial value */
+    bytesConsumed = 0;  /* initial value */
+
+    {
+        uint32_t const andSize = (uint32_t)
+            (((1 * hdrP->bm_width + 31) / 32) * 4 * hdrP->bm_height / 2);
+
+        if (sizeRemaining < andSize) {
+            pm_message ("image %2u: "
+                        "Input image ends %u bytes into the %u-byte "
+                        "AND mask.  Implying remainder of mask",
+                        index, sizeRemaining, andSize);
+            truncatedAndSize = sizeRemaining;
+        } else
+            truncatedAndSize = andSize;
+    }
+
+    bytesPerRow = ((1 * hdrP->bm_width + 31) / 32) * 4;
+
+    for (row = 0; row < hdrP->bm_height / 2; ++row) {
+        uint32_t offset;
+
+        if (hdrP->top_down)
+            offset = row * bytesPerRow;
+        else
+            offset = (hdrP->bm_height / 2 - row - 1) * bytesPerRow;
+
+        if (offset + bytesPerRow <= sizeRemaining) {
+            unsigned int col;
+            
+            for (col = 0; col < hdrP->bm_width; ++col) {
+                tuples[row][col][plane] =
+                    ((u8_le(bitmap, offset + col/8)
+                      & (1 << (7 - (col & 0x7)))) == 0x00) ?
+                    maxval : 0
+                ;
+            }
+        }
+    }
+    sizeRemaining -= truncatedAndSize;
+    bytesConsumed += truncatedAndSize;
+}
+
+
+
+static void
+dumpBmpHeader(struct BitmapInfoHeader const hdr,
+              unsigned int            const imageIndex) {
+
+    pm_message("BMP header for Image %u:", imageIndex);
+
+    pm_message("header size: %u", hdr.header_size);
+    pm_message("bitmap width: %u", hdr.bm_width);
+    pm_message("bitmap height * 2: %u", hdr.bm_height);
+    pm_message("row order: %s", hdr.top_down ? "top down" : "bottom up");
+    pm_message("# color planes: %u", hdr.color_planes);
+    pm_message("bits per pixel: %u", hdr.bits_per_pixel);
+    pm_message("image size: %u", hdr.image_size);
+    pm_message("horizontal resolution: %u", hdr.horizontal_resolution);
+    pm_message("vertical resolution: %u", hdr.vertical_resolution);
+    pm_message("# colors in palette: %u", hdr.colors_in_palette);
+    pm_message("# important colors: %u", hdr.important_colors);
+}
+
+
+
+static void
+readBmpHeader(const unsigned char *     const image,
+              uint32_t                  const size,
+              unsigned int              const imageIndex,
+              bool                      const needHeaderDump,
+              struct BitmapInfoHeader * const hdrP) {
+
+    /*  BITMAPINFOHEADER structure */
+
+    if (size < 40)
+        pm_error("image %2u: reading BITMAPINFOHEADER: not enough data.",
+                 imageIndex);
+
+    hdrP->header_size           = u32_le(image,  0);
+    hdrP->bm_width              = s32_le(image,  4);
+    hdrP->bm_height             = s32_le(image,  8);
+    hdrP->color_planes          = u16_le(image, 12);
+    hdrP->bits_per_pixel        = u16_le(image, 14);
+    hdrP->compression_method    = u32_le(image, 16);
+    hdrP->image_size            = u32_le(image, 20);
+    hdrP->horizontal_resolution = s32_le(image, 24);
+    hdrP->vertical_resolution   = s32_le(image, 28);
+    hdrP->colors_in_palette     = u32_le(image, 32);
+    hdrP->important_colors      = u32_le(image, 36);
+
+    if (hdrP->bm_height > 0) {
+        hdrP->top_down = false;
+    } else {
+        hdrP->top_down   = true;
+        hdrP->bm_height *= -1;
+    }
+
+    if (hdrP->header_size < 36
+        || hdrP->bm_width == 0 || hdrP->bm_height == 0
+        || (hdrP->bm_height & 1) != 0x0000) {
+        pm_error("image %2u: format violation: invalid BMP header.",
+                 imageIndex);
+    }
+
+    if (needHeaderDump)
+        dumpBmpHeader(*hdrP, imageIndex);
+}
+
+
+
+static void
+readXorMask(struct BitmapInfoHeader * const hdrP,
+            const unsigned char *     const imageCursor,
+            uint32_t                  const imageSize,
+            tuple **                  const tuples,
+            uint16_t                  const index,
+            bool                      const needHeaderDump,
+            bool *                    const haveAlphaP,
+            uint32_t *                const bytesConsumedP) {
+/*----------------------------------------------------------------------------
+   Read the so-called XOR mask (for non-monochrome images, this is the
+   color pixmap)
+-----------------------------------------------------------------------------*/
+    /*  preset the PAM with fully opaque black (just in case the image
+        is truncated and not all pixels are filled in below).
+    */
+    {
+        unsigned int row;
+
+        for (row = 0; row < hdrP->bm_height / 2; ++row) {
+            unsigned int col;
+            for (col = 0; col < hdrP->bm_width; ++col) {
+                tuples[row][col][PAM_RED_PLANE] = 0;
+                tuples[row][col][PAM_GRN_PLANE] = 0;
+                tuples[row][col][PAM_BLU_PLANE] = 0;
+                tuples[row][col][PAM_TRN_PLANE] = 255;
+            }
+        }
+    }
+
+    if (hdrP->bits_per_pixel < 16) {
+        readXorPalette(hdrP, imageCursor, imageSize, tuples, index,
+                       needHeaderDump,
+                       bytesConsumedP);
+        *haveAlphaP = false;
+    } else
+        readXorBitfields(hdrP, imageCursor, imageSize, tuples, index,
+                         haveAlphaP, bytesConsumedP);
+}
+
+
+
+static void
+reportImage(unsigned int            const imageIndex,
+            struct BitmapInfoHeader const hdr,
+            bool                    const haveAlpha) {
+
+    const char * const style = 
+        haveAlpha ? "RGB +alpha" :
+        hdr.bits_per_pixel < 16 ? "RGB/palette" :
+        "RGB"
+        ;
+
+    pm_message("image %2u: "
+               "BMP %3u x %3u x %2u (%s)",
+               imageIndex,
+               hdr.bm_width, hdr.bm_height / 2, hdr.bits_per_pixel,
+               style);
+}
+
+
+
+static void
+convertBmp(const unsigned char * const image,
+           FILE *                const ofP,
+           struct IconDirEntry * const dirEntryP,
+           bool                  const needHeaderDump,
+           bool                  const wantAndMaskPlane) {
+    
+    struct BitmapInfoHeader hdr;
+    uint32_t                offset;
+    bool                    haveAlpha;
+    uint32_t                xorByteCt;
+
+    struct pam outpam;
+    tuple **   tuples;
+
+    readBmpHeader(image, dirEntryP->size, dirEntryP->index, needHeaderDump,
+                  &hdr);
+
+    offset = hdr.header_size;  /* Start after header */
+
+    if ((dirEntryP->width != hdr.bm_width)
+        || (dirEntryP->height != hdr.bm_height / 2)) {
+        pm_message("image %2u: "
+                   "mismatch in header and image dimensions "
+                   "(%u x %u vs. %u x %u)",
+                   dirEntryP->index,
+                   dirEntryP->width,
+                   dirEntryP->height,
+                   hdr.bm_width,
+                   hdr.bm_height / 2);
+    }
+
+    if ((dirEntryP->bits_per_pixel != 0)
+        && (dirEntryP->bits_per_pixel != hdr.bits_per_pixel)) {
+        pm_message("image %2u "
+                   "mismatch in header and image bpp value"
+                   "(%u vs. %u)",
+                   dirEntryP->index,
+                   dirEntryP->bits_per_pixel,
+                   hdr.bits_per_pixel);
+    }
+
+    outpam.size   = sizeof(struct pam);
+    outpam.len    = PAM_STRUCT_SIZE(allocation_depth);
+    outpam.file   = ofP;
+    outpam.format = PAM_FORMAT;
+    outpam.width  = hdr.bm_width;
+    outpam.height = hdr.bm_height / 2;
+    outpam.maxval = 255;
+    outpam.allocation_depth = 5;
+    outpam.depth  = 0;
+        /* Just for tuple array allocation; we set the value for the actual
+           output image below.
+        */
+
+    tuples = pnm_allocpamarray(&outpam);
+
+    readXorMask(&hdr, &image[offset], 
+                dirEntryP->size - offset,
+                tuples, dirEntryP->index, needHeaderDump,
+                &haveAlpha, &xorByteCt);
+
+    offset += xorByteCt;
+
+    {
+        /* If there is no alpha channel in XOR mask, store the AND mask to
+           the transparency plane.  Else, here are two transparency
+           maps. If requested, store the AND mask to a fifth PAM plane
+        */
+        bool haveAnd;
+        unsigned int andPlane;
+
+        if (!haveAlpha) {
+            haveAnd = true;
+            andPlane = PAM_TRN_PLANE;
+            strcpy (outpam.tuple_type, "RGB_ALPHA");
+            outpam.depth  = 4;
+        } else if (wantAndMaskPlane) {
+            haveAnd = true;
+            andPlane = PAM_TRN_PLANE + 1;
+            outpam.depth  = 5;
+            strcpy(outpam.tuple_type, "RGB_ALPHA_ANDMASK");
+        } else {
+            haveAnd = false;
+            strcpy (outpam.tuple_type, "RGB_ALPHA");
+            outpam.depth  = 4;
+        }
+        if (haveAnd) {
+            readAnd(&hdr, &image[offset], dirEntryP->size - offset,
+                    tuples, dirEntryP->index, andPlane, outpam.maxval);
+        }
+    }
+    pnm_writepam(&outpam, tuples);
+    pnm_freepamarray(tuples, &outpam);
+
+    reportImage(dirEntryP->index, hdr, haveAlpha);
+}
+
+
+
+static void
+reportPngInfo(const unsigned char * const image,
+              struct IconDirEntry * const dirEntryP) {
+    
+    struct PngIhdr ihdr;
+
+    ihdr.length      = u32_be (image, sizeof(pngHeader)  +0);
+    ihdr.signature   = u32_xx (image, sizeof(pngHeader)  +4);
+    ihdr.width       = u32_be (image, sizeof(pngHeader)  +8);
+    ihdr.height      = u32_be (image, sizeof(pngHeader) +12);
+    ihdr.bit_depth   = u8_be  (image, sizeof(pngHeader) +16);
+    ihdr.color_type  = u8_be  (image, sizeof(pngHeader) +17);
+    ihdr.compression = u8_be  (image, sizeof(pngHeader) +18);
+    ihdr.filter      = u8_be  (image, sizeof(pngHeader) +19);
+    ihdr.interlace   = u8_be  (image, sizeof(pngHeader) +20);
+
+    if ((ihdr.length != 13)
+        || ihdr.signature != *(uint32_t*)"IHDR") {
+        pm_message("image %2u: PNG (uncommonly formatted)",
+                   dirEntryP->index);
+    } else {
+        uint32_t depth;
+        const char * colorType;
+
+        switch (ihdr.color_type) {
+        case 0:
+            colorType = "grayscale";
+            depth     = ihdr.bit_depth;
+            break;
+
+        case 2:
+            colorType = "RGB";
+            depth     = ihdr.bit_depth * 3;
+            break;
+
+        case 3:
+            colorType = "RGB/palette";
+            depth     = 8;
+            break;
+
+        case 4:
+            colorType = "grayscale + alpha";
+            depth     = ihdr.bit_depth * 2;
+            break;
+
+        case 6:
+            colorType = "RGB + alpha";
+            depth     = ihdr.bit_depth * 4;
+            break;
+
+        default:
+            colorType = "unknown color system";
+            depth     = 0;
+            break;
+        }
+        pm_message("image %2u: PNG %3u x %3u x %2u (%s)",
+                   dirEntryP->index,
+                   ihdr.width, ihdr.height, depth, colorType);
+
+        if ((dirEntryP->width != ihdr.width)
+            || (dirEntryP->height != ihdr.height)) {
+            pm_message("image %2u:"
+                       " mismatch in header and image dimensions"
+                       " (%u x %u vs %u x %u)",
+                       dirEntryP->index, dirEntryP->width, dirEntryP->height,
+                       ihdr.width, ihdr.height);
+        }
+        /* Mismatch between dirEntryP->bits_per_pixel and 'depth' is
+           normal, because the creator of the winicon file doesn't necessarily
+           know the true color resolution.
+        */
+    }
+}
+
+
+
+static void
+convertPng(const unsigned char * const image,
+           FILE *                const ofP,
+           struct IconDirEntry * const dirEntryP) {
+
+    struct bufferDesc imageBuffer;
+
+    reportPngInfo(image, dirEntryP);
+
+    imageBuffer.size = dirEntryP->size;
+    imageBuffer.buffer = (unsigned char *)image;
+
+    fflush (stdout);
+    pm_system(pm_feed_from_memory, &imageBuffer,
+              NULL /* stdout accepter */, NULL,
+              "pngtopam -alphapam");
+}
+
+
+
+static uint32_t
+bestImage(struct IconDir * const dirP) {
+
+    uint32_t imageIndex;
+    uint32_t bestPixelCt;
+    uint32_t bestColorCt;
+    uint16_t best;
+
+    bestPixelCt = 0;  /* initial value */
+    bestColorCt = 0;  /* initial value */
+    best        = 0;  /* initial value */
+    
+    for (imageIndex = 0; dirP->count > imageIndex; ++imageIndex) {
+        struct IconDirEntry * const dirEntryP = &dirP->entries[imageIndex];
+
+        uint32_t const pixelCt = dirEntryP->width * dirEntryP->height;
+
+        uint32_t colorCt;
+
+        /*  32-bit icons have 24 bit color information only.
+         
+            Since NT 5.1 (aka WinXP), it is allowed to place 8-bit
+            transparency information in the remaining bits (to check,
+            you have to read all these bits in the image!), so I prefer
+            32-bit images over 24-bit images (which violate the
+            spec. anyway).
+        */
+        if (dirEntryP->bits_per_pixel > 24)
+            colorCt = 1u << 25;
+        else
+            colorCt = 1u << dirEntryP->bits_per_pixel;
+
+        if (dirEntryP->color_count != 0 && colorCt > dirEntryP->color_count)
+            colorCt = dirEntryP->color_count;
+
+        if ((pixelCt > bestPixelCt)
+            || ((pixelCt == bestPixelCt) && (colorCt > bestColorCt))) {
+            /* This is a new best */
+            bestPixelCt = pixelCt;
+            bestColorCt = colorCt;
+            best        = imageIndex;
+        }
+    }
+    return best;
+}
+
+
+
+static void
+convertImage(struct File *         const icoP,
+             struct IconDirEntry * const dirEntryP,
+             FILE *                const ofP,
+             bool                  const needHeaderDump,
+             bool                  const wantAndMaskPlane) {
+
+    const unsigned char * image;  /* malloced */
+
+    image = readImage(icoP, dirEntryP);
+
+    if (MEMEQ(image, pngHeader, sizeof (pngHeader)))
+        convertPng(image, ofP, dirEntryP);
+    else
+        convertBmp(image, ofP, dirEntryP, needHeaderDump, wantAndMaskPlane);
+
+    free((void *)image);
+}
+
+
+
+int
+main (int argc, const char *argv []) {
+
+    struct File ico;
+    struct IconDir * dirP;
+    struct CmdlineInfo cmdline;
+
+    pm_proginit (&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    verbose = cmdline.verbose;
+
+    ico.name =
+        streq(cmdline.inputFileName, "-") ?  "<stdin>" : cmdline.inputFileName;
+    ico.pos   = 0;
+    ico.fileP = pm_openr(cmdline.inputFileName);
+
+    dirP = readIconDir(&ico, cmdline.headerdump);
+
+    if (cmdline.allimages) {
+        unsigned int i;
+        for (i = 0; i < dirP->count; ++i)
+            convertImage(&ico, &dirP->entries[i], stdout,
+                         cmdline.headerdump, cmdline.andmasks);
+    } else if (cmdline.imageSpec) {
+        unsigned int i;
+        bool found;
+        for (i = 0, found = false; i < dirP->count; ++i) {
+            if (dirP->entries[i].index == cmdline.image) {
+                found = true;
+                convertImage(&ico, &dirP->entries[i], stdout,
+                             cmdline.headerdump, cmdline.andmasks);
+            }
+        }
+        if (!found)
+            pm_error("no image index %u in.input", cmdline.image);
+    } else {
+        convertImage(&ico, &dirP->entries[bestImage(dirP)], stdout,
+                     cmdline.headerdump, cmdline.andmasks);
+    }
+    
+    freeIconDir(dirP);
+
+    if (ico.fileP != stdin)
+        pm_close(ico.fileP);
+
+    return 0;
+}
+
+
+
diff --git a/converter/pbm/pbmtolj.c b/converter/pbm/pbmtolj.c
index 89dcb76c..0cceb4fe 100644
--- a/converter/pbm/pbmtolj.c
+++ b/converter/pbm/pbmtolj.c
@@ -545,7 +545,7 @@ main(int argc, char * argv[]) {
 
     struct cmdlineInfo cmdline;
     FILE * ifP;
-    bool eof;
+    int eof;
 
     pbm_init(&argc, argv);
 
diff --git a/converter/pbm/pbmtopsg3.c b/converter/pbm/pbmtopsg3.c
index 2878686b..8163b70a 100644
--- a/converter/pbm/pbmtopsg3.c
+++ b/converter/pbm/pbmtopsg3.c
@@ -323,7 +323,7 @@ doPages(FILE *         const ifP,
         unsigned int * const pagesP,
         double         const dpi) {
 
-    bool eof;
+    int eof;
     unsigned int pagesDone;
 
     eof = FALSE;
diff --git a/converter/ppm/411toppm.c b/converter/ppm/411toppm.c
index b5e3c03b..eb2372a5 100644
--- a/converter/ppm/411toppm.c
+++ b/converter/ppm/411toppm.c
@@ -192,6 +192,7 @@ YUVtoPPM(FILE  * const ifP,
 int
 main(int argc, const char **argv) {
 
+    pixval const maxval = 255;
     struct CmdlineInfo cmdline;
     FILE  * ifP;
     pixel * pixrow;
@@ -208,13 +209,16 @@ main(int argc, const char **argv) {
 
     ifP = pm_openr(cmdline.inputFileName);
 
-    ppm_writeppminit(stdout, cmdline.width, cmdline.height, 255, 0);
+    ppm_writeppminit(stdout, cmdline.width, cmdline.height, maxval, 0);
 
-    for (row = 0; row < cmdline.height; row++) {
+    for (row = 0; row < cmdline.height; ++row) {
         YUVtoPPM(ifP, cmdline.width, cmdline.height, pixrow);
-        ppm_writeppmrow(stdout, pixrow, cmdline.width, 255, 0);
+        ppm_writeppmrow(stdout, pixrow, cmdline.width, maxval, 0);
     }
 
+    if (fgetc(ifP) != EOF)
+        pm_message("Extraneous data at end of image.");
+
     pm_close(ifP);
     ppm_freerow(pixrow);
 
diff --git a/converter/ppm/ppmtompeg/bframe.c b/converter/ppm/ppmtompeg/bframe.c
index 1dbc1846..f5009d6c 100644
--- a/converter/ppm/ppmtompeg/bframe.c
+++ b/converter/ppm/ppmtompeg/bframe.c
@@ -523,7 +523,7 @@ makeNonSkipBlock(int              const y,
                  MpegFrame *      const curr, 
                  MpegFrame *      const prev, 
                  MpegFrame *      const next,
-                 boolean          const specificsOn,
+                 bool             const specificsOn,
                  int              const mbAddress,
                  int              const QScale,
                  const LumBlock * const currentBlockP,
diff --git a/converter/ppm/ppmtompeg/frame.c b/converter/ppm/ppmtompeg/frame.c
index 09f46f66..75b209f8 100644
--- a/converter/ppm/ppmtompeg/frame.c
+++ b/converter/ppm/ppmtompeg/frame.c
@@ -753,7 +753,7 @@ Frame_AllocHalf(MpegFrame * const frameP) {
  *===========================================================================*/
 void
 Frame_AllocDecoded(MpegFrame * const frameP,
-                   boolean     const makeReference) {
+                   bool        const makeReference) {
 
     if (frameP->decoded_y != NULL) {
         /* already allocated */
diff --git a/converter/ppm/ppmtompeg/headers/frames.h b/converter/ppm/ppmtompeg/headers/frames.h
index f2bcf6ae..966d9214 100644
--- a/converter/ppm/ppmtompeg/headers/frames.h
+++ b/converter/ppm/ppmtompeg/headers/frames.h
@@ -255,7 +255,6 @@ extern int gopSize;
 extern int slicesPerFrame;
 extern int blocksPerSlice;
 extern int referenceFrame;
-extern boolean specificsOn;
 extern int quietTime;       /* shut up for at least quietTime seconds;
                  * negative means shut up forever
                  */
diff --git a/converter/ppm/ppmtompeg/headers/param.h b/converter/ppm/ppmtompeg/headers/param.h
index c7f57b44..0c6d8e5c 100644
--- a/converter/ppm/ppmtompeg/headers/param.h
+++ b/converter/ppm/ppmtompeg/headers/param.h
@@ -51,7 +51,7 @@ extern char machineName[MAX_MACHINES][256];
 extern char userName[MAX_MACHINES][256];
 extern char executable[MAX_MACHINES][1024];
 extern char remoteParamFile[MAX_MACHINES][1024];
-extern boolean remote[MAX_MACHINES];
+extern bool remote[MAX_MACHINES];
 extern char currentPath[MAXPATHLEN];
 extern char currentFramePath[MAXPATHLEN];
 extern char currentGOPPath[MAXPATHLEN];
@@ -62,12 +62,21 @@ extern int realWidth, realHeight;
 extern char ioConversion[1024];
 extern char slaveConversion[1024];
 extern FILE * bitRateFile;
-extern boolean showBitRatePerFrame;
-extern boolean computeMVHist;
 extern const double VidRateNum[9];
-extern boolean keepTempFiles;
+extern bool keepTempFiles;
+extern int outputWidth, outputHeight;
+extern bool specificsOn;
+extern char specificsFile[256];
+extern char specificsDefines[1024];
+extern bool GammaCorrection;
+extern float GammaValue;
+extern char userDataFileName[256];
 
 
+/* Defined in ppmtompeg.c; computed from command line */
+extern bool showBitRatePerFrame;
+extern bool computeMVHist;
+
 /*
  * Copyright (c) 1995 The Regents of the University of California.
  * All rights reserved.
diff --git a/converter/ppm/ppmtompeg/parallel.c b/converter/ppm/ppmtompeg/parallel.c
index 50381271..2835c67c 100644
--- a/converter/ppm/ppmtompeg/parallel.c
+++ b/converter/ppm/ppmtompeg/parallel.c
@@ -968,7 +968,7 @@ IoServer(struct inputSource * const inputSourceP,
 -----------------------------------------------------------------------------*/
     int       ioPortNum;
     int       serverSocket;
-    boolean   done;
+    bool   done;
     unsigned char   *bigBuffer;
         /* A work buffer that we keep around permanently.  We increase
            its size as needed, but never shrink it.
diff --git a/converter/ppm/ppmtompeg/param.c b/converter/ppm/ppmtompeg/param.c
index 15f13473..45605981 100644
--- a/converter/ppm/ppmtompeg/param.c
+++ b/converter/ppm/ppmtompeg/param.c
@@ -73,14 +73,14 @@
 #define LAST_OPTION           15
 
 /* put any non-required options after LAST_OPTION */
-#define OPTION_RESIZE	      16
+#define OPTION_RESIZE         16
 #define OPTION_IO_CONVERT     17
 #define OPTION_SLAVE_CONVERT  18
-#define OPTION_IQTABLE	      19
-#define OPTION_NIQTABLE	      20
+#define OPTION_IQTABLE        19
+#define OPTION_NIQTABLE       20
 #define OPTION_FRAME_RATE     21
 #define OPTION_ASPECT_RATIO   22
-#define OPTION_YUV_SIZE	      23
+#define OPTION_YUV_SIZE       23
 #define OPTION_SPECIFICS      24
 #define OPTION_DEFS_SPECIFICS 25
 #define OPTION_BUFFER_SIZE    26
@@ -98,48 +98,49 @@
  * GLOBAL VARIABLES *
  *==================*/
 
-extern char currentPath[MAXPATHLEN];
-char	outputFileName[256];
-int	outputWidth, outputHeight;
+char outputFileName[256];
+int outputWidth, outputHeight;
 char inputConversion[1024];
 char ioConversion[1024];
 char slaveConversion[1024];
 char yuvConversion[256];
 char specificsFile[256],specificsDefines[1024]="";
-boolean GammaCorrection=FALSE;
-float   GammaValue;
+bool GammaCorrection=FALSE;
+float GammaValue;
 char userDataFileName[256]={0};
-boolean specificsOn = FALSE;
+bool specificsOn = FALSE;
 char currentGOPPath[MAXPATHLEN];
 char currentFramePath[MAXPATHLEN];
-boolean keepTempFiles;
+bool keepTempFiles;
+int numMachines;
+char machineName[MAX_MACHINES][256];
+char userName[MAX_MACHINES][256];
+char executable[MAX_MACHINES][1024];
+char remoteParamFile[MAX_MACHINES][1024];
+bool remote[MAX_MACHINES];
+int mult_seq_headers = 0;  /* 0 for none, N for header/N GOPs */
+
+
+extern char currentPath[MAXPATHLEN];
 
 static const char * const optionText[LAST_OPTION+1] = { 
     "GOP_SIZE", "PATTERN", "PIXEL", "PQSCALE",
     "OUTPUT", "RANGE", "PSEARCH_ALG", "IQSCALE", "INPUT_DIR",
     "INPUT_CONVERT", "INPUT", "BQSCALE", "BASE_FILE_FORMAT",
     "SLICES_PER_FRAME", "BSEARCH_ALG", "REFERENCE_FRAME"};
-static boolean optionSeen[NUM_OPTIONS+1];
+static bool optionSeen[NUM_OPTIONS+1];
     /* optionSeen[x] means we have seen option x in the parameter file we've
        been reading.
     */
 
-int numMachines;
-char	machineName[MAX_MACHINES][256];
-char	userName[MAX_MACHINES][256];
-char	executable[MAX_MACHINES][1024];
-char	remoteParamFile[MAX_MACHINES][1024];
-boolean	remote[MAX_MACHINES];
-int mult_seq_headers = 0;  /* 0 for none, N for header/N GOPs */
-
 
 /*===========================================================================*
  *
  * SkipSpacesTabs
  *
- *	skip all spaces and tabs
+ *  skip all spaces and tabs
  *
- * RETURNS:	point to next character not a space or tab
+ * RETURNS: point to next character not a space or tab
  *
  * SIDE EFFECTS:    none
  *
@@ -172,13 +173,13 @@ static int
 GetAspectRatio(const char * const p)
 {
   float   ratio;
-  int	  ttRatio;
+  int     ttRatio;
   int     retval;
 
   sscanf(p, "%f", &ratio);
   ttRatio = (int)(0.5+ratio*10000.0);
 
-  if ( ttRatio == 10000 )	      retval = 1;
+  if ( ttRatio == 10000 )         retval = 1;
   else if ( ttRatio ==  6735 )    retval = 2;
   else if ( ttRatio ==  7031 )    retval = 3;
   else if ( ttRatio ==  7615 )    retval = 4;
@@ -205,9 +206,9 @@ GetAspectRatio(const char * const p)
  *
  * ReadMachineNames
  *
- *	read a list of machine names for parallel execution
+ *  read a list of machine names for parallel execution
  *
- * RETURNS:	nothing
+ * RETURNS: nothing
  *
  * SIDE EFFECTS:    machine info updated
  *
@@ -219,7 +220,7 @@ ReadMachineNames(FILE * const fpointer)
   const char *charPtr;
 
   while ( (fgets(input, 256, fpointer) != NULL) &&
-	 (strncmp(input, "END_PARALLEL", 12) != 0) ) {
+     (strncmp(input, "END_PARALLEL", 12) != 0) ) {
     if ( input[0] == '#' || input[0] == '\n') {
       continue;
     }
@@ -229,13 +230,13 @@ ReadMachineNames(FILE * const fpointer)
       remote[numMachines] = TRUE;
 
       sscanf(charPtr, "%s %s %s %s", machineName[numMachines],
-	     userName[numMachines], executable[numMachines],
-	     remoteParamFile[numMachines]);
+         userName[numMachines], executable[numMachines],
+         remoteParamFile[numMachines]);
     } else {
       remote[numMachines] = FALSE;
 
       sscanf(input, "%s %s %s", machineName[numMachines],
-	     userName[numMachines], executable[numMachines]);
+         userName[numMachines], executable[numMachines]);
     }
 
     numMachines++;
@@ -259,13 +260,13 @@ static int
 GetFrameRate(const char * const p)
 {
   float   rate;
-  int	  thouRate;
+  int     thouRate;
   int     retval;
 
   sscanf(p, "%f", &rate);
   thouRate = (int)(0.5+1000.0*rate);
 
-  if ( thouRate == 23976 )	       retval = 1;
+  if ( thouRate == 23976 )         retval = 1;
   else if ( thouRate == 24000 )    retval = 2;
   else if ( thouRate == 25000 )    retval = 3;
   else if ( thouRate == 29970 )    retval = 4;
diff --git a/converter/ppm/ppmtompeg/ppmtompeg.c b/converter/ppm/ppmtompeg/ppmtompeg.c
index 6e7e9833..b8ef37f1 100644
--- a/converter/ppm/ppmtompeg/ppmtompeg.c
+++ b/converter/ppm/ppmtompeg/ppmtompeg.c
@@ -65,7 +65,8 @@ int main _ANSI_ARGS_((int argc, char **argv));
  * GLOBAL VARIABLES *
  *==================*/
 
-boolean showBitRatePerFrame;
+bool showBitRatePerFrame;
+bool computeMVHist = FALSE;
 boolean frameSummary;
 
 extern time_t IOtime;
@@ -79,9 +80,7 @@ boolean noFrameSummaryOption = FALSE;
 boolean debugSockets = FALSE;
 boolean debugMachines = FALSE;
 boolean bitRateInfoOption = FALSE;
-boolean computeMVHist = FALSE;
 int     baseFormat;
-extern  boolean specificsOn;
 extern  FrameSpecList *fsl;
 boolean pureDCT=FALSE;
 char    encoder_name[1024];
diff --git a/converter/ppm/ppmtompeg/readframe.c b/converter/ppm/ppmtompeg/readframe.c
index 112ebdf0..cac6bdad 100644
--- a/converter/ppm/ppmtompeg/readframe.c
+++ b/converter/ppm/ppmtompeg/readframe.c
@@ -67,9 +67,6 @@ struct YuvLine {
  * Global VARIABLES *
  *==================*/
 
-extern boolean GammaCorrection;
-extern float GammaValue;
-extern int outputWidth,outputHeight;
 boolean resizeFrame;
 const char *CurrFile;
 
@@ -828,7 +825,7 @@ MpegFrame *mf;
 int w,h;
 {
   static int GammaVal[256];
-  static boolean init_done=FALSE;
+  static bool init_done=FALSE;
   int i,j;
 
   if (!init_done) {
@@ -882,7 +879,7 @@ DoKillDim(mf, w, h)
 MpegFrame *mf;
 int w,h;
 {
-  static boolean init_done=FALSE;
+  static bool init_done=FALSE;
   static unsigned char mapper[256];
   register int i,j;
   double slope, intercept;
diff --git a/converter/ppm/ppmtompeg/specifics.c b/converter/ppm/ppmtompeg/specifics.c
index d2093e7f..ffbce80a 100644
--- a/converter/ppm/ppmtompeg/specifics.c
+++ b/converter/ppm/ppmtompeg/specifics.c
@@ -46,14 +46,12 @@
 #include <stdio.h>
 #include <string.h>
 #include "prototypes.h"
+#include "param.h"
 
 /*==================*
  * GLOBAL VARIABLES *
  *==================*/
 
-extern boolean specificsOn;
-extern char specificsFile[];
-extern char specificsDefines[];
 FrameSpecList *fsl;
 
 /*=====================*
diff --git a/converter/ppm/ppmtopjxl.c b/converter/ppm/ppmtopjxl.c
index 91cd1a45..ddf49638 100644
--- a/converter/ppm/ppmtopjxl.c
+++ b/converter/ppm/ppmtopjxl.c
@@ -12,6 +12,7 @@
  *
  */
 
+#include <assert.h>
 #include <stdio.h>
 #include <math.h>
 #include <string.h>
@@ -33,7 +34,7 @@ const char * const usage="[-nopack] [-gamma <n>] [-presentation] [-dark]\n\
 #define PCL_MAXHEIGHT 32767
 #define PCL_MAXVAL 255
 
-static int nopack = 0;
+static bool nopack = false;
 static int dark = 0;
 static int diffuse = 0;
 static int dither = 0;
@@ -73,16 +74,28 @@ static const struct options {
    {"-nopack",       BOOL, &nopack },
 };
 
-#define putword(w) (putchar(((w)>>8) & 255), putchar((w) & 255))
 
-static int 
-bitsperpixel(int v) {
-   int bpp = 0;
-   while (v > 0) {  /* calculate # bits for value */
-      ++bpp;
-      v>>=1;
-   }
-   return (bpp);
+
+static void
+putword(unsigned short const w) {
+    putchar((w >> 8) & 0xff);
+    putchar((w >> 0) & 0xff);
+}
+
+
+
+static unsigned int
+bitsperpixel(unsigned int v) {
+
+    unsigned int bpp;
+
+    /* calculate # bits for value */
+    
+    for (bpp = 0; v > 0; ) {
+        ++bpp;
+        v >>= 1;
+    }
+    return bpp;
 }
 
 
@@ -94,101 +107,117 @@ static char *outrow = NULL;
 static signed char *runcnt = NULL;
 
 static void 
-putbits(b, n) {
-    /* put #n bits in b out, packing into bytes; n=0 flushes bits */
-    /* n should never be > 8 */
-
-   static int out = 0;
-   static int cnt = 0;
-   static int num = 0;
-   static int pack = 0;
-   if (n) {
-      int xo = 0;
-      int xc = 0;
-      if (cnt+n > 8) {  /* overflowing current byte? */
-     xc = cnt + n - 8;
-     xo = (b & ~(-1 << xc)) << (8-xc);
-     n -= xc;
-     b >>= xc;
-      }
-      cnt += n;
-      out |= (b & ~(-1 << n)) << (8-cnt);
-      if (cnt >= 8) {
-     inrow[num++] = out;
-     out = xo;
-     cnt = xc;
-      }
-   } else { /* flush row */
-      int i;
-      if (cnt) {
-     inrow[num++] = out;
-     out = cnt = 0;
-      }
-      for (; num > 0 && inrow[num-1] == 0; num--); /* remove trailing zeros */
-      printf("\033*b"); 
-      if (num && !nopack) {            /* TIFF 4.0 packbits encoding */
-     int start = 0;
-     int next;
-     runcnt[start] = 0;
-     for (i = 1; i < num; i++) {
-        if (inrow[i] == inrow[i-1]) {
-           if (runcnt[start] <= 0 && runcnt[start] > -127)
-          runcnt[start]--;
-           else
-          runcnt[start = i] = 0;
-        } else {
-           if (runcnt[start] >= 0 && runcnt[start] < 127)
-          runcnt[start]++;
-           else
-          runcnt[start = i] = 0;
+putbits(int const bArg,
+        int const nArg) {
+/*----------------------------------------------------------------------------
+  Put 'n' bits in 'b' out, packing into bytes; n=0 flushes bits.
+
+  n should never be > 8 
+-----------------------------------------------------------------------------*/
+    static int out = 0;
+    static int cnt = 0;
+    static int num = 0;
+    static bool pack = false;
+
+    int b;
+    int n;
+
+    b = bArg;
+    n = nArg;
+
+    if (n) {
+        int xo = 0;
+        int xc = 0;
+
+        assert(n <= 8);
+
+        if (cnt + n > 8) {  /* overflowing current byte? */
+            xc = cnt + n - 8;
+            xo = (b & ~(-1 << xc)) << (8-xc);
+            n -= xc;
+            b >>= xc;
         }
-     }
-     start = 0;
-     for (i = 0; i < num; i = next) {
-        int count = runcnt[i];
-        int from = i;
-        if (count >= 0) { /* merge two-byte runs */
-           for (;;) {
-          next = i+1+runcnt[i];
-          if(next >= num || runcnt[next] < 0 ||
-             count+runcnt[next]+1 > 127)
-             break;
-          count += runcnt[next]+1;
-          i = next;
-           }
+        cnt += n;
+        out |= (b & ~(-1 << n)) << (8-cnt);
+        if (cnt >= 8) {
+            inrow[num++] = out;
+            out = xo;
+            cnt = xc;
         }
-        next =  i + 1 + ((runcnt[i] < 0) ? -runcnt[i] : runcnt[i]);
-        if (next < num && count > 0 &&
-        runcnt[next] < 0 && runcnt[next] > -127) {
-           count--;
-           next--;
-           runcnt[next] = runcnt[next+1]-1;
+    } else { /* flush row */
+        if (cnt) {
+            inrow[num++] = out;
+            out = cnt = 0;
         }
-        outrow[start++] = count;
-        if (count >= 0) {
-           while (count-- >= 0)
-          outrow[start++] = inrow[from++];
-        } else
-           outrow[start++] = inrow[from];
-     }
-     if (start < num) {
-        num = start;
-        if (!pack) {
-           printf("2m");
-           pack = 1;
+        for (; num > 0 && inrow[num-1] == 0; --num);
+            /* remove trailing zeros */
+        printf("\033*b"); 
+        if (num && !nopack) {            /* TIFF 4.0 packbits encoding */
+            unsigned int i;
+            int start = 0;
+            int next;
+            runcnt[start] = 0;
+            for (i = 1; i < num; ++i) {
+                if (inrow[i] == inrow[i-1]) {
+                    if (runcnt[start] <= 0 && runcnt[start] > -127)
+                        runcnt[start]--;
+                    else
+                        runcnt[start = i] = 0;
+                } else {
+                    if (runcnt[start] >= 0 && runcnt[start] < 127)
+                        runcnt[start]++;
+                    else
+                        runcnt[start = i] = 0;
+                }
+            }
+            for (i = 0, start = 0; i < num; i = next) {
+                int count = runcnt[i];
+                int from = i;
+                if (count >= 0) { /* merge two-byte runs */
+                    for (;;) {
+                        next = i+1+runcnt[i];
+                        if(next >= num || runcnt[next] < 0 ||
+                           count+runcnt[next]+1 > 127)
+                            break;
+                        count += runcnt[next]+1;
+                        i = next;
+                    }
+                }
+                next =  i + 1 + ((runcnt[i] < 0) ? -runcnt[i] : runcnt[i]);
+                if (next < num && count > 0 &&
+                    runcnt[next] < 0 && runcnt[next] > -127) {
+                    --count;
+                    --next;
+                    runcnt[next] = runcnt[next+1]-1;
+                }
+                outrow[start++] = count;
+                if (count >= 0) {
+                    while (count-- >= 0)
+                        outrow[start++] = inrow[from++];
+                } else
+                    outrow[start++] = inrow[from];
+            }
+            if (start < num) {
+                num = start;
+                if (!pack) {
+                    printf("2m");
+                    pack = true;
+                }
+            } else {
+                if (pack) {
+                    printf("0m");
+                    pack = false;
+                }
+            }
         }
-     } else {
-        if (pack) {
-           printf("0m");
-           pack = 0;
+        printf("%dW", num);
+        {
+            unsigned int i;
+            for (i = 0; i < num; ++i)
+                putchar(pack ? outrow[i] : inrow[i]);
         }
-     }
-      }
-      printf("%dW", num);
-      for (i = 0; i < num; i++)
-     putchar(pack ? outrow[i] : inrow[i]);
-      num = 0; /* new row */
-   }
+        num = 0; /* new row */
+    }
 }
 
 
diff --git a/converter/ppm/ppmtoyuv.c b/converter/ppm/ppmtoyuv.c
index 7d843cc0..75f79c1e 100644
--- a/converter/ppm/ppmtoyuv.c
+++ b/converter/ppm/ppmtoyuv.c
@@ -19,79 +19,102 @@
 
 #include "ppm.h"
 
-int
-main(argc, argv)
-char **argv;
-{
-	FILE *ifp;
-	pixel          *pixelrow;
-	register pixel *pP;
-	int             rows, cols, format, row;
-	register int    col;
-	pixval          maxval;
-	unsigned long   y1, y2=0, u=0, v=0, u0=0, u1, u2, v0=0, v1, v2;
-	unsigned char  *yuvbuf;
-
-
-	ppm_init(&argc, argv);
 
-	if (argc > 2) pm_usage("[ppmfile]");
 
-	if (argc == 2) ifp = pm_openr(argv[1]);
-	else ifp = stdin;
-
-	ppm_readppminit(ifp, &cols, &rows, &maxval, &format);
+static void
+convertRow(const pixel *   const pixelrow,
+           unsigned int    const cols,
+           unsigned char * const yuvBuf,
+           unsigned long * const uP,
+           unsigned long * const vP,
+           unsigned long * const u0P,
+           unsigned long * const v0P,
+           unsigned long * const y2CarryP) {
+
+    unsigned int col;
+    unsigned char * yuvptr;
+
+    for (col = 0, yuvptr = &yuvBuf[0]; col < cols; col += 2) {
+        unsigned long y1, y2, u1, u2, v1, v2;
+
+        {
+            /* first pixel gives Y and 0.5 of chroma */
+            pixval const r = PPM_GETR(pixelrow[col]);
+            pixval const g = PPM_GETG(pixelrow[col]);
+            pixval const b = PPM_GETB(pixelrow[col]);
+            
+            y1 = 16829 * r + 33039 * g +  6416 * b + (*y2CarryP & 0xffff);
+            u1 = -4853 * r -  9530 * g + 14383 * b;
+            v1 = 14386 * r - 12046 * g -  2340 * b;
+        }
+        {
+            /* second pixel gives Y and 0.25 of chroma */
+            pixval const r = PPM_GETR(pixelrow[col + 1]);
+            pixval const g = PPM_GETG(pixelrow[col + 1]);
+            pixval const b = PPM_GETB(pixelrow[col + 1]);
+
+            y2 = 16829 * r + 33039 * g + 6416 * b + (y1 & 0xffff);
+            u2 = -2426 * r -  4765 * g + 7191 * b;
+            v2 =  7193 * r -  6023 * g - 1170 * b;
+        }
+        /* filter the chroma */
+        *uP = *u0P + u1 + u2 + (*uP & 0xffff);
+        *vP = *v0P + v1 + v2 + (*vP & 0xffff);
+
+        *u0P = u2;
+        *v0P = v2;
+
+        *yuvptr++ = (*uP >> 16) + 128;
+        *yuvptr++ = (y1  >> 16) +  16;
+        *yuvptr++ = (*vP >> 16) + 128;
+        *yuvptr++ = (y2  >> 16) +  16;
+
+        *y2CarryP = y2;
+    }
+}
 
-    if (cols % 2 != 0)
-        pm_error("Image must have even number of columns.\n"
-                 "This image is %d columns wide.  Try Pnmcut.", cols);
 
-	pixelrow = ((pixel*) pm_allocrow( cols, sizeof(pixel) ));
-	yuvbuf = (unsigned char *) pm_allocrow( cols, 2 );
 
-	for (row = 0; row < rows; ++row) {
-		unsigned char *yuvptr;
+int
+main(int argc, const char **argv) {
 
-		ppm_readppmrow(ifp, pixelrow, cols, maxval, format);
+    FILE * ifP;
+    pixel * pixelrow;
+    int rows, cols, format;
+    pixval maxval;
+    unsigned int row;
+    unsigned char  * yuvBuf;
+    unsigned long u, v, u0, v0, y2Carry;
 
-		for (col = 0, pP = pixelrow, yuvptr=yuvbuf; col < cols; col += 2, ++pP) {
-			pixval r, g, b;
+    pm_proginit(&argc, argv);
 
-			/* first pixel gives Y and 0.5 of chroma */
-			r = PPM_GETR(*pP);
-			g = PPM_GETG(*pP);
-			b = PPM_GETB(*pP);
+    if (argc-1 > 1)
+        pm_error("Too many arguments: %u.  The only possible argument "
+                 "is the name of the input file", argc-1);
 
-			y1 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y2);
-			u1 = -4853 * r - 9530 * g + 14383 * b;
-			v1 = 14386 * r - 12046 * g - 2340 * b;
+    if (argc-1 == 1)
+        ifP = pm_openr(argv[1]);
+    else
+        ifP = stdin;
 
-			pP++;
-			/* second pixel just yields a Y and 0.25 U, 0.25 V */
-			r = PPM_GETR(*pP);
-			g = PPM_GETG(*pP);
-			b = PPM_GETB(*pP);
+    ppm_readppminit(ifP, &cols, &rows, &maxval, &format);
 
-			y2 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y1);
-			u2 = -2426 * r - 4765 * g + 7191 * b;
-			v2 = 7193 * r - 6023 * g - 1170 * b;
+    if (cols % 2 != 0)
+        pm_error("Image must have even number of columns.\n"
+                 "This image is %u columns wide.  Try Pamcut.", cols);
 
-			/* filter the chroma */
-			u = u0 + u1 + u2 + (0xffff & u);
-			v = v0 + v1 + v2 + (0xffff & v);
+    pixelrow = ppm_allocrow(cols);
+    yuvBuf = (unsigned char *) pm_allocrow(cols, 2);
 
-			u0 = u2;
-			v0 = v2;
+    for (row = 0, u = v = u0 = v0 = y2Carry = 0; row < rows; ++row) {
+        ppm_readppmrow(ifP, pixelrow, cols, maxval, format);
 
-			*yuvptr++ = (u >> 16) + 128;
-			*yuvptr++ = (y1 >> 16) + 16;
-			*yuvptr++ = (v >> 16) + 128;
-			*yuvptr++ = (y2 >> 16) + 16;
-		}
-		fwrite(yuvbuf, cols*2, 1, stdout);
-	}
+        convertRow(pixelrow, cols, yuvBuf, &u, &v, &u0, &v0, &y2Carry);
+        
+        fwrite(yuvBuf, cols*2, 1, stdout);
+    }
 
-	pm_close(ifp);
+    pm_close(ifP);
 
-	exit(0);
+    return 0;
 }
diff --git a/converter/ppm/sldtoppm.c b/converter/ppm/sldtoppm.c
index ad16a649..6ba4cb40 100644
--- a/converter/ppm/sldtoppm.c
+++ b/converter/ppm/sldtoppm.c
@@ -26,23 +26,20 @@
 #include <string.h>
 #include <math.h>
 
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "ppmdraw.h"
 #include "nstring.h"
-#ifdef DEBUG
 #include <assert.h>
-#else
-#define assert(x)
-#endif
+
+#include "autocad.h"                  /* AutoCAD standard color assignments */
+
 
 /*  Define a variable type accepting numbers -127 <= n <= 127.  But note
     that we still expect it to act UNSIGNED. */
 
 #define smallint unsigned char        /* Small integers */
 
-#define TRUE     1
-#define FALSE    0
-
 #define EOS     '\0'
 
 /* Screen point */
@@ -70,18 +67,17 @@ typedef void (slvecfn)(struct svector * vec, int color);
 typedef void (slfloodfn)(struct spolygon * poly, int color);
 
 
+static unsigned long const pixmaxval = 255;  /* Largest pixel value */
+
 static int ixdots, iydots;        /* Screen size in dots */
-static FILE *slfile;              /* Slide file descriptor */
-static int blither = FALSE;       /* Dump slide file information ? */
-static int info = FALSE;          /* Print header information */
+static FILE * slfile;             /* Slide file descriptor */
+static bool blither;              /* Dump slide file information ? */
+static bool info;                 /* Print header information */
 static pixel **pixels;            /* Pixel map */
-static int pixcols, pixrows;          /* Pixel map size */
-#define pixmaxval 255             /* Largest pixel value */
+static int pixcols, pixrows;      /* Pixel map size */
 static double uscale = -1;        /* Uniform scale factor */
 static int sxsize = -1, sysize = -1;  /* Scale to X, Y size ? */
 
-#include "autocad.h"                  /* AutoCAD standard color assignments */
-
 /*  Local variables  */
 
 struct slhead {
@@ -94,11 +90,11 @@ struct slhead {
     char spad;                /* Pad to even byte length */
 };
 
-static int adjust = FALSE;        /* Adjust to correct aspect ratio ? */
-static struct slhead slfrof;          /* Slide file header */
-static long xfac, yfac;           /* Aspect ratio scale factors */
+static bool adjust;           /* Adjust to correct aspect ratio ? */
+static struct slhead slfrof;  /* Slide file header */
+static long xfac, yfac;       /* Aspect ratio scale factors */
 
-static int sdrawkcab;
+static bool sdrawkcab;
     /* Slide drawing kinematic conversion of ass-backwards data flag */
 
 
@@ -108,7 +104,7 @@ static int sdrawkcab;
 */
 
 static int
-extend(smallint ch) {
+extend(unsigned char const ch) {
     return ((int) ((ch & 0x80) ? (ch | ~0xFF) : ch));
 }
 
@@ -136,9 +132,9 @@ sli(void) {
 
 static int 
 slib(void) {
-    smallint ch = 0;
+    unsigned char ch;
 
-    if (fread(&ch, sizeof ch, 1, slfile) != 1) {
+    if (fread(&ch, sizeof(ch), 1, slfile) != 1) {
         pm_error("error reading slide file");
     }
     return extend(ch);
@@ -171,22 +167,28 @@ slidefind(const char * const sname,
     char uname[32];
     unsigned char libent[36];
     long pos;
+    bool found;
+    bool eof;
 
     if (dironly)
         pm_message("Slides in library:");
     else {
-        int i;
+        unsigned int i;
         const char * ip;
         
         ip = sname; /* initial value */
         
-        for (i = 0; i < 31; i++) {
-            char ch = *ip++;
+        for (i = 0; i < 31; ++i) {
+            char const ch = *ip++;
             if (ch == EOS)
                 break;
-            if (ucasen && ISLOWER(ch))
-                ch = TOUPPER(ch);
-            uname[i] = ch;
+
+            {
+                char const upperCh =
+                    ucasen && islower(ch) ? toupper(ch) : ch;
+                
+                uname[i] = upperCh;
+            }
         }
         uname[i] = EOS;
     }
@@ -199,31 +201,38 @@ slidefind(const char * const sname,
     }
     pos = 32;
     
-    /* Search for a slide with the requested name. */
+    /* Search for a slide with the requested name or list the directory */
     
-    while (TRUE) {
-        if ((fread(libent, 36, 1, slfile) != 1) ||
-            (strlen((char *)libent) == 0)) {
-            if (dironly) {
-                return;
-            }
-            pm_error("slide %s not in library.", sname);
-        }
+    for (found = false, eof = false; !found && !eof; ) {
+        size_t readCt;
+        readCt = fread(libent, 36, 1, slfile);
+        if (readCt != 1)
+            eof = true;
+        else if (strlen((char *)libent) == 0)
+            eof = true;
+    }
+    if (!eof) {
         pos += 36;
         if (dironly) {
             pm_message("  %s", libent);
         } else if (streq((char *)libent, uname)) {
-            long dpos = (((((libent[35] << 8) | libent[34]) << 8) |
-                          libent[33]) << 8) | libent[32];
+            long dpos;
+
+            dpos = (((((libent[35] << 8) | libent[34]) << 8) |
+                     libent[33]) << 8) | libent[32];
+
             if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
                 dpos -= pos;
         
                 while (dpos-- > 0)
                     getc(slfile);
             }
-            break;
+            found = true;
         }
     }
+
+    if (!found && !dironly)
+        pm_error("slide '%s' not in library.", sname);
 }
 
 
@@ -329,7 +338,7 @@ slider(slvecfn   slvec,
     
     /* Process the header of the slide file.  */
     
-    sdrawkcab = FALSE;            /* Initially guess byte order is OK */
+    sdrawkcab = false;            /* Initially guess byte order is OK */
     fread(slfrof.slh, 17, 1, slfile);
     fread(&slfrof.sntype, sizeof(char), 1, slfile);
     fread(&slfrof.slevel, sizeof(char), 1, slfile);
@@ -364,12 +373,12 @@ slider(slvecfn   slvec,
     */
 
     if (btest != rtest) {
-        sdrawkcab = TRUE;
-#define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8)
+        sdrawkcab = true;
+        #define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8)
         rshort(slfrof.sxdots);
         rshort(slfrof.sydots);
         rshort(slfrof.shwfill);
-#undef rshort
+        #undef rshort
     }
     
     /* Dump the header if we're blithering. */
@@ -413,7 +422,7 @@ slider(slvecfn   slvec,
         ixdots = slfrof.sxdots;
         iydots = slfrof.sydots;
         dsar = slfrof.sdsar;
-        adjust = FALSE;           /* Mark no adjustment needed */
+        adjust = false;           /* Mark no adjustment needed */
     }
 
     /* If there's a uniform scale factor specified, apply it. */
@@ -571,32 +580,42 @@ slider(slvecfn   slvec,
 /*  Main program. */
 
 int
-main(int    argc,
-     char * argv[]) {
+main(int          argc,
+     const char * argv[]) {
 
     int argn;
     const char * const usage = "[-verbose] [-info] [-adjust] [-scale <s>]\n\
 [-dir] [-lib|-Lib <name>]\n\
 [-xsize|-width <x>] [-ysize|-height <y>] [sldfile]";
-    int scalespec = FALSE, widspec = FALSE, hgtspec = FALSE, dironly = FALSE,
-        ucasen;
+    bool dironly;
+    bool hgtspec;
+    bool widspec;
+    bool scalespec;
+    bool ucasen;
     const char * slobber;       /* Slide library item */
 
+    pm_proginit(&argc, argv);
+    argn = 1;
 
     slobber = NULL;
-
-    ppm_init(&argc, argv);
-    argn = 1;
+    dironly = false;
+    hgtspec = false;
+    widspec = false;
+    scalespec = false;
+    ucasen = false;
+    blither = false;
+    info = false;
+    adjust = false;
 
     while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
         if (pm_keymatch(argv[argn], "-verbose", 2)) {
-            blither = TRUE;
+            blither = true;
         } else if (pm_keymatch(argv[argn], "-adjust", 2)) {
-            adjust = TRUE;
+            adjust = true;
         } else if (pm_keymatch(argv[argn], "-dir", 2)) {
-            dironly = TRUE;
+            dironly = true;
         } else if (pm_keymatch(argv[argn], "-info", 2)) {
-            info = TRUE;
+            info = true;
         } else if (pm_keymatch(argv[argn], "-lib", 2)) {
             if (slobber)
                 pm_error("already specified a library item");
@@ -616,7 +635,7 @@ main(int    argc,
             if (uscale <= 0.0) {
                 pm_error("scale factor must be greater than 0");
             }
-            scalespec = TRUE;
+            scalespec = true;
         } else if (pm_keymatch(argv[argn], "-xsize", 2) ||
                    pm_keymatch(argv[argn], "-width", 2)) {
             if (widspec) {
@@ -625,7 +644,7 @@ main(int    argc,
             argn++;
             if ((argn == argc) || (sscanf(argv[argn], "%d", &sxsize) != 1))
                 pm_usage(usage);
-            widspec = TRUE;
+            widspec = true;
         } else if (pm_keymatch(argv[argn], "-ysize", 2) ||
                    pm_keymatch(argv[argn], "-height", 2)) {
             if (hgtspec) {
@@ -634,7 +653,7 @@ main(int    argc,
             argn++;
             if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1))
                 pm_usage(usage);
-            hgtspec = TRUE;
+            hgtspec = true;
         } else {
             pm_usage(usage);
         }
@@ -665,7 +684,7 @@ main(int    argc,
  
     if (!dironly) {
         slider(draw, flood);
-        ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE);
+        ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, 0);
     }
     pm_close(slfile);
     pm_close(stdout);
diff --git a/converter/ppm/winicontoppm.c b/converter/ppm/winicontoppm.c
index 014eab40..6b1376b2 100644
--- a/converter/ppm/winicontoppm.c
+++ b/converter/ppm/winicontoppm.c
@@ -31,10 +31,9 @@
 #define MAJVERSION 0
 #define MINVERSION 4
 
-static int file_offset = 0;    /* not actually used, but useful for debug */
+static int fileOffset = 0;    /* not actually used, but useful for debug */
 static const char     er_read[] = "%s: read error";
 static const char *   infname;
-static FILE *   ifp;
 
 struct cmdlineInfo {
     /* All the information the user supplied in the command line,
@@ -53,8 +52,8 @@ struct cmdlineInfo {
 
 
 static void
-parseCommandLine ( int argc, char ** argv,
-                   struct cmdlineInfo *cmdlineP ) {
+parseCommandLine (int argc, const char ** argv,
+                  struct cmdlineInfo *cmdlineP ) {
 /*----------------------------------------------------------------------------
    parse program command line described in Unix standard form by argc
    and argv.  Return the information in the options as *cmdlineP.  
@@ -65,13 +64,15 @@ parseCommandLine ( int argc, char ** argv,
    Note that the strings we return are stored in the storage that
    was passed to us as the argv array.  We also trash *argv.
 -----------------------------------------------------------------------------*/
-    optEntry *option_def = malloc(100*sizeof(optEntry));
+    optEntry * option_def;
         /* Instructions to pm_optParseOptions3 on how to parse our options.
          */
     optStruct3 opt;
 
     unsigned int option_def_index;
 
+    MALLOCARRAY(option_def, 100);
+
     option_def_index = 0;   /* incremented by OPTENT3 */
     OPTENT3(0, "allicons",     OPT_FLAG,   NULL,                  
             &cmdlineP->allicons,       0 );
@@ -88,10 +89,9 @@ parseCommandLine ( int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
-
     if (argc-1 < 1) 
         cmdlineP->inputFilespec = "-";
     else
@@ -116,37 +116,37 @@ parseCommandLine ( int argc, char ** argv,
 
 
 static int 
-GetByte(void) {
+GetByte(FILE * const ifP) {
+
     int v;
    
-    if ((v = getc(ifp)) == EOF)
-    {
+    v = getc(ifP);
+    if (v == EOF)
         pm_error(er_read, infname);
-    }
    
     return v;
 }
+
+
    
 static short 
-GetShort(void) {
+GetShort(FILE * const ifP) {
+
     short v;
    
-    if (pm_readlittleshort(ifp, &v) == -1)
-    {
-        pm_error(er_read, infname);
-    }
-   
+    pm_readlittleshort(ifP, &v);
+
     return v;
 }
+
+
    
 static long 
-GetLong(void) {
+GetLong(FILE * const ifP) {
+
     long v;
    
-    if (pm_readlittlelong(ifp, &v) == -1)
-    {
-        pm_error(er_read, infname);
-    }
+    pm_readlittlelong(ifP, &v);
    
     return v;
 }
@@ -158,14 +158,18 @@ GetLong(void) {
  * functions.
  */
 static u1 
-readU1 (void) {
-    file_offset++;
-    return GetByte();
+readU1(FILE * const ifP) {
+
+    ++fileOffset;
+
+    return GetByte(ifP);
 }
 
+
+
 static u1 * 
-readU1String (int length)
-{
+readU1String (FILE *       const ifP,
+              unsigned int const length) {
    
     u1 * string;
     
@@ -173,150 +177,173 @@ readU1String (int length)
     if (string == NULL)
         pm_error("out of memory");
 
-    fread(string,sizeof(u1),length,ifp);
+    fread(string, sizeof(u1), length, ifP);
     string[length] = 0;
-    file_offset += length * sizeof(u1);
+    fileOffset += length * sizeof(u1);
+
     return string;
 }
 
+
+
 static u2 
-readU2 (void) {
-    file_offset +=2;
-    return GetShort();
+readU2 (FILE * const ifP) {
+
+    fileOffset +=2;
+
+    return GetShort(ifP);
 }
 
+
+
 static u4 
-readU4 (void) {
-    file_offset += 4;
-    return GetLong();
+readU4 (FILE * const ifP) {
+
+    fileOffset += 4;
+
+    return GetLong(ifP);
 }
 
+
+
 static IC_Entry 
-readICEntry (void) 
-{
-    IC_Entry entry;
+readICEntry(FILE * const ifP) {
+
+    IC_Entry entryP;
 
-    MALLOCVAR(entry);
+    MALLOCVAR(entryP);
 
-    if (entry == NULL)
+    if (entryP == NULL)
         pm_error("Unable to allcoate memory for IC entry");
 
-    entry->width         = readU1();
-    entry->height        = readU1();
-    entry->color_count   = readU1();
-    entry->reserved      = readU1();
-    entry->planes        = readU2();
-    entry->bitcount      = readU2();
-    entry->size_in_bytes = readU4();
-    entry->file_offset   = readU4();
-    entry->colors        = NULL;
-    entry->ih            = NULL;
-    entry->xorBitmap     = NULL;
-    entry->andBitmap     = NULL;
+    entryP->width         = readU1(ifP);
+    entryP->height        = readU1(ifP);
+    entryP->color_count   = readU1(ifP);
+    entryP->reserved      = readU1(ifP);
+    entryP->planes        = readU2(ifP);
+    entryP->bitcount      = readU2(ifP);
+    entryP->size_in_bytes = readU4(ifP);
+    entryP->file_offset   = readU4(ifP);
+    entryP->colors        = NULL;
+    entryP->ih            = NULL;
+    entryP->xorBitmap     = NULL;
+    entryP->andBitmap     = NULL;
     
-    return entry;
+    return entryP;
 }
 
 
 
 static IC_InfoHeader 
-readInfoHeader (IC_Entry entry) 
-{
-    IC_InfoHeader ih;
+readInfoHeader (FILE *   const ifP,
+                IC_Entry const entryP) {
+
+    IC_InfoHeader ihP;
 
-    MALLOCVAR(ih);
+    MALLOCVAR(ihP);
     
-    if (ih == NULL)
+    if (ihP == NULL)
         pm_error("Unable to allocate memory for info header");
 
-    ih->size            = readU4();
-    ih->width           = readU4();
-    ih->height          = readU4();
-    ih->planes          = readU2();
-    ih->bitcount        = readU2();
-    ih->compression     = readU4();
-    ih->imagesize       = readU4();
-    ih->x_pixels_per_m  = readU4();
-    ih->y_pixels_per_m  = readU4();
-    ih->colors_used     = readU4();
-    ih->colors_important = readU4();
+    ihP->size             = readU4(ifP);
+    ihP->width            = readU4(ifP);
+    ihP->height           = readU4(ifP);
+    ihP->planes           = readU2(ifP);
+    ihP->bitcount         = readU2(ifP);
+    ihP->compression      = readU4(ifP);
+    ihP->imagesize        = readU4(ifP);
+    ihP->x_pixels_per_m   = readU4(ifP);
+    ihP->y_pixels_per_m   = readU4(ifP);
+    ihP->colors_used      = readU4(ifP);
+    ihP->colors_important = readU4(ifP);
     
-    if (!entry->bitcount) entry->bitcount = ih->bitcount;
-    if (entry->color_count == 0 && 
-        entry->bitcount <= 8) entry->color_count = 256;
-    if (ih->compression) {
+    if (!entryP->bitcount)
+        entryP->bitcount = ihP->bitcount;
+    
+    if (entryP->color_count == 0 && entryP->bitcount <= 8)
+        entryP->color_count = 256;
+
+    if (ihP->compression) {
         pm_error("Can't handle compressed icons");
     }
-    return ih;
+    return ihP;
 }
 
-/*
- * I don't know why this isn't the same as the spec, it just <b>isn't</b>
- * The colors honestly seem to be stored BGR.  Bizarre.
- * 
- * I've checked this in the BMP code for bmptoppm and the gimp.  Guess the
- * spec I have is just plain wrong.
- */
+
+
 static IC_Color 
-readICColor (void) 
-{
-    IC_Color col;
+readICColor(FILE * const ifP)  {
+
+    IC_Color colorP;
 
-    MALLOCVAR(col);
+    MALLOCVAR(colorP);
 
-    if (col == NULL)
+    if (colorP == NULL)
         pm_error("Unable to allocate memory for color");
 
-    col->blue     = readU1();
-    col->green    = readU1();
-    col->red      = readU1();
-    col->reserved = readU1();
-    return col;
+    /* I don't know why this isn't the same as the spec, it just isn't.
+       The colors honestly seem to be stored BGR.  Bizarre.
+      
+       I've checked this in the BMP code for bmptoppm and the gimp.  Guess the
+       spec I have is just plain wrong.
+    */
+
+    colorP->blue     = readU1(ifP);
+    colorP->green    = readU1(ifP);
+    colorP->red      = readU1(ifP);
+    colorP->reserved = readU1(ifP);
+
+    return colorP;
 }
    
 
 
-/*
- * Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the 
- * encoding mechanism is different.
- * 
- * 8bpp => 1 byte/palette index.
- * 4bpp => High Nibble, Low Nibble
- * 1bpp => 1 palette value per bit, high bit 1st.
- */
 static u1 * 
-read1Bitmap (int width, int height) 
-{
-    int tmp;
-    int xBytes;
+read1Bitmap (FILE *       const ifP,
+             unsigned int const width,
+             unsigned int const height) {
+
+    unsigned int row;
+    unsigned int xByteCt;
     u1 * bitmap;
-    int wt = width;
+    unsigned int wt;
 
     MALLOCARRAY(bitmap, width * height);
     if (bitmap == NULL)
         pm_error("out of memory");
 
-    wt >>= 3;
-    if (wt & 3) {
-        wt = (wt & ~3) + 4;
+    /* Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the 
+       encoding mechanism is different.
+  
+       8bpp => 1 byte/palette index.
+       4bpp => High Nibble, Low Nibble
+       1bpp => 1 palette value per bit, high bit 1st.
+    */
+
+    wt = width >> 3;
+
+    if ((wt & 0x3) != 0) {
+        wt = (wt & ~0x3) + 4;
     }
-    xBytes = wt;
-    for (tmp = 0; tmp<height; tmp++ ) {
-        int x;
-        int rowByte = 0;
-        int xOrVal = 128;
-        u1 * row = readU1String(xBytes);
-        for (x = 0; x< width; x++) {
-            *(bitmap+((height-tmp-1)*width) + (x)) = 
-                (row[rowByte] & xOrVal) / xOrVal;
-            if (xOrVal == 1) {
-                xOrVal = 128;
-                rowByte++;
-            } else {
+    xByteCt = wt;
+
+    for (row = 0; row < height; ++row) {
+        u1 * const imgRow = readU1String(ifP, xByteCt);
+
+        unsigned int col;
+        unsigned int rowByte;
+        unsigned int xOrVal;
+        
+        for (col = 0, rowByte = 0, xOrVal = 0x80; col < width; ++col) {
+            *(bitmap+((height - row - 1) * width) + col) = 
+                (imgRow[rowByte] & xOrVal) / xOrVal;
+            if (xOrVal == 0x01) {
+                xOrVal = 0x80;
+                ++rowByte;
+            } else
                 xOrVal >>= 1;
-            }
         }
-        free(row);
+        free(imgRow);
     }
     return bitmap;
 }
@@ -324,43 +351,46 @@ read1Bitmap (int width, int height)
 
    
 static u1 * 
-read4Bitmap (int width, int height) 
-{
-    int tmp;
+read4Bitmap (FILE *       const ifP,
+             unsigned int const width,
+             unsigned int const height) {
+
+    unsigned int row;
     u1 * bitmap;
 
-    int wt = width;
-    int xBytes;
+    unsigned int wt;
+    unsigned int xByteCt;
 
     MALLOCARRAY(bitmap, width * height);
     if (bitmap == NULL)
         pm_error("out of memory");
 
+    wt = width >> 1;
 
-    wt >>= 1;
-    if (wt & 3) {
-        wt = (wt & ~3) + 4;
+    if (wt & 0x3) {
+        wt = (wt & ~0x3) + 4;
     }
-    xBytes = wt;
-    for (tmp = 0; tmp<height ; tmp++ ) {
-        int rowByte = 0;
-        int bottom = 1;
-        int x;
-        u1 * row = readU1String(xBytes);
-        for (x = 0; x< width; x++) {
-            /*
-             * 2 nibbles, 2 values.
-             */
+    xByteCt = wt;
+
+    for (row = 0; row < height; ++row) {
+        u1 * const imgRow = readU1String(ifP, xByteCt);
+
+        unsigned int rowByte;
+        bool bottom;
+        unsigned int col;
+        for (col = 0, rowByte = 0, bottom = true; col < width; ++col) {
+            /* 2 nibbles, 2 values */
             if (bottom) {
-                *(bitmap+((height-tmp-1)*width) + (x)) = 
-                    (row[rowByte] & 0xF0) >> 4;
+                *(bitmap + ((height - row - 1) * width) + col) = 
+                    (imgRow[rowByte] & 0xF0) >> 4;
             } else {
-                *(bitmap+((height-tmp-1)*width) + (x)) = (row[rowByte] & 0xF);
-                rowByte++;
+                *(bitmap + ((height - row -1) * width) + col) =
+                    (imgRow[rowByte] & 0xF);
+                ++rowByte;
             }
             bottom = !bottom;
         }
-    free(row);
+        free(imgRow);
     }
     return bitmap;
 }
@@ -368,52 +398,57 @@ read4Bitmap (int width, int height)
 
    
 static u1 * 
-read8Bitmap (int width, int height) 
-{
-    int tmp;
-    unsigned int xBytes;
-    unsigned int wt = width;
+read8Bitmap (FILE *       const ifP,
+             unsigned int const width,
+             unsigned int const height) {
+
+    unsigned int row;
+    unsigned int xByteCt;
+    unsigned int wt;
     u1 * bitmap;
    
     MALLOCARRAY(bitmap, width * height);
     if (bitmap == NULL)
         pm_error("out of memory");
 
-    if (wt & 3) {
-        wt = (wt & ~3) + 4;
+    wt = width;
+    if (wt & 0x3) {
+        wt = (wt & ~0x3) + 4;
     }
-    xBytes = wt;
-    for (tmp = 0; tmp<height ; tmp++ ) {
-        int rowByte = 0;
-        int x;
-        u1 * row = readU1String(xBytes);
-        for ( x = 0; x< width; x++) {
-            *(bitmap+((height-tmp-1)*width) + (x)) = row[rowByte];
-            rowByte++;
-        }
-        free(row);
+    xByteCt = wt;
+
+    for (row = 0; row < height; ++row) {
+        u1 * imgRow = readU1String(ifP, xByteCt);
+
+        unsigned int rowByte;
+        unsigned int col;
+        for (col = 0, rowByte = 0; col < width; ++col)
+            *(bitmap + ((height - row - 1) * width) + col) = imgRow[rowByte++];
+
+        free(imgRow);
     }
     return bitmap;
 }
 
 
 
-/*
- * Read a true color bitmap. (24/32 bits)
- * 
- * The output routine deplanarizes it for us, we keep it flat here.
- */
 static u1 *
-readXBitmap (int const width, 
-             int const height, 
-             int const bpp) {
-    int          const bytes  = bpp >> 3;
-    unsigned int const xBytes = width * bytes;
+readXBitmap (FILE *       const ifP,
+             unsigned int const width, 
+             unsigned int const height, 
+             unsigned int const bpp) {
+/*----------------------------------------------------------------------------
+  Read a true color bitmap. (24/32 bits)
+  
+  The output routine deplanarizes it for us, we keep it flat here.
+-----------------------------------------------------------------------------*/
+    unsigned int const byteCt = bpp >> 3;
+    unsigned int const xByteCt = width * byteCt;
 
     u1 * bitmap;
         /* remember - bmp (dib) stored upside down, so reverse */
 
-    MALLOCARRAY(bitmap, bytes * width * height);
+    MALLOCARRAY(bitmap, byteCt * width * height);
     if (bitmap == NULL)
         pm_error("out of memory allocating bitmap array");
 
@@ -421,12 +456,12 @@ readXBitmap (int const width,
         unsigned int i;
         u1 * bitcurptr;
 
-        for (i = 0, bitcurptr = &bitmap[bytes * width * (height-1)];
+        for (i = 0, bitcurptr = &bitmap[byteCt * width * (height-1)];
              i < height; 
-             ++i, bitcurptr -= xBytes) {
+             ++i, bitcurptr -= xByteCt) {
 
-            u1 * const row = readU1String(xBytes);
-            memcpy(bitcurptr, row, xBytes);
+            u1 * const row = readU1String(ifP, xByteCt);
+            memcpy(bitcurptr, row, xByteCt);
             free(row);
         }
     }
@@ -436,80 +471,70 @@ readXBitmap (int const width,
 
 
 static MS_Ico 
-readIconFile (bool const verbose) {
-    int iter,iter2;
+readIconFile(FILE * const ifP,
+             bool   const verbose) {
+
+    unsigned int i;
 
     MS_Ico MSIconData;
 
     MALLOCVAR(MSIconData);
    
-    /*
-     * reserved - should equal 0.
-     */
-    MSIconData->reserved = readU2();
-    /*
-     * Type - should equal 1
-     */
-    MSIconData->type     = readU2();
-    /*
-     * count - no of icons in file..
-     */
-    MSIconData->count    = readU2();
-    /*
-     * Allocate "count" array of entries.
-     */
+    MSIconData->reserved = readU2(ifP);  /* should be 0 */
+    MSIconData->type     = readU2(ifP);  /* should be 1 */
+    MSIconData->count    = readU2(ifP);  /* # icons in file */
+
     if (verbose) 
         pm_message("Icon file contains %d icons.", MSIconData->count);
 
     MALLOCARRAY(MSIconData->entries, MSIconData->count);
     if (MSIconData->entries == NULL)
         pm_error("out of memory");
-    /*
-     * Read in each of the entries
-     */
-    for (iter = 0;iter < MSIconData->count ; iter++ ) {
-        MSIconData->entries[iter] = readICEntry();
-    }
-    /* After that, we have to read in the infoheader, color map (if
-     * any) and the actual bit/pix maps for the icons.  
-     */
+
+    /* Read in each of the entries */
+    for (i = 0; i < MSIconData->count; ++i)
+        MSIconData->entries[i] = readICEntry(ifP);
+
+    /* Read in the infoheader, color map (if any) and the actual bit/pix maps
+       for the icons.
+    */
     if (verbose) 
-        fprintf (stderr,"#\tColors\tBPP\tWidth\tHeight\n");
-    for (iter = 0;iter < MSIconData->count ; iter++ ) {
-        int bpp;
-        MSIconData->entries[iter]->ih =
-            readInfoHeader (MSIconData->entries[iter]);
+        pm_message("#\tColors\tBPP\tWidth\tHeight\n");
+
+    for (i = 0; i < MSIconData->count; ++i) {
+        unsigned int bpp;  /* bits per pixel */
+
+        MSIconData->entries[i]->ih =
+            readInfoHeader(ifP, MSIconData->entries[i]);
        
-        /* What's the bits per pixel? */
-        bpp = MSIconData->entries[iter]->bitcount; 
+        bpp = MSIconData->entries[i]->bitcount; 
+
         /* Read the palette, if appropriate */
         switch (bpp) {
         case 24:
         case 32:
             /* 24/32 bpp icon has no palette */
             break;
-        default:
-            MALLOCARRAY(MSIconData->entries[iter]->colors, 
-                        MSIconData->entries[iter]->color_count);
-            if (MSIconData->entries[iter]->colors == NULL)
+        default: {
+            unsigned int j;
+
+            MALLOCARRAY(MSIconData->entries[i]->colors, 
+                        MSIconData->entries[i]->color_count);
+            if (MSIconData->entries[i]->colors == NULL)
                 pm_error("out of memory");
 
-            for (iter2 = 0;
-                 iter2 < MSIconData->entries[iter]->color_count ; 
-                 iter2++ ) {
-                MSIconData->entries[iter]->colors[iter2] = readICColor();
-            }
-            break;
+            for (j = 0; j < MSIconData->entries[i]->color_count; ++j)
+                MSIconData->entries[i]->colors[j] = readICColor(ifP);
+        }
         }
         if (verbose) {
-            char cols_text[10];
-            sprintf (cols_text, "%d", MSIconData->entries[iter]->color_count);
-            fprintf (stderr,
-                     "%d\t%s\t%d\t%d\t%d\n", iter,
-                     MSIconData->entries[iter]->color_count ? 
-                     cols_text : "TRUE",
-                     bpp, MSIconData->entries[iter]->width, 
-                     MSIconData->entries[iter]->height);
+            char colsText[10];
+            sprintf (colsText, "%d", MSIconData->entries[i]->color_count);
+            pm_message("%d\t%s\t%d\t%d\t%d\n", i,
+                       MSIconData->entries[i]->color_count ? 
+                       colsText : "TRUE",
+                       bpp, MSIconData->entries[i]->width, 
+                       MSIconData->entries[i]->height);
         }
         /* Pixels are stored bottom-up, left-to-right. Pixel lines are
          * padded with zeros to end on a 32bit (4byte) boundary. Every
@@ -528,35 +553,40 @@ readIconFile (bool const verbose) {
              */
             switch (bpp) {
             case 1:
-                MSIconData->entries[iter]->xorBitmap = 
-                    read1Bitmap(MSIconData->entries[iter]->width,
-                                MSIconData->entries[iter]->height);
+                MSIconData->entries[i]->xorBitmap = 
+                    read1Bitmap(ifP,
+                                MSIconData->entries[i]->width,
+                                MSIconData->entries[i]->height);
                 break;
             case 4:
-                MSIconData->entries[iter]->xorBitmap = 
-                    read4Bitmap(MSIconData->entries[iter]->width,
-                                MSIconData->entries[iter]->height);
+                MSIconData->entries[i]->xorBitmap = 
+                    read4Bitmap(ifP,
+                                MSIconData->entries[i]->width,
+                                MSIconData->entries[i]->height);
                 break;
             case 8:
-                MSIconData->entries[iter]->xorBitmap = 
-                    read8Bitmap(MSIconData->entries[iter]->width,
-                                MSIconData->entries[iter]->height);
+                MSIconData->entries[i]->xorBitmap = 
+                    read8Bitmap(ifP,
+                                MSIconData->entries[i]->width,
+                                MSIconData->entries[i]->height);
                 break;
             case 24:
             case 32:
-                MSIconData->entries[iter]->xorBitmap = 
-                    readXBitmap(MSIconData->entries[iter]->width,
-                                MSIconData->entries[iter]->height,bpp);
+                MSIconData->entries[i]->xorBitmap = 
+                    readXBitmap(ifP,
+                                MSIconData->entries[i]->width,
+                                MSIconData->entries[i]->height,bpp);
                 break;
             default:
-                pm_error("Uncatered bit depth %d",bpp);
+                pm_error("Uncatered bit depth %u", bpp);
             }
             /*
              * Read AND Bitmap
              */
-            MSIconData->entries[iter]->andBitmap = 
-                read1Bitmap(MSIconData->entries[iter]->width,
-                            MSIconData->entries[iter]->height);
+            MSIconData->entries[i]->andBitmap = 
+                read1Bitmap(ifP,
+                            MSIconData->entries[i]->width,
+                            MSIconData->entries[i]->height);
         }
       
     }
@@ -566,15 +596,14 @@ readIconFile (bool const verbose) {
 
 
 static char * 
-trimOutputName(const char inputName[])
-{
+trimmedOutputName(const char inputName[]) {
     /*
      * Just trim off the final ".ppm", if there is one, else return as is.
      * oh, for =~ ... :)
      */
-    char * outFile = strdup(inputName);
-    if (streq(outFile + (strlen (outFile) - 4), ".ppm")) {
-        *(outFile + (strlen (outFile) - 4)) = 0;
+    char * const outFile = strdup(inputName);
+    if (streq(outFile + (strlen(outFile) - 4), ".ppm")) {
+        *(outFile + (strlen(outFile) - 4)) = 0;
     }
     return outFile;
 
@@ -585,29 +614,34 @@ trimOutputName(const char inputName[])
 static int 
 getBestQualityIcon(MS_Ico MSIconData)
 {
-    int x,best,best_size,best_bpp,bpp,size;
-    IC_Entry entry;
-
-    best_size = best_bpp = 0;
-    for (x = 0; x < MSIconData->count; x++) {
-        entry =  MSIconData->entries[x];
-        size = entry->width * entry->height;
-        bpp  = entry->bitcount ? entry->bitcount : entry->ih->bitcount;
-        if (size > best_size) {
-            best = x;
-            best_size = size;
-        } else if (size == best_size && bpp > best_bpp) {
-            best = x;
-            best_bpp = bpp;
+    unsigned int i;
+    unsigned int best;
+    unsigned int bestSize;
+    unsigned int bestBpp;
+
+    for (i = 0, bestSize = 0, bestBpp = 0; i < MSIconData->count; ++i) {
+        IC_Entry const entryP = MSIconData->entries[i];
+        unsigned int const size = entryP->width * entryP->height;
+        unsigned int const bpp  =
+            entryP->bitcount ? entryP->bitcount : entryP->ih->bitcount;
+
+        if (size > bestSize) {
+            best = i;
+            bestSize = size;
+        } else if (size == bestSize && bpp > bestBpp) {
+            best = i;
+            bestBpp = bpp;
         }
     }
     return best;
 }
 
+
+
 static void
 writeXors(FILE *   const multiOutF,
-          char           outputFileBase[], 
-          IC_Entry const entry,
+          char *   const outputFileBase,
+          IC_Entry const entryP,
           int      const entryNum,
           bool     const multiple, 
           bool     const xor) {
@@ -625,85 +659,79 @@ writeXors(FILE *   const multiOutF,
    we are to open a file using outputFileBase[] and 'entryNum' and 'xor'
    to derive its name, and close it afterward.
 -----------------------------------------------------------------------------*/
-    FILE * outF;
-    pixel ** ppm_array;
-    int row;
-    int pel_size;
-    const char *outputFile;
-    int maxval;
-    int forcetext;
+    FILE * ofP;
+    pixel ** pixArray;
+    unsigned int row;
+    const char * outputFileName;
 
     if (multiOutF) {
-        outF = multiOutF;
-        outputFile = strdup("");
+        ofP = multiOutF;
+        outputFileName = strdup("");
     } else {
         if (outputFileBase) {
             if (multiple) {
-                pm_asprintf(&outputFile, "%s%s_%d.ppm",
+                pm_asprintf(&outputFileName, "%s%s_%d.ppm",
                             outputFileBase,(xor ? "_xor" : ""), entryNum);
             } else { 
-                pm_asprintf(&outputFile, "%s%s.ppm",
+                pm_asprintf(&outputFileName, "%s%s.ppm",
                             outputFileBase,(xor ? "_xor" : ""));
             }
         } else
-            outputFile = strdup("-");
+            outputFileName = strdup("-");
         
-        outF = pm_openw(outputFile);
+        ofP = pm_openw(outputFileName);
     }
     /* 
-     * allocate an array to save the bmp data into.
-     * note that entry->height will be 1/2 entry->ih->height,
-     * as the latter adds "and" and "xor" height.
-     */
-    ppm_array = ppm_allocarray(entry->width, entry->height);
-    for (row=0; row < entry->height; row++) {
-        u1 * xorRow;
-        int col;
-        switch (entry->bitcount) {
+       Allocate an array to save the bmp data into.
+       note that entry->height will be 1/2 entry->ih->height,
+       as the latter adds "and" and "xor" height.
+    */
+    pixArray = ppm_allocarray(entryP->width, entryP->height);
+    for (row = 0; row < entryP->height; ++row) {
+        switch (entryP->bitcount) {
         case 24:
-        case 32:
-            pel_size = entry->bitcount >> 3;
-            xorRow = entry->xorBitmap + row * entry->width * pel_size;
-            for (col=0; col < entry->width*pel_size;col+=pel_size) {
-                PPM_ASSIGN(ppm_array[row][col/pel_size],
-                           xorRow[col+2],xorRow[col+1],xorRow[col]);
-            }
-            break;
-        default:
-            xorRow = entry->xorBitmap + row * entry->width;
-            for (col=0; col < entry->width; col++) {
-                int colorIndex;
-                IC_Color color;
-                colorIndex  = xorRow[col];
-                color = entry->colors[colorIndex];
-                PPM_ASSIGN(ppm_array[row][col],
-                           color->red,color->green,color->blue);
+        case 32: {
+            unsigned int const pixelSize = entryP->bitcount >> 3;
+            u1 * const xorRow =
+                entryP->xorBitmap + row * entryP->width * pixelSize;
+            unsigned int col;
+            for (col = 0; col < entryP->width * pixelSize; col += pixelSize)
+                PPM_ASSIGN(pixArray[row][col/pixelSize],
+                           xorRow[col+2], xorRow[col+1], xorRow[col]);
+        } break;
+        default: {
+            u1 * const xorRow = entryP->xorBitmap + row * entryP->width;
+            unsigned int col;
+            for (col = 0; col < entryP->width; ++col) {
+                unsigned int const colorIndex = xorRow[col];
+                IC_Color const colorP = entryP->colors[colorIndex];
+                PPM_ASSIGN(pixArray[row][col],
+                           colorP->red, colorP->green, colorP->blue);
             }
-            break;
+        } break;
         }
     }    
     
-    maxval = 255;
-    forcetext = 0;
-
-    ppm_writeppm(outF,ppm_array,entry->width, entry->height, 
-                 (pixval) maxval, forcetext);
-    ppm_freearray(ppm_array,entry->height);
+    ppm_writeppm(ofP, pixArray, entryP->width, entryP->height, 
+                 255 /* maxval */, false /* text */);
+    ppm_freearray(pixArray, entryP->height);
 
-    pm_strfree(outputFile);
+    pm_strfree(outputFileName);
     
     if (!multiOutF) 
-        pm_close(outF);
+        pm_close(ofP);
 }
             
 
 
 static void
-writeAnds(FILE * const multiOutF, 
-          char outputFileBase[], IC_Entry const entry, int const entryNum, 
-          bool multiple) {
+writeAnds(FILE *       const multiOutF, 
+          char         const outputFileBase[],
+          IC_Entry     const entryP,
+          unsigned int const entryNum, 
+          bool         const multiple) {
 /*----------------------------------------------------------------------------
-   Write the "and" image (i.e. the alpha mask) of the image 'IC_Entry' out.
+   Write the "and" image (i.e. the alpha mask) of the image *entryP out.
 
    'multiple' means this is one of multiple images that are being written.
    'entryNum' is the sequence number within the winicon file of the image
@@ -714,115 +742,122 @@ writeAnds(FILE * const multiOutF,
    we are to open a file using outputFileBase[] and 'entryNum' and 'xor'
    to derive its name, and close it afterward.
 -----------------------------------------------------------------------------*/
-    FILE * outF;
-    bit ** pbm_array;
-    u1 * andRow;
-    int row;
+    FILE * ofP;
+    bit ** bitArray;
+    unsigned int row;
 
     if (multiOutF)
-        outF = multiOutF;
+        ofP = multiOutF;
     else {
-        const char *outputFile;
+        const char * outputFileName;
 
         assert(outputFileBase);
 
         if (multiple) 
-            pm_asprintf(&outputFile, "%s_and_%d.pbm",
+            pm_asprintf(&outputFileName, "%s_and_%u.pbm",
                         outputFileBase, entryNum);
         else 
-            pm_asprintf(&outputFile, "%s_and.pbm", outputFileBase);
-        outF = pm_openw(outputFile);
-        pm_strfree(outputFile);
+            pm_asprintf(&outputFileName, "%s_and.pbm", outputFileBase);
+        ofP = pm_openw(outputFileName);
+        pm_strfree(outputFileName);
     }
-    pbm_array = pbm_allocarray(entry->width, entry->height);
-    for (row=0; row < entry->height; row++) {
-        int col;
-        andRow = entry->andBitmap + row * entry->width;
-        for (col=0; col < entry->width; col++) {
+    bitArray = pbm_allocarray(entryP->width, entryP->height);
+    for (row = 0; row < entryP->height; ++row) {
+        u1 * const andRow = entryP->andBitmap + row * entryP->width;
+        unsigned int col;
+        for (col = 0; col < entryP->width; ++col) {
             /* Note: black is transparent in a Netpbm alpha mask */
-            pbm_array[row][col] = andRow[col] ? PBM_BLACK: PBM_WHITE;
+            bitArray[row][col] = andRow[col] ? PBM_BLACK: PBM_WHITE;
         }
     }
 
-    pbm_writepbm(outF, pbm_array, entry->width, entry->height, 0);
+    pbm_writepbm(ofP, bitArray, entryP->width, entryP->height, 0);
 
-    pbm_freearray(pbm_array, entry->height);
+    pbm_freearray(bitArray, entryP->height);
     if (!multiOutF)
-        pm_close (outF);     
+        pm_close(ofP);
 }
 
 
 
 static void
-openMultiXor(char          outputFileBase[], 
+openMultiXor(char    const outputFileBase[], 
              bool    const writeands,
              FILE ** const multiOutFP) {
 
-    const char *outputFile;
+    const char * outputFileName;
 
     if (outputFileBase) {
-        pm_asprintf(&outputFile, "%s%s.ppm",
+        pm_asprintf(&outputFileName, "%s%s.ppm",
                     outputFileBase, (writeands ? "_xor" : ""));
     } else
-        outputFile = strdup("-");
+        outputFileName = strdup("-");
 
-    /*
-     * Open the output file now, it'll stay open the whole time.
-     */
-    *multiOutFP = pm_openw(outputFile);
+    *multiOutFP = pm_openw(outputFileName);
 
-    pm_strfree(outputFile);
+    pm_strfree(outputFileName);
 }
 
 
 
 static void
-openMultiAnd(char outputFileBase[], FILE ** const multiAndOutFP) {
+openMultiAnd(char    const outputFileBase[],
+             FILE ** const multiAndOutFP) {
 
-    const char *outputFile;
+    const char * outputFileName;
 
     assert(outputFileBase);
 
-    pm_asprintf(&outputFile, "%s_and.pbm", outputFileBase);
+    pm_asprintf(&outputFileName, "%s_and.pbm", outputFileBase);
     
-    *multiAndOutFP = pm_openw(outputFile);
+    *multiAndOutFP = pm_openw(outputFileName);
 
-    pm_strfree(outputFile);
+    pm_strfree(outputFileName);
 }
 
-static void free_iconentry(IC_Entry entry) {
-    int x;
-    if (entry->colors && entry->color_count) {
-        for (x=0;x<entry->color_count;x++) free(entry->colors[x]);
-        free(entry->colors);
+
+
+static void
+freeIconentry(IC_Entry const entryP) {
+
+    if (entryP->colors && entryP->color_count) {
+        unsigned int i;
+        for (i = 0; i <entryP->color_count; ++i)
+            free(entryP->colors[i]);
+        free(entryP->colors);
     }
-    if (entry->andBitmap) free(entry->andBitmap);
-    if (entry->xorBitmap) free(entry->xorBitmap);
-    if (entry->ih) free(entry->ih);
-    free(entry);
+    if (entryP->andBitmap) free(entryP->andBitmap);
+    if (entryP->xorBitmap) free(entryP->xorBitmap);
+    if (entryP->ih) free(entryP->ih);
+    free(entryP);
 }
 
-static void free_icondata(MS_Ico MSIconData)
-{
-    int x;
-    for (x=0;x<MSIconData->count;x++) {
-    free_iconentry(MSIconData->entries[x]);
-    }
-    free(MSIconData);
+
+
+static void
+freeIcondata(MS_Ico const MSIconDataP) {
+
+    unsigned int i;
+    for (i = 0; i < MSIconDataP->count; ++i)
+        freeIconentry(MSIconDataP->entries[i]);
+
+    free(MSIconDataP);
 }
 
 
+
 int 
-main(int argc, char *argv[]) {
+main(int argc, const char *argv[]) {
 
     struct cmdlineInfo cmdline;
-    int startEntry, endEntry;
-    MS_Ico MSIconData;
+    FILE * ifP;
+    unsigned int startEntry, endEntry;
+    MS_Ico MSIconDataP;
     char * outputFileBase;
     FILE * multiOutF;
     FILE * multiAndOutF;
    
-    ppm_init (&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
@@ -833,13 +868,13 @@ main(int argc, char *argv[]) {
     if (streq(cmdline.outputFilespec, "-"))
         outputFileBase = NULL;
     else
-        outputFileBase = trimOutputName(cmdline.outputFilespec);
+        outputFileBase = trimmedOutputName(cmdline.outputFilespec);
 
-    ifp = pm_openr(cmdline.inputFilespec);
+    ifP = pm_openr(cmdline.inputFilespec);
 
     infname = cmdline.inputFilespec;
 
-    MSIconData = readIconFile(cmdline.verbose);
+    MSIconDataP = readIconFile(ifP, cmdline.verbose);
     /*
      * Now we've read the icon file in (Hopefully! :)
      * Go through each of the entries, and write out files of the
@@ -853,18 +888,15 @@ main(int argc, char *argv[]) {
     /*
      * If allicons is set, we want everything, if not, just go through once.
      */
-    startEntry = 0;
-    if (cmdline.allicons) {
-        endEntry = MSIconData->count;
-    } else {
-        endEntry = 1;
-    }
-    /*
-     * If bestqual is set, find the icon with highest size & bpp.
-     */
     if (cmdline.bestqual) {
-        startEntry = getBestQualityIcon(MSIconData);
+        startEntry = getBestQualityIcon(MSIconDataP);
         endEntry = startEntry+1;
+    } else {
+        startEntry = 0;
+        if (cmdline.allicons)
+            endEntry = MSIconDataP->count;
+        else
+            endEntry = 1;
     }
    
     if (cmdline.multippm) 
@@ -878,24 +910,25 @@ main(int argc, char *argv[]) {
         multiAndOutF = NULL;
 
     {
-        int entryNum;
+        unsigned int entryNum;
 
-        for (entryNum = startEntry ; entryNum < endEntry ; entryNum++ ) {
-            IC_Entry const entry = MSIconData->entries[entryNum];
+        for (entryNum = startEntry; entryNum < endEntry; ++entryNum) {
+            IC_Entry const entryP = MSIconDataP->entries[entryNum];
 
-            writeXors(multiOutF, outputFileBase, entry, entryNum, 
+            writeXors(multiOutF, outputFileBase, entryP, entryNum, 
                       cmdline.allicons, cmdline.writeands);
             if (cmdline.writeands)
                 writeAnds(multiAndOutF, outputFileBase, 
-                          entry, entryNum, cmdline.allicons);
+                          entryP, entryNum, cmdline.allicons);
         }
     }
     if (multiOutF)
-        pm_close (multiOutF);    
+        pm_close(multiOutF);    
     if (multiAndOutF)
         pm_close(multiAndOutF);
     
     /* free up the image data here. */
-    free_icondata(MSIconData);
+    freeIcondata(MSIconDataP);
+
     return 0;
 }
diff --git a/converter/ppm/yuvtoppm.c b/converter/ppm/yuvtoppm.c
index 2b44c65f..151ff9f9 100644
--- a/converter/ppm/yuvtoppm.c
+++ b/converter/ppm/yuvtoppm.c
@@ -20,96 +20,201 @@
 ** implied warranty.
 */
 
-#include "ppm.h"
+#include "pm_c_util.h"
 #include "mallocvar.h"
+#include "shhopt.h"
+#include "ppm.h"
 
-/* x must be signed for the following to work correctly */
-#define limit(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
 
-int
-main(argc, argv)
-	char          **argv;
-{
-	FILE           *ifp;
-	pixel          *pixrow;
-	int             argn, rows, cols, row;
-	const char     * const usage = "<width> <height> [yuvfile]";
-    struct yuv {
-        /* This is an element of a YUV file.  It describes two 
-           side-by-side pixels.
-        */
-        unsigned char u;
-        unsigned char y1;
-        unsigned char v;
-        unsigned char y2;
-    } *yuvbuf;
-
-	ppm_init(&argc, argv);
-
-	argn = 1;
-
-	if (argn + 2 > argc)
-		pm_usage(usage);
-
-	cols = atoi(argv[argn++]);
-	rows = atoi(argv[argn++]);
-	if (cols <= 0 || rows <= 0)
-		pm_usage(usage);
-
-	if (argn < argc) {
-		ifp = pm_openr(argv[argn]);
-		++argn;
-	} else
-		ifp = stdin;
-
-	if (argn != argc)
-		pm_usage(usage);
-
-    if (cols % 2 != 0) {
-        pm_error("Number of columns (%d) is odd.  A YUV image must have an "
-                 "even number of columns.", cols);
+
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    unsigned int cols;
+    unsigned int rows;
+    const char * inputFileName;  /* Name of input file */
+};
+
+
+
+static void
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP) {
+
+    optEntry * option_def;
+        /* Instructions to OptParseOptions3 on how to parse our options */
+    optStruct3 opt;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    OPTENTINIT;
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (argc-1 < 2)
+        pm_error("You need at least two arguments: width and height in "
+                 "pixels.  You specified %u", argc-1);
+    else {
+        int const widthArg  = atoi(argv[1]);
+        int const heightArg = atoi(argv[2]);
+
+        if (widthArg < 0)
+            pm_error("Negative number for width: %d", widthArg);
+        if (heightArg < 0)
+            pm_error("Negative number for height: %d", heightArg);
+
+        cmdlineP->cols = widthArg;
+        cmdlineP->rows = heightArg;
+                 
+        if (cmdlineP->cols % 2 != 0)
+            pm_error("Number of columns (%u) is odd.  "
+                     "A YUV image must have an "
+                     "even number of columns.", cmdlineP->cols);
+
+        if (argc-1 < 3)
+            cmdlineP->inputFileName = "-";
+        else {
+            cmdlineP->inputFileName = argv[3];
+
+            if (argc-1 > 3)
+                pm_error("Too many arguments: %u.  "
+                         "The only possible arguments are "
+                         "width, height, and input file name", argc-1);
+        }
     }
+}
 
-	ppm_writeppminit(stdout, cols, rows, (pixval) 255, 0);
-	pixrow = ppm_allocrow(cols);
-    MALLOCARRAY(yuvbuf, (cols+1)/2);
-    if (yuvbuf == NULL)
-        pm_error("Unable to allocate YUV buffer for %d columns.", cols);
 
-	for (row = 0; row < rows; ++row) {
-		int    col;
 
-		fread(yuvbuf, cols * 2, 1, ifp);
+static int
+limit(int const x) {
 
-		for (col = 0; col < cols; col += 2) {
-            /* Produce two pixels in pixrow[] */
-            int y1, u, v, y2, r, g, b;
+    if (x > 0xffffff)
+        return 0xff;
+    else if (x <= 0xffff)
+        return 0;
+    else
+        return ((x >> 16) & 0xff);
+}
+
+
+
+static int
+nonneg(int const x) {
+/*----------------------------------------------------------------------------
+  Raise 'x' to 0 if negative
+-----------------------------------------------------------------------------*/
+    return x < 0 ? 0 : x;
+}
+
+
+
+struct Yuv {
+/*----------------------------------------------------------------------------
+  This is an element of a YUV file.  It describes two side-by-side pixels.
+
+  This is the actual layout of the data in the file (4 bytes).
+-----------------------------------------------------------------------------*/
+    unsigned char u;
+    unsigned char y1;
+    unsigned char v;
+    unsigned char y2;
+};
 
-			u = yuvbuf[col/2].u-128;
 
-            y1 = yuvbuf[col/2].y1 - 16;
-			if (y1 < 0) y1 = 0;
 
-            v = yuvbuf[col/2].v - 128;
+static void
+readYuv(FILE *       const ifP,
+        struct Yuv * const yuvP) {
 
-            y2 = yuvbuf[col/2].y2 - 16;
-			if (y2 < 0) y2 = 0;
+    size_t readCt;
 
-			r = 104635 * v;
-			g = -25690 * u + -53294 * v;
-			b = 132278 * u;
+    readCt = fread(yuvP, sizeof(*yuvP), 1, ifP);
 
-			y1*=76310; y2*=76310;
+    if (readCt != 1) {
+        if (feof(ifP))
+            pm_error("Premature end of input.");
+        else
+            pm_error("Error reading input.");
+    }
+}
+
+
+
+static void
+yuvtoppm(FILE *       const ifP,
+         unsigned int const cols,
+         unsigned int const rows,
+         FILE *       const ofP) {
+
+    pixval const maxval = 255;
+
+    pixel * pixrow;
+    unsigned int row;
+
+    ppm_writeppminit(ofP, cols, rows, maxval, 0);
+
+    pixrow = ppm_allocrow(cols);
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        for (col = 0; col < cols; col += 2) {
+            /* Produce two pixels in pixrow[] */
+            struct Yuv yuv;
+            int     y1, u, v, y2, r, g, b;
+
+            readYuv(ifP, &yuv);
+
+            u = yuv.u - 128;
+            y1 = nonneg (yuv.y1 - 16);
+            v = yuv.v - 128;
+            y2 = nonneg (yuv.y2 - 16);
+
+            r = 104635 * v;
+            g = -25690 * u + -53294 * v;
+            b = 132278 * u;
+
+            y1 *= 76310;
+            y2 *= 76310;
+
+            PPM_ASSIGN(pixrow[col],
+                       limit(r + y1), limit(g + y1), limit(b + y1));
+            PPM_ASSIGN(pixrow[col + 1],
+                       limit(r + y2), limit(g + y2), limit(b + y2));
+        }
+        ppm_writeppmrow(ofP, pixrow, cols, maxval, 0);
+    }
 
-			PPM_ASSIGN(pixrow[col], limit(r+y1), limit(g+y1), limit(b+y1));
-			PPM_ASSIGN(pixrow[col+1], limit(r+y2), limit(g+y2), limit(b+y2));
-		}
-		ppm_writeppmrow(stdout, pixrow, cols, (pixval) 255, 0);
-	}
-    free(yuvbuf);
     ppm_freerow(pixrow);
-	pm_close(ifp);
-	pm_close(stdout);
 
-	exit(0);
+    if (fgetc(ifP) != EOF)
+        pm_message("Extraneous data at end of image.");
+}
+
+
+
+int
+main (int argc, const char ** argv) {
+
+    FILE * ifP;
+    struct CmdlineInfo cmdline;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    yuvtoppm(ifP, cmdline.cols, cmdline.rows, stdout);
+    
+    pm_close(ifP);
+    pm_close(stdout);
+
+    return 0;
 }