about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2018-06-30 20:05:55 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2018-06-30 20:05:55 +0000
commit81ba0303f29b08507cccad29eecf2b30b012df63 (patch)
tree981bdae8afd0d4fac5e4834ae2c0b3b9a0462d5a
parentd9c9d6a198247612248ad094ed7d40dcd4fa9031 (diff)
downloadnetpbm-mirror-81ba0303f29b08507cccad29eecf2b30b012df63.tar.gz
netpbm-mirror-81ba0303f29b08507cccad29eecf2b30b012df63.tar.xz
netpbm-mirror-81ba0303f29b08507cccad29eecf2b30b012df63.zip
Promote current Development release as Advanced
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@3289 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--analyzer/Makefile1
-rw-r--r--analyzer/pamgetcolor.c501
-rw-r--r--analyzer/pgmtexture.c60
-rw-r--r--converter/other/cameratopam/camera.c37
-rw-r--r--converter/other/fiasco/codec/decoder.c310
-rw-r--r--converter/other/jpeg2000/pamtojpeg2k.c6
-rw-r--r--converter/other/pamtotiff.c2
-rw-r--r--converter/other/pclxl.h14
-rw-r--r--converter/other/pngtopam.c5
-rw-r--r--converter/other/pngx.c36
-rw-r--r--converter/other/pngx.h6
-rw-r--r--converter/other/pnmtopalm/palmtopnm.c207
-rw-r--r--converter/other/pnmtopclxl.c126
-rw-r--r--converter/other/pstopnm.c281
-rw-r--r--converter/ppm/ilbmtoppm.c809
-rw-r--r--doc/HISTORY33
-rw-r--r--doc/TESTS50
-rw-r--r--editor/Makefile2
-rw-r--r--editor/pamcomp.c118
-rw-r--r--editor/pamflip/flip.h2
-rw-r--r--editor/pamflip/pamflip.c222
-rw-r--r--editor/pamflip/pamflip_sse.c44
-rw-r--r--editor/pamflip/pamflip_sse.h2
-rw-r--r--editor/pamlevels.c515
-rw-r--r--editor/pamrecolor.c2
-rw-r--r--editor/pamscale.c314
-rw-r--r--editor/pbmclean.c55
-rw-r--r--editor/pbmmask.c394
-rw-r--r--editor/pnmremap.c8
-rw-r--r--editor/specialty/pammixinterlace.c61
-rw-r--r--generator/pbmmake.c16
-rw-r--r--generator/pbmtext.c206
-rw-r--r--generator/pbmtextps.c57
-rw-r--r--generator/pgmnoise.c21
-rw-r--r--generator/pgmramp.c31
-rw-r--r--lib/colorname.c26
-rw-r--r--lib/colorname.h6
-rw-r--r--lib/libpam.h6
-rw-r--r--lib/libpamcolor.c397
-rw-r--r--lib/libpamn.c140
-rw-r--r--lib/libpbm2.c24
-rw-r--r--lib/libpm.c50
-rw-r--r--lib/libppmcolor.c464
-rw-r--r--lib/libsystem.c1
-rw-r--r--lib/pam.h33
-rw-r--r--lib/util/mallocvar.c8
-rw-r--r--lib/util/mallocvar.h18
-rw-r--r--lib/util/nstring.c75
-rw-r--r--lib/util/nstring.h27
-rw-r--r--other/pampick.c12
-rwxr-xr-xtest/Execute-Tests2
-rw-r--r--test/Test-Order3
-rw-r--r--test/pbmtext-bdf.ok8
-rwxr-xr-xtest/pbmtext-bdf.test99
-rw-r--r--test/pbmtext-iso88591.ok4
-rwxr-xr-xtest/pbmtext-iso88591.test46
-rw-r--r--test/pbmtext-utf8.ok8
-rwxr-xr-xtest/pbmtext-utf8.test91
-rw-r--r--test/pbmtext.ok8
-rwxr-xr-xtest/pbmtext.test93
-rw-r--r--version.mk4
61 files changed, 3919 insertions, 2288 deletions
diff --git a/analyzer/Makefile b/analyzer/Makefile
index 18be9d8c..abd87d7c 100644
--- a/analyzer/Makefile
+++ b/analyzer/Makefile
@@ -15,6 +15,7 @@ include $(BUILDDIR)/config.mk
 # build.
 
 PORTBINARIES = \
+  pamgetcolor \
   pamfile \
   pammosaicknit \
   pamslice \
diff --git a/analyzer/pamgetcolor.c b/analyzer/pamgetcolor.c
new file mode 100644
index 00000000..23396967
--- /dev/null
+++ b/analyzer/pamgetcolor.c
@@ -0,0 +1,501 @@
+#include <string.h>
+#include <nstring.h>
+#include <pm_gamma.h>
+#include <pam.h>
+
+#include "shhopt.h"
+#include "mallocvar.h"
+
+typedef unsigned int  uint;
+
+/* specification of a cirtular "region" over which to measre the avg. color: */
+typedef struct {
+    uint         x;        /* coordinates of the center                      */
+    uint         y;        /* of the region;                                 */
+    char const * label;    /* optional label supplied on the command line    */
+} RegSpec;
+
+/* represents a single color measurement over a "region": */
+typedef struct {
+    uint         area;     /* area in pixels over which to average the color */
+    /* cumulative normalised intensity-proportiunal value of the region:     */
+    double       color[3];
+} RegData;
+
+/*command-line parameters: */
+typedef struct {
+    uint         linear;
+    uint         radius;
+    uint         regN;      /* number of regions                             */
+    uint         maxLbLen;  /* maximum label length                          */
+    RegSpec *    regSpecs;
+        /* list of points to sample, dymamically allocated*/
+    char const * formatStr; /* output color format as string                 */
+    uint         formatId;  /* the Id of the selected color format           */
+    uint         formatArg; /* the argument to the color formatting function */
+    char const * infile;
+} CmdlineInfo;
+
+/* Generic pointer to a color-formatting function. Returns the textual
+   representation of the color <tuple> in terms of the image pointed-to
+   by <pamP>. <param> is a generic integer parameter that depends on the
+   specific funcion and may denote precison or maxval.
+*/
+typedef char const *
+(*FormatColor)(struct pam * const pamP,
+               tuple        const color,
+               uint         const param);
+
+/* The color format specificaiton: */
+typedef struct ColorFormat {
+    /* format id (compared against the -format command-line argument):       */
+    char        const * id;
+    /* function that returns converts a color into this format:              */
+    FormatColor const   formatColor;
+    /* meaning of the <param> argument of <formatColor>():                   */
+    char        const * argName;
+    uint        const   defParam;   /* default value of that argument        */
+    uint        const   maxParam;   /* maximum value of that argument        */
+} ColorFormat;
+
+
+
+static char const *
+fcInt(struct pam * const pamP,
+      tuple        const color,
+      uint         const param) {
+/* format <color> as an integer tuple with maxval <param> */
+    return pnm_colorspec_rgb_integer(pamP, color, param);
+}
+
+
+
+static char const *
+fcNorm(struct pam * const pamP,
+       tuple        const color,
+       uint         const param) {
+/* format <color> as normalised tuple with precision <param> */
+    return pnm_colorspec_rgb_norm(pamP, color, param);
+}
+
+
+
+static char const *
+fcX11(struct pam * const pamP,
+      tuple        const color,
+      uint         const param) {
+/* format <color> as hexadecimal tuple with <param> digits*/
+    return pnm_colorspec_rgb_x11(pamP, color, param);
+}
+
+
+
+#define FormatsN 3
+
+static int const DefaultFormat = 0;
+/* Table with the full information about color formats */
+ColorFormat formats[ FormatsN ] = {
+    /*   Id     Function  Argument name  Default  Max   */
+    {   "int",  &fcInt,   "maxval",      255,     65535  },
+    {   "norm", &fcNorm,  "digit count",   3,         6  },
+    {   "x11",  &fcX11,   "digit count",   2,         4  }
+};
+
+
+
+static inline uint
+sqri(int const v) {
+
+    return v * v;
+}
+
+
+
+static RegSpec
+parseRegSpec(char const * const s) {
+/*----------------------------------------------------------------------------
+  Parse region specification <s> from the command line and return its
+  structured representation.  A specification is of the format <x,y[:label].
+-----------------------------------------------------------------------------*/
+    char* end, *start;
+    RegSpec res;
+
+    start = (char *)s;
+
+    res.x = strtol(start, &end, 10);
+    do {
+        if (start == end)
+            break; /* x not parsed */
+        start = end;
+        if (*end != ',')
+            break;  /* no comma after x */
+        start = end + 1;
+
+        res.y = strtol(start, &end, 10);
+        if (start == end)
+            break; /* y not parsed */
+
+        /* these multiple returns to avoid goto and deep nesting: */
+        if (*end == '\0') { /* no label specified */
+            res.label = (char *)s;
+            return res;
+        }
+        if (*end == ':') { /* a label specified */
+            res.label = end + 1;
+            if (*res.label == '\0')
+                break; /* empty label */
+            return res;
+        }
+    }
+    while (1 == 0);
+
+    pm_error("Wrong region specification: %s", s);
+
+    return res; /* to avoid the false warning that nothing is returned */
+}
+
+
+
+static void
+parseColorFmt(CmdlineInfo * const cmdLineP) {
+/*----------------------------------------------------------------------------
+  Parse the color format specificaction from the command line stored in the
+  <formatStr> member of <cmdLineP> and save it into members <formatId> and
+  <formatArg>.  A format specification is <format>[:<arg>].
+-----------------------------------------------------------------------------*/
+    const int     FmtNotFound = -1;
+    const char *  ErrSpec = "Wrong color format specification: ";
+    const char *  formatStr;
+          char *  colonLoc; /* location of the colon in the specification */
+    uint          n, f;
+    ColorFormat * formatP;
+
+    formatStr = cmdLineP->formatStr;
+    colonLoc  = strchr(formatStr, ':');
+    if (colonLoc != NULL) n = colonLoc - formatStr;
+    else                  n = strlen(formatStr);
+
+    cmdLineP->formatId = FmtNotFound;
+
+    for (f = 0; f < FormatsN; f++) {
+        if (strncmp(formatStr, formats[f].id, n) == 0) {
+            cmdLineP->formatId = f;
+            break;
+        }
+    }
+    if (cmdLineP->formatId == FmtNotFound) {
+        pm_error("Color format not recognised.");
+    }
+    formatP = &formats[cmdLineP->formatId];
+    if (colonLoc != NULL) {
+        long int arg;
+        char *argStart, *argEnd;
+
+        argStart = colonLoc + 1;
+        if (*argStart == '\0')
+            pm_error("%sthe colon should be followed by %s.",
+                ErrSpec, formatP->argName);
+
+        arg = strtol(argStart, &argEnd, 10);
+        if (*argEnd != '\0')
+            pm_error("%sfailed to parse the %s: %s.",
+                ErrSpec, formatP->argName, argStart);
+
+        if (arg < 1)
+            pm_error("%s%s must be greater than zero.",
+                ErrSpec, formatP->argName);
+
+        if (arg > formatP->maxParam)
+            pm_error("%s%s cannot exceed %i.",
+                ErrSpec, formatP->argName, formatP->maxParam);
+        cmdLineP->formatArg = arg;
+    }
+    else
+        cmdLineP->formatArg = formatP->defParam;
+}
+
+
+
+static CmdlineInfo
+parseCommandLine(int argc, char const ** argv) {
+/*----------------------------------------------------------------------------
+  Parse the command-line arguments and store them in a form convenient for the
+  program.
+-----------------------------------------------------------------------------*/
+    int         r;
+    uint        formatSet;
+    CmdlineInfo cmdLine;
+    optStruct3  opt;
+    uint        option_def_index = 0;
+
+    optEntry * option_def;
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    cmdLine.radius    = 0;
+
+    opt.opt_table     = option_def;
+    opt.short_allowed = 0;
+    opt.allowNegNum   = 0;
+
+    OPTENT3(0, "infile",    OPT_STRING, &cmdLine.infile,    NULL,       0);
+    OPTENT3(0, "radius",    OPT_INT,    &cmdLine.radius,    NULL,       0);
+    OPTENT3(0, "format",    OPT_STRING, &cmdLine.formatStr, &formatSet, 0);
+    OPTENT3(0, "linear",    OPT_FLAG,   &cmdLine.linear,    NULL,       0);
+    OPTENT3(0,  0,          OPT_END,    NULL,               NULL,       0);
+
+    cmdLine.radius = 0;
+    cmdLine.linear = 0;
+    cmdLine.infile = "-";
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+
+    if (formatSet) {
+        parseColorFmt(&cmdLine);
+    } else {
+        cmdLine.formatId  = DefaultFormat;
+        cmdLine.formatArg = formats[DefaultFormat].defParam;
+    }
+
+    cmdLine.regN    = argc - 1;
+    MALLOCARRAY_NOFAIL(cmdLine.regSpecs, cmdLine.regN);
+
+    cmdLine.maxLbLen = 0;
+    if (argc < 2)
+        pm_error("No regions specified.");
+
+    for (r = 0; r < argc - 1; r++) {
+        size_t lbLen;
+        cmdLine.regSpecs[r] = parseRegSpec(argv[r+1]);
+        lbLen = strlen(cmdLine.regSpecs[r].label);
+        if (lbLen > cmdLine.maxLbLen)
+            cmdLine.maxLbLen = lbLen;
+    }
+
+    free(option_def);
+    return cmdLine;
+}
+
+
+
+static RegData * allocRegSamples(uint n) {
+/*----------------------------------------------------------------------------
+  Allocate an array of <n> initialised region samles.  The array should be
+  freed after use.
+-----------------------------------------------------------------------------*/
+    uint r;
+    RegData * regSamples;
+    regSamples = calloc(n, sizeof(RegData));
+    for (r = 0; r < n; r++) {
+        uint l;
+
+        regSamples[r].area = 0;
+
+        for (l = 0; l < 3; l++)
+            regSamples[r].color[l] = 0.0;
+    }
+    return regSamples;
+}
+
+
+
+static uint getYmax(struct pam * const pamP,
+                    CmdlineInfo  const cmdLine) {
+/*----------------------------------------------------------------------------
+  Find the maximum row in the image that contains a pixel from a region.
+-----------------------------------------------------------------------------*/
+    uint ymax, r, ycmax;
+    ycmax = 0;
+    for (r = 0; r < cmdLine.regN; r++) {
+        RegSpec spec = cmdLine.regSpecs[r];
+        if (spec.y >= pamP->height || spec.x >= pamP->width)
+            pm_error("Region at %i,%i is outside the image boundaries.",
+                     spec.x, spec.y);
+
+        if (spec.y > ycmax)
+            ycmax = spec.y;
+    }
+    ymax = ycmax + cmdLine.radius;
+    if (ymax > pamP->height - 1)
+        ymax = pamP->height - 1;
+    return ymax;
+}
+
+
+
+static void
+readChord(RegData *    const dataP,
+          uint         const linear,
+          struct pam * const pamP,
+          tuple *      const row,
+          uint         const x0,
+          uint         const x1) {
+/*----------------------------------------------------------------------------
+  Update region sample <dataP> with the data from horisontal chord lying in
+  row <row> and going from <x0> to <x1>. <linear> denotes whether <pamP> is
+  true PPM or the linear variation.
+-----------------------------------------------------------------------------*/
+    uint x;
+
+    for (x = x0; x <= x1; x++) {
+        uint l;
+
+        for (l = 0; l < 3; l++) {
+            double val;
+
+            val = (double)row[x][l] / pamP->maxval;
+            /* convert to intensity because brightness is not additive: */
+            if (!linear)
+                val = pm_ungamma709(val);
+            dataP->color[l] += val;
+        }
+        dataP->area++;
+    }
+}
+
+
+
+static void
+processRow(tuple *      const   row,
+           uint         const   y,
+           struct pam * const   pamP,
+           CmdlineInfo  const * cmdLineP,
+           RegData *    const   regSamples) {
+/*----------------------------------------------------------------------------
+  Reads a row from image <pamP> into allocated tuple array <row>, and updates
+  region samples <regSamples[]> from it.  <y> is the position of the row.
+-----------------------------------------------------------------------------*/
+    uint r;
+
+    pnm_readpamrow(pamP, row);
+    for (r = 0; r < cmdLineP->regN; r++) {
+        RegSpec   spec;
+        RegData * dataP;
+        uint      yd, xd, xd2;
+        int       x0, x1;
+
+        spec  = cmdLineP->regSpecs[r];
+        dataP = &regSamples[r];
+        yd    = spec.y - y;
+        if (abs(yd) > cmdLineP->radius)
+            continue; /* to avoid the slow root operation when possible */
+        xd2 = sqri(cmdLineP->radius) - sqri(yd);
+        xd = (int)(sqrt((double)xd2) + 0.5);
+        x0 = spec.x - xd;
+        x1 = spec.x + xd;
+
+        /* clip horisontal chord to image boundaries: */
+        if (x0 < 0)
+            x0 = 0;
+        if (x1 >= pamP->width)
+            x1 = pamP->width - 1;
+
+        readChord(dataP, cmdLineP->linear, pamP, row, x0, x1);
+    }
+}
+
+
+
+static RegData *
+getColors(struct pam * const pamP,
+          CmdlineInfo  const cmdLine) {
+/*----------------------------------------------------------------------------
+  Scans image <pamP> and collects color data for the regions.
+-----------------------------------------------------------------------------*/
+    uint      y, ymax;
+    RegData * samples;
+    tuple *   row;
+    FILE *    inFile;
+
+    inFile = pm_openr(cmdLine.infile);
+    pnm_readpaminit(inFile, pamP, PAM_STRUCT_SIZE(tuple_type));
+
+    ymax = getYmax( pamP, cmdLine );
+
+    samples = allocRegSamples( cmdLine.regN );
+    row     = pnm_allocpamrow(pamP);
+    y       = 0;
+    for (y = 0; y <= ymax; y++)
+        processRow( row, y, pamP, &cmdLine, samples );
+
+    pnm_freepamrow(row);
+    pm_close(inFile);
+    return samples;
+}
+
+
+
+static char const *
+formatColor(RegData      const data,
+            CmdlineInfo  const cmdLine,
+            struct pam * const pamP,
+            tuple        const tup) {
+/*----------------------------------------------------------------------------
+  Format the color of region sample <data> according to the format specified
+  in <cmdLine>.  The image <pamP> and tuple <tup> are required by the Netpbm
+  formatting functions.
+-----------------------------------------------------------------------------*/
+    uint l;
+
+    for (l = 0; l < 3; l++)
+        tup[l] = pm_gamma709(data.color[l]/data.area) * pamP->maxval;
+
+    return formats[cmdLine.formatId].
+        formatColor(pamP, tup, cmdLine.formatArg);
+}
+
+
+
+static void
+printColors(struct pam * const pamP,
+            CmdlineInfo  const cmdLine,
+            FILE *       const outChan,
+            RegData      const regSamples[]) {
+/*----------------------------------------------------------------------------
+  Prints the colors or <regSamples> to channel <outChan> in the format
+  specified in <cmdLine>. <pamP> is required by the formatting function.
+-----------------------------------------------------------------------------*/
+    char  fmt[20];
+    uint  r;
+    tuple tup;
+
+    tup = pnm_allocpamtuple(pamP);
+    sprintf(fmt, "%%%is: %%s\n", cmdLine.maxLbLen);
+    for (r = 0; r < cmdLine.regN; r++) {
+        RegSpec      spec;
+        RegData      data;
+        char const * color;
+
+        spec  = cmdLine.regSpecs[r];
+        data  = regSamples[r];
+        color = formatColor( data, cmdLine, pamP, tup );
+        fprintf(outChan, fmt, spec.label, color);
+        pm_strfree(color);
+    }
+    pnm_freepamtuple(tup);
+}
+
+
+
+int
+main(int argc, char const *argv[]) {
+
+    RegData *   regSamples;
+    CmdlineInfo cmdLine;
+    struct pam  pam;
+
+    pm_proginit(&argc, argv);
+
+    cmdLine    = parseCommandLine(argc, argv);
+
+    regSamples = getColors(&pam, cmdLine);
+
+    printColors(&pam, cmdLine, stdout, regSamples);
+
+    free(cmdLine.regSpecs); /* Asymmetrical: maybe write freeCommandLine() ? */
+    free(regSamples);
+
+    return 0;
+}
+
+
+
diff --git a/analyzer/pgmtexture.c b/analyzer/pgmtexture.c
index 84c6bf4a..58833277 100644
--- a/analyzer/pgmtexture.c
+++ b/analyzer/pgmtexture.c
@@ -34,9 +34,9 @@
 ** ANY SUCH ITEM. LICENSEE AND/OR USER AGREES TO INDEMNIFY AND HOLD
 ** TAES AND TAMUS HARMLESS FROM ANY CLAIMS ARISING OUT OF THE USE OR
 ** POSSESSION OF SUCH ITEMS.
-** 
+**
 ** Modification History:
-** 24 Jun 91 - J. Michael Carstensen <jmc@imsor.dth.dk> supplied fix for 
+** 24 Jun 91 - J. Michael Carstensen <jmc@imsor.dth.dk> supplied fix for
 **             correlation function.
 **
 ** 05 Oct 05 - Marc Breithecker <Marc.Breithecker@informatik.uni-erlangen.de>
@@ -151,7 +151,7 @@ matrix (unsigned int const nrl,
 
 
 
-static void 
+static void
 results (const char *  const name,
          const float * const a) {
 
@@ -167,7 +167,7 @@ results (const char *  const name,
 
 
 
-static void 
+static void
 simplesrt (unsigned int  const n,
            float *       const arr) {
 
@@ -190,7 +190,7 @@ simplesrt (unsigned int  const n,
 
 
 
-static void 
+static void
 mkbalanced (float **     const a,
             unsigned int const n) {
 
@@ -240,7 +240,7 @@ mkbalanced (float **     const a,
 
 
 
-static void 
+static void
 reduction (float **     const a,
            unsigned int const n) {
 
@@ -262,7 +262,7 @@ reduction (float **     const a,
             for (j = m - 1; j <= n; ++j)
                 SWAP(a[i][j], a[m][j]);
             for (j = 1; j <= n; j++)
-                SWAP(a[j][i], a[j][m]); 
+                SWAP(a[j][i], a[j][m]);
             a[j][i] = a[j][i];
         }
         if (x != 0.0) {
@@ -302,7 +302,7 @@ norm(float **     const a,
 
 
 
-static void 
+static void
 hessenberg(float **     const a,
            unsigned int const n,
            float *      const wr,
@@ -344,7 +344,7 @@ hessenberg(float **     const a,
                     float const z = sqrt(fabs(q));
                     x += t;
                     if (q >= 0.0) {
-                        float const z2 = p + sign(z, p); 
+                        float const z2 = p + sign(z, p);
                         wr[nn - 1] = wr[nn] = x + z2;
                         if (z2)
                             wr[nn] = x - w / z2;
@@ -386,7 +386,7 @@ hessenberg(float **     const a,
                         if (m == l)
                             break;
                         u = fabs(a[m][m - 1]) * (fabs(q) + fabs(r));
-                        v = fabs(p) * (fabs(a[m - 1][m - 1]) + fabs(z) + 
+                        v = fabs(p) * (fabs(a[m - 1][m - 1]) + fabs(z) +
                                        fabs(a[m + 1][m + 1]));
                         if (u + v == v)
                             break;
@@ -454,7 +454,7 @@ hessenberg(float **     const a,
 
 
 
-static float 
+static float
 f1_a2m(float **     const p,
        unsigned int const ng) {
 /*----------------------------------------------------------------------------
@@ -478,12 +478,12 @@ f1_a2m(float **     const p,
 
 
 
-static float 
+static float
 f2_contrast(float **     const p,
             unsigned int const ng) {
 /*----------------------------------------------------------------------------
    Contrast
-   
+
    The contrast feature is a difference moment of the P matrix and is a
    measure of the contrast or the amount of local variations present in an
    image.
@@ -508,7 +508,7 @@ f2_contrast(float **     const p,
 
 
 
-static float 
+static float
 f3_corr(float **     const p,
         unsigned int const ng) {
 /*----------------------------------------------------------------------------
@@ -560,7 +560,7 @@ f3_corr(float **     const p,
 
 
 
-static float 
+static float
 f4_var (float **     const p,
         unsigned int const ng) {
 /*----------------------------------------------------------------------------
@@ -584,7 +584,7 @@ f4_var (float **     const p,
 
 
 
-static float 
+static float
 f5_idm (float **     const p,
         unsigned int const ng) {
 /*----------------------------------------------------------------------------
@@ -603,7 +603,7 @@ f5_idm (float **     const p,
 
 
 
-static float 
+static float
 f6_savg (float **     const p,
          unsigned int const ng) {
 /*----------------------------------------------------------------------------
@@ -631,7 +631,7 @@ f6_savg (float **     const p,
 
 
 
-static float 
+static float
 f7_svar (float **     const p,
          unsigned int const ng,
          float        const s) {
@@ -660,7 +660,7 @@ f7_svar (float **     const p,
 
 
 
-static float 
+static float
 f8_sentropy (float **     const p,
              unsigned int const ng) {
 /*----------------------------------------------------------------------------
@@ -688,7 +688,7 @@ f8_sentropy (float **     const p,
 
 
 
-static float 
+static float
 f9_entropy (float **     const p,
             unsigned int const ng) {
 /*----------------------------------------------------------------------------
@@ -707,9 +707,9 @@ f9_entropy (float **     const p,
 
 
 
-static float 
-f10_dvar (float **     const p,
-          unsigned int const ng) {
+static float
+f10_dvar(float **     const p,
+         unsigned int const ng) {
 /*----------------------------------------------------------------------------
    Difference Variance
 -----------------------------------------------------------------------------*/
@@ -728,7 +728,7 @@ f10_dvar (float **     const p,
     for (i = 0; i < ng; ++i) {
         unsigned int j;
         for (j = 0; j < ng; ++j)
-            pxpy[abs(i - j)] += p[i][j];
+            pxpy[abs((int)i - (int)j)] += p[i][j];
     }
     /* Now calculate the variance of Pxpy (Px-y) */
     for (i = 0, sum = 0.0, sumSqr = 0.0; i < ng; ++i) {
@@ -743,7 +743,7 @@ f10_dvar (float **     const p,
 
 
 
-static float 
+static float
 f11_dentropy (float **     const p,
               unsigned int const ng) {
 /*----------------------------------------------------------------------------
@@ -761,7 +761,7 @@ f11_dentropy (float **     const p,
     for (i = 0; i < ng; ++i) {
         unsigned int j;
         for (j = 0; j < ng; ++j)
-            pxpy[abs(i - j)] += p[i][j];
+            pxpy[abs((int)i - (int)j)] += p[i][j];
     }
     for (i = 0, sum = 0.0; i < ng; ++i)
         sum += pxpy[i] * log10(pxpy[i] + EPSILON);
@@ -771,7 +771,7 @@ f11_dentropy (float **     const p,
 
 
 
-static float 
+static float
 f12_icorr (float **     const p,
            unsigned int const ng) {
 /*----------------------------------------------------------------------------
@@ -817,8 +817,8 @@ f12_icorr (float **     const p,
 
 
 
-static float 
-f13_icorr (float **     const p, 
+static float
+f13_icorr (float **     const p,
            unsigned int const ng) {
 /*----------------------------------------------------------------------------
   Information Measures of Correlation
@@ -863,7 +863,7 @@ f13_icorr (float **     const p,
 
 
 
-static float 
+static float
 f14_maxcorr (float **     const p,
              unsigned int const ng) {
 /*----------------------------------------------------------------------------
diff --git a/converter/other/cameratopam/camera.c b/converter/other/cameratopam/camera.c
index f6196777..439c9413 100644
--- a/converter/other/cameratopam/camera.c
+++ b/converter/other/cameratopam/camera.c
@@ -1,8 +1,6 @@
 #define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */
-#define _BSD_SOURCE
-    /* Make sure strcasecmp is in string.h */
-#define _XOPEN_SOURCE
-    /* Make sure putenv is in stdlib.h */
+#define _XOPEN_SOURCE 500
+    /* Make sure putenv is in stdlib.h, strcaseeq is in nstring.h */
 
 #include <stdlib.h>
 #include <string.h>
@@ -17,6 +15,7 @@
 #include "pm.h"
 #include "mallocvar.h"
 #include "pm_c_util.h"
+#include "nstring.h"
 
 #include "global_variables.h"
 #include "cameratopam.h"
@@ -47,8 +46,8 @@
 #define FORC3 for (c=0; c < 3; c++)
 #define FORC4 for (c=0; c < colors; c++)
 
-static void 
-merror (const void *ptr, const char *where) 
+static void
+merror (const void *ptr, const char *where)
 {
     if (ptr == NULL)
         pm_error ("Out of memory in %s", where);
@@ -57,7 +56,7 @@ merror (const void *ptr, const char *where)
 
 
 
-static void  
+static void
 adobeCopyPixel(Image             const image,
                unsigned int      const row,
                unsigned int      const col,
@@ -307,7 +306,7 @@ minolta_z2()
 
 void
 nikon_e2100_load_raw(Image const image) {
-        
+
   unsigned char   data[3432], *dp;
   unsigned short pixel[2288], *pix;
   int row, col;
@@ -384,7 +383,7 @@ fuji_s3_load_raw(Image const image) {
   }
 }
 
-static void 
+static void
 fuji_common_load_raw(Image        const image,
                      unsigned int const ncol,
                      unsigned int const icol,
@@ -1044,7 +1043,7 @@ static void  sony_decrypt (unsigned *data, int len, int start, int key)
         u.bytes[1] = pad[p] >> 16;
         u.bytes[2] = pad[p] >>  8;
         u.bytes[3] = pad[p] >>  0;
-        
+
         pad[p] = u.word;
     }
   }
@@ -1154,9 +1153,9 @@ static void  ciff_block_1030()
 /*
    Parse a CIFF file, better known as Canon CRW format.
  */
-void 
-parse_ciff(FILE * const ifp, 
-           int    const offset, 
+void
+parse_ciff(FILE * const ifp,
+           int    const offset,
            int    const length)
 {
   int tboff, nrecs, i, type, len, roff, aoff, save, wbi=-1;
@@ -1309,7 +1308,7 @@ parse_rollei(FILE * const ifp)
 
 
 void
-parse_mos(FILE * const ifp, 
+parse_mos(FILE * const ifp,
           int    const offset)
 {
     char data[40];
@@ -1358,7 +1357,7 @@ static double getrat()
 
 
 
-static void 
+static void
 parse_makernote(FILE * const ifp)
 {
   unsigned base=0, offset=0, entries, tag, type, len, save;
@@ -1504,7 +1503,7 @@ get_timestamp(FILE * const ifp)
     timestamp = ts;
 }
 
-static void 
+static void
 parse_exif(FILE * const ifp, int base)
 {
   int entries, tag, len, val, save;
@@ -1529,7 +1528,7 @@ parse_exif(FILE * const ifp, int base)
   }
 }
 
-static int 
+static int
 parse_tiff_ifd(FILE * const ifp, int base, int level)
 {
   unsigned entries, tag, type, len, plen=16, save;
@@ -1690,7 +1689,7 @@ guess_cfa_pc:
       case 50723:           /* CameraCalibration1 */
       case 50724:           /* CameraCalibration2 */
     for (i=0; i < colors; i++)
-      FORC4 cc[i][c] = getrat();    
+      FORC4 cc[i][c] = getrat();
       case 50727:           /* AnalogBalance */
     FORC4 ab[c] = getrat();
     break;
@@ -1770,7 +1769,7 @@ parse_external_jpeg(const char * const ifname)
     strcpy (jname, ifname);
     jfile = jname + (file - ifname);
     jext  = jname + (ext  - ifname);
-    if (strcasecmp (ext, ".jpg")) {
+    if (!strcaseeq (ext, ".jpg")) {
         strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
         memcpy (jfile, file+4, 4);
         memcpy (jfile+4, file, 4);
diff --git a/converter/other/fiasco/codec/decoder.c b/converter/other/fiasco/codec/decoder.c
index 8e2855ef..229996b6 100644
--- a/converter/other/fiasco/codec/decoder.c
+++ b/converter/other/fiasco/codec/decoder.c
@@ -3,11 +3,11 @@
  *
  *  Written by:     Ullrich Hafner
  *          Michael Unger
- *      
+ *
  *  This file is part of FIASCO (Fractal Image And Sequence COdec)
  *  Copyright (C) 1994-2000 Ullrich Hafner
  */
- 
+
 /*
  *  $Date: 2000/10/22 10:44:48 $
  *  $Author: hafner $
@@ -37,7 +37,7 @@
 /*****************************************************************************
 
                 prototypes
-  
+
 *****************************************************************************/
 
 static void
@@ -63,7 +63,7 @@ duplicate_state_image (const word_t *domain, unsigned offset, unsigned level);
 /*****************************************************************************
 
                 public code
-  
+
 *****************************************************************************/
 
 video_t *
@@ -78,7 +78,7 @@ alloc_video (bool_t store_wfa)
  */
 {
    video_t *video = Calloc (1, sizeof (video_t));
-   
+
    video->future_display = -1;
    video->display        = 0;
 
@@ -138,13 +138,13 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
  *  Get next frame of the WFA 'video' from stream 'input'.
  *  'orig_wfa' is the constant part of the WFA used by all frames.
  *  Depending on values of 'enlarge_factor' and 'smoothing' enlarge and
- *  smooth image, respectively. 
+ *  smooth image, respectively.
  *  If 'store_wfa' is TRUE, then store WFA structure of reference frames
  *  (used by analysis tool xwfa).
  *  If 'reference_frame' is not NULL, then load image 'reference_frame'
  *  from disk.
  *  'format' gives the color format to be used (either 4:2:0 or 4:4:4).
- *  If 'timer' is not NULL, then accumulate running time statistics. 
+ *  If 'timer' is not NULL, then accumulate running time statistics.
  *
  *  Return value:
  *  pointer to decoded frame
@@ -157,7 +157,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
    image_t *sframe            = NULL; /* current smoothed frame */
    bool_t   current_frame_is_future_frame = NO;
 
-   if (video->future_display == video->display)  
+   if (video->future_display == video->display)
    {
       /*
        *  Future frame is already computed since it has been used
@@ -189,7 +189,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
      clock_t       ptimer;
      unsigned int  stop_timer [3];
      wfa_t        *tmp_wfa = NULL;
-     
+
      if (!store_wfa)
         video->wfa = orig_wfa;
      else
@@ -198,7 +198,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
         copy_wfa (tmp_wfa, video->wfa);
         copy_wfa (video->wfa, orig_wfa);
      }
-   
+
      /*
       *  First step: read WFA from disk
       */
@@ -210,7 +210,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
         timer->input [video->wfa->frame_type] += stop_timer [0];
         timer->frames [video->wfa->frame_type]++;
      }
-      
+
      /*
       *  Read reference frame from disk if required
       *  (i.e., 1st frame is of type B or P)
@@ -225,7 +225,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
         video->frame  = read_image_file (reference_frame);
         video->sframe = NULL;
      }
-   
+
      /*
       *  Depending on current frame type update past and future frames
       */
@@ -313,7 +313,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
      }
      if (tmp_wfa)
         free_wfa (tmp_wfa);
-     
+
      current_frame_is_future_frame = NO;
      /*
       *  Second step: decode image
@@ -323,7 +323,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
         unsigned orig_width, orig_height;
 
         stop_timer [0] = stop_timer [1] = stop_timer [2] = 0;
-     
+
         enlarge_image (enlarge_factor, format,
                (video->wfa->wfainfo->color
                 && format == FORMAT_4_2_0)
@@ -332,10 +332,10 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
         if (enlarge_factor > 0)
         {
            orig_width  = video->wfa->wfainfo->width  << enlarge_factor;
-           orig_height = video->wfa->wfainfo->height << enlarge_factor; 
+           orig_height = video->wfa->wfainfo->height << enlarge_factor;
         }
         else
-        { 
+        {
            orig_width  = video->wfa->wfainfo->width  >> - enlarge_factor;
            orig_height = video->wfa->wfainfo->height >> - enlarge_factor;
            if (orig_width & 1)
@@ -343,7 +343,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
            if (orig_height & 1)
           orig_height++;
         }
-     
+
         frame = decode_image (orig_width, orig_height, format,
                   timer != NULL ? stop_timer : NULL,
                   video->wfa);
@@ -381,7 +381,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
      }
      else
         sframe = NULL;
-     
+
      stop_timer [0] = prg_timer (&ptimer, STOP);
      if (timer)
         timer->smooth [video->wfa->frame_type] += stop_timer [0];
@@ -399,7 +399,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
         video->future_display     = frame_number;
         current_frame_is_future_frame = YES;
      }
-      
+
      if (!store_wfa)
         remove_states (video->wfa->basis_states, video->wfa);
       } while (!video->frame);
@@ -407,7 +407,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor,
       if (!store_wfa)
      video->wfa = NULL;
    }
-   
+
    return video->sframe ? video->sframe : video->frame;
 }
 
@@ -418,8 +418,8 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format,
  *  Compute image which is represented by the given 'wfa'.
  *  'orig_width'x'orig_height' gives the resolution of the image at
  *  coding time. Use 4:2:0 subsampling or 4:4:4 'format' for color images.
- *  If 'dec_timer' is given, accumulate running time statistics. 
- *  
+ *  If 'dec_timer' is given, accumulate running time statistics.
+ *
  *  Return value:
  *  pointer to decoded image
  *
@@ -458,7 +458,7 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format,
    for (max_level = 0, state = wfa->basis_states; state < wfa->states; state++)
       if (isedge (wfa->into [state][0][0]) || isedge (wfa->into [state][1][0]))
      max_level = MAX(max_level, wfa->level_of_state [state]);
-   
+
 
    /*
     *  Allocate frame buffer for decoded image
@@ -468,7 +468,7 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format,
    width  = MAX(width, orig_width);
    height = MAX(height, orig_height);
    frame = alloc_image (width, height, wfa->wfainfo->color, format);
-   
+
    /*
     *  Allocate buffers for intermediate state images
     */
@@ -478,7 +478,7 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format,
       wfa->level_of_state [wfa->tree[wfa->root_state][0]] = 128;
       wfa->level_of_state [wfa->tree[wfa->root_state][1]] = 128;
    }
-   alloc_state_images (&images, &offsets, frame, root_state, 0, max_level, 
+   alloc_state_images (&images, &offsets, frame, root_state, 0, max_level,
                format, wfa);
 
    if (dec_timer)
@@ -498,20 +498,20 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format,
    prg_timer (&ptimer, START);
    free_state_images (max_level, frame->color, images, offsets, root_state, 0,
               format, wfa);
-   
+
    /*
     *  Crop decoded image if the image size differs.
     */
    if (orig_width != width || orig_height != height)
    {
-      frame->height = orig_height;  
-      frame->width  = orig_width;   
-      if (orig_width != width)      
+      frame->height = orig_height;
+      frame->width  = orig_width;
+      if (orig_width != width)
       {
      color_e   band;        /* current color band */
      word_t   *src, *dst;       /* source and destination pointers */
      unsigned  y;           /* current row */
-     
+
      for (band  = first_band (frame->color);
           band <= last_band (frame->color); band++)
      {
@@ -546,7 +546,7 @@ decode_state (unsigned state, unsigned level, wfa_t *wfa)
  *  pointer to decoded state image
  *
  *  Side effects:
- *  'wfa' states > 'state' are removed.  
+ *  'wfa' states > 'state' are removed.
  */
 {
    word_t  *domains [2];
@@ -571,7 +571,7 @@ decode_state (unsigned state, unsigned level, wfa_t *wfa)
    {
       word_t   *src, *dst;
       unsigned  y;
-        
+
       src = domains [0];
       dst = img->pixels [GRAY];
       for (y = img->height; y; y--)
@@ -603,73 +603,73 @@ decode_range (unsigned range_state, unsigned range_label, unsigned range_level,
  *  'wfa->level_of_state []' is changed
  */
 {
-   image_t   *state_image;      /* regenerated state image */
-   word_t   **images;           /* pointer to array of pointers
-                       to state images */
-   u_word_t  *offsets;          /* pointer to array of state image
-                       offsets */
-   word_t    *range;
-
-   enlarge_image (range_level - (wfa->level_of_state [range_state] - 1),
-          FORMAT_4_4_4, -1, wfa);
-   state_image    = alloc_image (width_of_level (range_level + 1),
-                 height_of_level (range_level + 1),
-                 NO, FORMAT_4_4_4);
-   alloc_state_images (&images, &offsets, state_image, NULL, range_state,
-               range_level + 1, NO, wfa);
-   compute_state_images (range_level + 1, images, offsets, wfa);
-
-   range = Calloc (size_of_level (range_level), sizeof (word_t));
-
-   if ((range_level & 1) == 0)      /* square image */
-   {
-      memcpy (range,
-          images [range_state + (range_level + 1) * wfa->states]
-          + range_label * size_of_level (range_level),
-          size_of_level (range_level) * sizeof (word_t));
-   }
-   else                 /* rectangle */
-   {
-      word_t   *src, *dst;
-      unsigned  y;
-      
-      src = images [range_state + (range_level + 1) * wfa->states]
-        + range_label * width_of_level (range_level);
-      dst = range;
-      for (y = height_of_level (range_level); y; y--)
-      {
-     memcpy (dst, src, width_of_level (range_level) * sizeof (word_t));
-     dst += width_of_level (range_level);
-     src += width_of_level (range_level + 1);
-      }
-   }
-
-   if (domain != NULL)          /* copy domain images */
-   {
-      int      s;           /* domain state */
-      unsigned edge;            /* counter */
-        
-      if (ischild (s = wfa->tree [range_state][range_label]))
-     *domain++ = duplicate_state_image (images [s + (range_level)
-                           * wfa->states],
-                        offsets [s + (range_level)
-                            * wfa->states],
-                        range_level);
-      for (edge = 0; isedge (s = wfa->into[range_state][range_label][edge]);
-       edge++)
-     *domain++ = duplicate_state_image (images [s + (range_level)
-                           * wfa->states],
-                        offsets [s + (range_level)
-                            * wfa->states],
-                        range_level);
-      *domain = NULL;
-   }
-   
-   free_state_images (range_level + 1, NO, images, offsets, NULL, range_state,
-              NO, wfa);
-   free_image (state_image);
-   
-   return range;
+    image_t   *state_image;      /* regenerated state image */
+    word_t   **images;           /* pointer to array of pointers
+                                    to state images */
+    u_word_t  *offsets;          /* pointer to array of state image
+                                    offsets */
+    word_t    *range;
+
+    enlarge_image (range_level - (wfa->level_of_state [range_state] - 1),
+                   FORMAT_4_4_4, -1, wfa);
+    state_image = alloc_image (width_of_level (range_level + 1),
+                               height_of_level (range_level + 1),
+                               NO, FORMAT_4_4_4);
+    alloc_state_images (&images, &offsets, state_image, NULL, range_state,
+                        range_level + 1, FORMAT_4_4_4, wfa);
+    compute_state_images (range_level + 1, images, offsets, wfa);
+
+    range = Calloc (size_of_level (range_level), sizeof (word_t));
+
+    if ((range_level & 1) == 0)      /* square image */
+    {
+        memcpy (range,
+                images [range_state + (range_level + 1) * wfa->states]
+                + range_label * size_of_level (range_level),
+                size_of_level (range_level) * sizeof (word_t));
+    }
+    else                 /* rectangle */
+    {
+        word_t   *src, *dst;
+        unsigned  y;
+
+        src = images [range_state + (range_level + 1) * wfa->states]
+            + range_label * width_of_level (range_level);
+        dst = range;
+        for (y = height_of_level (range_level); y; y--)
+        {
+            memcpy (dst, src, width_of_level (range_level) * sizeof (word_t));
+            dst += width_of_level (range_level);
+            src += width_of_level (range_level + 1);
+        }
+    }
+
+    if (domain != NULL)          /* copy domain images */
+    {
+        int      s;           /* domain state */
+        unsigned edge;            /* counter */
+
+        if (ischild (s = wfa->tree [range_state][range_label]))
+            *domain++ = duplicate_state_image (images [s + (range_level)
+                                                       * wfa->states],
+                                               offsets [s + (range_level)
+                                                        * wfa->states],
+                                               range_level);
+        for (edge = 0; isedge (s = wfa->into[range_state][range_label][edge]);
+             edge++)
+            *domain++ = duplicate_state_image (images [s + (range_level)
+                                                       * wfa->states],
+                                               offsets [s + (range_level)
+                                                        * wfa->states],
+                                               range_level);
+        *domain = NULL;
+    }
+
+    free_state_images (range_level + 1, NO, images, offsets, NULL, range_state,
+                       FORMAT_4_4_4, wfa);
+    free_image (state_image);
+
+    return range;
 }
 
 void
@@ -685,7 +685,7 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image)
  */
 {
    int      is, inegs;          /* integer factors of s and 1 - s*/
-   unsigned state;          
+   unsigned state;
    unsigned img_width  = image->width;
    unsigned img_height = image->height;
    real_t   s          = 1.0 - sf / 200.0;
@@ -695,7 +695,7 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image)
 
    is    = s * 512 + .5;        /* integer representation of s */
    inegs = (1 - s) * 512 + .5;      /* integer representation of 1 - s */
-   
+
    for (state = wfa->basis_states;
     state < (wfa->wfainfo->color
          ? wfa->tree [wfa->root_state][0]
@@ -706,10 +706,10 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image)
       unsigned  level  = wfa->level_of_state[state]; /* level of state image */
       unsigned  width  = width_of_level (level); /* size of state image */
       unsigned  height = height_of_level (level); /* size of state image */
-      
+
       if (wfa->y [state][1] >= img_height || wfa->x [state][1] >= img_width)
      continue;          /* outside visible area */
-     
+
       if (level % 2)            /* horizontal smoothing */
       {
      unsigned  i;           /* line counter */
@@ -719,12 +719,12 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image)
      img1 = bptr + (wfa->y [state][1] - 1) * img_width
         + wfa->x [state][1];
      img2 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1];
-     
+
      for (i = MIN(width, img_width - wfa->x [state][1]); i;
           i--, img1++, img2++)
      {
         int tmp = *img1;
-        
+
 #ifdef HAVE_SIGNED_SHIFT
         *img1 = (((is * tmp) >> 10) << 1)
             + (((inegs * (int) *img2) >> 10) << 1);
@@ -746,12 +746,12 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image)
 
      img1 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1] - 1;
      img2 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1];
-     
+
      for (i = MIN(height, img_height - wfa->y [state][1]); i;
           i--, img1 += img_width, img2 += img_width)
      {
         int tmp = *img1;
-        
+
 #ifdef HAVE_SIGNED_SHIFT
         *img1 = (((is * tmp) >> 10) << 1)
             + (((inegs * (int) *img2) >> 10) << 1);
@@ -771,7 +771,7 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image)
 /*****************************************************************************
 
                 private code
-  
+
 *****************************************************************************/
 
 static void
@@ -789,7 +789,7 @@ enlarge_image (int enlarge_factor, format_e format, unsigned y_root,
  *  are modified.
  */
 {
-   
+
    if (enlarge_factor != 0 || format == FORMAT_4_2_0)
    {
       unsigned state;
@@ -801,11 +801,11 @@ enlarge_image (int enlarge_factor, format_e format, unsigned y_root,
       }
       else
      state = wfa->basis_states;
-      
+
       for (; state < wfa->states; state++)
       {
      unsigned label, n;
-     
+
      wfa->level_of_state [state]
         = MAX(wfa->level_of_state [state] + enlarge_factor * 2, 0);
 
@@ -855,12 +855,12 @@ compute_actual_size (unsigned luminance_root,
 {
    unsigned x = 0, y = 0;       /* maximum coordinates */
    unsigned state;          /* counter */
-   
+
    for (state = wfa->basis_states; state < wfa->states; state++)
       if (isedge (wfa->into [state][0][0]) || isedge (wfa->into [state][1][0]))
       {
           unsigned mult = state > luminance_root ? 2 : 1;
-          
+
           x = MAX((wfa->x [state][0]
                    + width_of_level (wfa->level_of_state [state])) * mult, x);
           y = MAX((wfa->y [state][0]
@@ -886,7 +886,7 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame,
  *  'max_level' fives the max. level of a linear combination.
  *  Memory is allocated for every required state image.
  *  Use 4:2:0 subsampling or 4:4:4 'format' for color images.
- *  If 'range_state' > 0 then rather compute image of 'range_state' than 
+ *  If 'range_state' > 0 then rather compute image of 'range_state' than
  *  image of 'wfa->root_state'.
  *
  *  Return values:
@@ -900,7 +900,7 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame,
    word_t   **simg;         /* ptr to list of state image ptr's */
    u_word_t  *offs;         /* ptr to list of offsets */
    unsigned   level;            /* counter */
-   
+
    simg = Calloc (wfa->states * (max_level + 1), sizeof (word_t *));
    offs = Calloc (wfa->states * (max_level + 1), sizeof (u_word_t));
 
@@ -938,7 +938,7 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame,
         }
       }
    }
-   
+
    /*
     *  Generate list of state images which must be computed at each level
     */
@@ -946,9 +946,9 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame,
    {
       int      child, domain;
       unsigned state, label, edge;
-      
+
       /*
-       *  Range approximation with child. 
+       *  Range approximation with child.
        */
       for (state = 1; state < (range_state > 0 ?
                    range_state + 1 : wfa->states); state++)
@@ -990,7 +990,7 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame,
           }
            }
       /*
-       *  Range approximation with linear combination 
+       *  Range approximation with linear combination
        */
       for (state = 1; state < (range_state > 0 ?
                    range_state + 1 : wfa->states); state++)
@@ -1008,7 +1008,7 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame,
             = width_of_level (level - 1);
           }
            }
-      
+
    }
 
    *images  = simg;
@@ -1039,7 +1039,7 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image,
    else
    {
       unsigned state;
-      
+
       /*
        *  Initialize state image array with states at 'max_level'
        */
@@ -1053,19 +1053,19 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image,
         level = max_level - 2;
      else
         level = max_level;
-      
+
      for (; state < wfa->states; state++)
         if (wfa->level_of_state [state] == level)
            state_image [state + level * wfa->states] = &marker;
       }
    }
-   
+
    for (level = max_level; level > 0; level--)
    {
       int      domain, child;
       unsigned state, label, edge;
       /*
-       *  Range approximation with child. 
+       *  Range approximation with child.
        */
       for (state = 1; state < (range_state > 0 ?
                    range_state + 1 : wfa->states); state++)
@@ -1080,7 +1080,7 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image,
           state_image [child + (level - 1) * wfa->states] = &marker;
            }
       /*
-       *  Range approximation with linear combination 
+       *  Range approximation with linear combination
        */
       for (state = 1; state < (range_state > 0 ?
                    range_state + 1 : wfa->states);
@@ -1089,7 +1089,7 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image,
         for (label = 0; label < MAXLABELS; label++)
            for (edge = 0; isedge (domain = wfa->into[state][label][edge]);
             edge++)
-          if (domain > 0    
+          if (domain > 0
               && (state_image [domain + (level - 1) * wfa->states]
               != NULL)
               && (state_image [domain + (level - 1) * wfa->states]
@@ -1112,7 +1112,7 @@ compute_state_images (unsigned max_level, word_t **simg,
  *  which are marked in the array 'simg' (offsets of state images
  *  are given by 'offset').
  *
- *  Warning: Several optimizations are used in this function making 
+ *  Warning: Several optimizations are used in this function making
  *  it difficult to understand.
  *
  *  No return value.
@@ -1123,7 +1123,7 @@ compute_state_images (unsigned max_level, word_t **simg,
  */
 {
    unsigned level, state;
-     
+
    /*
     *  Copy one-pixel images in case state_image pointer != &final distr.
     */
@@ -1138,17 +1138,17 @@ compute_state_images (unsigned max_level, word_t **simg,
     *  'weight' gives the weight in integer notation
     *  'src', 'dst', and 'idst' are pointers to the source and
     *  destination pixels (short or integer format), respectively.
-    *  Short format : one operation per register (16 bit mode). 
-    *  Integer format : two operations per register (32 bit mode). 
+    *  Short format : one operation per register (16 bit mode).
+    *  Integer format : two operations per register (32 bit mode).
     *  'src_offset', 'dst_offset', and 'dst_offset' give the number of
     *  pixels which have to be omitted when jumping to the next image row.
     */
-   for (level = 1; level <= max_level; level++) 
+   for (level = 1; level <= max_level; level++)
    {
       unsigned label;
       unsigned width  = width_of_level (level - 1);
       unsigned height = height_of_level (level - 1);
-      
+
       for (state = 1; state < wfa->states; state++)
      if (simg [state + level * wfa->states] != NULL)
         for (label = 0; label < MAXLABELS; label++)
@@ -1176,7 +1176,7 @@ compute_state_images (unsigned max_level, word_t **simg,
           }
 
           /*
-           *  Generate the state images by adding the corresponding 
+           *  Generate the state images by adding the corresponding
            *  weighted state images:
            *  subimage [label] =
            *       weight_1 * image_1 + ... + weight_n * image_n
@@ -1226,12 +1226,12 @@ compute_state_images (unsigned max_level, word_t **simg,
             src_offset = offset [domain + ((level - 1)
                                * wfa->states)] - width;
             weight     = wfa->int_weight [state][label][edge];
-            
+
             if (width == 1) /* can't add two-pixels in a row */
             {
                word_t   *dst;
                unsigned  dst_offset;
-               
+
                dst        = range;
                dst_offset = offset [state + level * wfa->states]
                     - width;
@@ -1240,7 +1240,7 @@ compute_state_images (unsigned max_level, word_t **simg,
 #else                   /* not HAVE_SIGNED_SHIFT */
                *dst++ = ((weight * (int) *src++) / 1024) * 2;
 #endif /* not HAVE_SIGNED_SHIFT */
-               if (height == 2) 
+               if (height == 2)
                {
                   src += src_offset;
                   dst += dst_offset;
@@ -1256,14 +1256,14 @@ compute_state_images (unsigned max_level, word_t **simg,
                unsigned  y;
                int      *idst;
                unsigned  idst_offset;
-               
+
                idst        = (int *) range;
                idst_offset = (offset [state + level * wfa->states]
                       - width) / 2;
                for (y = height; y; y--)
                {
                   int *comp_dst = idst + (width >> 1);
-                  
+
                   for (; idst != comp_dst; )
                   {
                  int tmp; /* temp. value of adjacent pixels */
@@ -1312,11 +1312,11 @@ compute_state_images (unsigned max_level, word_t **simg,
             {
                word_t   *dst;
                unsigned  dst_offset;
-               
+
                dst        = range;
                dst_offset = offset [state + level * wfa->states]
                     - width;
-               
+
                *dst++ = weight;
                if (height == 2)
                {
@@ -1329,7 +1329,7 @@ compute_state_images (unsigned max_level, word_t **simg,
                unsigned  x, y;
                int      *idst;
                unsigned  idst_offset;
-               
+
                weight      = (weight * 65536) | (weight & 0xffff);
                idst        = (int *) range;
                idst_offset = offset [state + level * wfa->states]
@@ -1351,7 +1351,7 @@ compute_state_images (unsigned max_level, word_t **simg,
           }
           else
              edge = 0;
-          
+
           /*
            *  Add remaining weighted domain images to current range
            */
@@ -1368,12 +1368,12 @@ compute_state_images (unsigned max_level, word_t **simg,
             src_offset = offset [domain + ((level - 1)
                                * wfa->states)] - width;
             weight     = wfa->int_weight [state][label][edge];
-            
+
             if (width == 1) /* can't add two-pixels in a row */
             {
                word_t   *dst;
                unsigned  dst_offset;
-               
+
                dst        = range;
                dst_offset = offset [state + level * wfa->states]
                     - width;
@@ -1383,7 +1383,7 @@ compute_state_images (unsigned max_level, word_t **simg,
 #else /* not HAVE_SIGNED_SHIFT */
                *dst++ += ((weight * (int) *src++) / 1024) * 2;
 #endif /* not HAVE_SIGNED_SHIFT */
-               if (height == 2) 
+               if (height == 2)
                {
                   src += src_offset;
                   dst += dst_offset;
@@ -1399,15 +1399,15 @@ compute_state_images (unsigned max_level, word_t **simg,
                int      *idst;
                unsigned  idst_offset;
                unsigned  y;
-               
+
                idst        = (int *) range;
                idst_offset = (offset [state + level * wfa->states]
                       - width) / 2;
-               
+
                for (y = height; y; y--)
                {
                   int *comp_dst = idst + (width >> 1);
-                  
+
                   for (; idst != comp_dst;)
                   {
                  int tmp; /* temp. value of adjacent pixels */
@@ -1457,11 +1457,11 @@ compute_state_images (unsigned max_level, word_t **simg,
             {
                word_t   *dst;
                unsigned  dst_offset;
-               
+
                dst        = range;
                dst_offset = offset [state + level * wfa->states]
                     - width;
-               
+
                *dst++ += weight;
                if (height == 2)
                {
@@ -1474,16 +1474,16 @@ compute_state_images (unsigned max_level, word_t **simg,
                int      *idst;
                unsigned  idst_offset;
                unsigned  y;
-               
+
                weight      = (weight * 65536) | (weight & 0xffff);
                idst        = (int *) range;
                idst_offset = (offset [state + level * wfa->states]
                       - width) /2;
-               
+
                for (y = height; y; y--)
                {
                   int *comp_dst = idst + (width >> 1);
-                  
+
                   for (; idst != comp_dst; )
                   {
                  *idst = (*idst + weight) & 0xfffefffe;
@@ -1494,14 +1494,14 @@ compute_state_images (unsigned max_level, word_t **simg,
             }
              }
           }
-           } 
+           }
    }
 }
 
 static word_t *
 duplicate_state_image (const word_t *domain, unsigned offset, unsigned level)
 /*
- *  Allocate new memory block 'pixels' and copy pixel values of 'domain' 
+ *  Allocate new memory block 'pixels' and copy pixel values of 'domain'
  *  (size and pixel offset are given by 'level' and 'offset')
  *  to the lock 'pixels'.
  *
diff --git a/converter/other/jpeg2000/pamtojpeg2k.c b/converter/other/jpeg2000/pamtojpeg2k.c
index 3d8a97af..1272a422 100644
--- a/converter/other/jpeg2000/pamtojpeg2k.c
+++ b/converter/other/jpeg2000/pamtojpeg2k.c
@@ -341,7 +341,7 @@ convertToJasperImage(struct pam *   const inpamP,
 
     createJasperImage(inpamP, &jasperP);
 
-    if (strncmp(inpamP->tuple_type, "RGB", 3) == 0) {
+    if (strneq(inpamP->tuple_type, "RGB", 3)) {
         if (inpamP->depth < 3)
             pm_error("Input tuple type is RGB*, but depth is only %d.  "
                      "It should be at least 3.", inpamP->depth);
@@ -355,8 +355,8 @@ convertToJasperImage(struct pam *   const inpamP,
                                   JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B));
         }
     } else {
-        if (strncmp(inpamP->tuple_type, "GRAYSCALE", 9 == 0) ||
-            strncmp(inpamP->tuple_type, "BLACKANDWHITE", 13) == 0) {
+        if (strneq(inpamP->tuple_type, "GRAYSCALE", 9) ||
+            strneq(inpamP->tuple_type, "BLACKANDWHITE", 13)) {
             jas_image_setclrspc(jasperP, JAS_CLRSPC_GENGRAY);
             jas_image_setcmpttype(jasperP, 0,
                                   JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y));
diff --git a/converter/other/pamtotiff.c b/converter/other/pamtotiff.c
index 139b1fd7..72c7dc31 100644
--- a/converter/other/pamtotiff.c
+++ b/converter/other/pamtotiff.c
@@ -21,9 +21,7 @@
 ** other special, indirect and consequential damages.
 */
 
-#define _DEFAULT_SOURCE  /* New name for SVID & BSD source defines */
 #define _XOPEN_SOURCE    /* Make sure stdio.h contains fileno() */
-#define _BSD_SOURCE      /* Make sure string.h contains strcasecmp() */
 
 #include <unistd.h>
 #include <stdio.h>
diff --git a/converter/other/pclxl.h b/converter/other/pclxl.h
index b1d1c043..5b3eae4b 100644
--- a/converter/other/pclxl.h
+++ b/converter/other/pclxl.h
@@ -48,7 +48,7 @@ enum DataOrg {
 };
 
 enum DataSource {
-    eDefault = 0
+    eDefaultDataSource = 0
 };
 
 enum DataType {
@@ -58,9 +58,9 @@ enum DataType {
     eSint16 = 3
 };
 
-enum DitherMatrix {  
+enum DitherMatrix {
     eDeviceBest = 0
-}; 
+};
 
 
 enum DuplexPageMode {
@@ -109,7 +109,7 @@ enum Measure {
 };
 
 enum MediaSource {
-    eDefaultSource = 0,
+    eDefaultMediaSource = 0,
     eAutoSelect = 1,
     eManualFeed = 2,
     eMultiPurposeTray = 3,
@@ -246,7 +246,7 @@ enum Attribute {
     aYSpacingData        = 176,
     aCharBoldValue       = 177
 };
-                                          
+
 enum Operator {
     oBeginSession        = 0x41,
     oEndSession          = 0x42,
@@ -317,7 +317,7 @@ enum Operator {
     oPiePath             = 0x9f,
     oRectangle           = 0xa0,
     oRectanglePath       = 0xa1,
-    oRoundRectangle      = 0xa2,  
+    oRoundRectangle      = 0xa2,
     oRoundRectanglePath  = 0xa3,
     oText                = 0xa8,
     oTextPath            = 0xa9,
@@ -384,7 +384,7 @@ struct sPaperFormat {
 enum {
     eSTART,
     eRLE,
-    eLIT 
+    eLIT
 } RLEstates;
 
 #endif
diff --git a/converter/other/pngtopam.c b/converter/other/pngtopam.c
index 01690520..1023c6c6 100644
--- a/converter/other/pngtopam.c
+++ b/converter/other/pngtopam.c
@@ -1238,9 +1238,8 @@ static void
 warnNonsquarePixels(struct pngx * const pngxP,
                     int *         const errorLevelP) {
 
-    if (pngx_chunkIsPresent(pngxP, PNG_INFO_pHYs)) {
-        float const r =
-            (float)pngx_xPixelsPerMeter(pngxP) / pngx_yPixelsPerMeter(pngxP);
+    if (pngx_pixelAspectRatioIsKnown(pngxP)) {
+        float const r = pngx_pixelAspectRatio(pngxP);
 
         if (r != 1.0) {
             const char * const baseMsg = "warning - non-square pixels";
diff --git a/converter/other/pngx.c b/converter/other/pngx.c
index a5171066..dfc74485 100644
--- a/converter/other/pngx.c
+++ b/converter/other/pngx.c
@@ -270,15 +270,39 @@ pngx_trns(struct pngx * const pngxP) {
 
 uint32_t
 pngx_xPixelsPerMeter(struct pngx * const pngxP) {
-
+/*----------------------------------------------------------------------------
+  Horizontal pixel density in pixel per meter; 0 if unknown.
+-----------------------------------------------------------------------------*/
     return png_get_x_pixels_per_meter(pngxP->png_ptr, pngxP->info_ptr);
 }
 
 
 
+float
+pngx_pixelAspectRatio(struct pngx * const pngxP) {
+/*----------------------------------------------------------------------------
+  Aspect ratio - y/x.  0.0 if unknown
+-----------------------------------------------------------------------------*/
+    return png_get_pixel_aspect_ratio(pngxP->png_ptr, pngxP->info_ptr);
+}
+
+
+
+bool
+pngx_pixelAspectRatioIsKnown(struct pngx * const pngxP) {
+/*----------------------------------------------------------------------------
+  There is pixel aspect ratio information in the PNG image.
+-----------------------------------------------------------------------------*/
+    return png_get_pixel_aspect_ratio(pngxP->png_ptr, pngxP->info_ptr) != 0.0;
+}
+
+
+
 uint32_t
 pngx_yPixelsPerMeter(struct pngx * const pngxP) {
-
+/*----------------------------------------------------------------------------
+  Vertical pixel density in pixel per meter; 0 if unknown.
+-----------------------------------------------------------------------------*/
     return png_get_y_pixels_per_meter(pngxP->png_ptr, pngxP->info_ptr);
 }
 
@@ -323,7 +347,7 @@ void
 pngx_setChrm(struct pngx *      const pngxP,
              struct pngx_chroma const chroma) {
 
-    png_set_cHRM(pngxP->png_ptr, pngxP->info_ptr, 
+    png_set_cHRM(pngxP->png_ptr, pngxP->info_ptr,
                  chroma.wx, chroma.wy,
                  chroma.rx, chroma.ry,
                  chroma.gx, chroma.gy,
@@ -460,7 +484,7 @@ void
 pngx_setPhys(struct pngx *    const pngxP,
              struct pngx_phys const phys) {
 
-    png_set_pHYs(pngxP->png_ptr, pngxP->info_ptr, 
+    png_set_pHYs(pngxP->png_ptr, pngxP->info_ptr,
                  phys.x, phys.y, phys.unit);
 }
 
@@ -664,7 +688,7 @@ pngx_readStart(struct pngx * const pngxP,
                FILE *        const ifP) {
 
     size_t sigByteCt;
-            
+
     verifyFileIsPng(ifP, &sigByteCt);
 
     /* Declare that we already read the signature bytes */
@@ -711,7 +735,7 @@ pngx_writeRow(struct pngx *    const pngxP,
 void
 pngx_readEnd(struct pngx * const pngxP) {
 
-    /* Note that some of info_ptr is not defined until png_read_end() 
+    /* Note that some of info_ptr is not defined until png_read_end()
        completes.  That's because it comes from chunks that are at the
        end of the stream.  In particular, text and time chunks may
        be at the end.  Furthermore, they may be in both places, in
diff --git a/converter/other/pngx.h b/converter/other/pngx.h
index 008081eb..be9b9558 100644
--- a/converter/other/pngx.h
+++ b/converter/other/pngx.h
@@ -116,6 +116,12 @@ pngx_xPixelsPerMeter(struct pngx * const pngxP);
 uint32_t
 pngx_yPixelsPerMeter(struct pngx * const pngxP);
 
+float
+pngx_pixelAspectRatio(struct pngx * const pngxP);
+
+bool
+pngx_pixelAspectRatioIsKnown(struct pngx * const pngxP);
+
 void
 pngx_removeChunk(struct pngx * const pngxP,
                  uint32_t      const chunkType);
diff --git a/converter/other/pnmtopalm/palmtopnm.c b/converter/other/pnmtopalm/palmtopnm.c
index b58c99bc..b3c0321a 100644
--- a/converter/other/pnmtopalm/palmtopnm.c
+++ b/converter/other/pnmtopalm/palmtopnm.c
@@ -26,8 +26,8 @@
 
 
 enum PalmCompressionType {
-    COMPRESSION_NONE, 
-    COMPRESSION_RLE, 
+    COMPRESSION_NONE,
+    COMPRESSION_RLE,
     COMPRESSION_SCANLINE,
     COMPRESSION_PACKBITS
 };
@@ -102,7 +102,7 @@ parseCommandLine(int argc, const char ** argv,
     unsigned int option_def_index;
 
     MALLOCARRAY_NOFAIL(option_def, 100);
-    
+
     option_def_index = 0;   /* incremented by OPTENTRY */
     OPTENT3(0, "verbose",     OPT_FLAG, NULL,
             &cmdlineP->verbose,  0);
@@ -110,7 +110,7 @@ parseCommandLine(int argc, const char ** argv,
             &cmdlineP->showhist, 0);
     OPTENT3(0, "transparent",    OPT_FLAG, NULL,
             &cmdlineP->transparent, 0);
-    OPTENT3(0, "rendition",  OPT_UINT, &cmdlineP->rendition, 
+    OPTENT3(0, "rendition",  OPT_UINT, &cmdlineP->rendition,
             &renditionSpec, 0);
 
     opt.opt_table = option_def;
@@ -124,9 +124,9 @@ parseCommandLine(int argc, const char ** argv,
     if (renditionSpec) {
         if (cmdlineP->rendition < 1)
             pm_error("The -rendition value must be at least 1");
-    } else 
+    } else
         cmdlineP->rendition = 1;
-    
+
     if (cmdlineP->transparent && cmdlineP->showhist)
         pm_error("You can't specify -showhist with -transparent");
 
@@ -144,7 +144,7 @@ parseCommandLine(int argc, const char ** argv,
 
 
 static xelval *
-createGraymap(unsigned int const ncolors, 
+createGraymap(unsigned int const ncolors,
               xelval       const maxval) {
     int i;
     xelval *map;
@@ -158,8 +158,8 @@ createGraymap(unsigned int const ncolors,
 
 
 
-static void 
-skipbytes(FILE *       const ifP, 
+static void
+skipbytes(FILE *       const ifP,
           unsigned int const nbytes) {
 
     unsigned char buf[256];
@@ -180,7 +180,7 @@ skipbytes(FILE *       const ifP,
                pm_error("Error reading Palm file.  Short read.");
             n = 0;
         }
-    }    
+    }
 }
 
 
@@ -188,7 +188,7 @@ skipbytes(FILE *       const ifP,
 static void
 interpretCompression(unsigned char              const compressionValue,
                      enum PalmCompressionType * const compressionTypeP) {
-    
+
     switch (compressionValue) {
     case PALM_COMPRESSION_RLE:
         *compressionTypeP = COMPRESSION_RLE;
@@ -224,17 +224,18 @@ readRestOfHeaderVersion3(FILE *           const ifP,
                          short *          const nextDepthOffsetP) {
 
     unsigned char unused;
-    
+
     pm_readcharu(ifP, sizeP);
     /* should be 0x18, but I can't see why we should really care */
     if (*sizeP != 0x18)
-        pm_message("Strange value for Palm bitmap header size: %hu", *sizeP);
+        pm_message("Strange value for Palm bitmap header size: %u",
+                   (unsigned)*sizeP);
 
     pm_readcharu(ifP, pixelFormatP);
     if (*pixelFormatP != PALM_FORMAT_INDEXED &&
         *pixelFormatP != PALM_FORMAT_565)
         pm_error("Unrecognized pixelformat type: %u", *pixelFormatP);
-    
+
     pm_readcharu(ifP, &unused);
 
 
@@ -248,15 +249,15 @@ readRestOfHeaderVersion3(FILE *           const ifP,
         *densityP != PALM_DENSITY_TRIPLE &&
         *densityP != PALM_DENSITY_QUADRUPLE)
         pm_error("Invalid value for -density: %d.", *densityP);
- 
+
     pm_readbiglong(ifP, transparentValueP);
     if (pixelSize < 16)
         *transparentIndexP = *transparentValueP;
     else
         *transparentIndexP = 0;
- 
+
     pm_readbiglong(ifP, nextBitmapOffsetP);
-    
+
     /* version < 3 specific */
     *nextDepthOffsetP = 0;
 }
@@ -273,18 +274,18 @@ readRestOfHeaderOld(FILE *           const ifP,
                     long *           const transparentValueP,
                     long *           const nextBitmapOffsetP,
                     short *          const nextDepthOffsetP) {
-    
+
     short pad;
     unsigned char transparentIndex;
-    
+
     pm_readbigshort(ifP, nextDepthOffsetP);
     pm_readcharu(ifP, &transparentIndex);
     *transparentIndexP = transparentIndex;
- 
+
     pm_readcharu(ifP,compressionTypeP);
-    
+
     pm_readbigshort(ifP, &pad); /* reserved by Palm as of 8/9/00 */
-    
+
     /* version 3 specific */
     *sizeP = 0;
     *pixelFormatP = 0;
@@ -310,7 +311,7 @@ interpretHeader(struct PalmHeader * const palmHeaderP,
                 long                const transparentValue,
                 unsigned int        const transparentIndex,
                 unsigned char       const compressionType) {
-    
+
     palmHeaderP->cols = cols;
     palmHeaderP->rows = rows;
     palmHeaderP->bytesPerRow = bytesPerRow;
@@ -333,11 +334,11 @@ interpretHeader(struct PalmHeader * const palmHeaderP,
         */
         pm_error("PALM_DIRECT_COLOR_FLAG is set but pixelFormat is not"
                  "PALM_FORMAT_565.");
-        
-    palmHeaderP->directColor = ((flags & PALM_DIRECT_COLOR_FLAG) || 
+
+    palmHeaderP->directColor = ((flags & PALM_DIRECT_COLOR_FLAG) ||
                                 palmHeaderP->pixelFormat == PALM_FORMAT_565);
-    
-    if (flags & PALM_IS_COMPRESSED_FLAG) 
+
+    if (flags & PALM_IS_COMPRESSED_FLAG)
         interpretCompression(compressionType,
                              &palmHeaderP->compressionType);
     else
@@ -362,7 +363,7 @@ readHeader(FILE *              const ifP,
     currentRendition = 1;
     while (!gotHeader) {
         short cols, rows, bytesPerRow, flags, nextDepthOffset, density;
-        unsigned char pixelSizeCode, version, compressionType, 
+        unsigned char pixelSizeCode, version, compressionType,
             size, pixelFormat;
         long transparentValue, nextBitmapOffset;
         unsigned int pixelSize, transparentIndex;
@@ -371,7 +372,7 @@ readHeader(FILE *              const ifP,
         pm_readbigshort(ifP, &rows);
         pm_readbigshort(ifP, &bytesPerRow);
         pm_readbigshort(ifP, &flags);
- 
+
         pm_readcharu(ifP, &pixelSizeCode);
         pixelSize = pixelSizeCode == 0 ? 1 : pixelSizeCode;
         if (pixelSizeCode != 0x00 &&
@@ -388,12 +389,12 @@ readHeader(FILE *              const ifP,
                      "bits per pixel.", bytesPerRow, cols, pixelSize);
 
         pm_readcharu(ifP, &version);
-        if (version > 3) 
+        if (version > 3)
             pm_error("Unknown encoding version type: %d", version);
         else if (version == 3)
             readRestOfHeaderVersion3(ifP, pixelSize,
                                      &size, &pixelFormat, &compressionType,
-                                     &density, &transparentIndex, 
+                                     &density, &transparentIndex,
                                      &transparentValue, &nextBitmapOffset,
                                      &nextDepthOffset);
         else
@@ -404,29 +405,29 @@ readHeader(FILE *              const ifP,
                                 &nextDepthOffset);
 
         if (currentRendition < requestedRendition) {
-             if (version < 3 && nextDepthOffset == 0 && pixelSizeCode != 0xFF) 
+             if (version < 3 && nextDepthOffset == 0 && pixelSizeCode != 0xFF)
                  pm_error("Not enough renditions in the input Palm Bitmap "
                           "to extract the %dth", requestedRendition);
-             if (version == 3 && nextBitmapOffset == 0) 
+             if (version == 3 && nextBitmapOffset == 0)
                  pm_error("Not enough renditions in the input Palm Bitmap "
                           "to extract the %dth", requestedRendition);
              /* nextDepthOffset is calculated in 4 byte words
-                from the beginning of this bitmap (so it equals its size) 
+                from the beginning of this bitmap (so it equals its size)
              */
              if (version < 3 && pixelSizeCode != 0xFF )
                  skipbytes(ifP, (nextDepthOffset*4)-16);
              else if (version == 3)
                  /* FIXME rewrite skipbytes to accept longs? */
-                 skipbytes(ifP, (short) nextBitmapOffset-24); 
+                 skipbytes(ifP, (short) nextBitmapOffset-24);
              if (pixelSizeCode != 0xFF)
                  ++currentRendition;
         } else if (pixelSizeCode != 0xFF) {
             gotHeader = TRUE;
-            
+
             interpretHeader(palmHeaderP,
                             cols, rows, bytesPerRow, flags, pixelSizeCode,
                             pixelSize, version, size, pixelFormat, density,
-                            transparentValue, transparentIndex, 
+                            transparentValue, transparentIndex,
                             compressionType);
         }
     }
@@ -466,9 +467,9 @@ reportPalmHeader(struct PalmHeader      const palmHeader,
     }
     pm_message("Dimensions: %hu columns x %hu rows",
                palmHeader.cols, palmHeader.rows);
-    pm_message("Row layout: %hu bytes per row, %hu bits per pixel",
+    pm_message("Row layout: %hu bytes per row, %u bits per pixel",
                palmHeader.bytesPerRow, palmHeader.pixelSize);
-    pm_message("Pixel Size code: %hu", palmHeader.pixelSizeCode);
+    pm_message("Pixel Size code: %u", (unsigned)palmHeader.pixelSizeCode);
     pm_message("Flags: 0x%04hx", palmHeader.flags);
     pm_message("  Direct Color: %s", yesno(palmHeader.directColor));
     pm_message("  Colormap:     %s", yesno(palmHeader.hasColormap));
@@ -478,9 +479,9 @@ reportPalmHeader(struct PalmHeader      const palmHeader,
         if (palmHeader.directColor) {
             /* Copied from doTransparent(...) */
             ColormapEntry const color = directColorInfo.transparentColor;
-            pm_message("Transparent value: #%02x%02x%02x", 
-                       (unsigned int)((color >> 16) & 0xFF), 
-                       (unsigned int)((color >>  8) & 0xFF), 
+            pm_message("Transparent value: #%02x%02x%02x",
+                       (unsigned int)((color >> 16) & 0xFF),
+                       (unsigned int)((color >>  8) & 0xFF),
                        (unsigned int)((color >>  0) & 0xFF));
         } else
             pm_message("Transparent index: %u", palmHeader.transparentIndex);
@@ -526,7 +527,7 @@ readRgbFormat(FILE *                     const ifP,
     pm_readcharu(ifP, &r);
     pm_readcharu(ifP, &g);
     pm_readcharu(ifP, &b);
-    
+
     if (r != 5 || g != 6 || b != 5)
         pm_error("This image has a direct color pixel format of "
                  "%u red, %u green, %u blue bits.  This program "
@@ -572,12 +573,12 @@ readDirectInfoType(FILE *                   const ifP,
     if ((palmHeader.directColor) && palmHeader.pixelSize != 16)
         pm_error("The image is of the direct color type, but has %u "
                  "bits per pixel.  The only kind of direct color images "
-                 "this program understands are 16 bit ones.", 
+                 "this program understands are 16 bit ones.",
                  palmHeader.pixelSize);
 
     if (palmHeader.version == 3) {
         /* All direct color info is in the header, because it'sversion
-           3 encoding.  No Direct Info Type section.  
+           3 encoding.  No Direct Info Type section.
         */
     } else {
         if (palmHeader.directColor) {
@@ -588,7 +589,7 @@ readDirectInfoType(FILE *                   const ifP,
             pm_readcharu(ifP, &padding);
             pm_readcharu(ifP, &padding);
 
-            readDirectTransparentColor(ifP, 
+            readDirectTransparentColor(ifP,
                                        &directInfoTypeP->transparentColor);
         } else {
             /* Not a direct color image; no Direct Info Type section. */
@@ -637,7 +638,7 @@ getColorInfo(struct PalmHeader        const palmHeader,
         directColorInfoP->pixelFormat.redbits   = 5;
         directColorInfoP->pixelFormat.greenbits = 6;
         directColorInfoP->pixelFormat.bluebits  = 5;
-        directColorInfoP->transparentColor = 
+        directColorInfoP->transparentColor =
             /* See convertRowToPnmDirect for this trick
 
                This will break once maxval isn't always set 255 for
@@ -657,7 +658,7 @@ getColorInfo(struct PalmHeader        const palmHeader,
     else if (palmHeader.pixelSize >= 8) {
         Colormap * const colormapP =
             palmcolor_build_default_8bit_colormap();
-        qsort(colormapP->color_entries, colormapP->ncolors, 
+        qsort(colormapP->color_entries, colormapP->ncolors,
               sizeof(ColormapEntry), palmcolor_compare_indices);
         *colormapPP = colormapP;
     } else
@@ -689,28 +690,28 @@ doTransparent(FILE *                 const ofP,
             ColormapEntry const searchTarget = transparentIndex << 24;
             ColormapEntry * const foundEntryP =
                 bsearch(&searchTarget,
-                        colormapP->color_entries, 
+                        colormapP->color_entries,
                         colormapP->ncolors,
-                        sizeof(searchTarget), 
+                        sizeof(searchTarget),
                         palmcolor_compare_indices);
             if (!foundEntryP)
                 pm_error("Invalid input; transparent index %u "
                          "is not among the %u colors in the image's colormap",
                          transparentIndex, colormapP->ncolors);
 
-            fprintf(ofP, "#%02x%02x%02x\n", 
+            fprintf(ofP, "#%02x%02x%02x\n",
                    (unsigned int) ((*foundEntryP >> 16) & 0xFF),
-                   (unsigned int) ((*foundEntryP >>  8) & 0xFF), 
+                   (unsigned int) ((*foundEntryP >>  8) & 0xFF),
                    (unsigned int) ((*foundEntryP >>  0) & 0xFF));
         } else if (directColor) {
             ColormapEntry const color = directColorInfo.transparentColor;
-            fprintf(ofP, "#%02x%02x%02x\n", 
-                   (unsigned int)((color >> 16) & 0xFF), 
-                   (unsigned int)((color >>  8) & 0xFF), 
+            fprintf(ofP, "#%02x%02x%02x\n",
+                   (unsigned int)((color >> 16) & 0xFF),
+                   (unsigned int)((color >>  8) & 0xFF),
                    (unsigned int)((color >>  0) & 0xFF));
         } else {
             unsigned int const maxval = pm_bitstomaxval(pixelSize);
-            unsigned int const grayval = 
+            unsigned int const grayval =
                 ((maxval - transparentIndex) * 256) / maxval;
             fprintf(ofP, "#%02x%02x%02x\n", grayval, grayval, grayval);
         }
@@ -728,10 +729,10 @@ createHistogram(unsigned int    const ncolors,
     MALLOCARRAY(seen, ncolors);
     if (!seen)
         pm_error("Can't allocate array for keeping track of "
-                 "how many pixels of each of %u colors are in the image.", 
+                 "how many pixels of each of %u colors are in the image.",
                  ncolors);
 
-    {    
+    {
         /* Initialize the counter for each color to zero */
         unsigned int i;
         for (i = 0; i < ncolors; ++i)
@@ -766,7 +767,7 @@ readScanlineRow(FILE *          const ifP,
 
         pm_readcharu(ifP, &diffmask);
         byteCount = MIN(bytesPerRow - j, 8);
-        
+
         for (k = 0; k < byteCount; ++k) {
             /* the first row cannot be compressed */
             if (firstRow || ((diffmask & (1 << (7 - k))) != 0)) {
@@ -805,7 +806,7 @@ readRleRow(FILE *          const ifP,
         memset(palmrow + j, inval, incount);
         j += incount;
     }
-} 
+}
 
 
 
@@ -815,7 +816,7 @@ readPackBitsRow16(FILE *          const ifP,
                   unsigned int    const bytesPerRow) {
 
     /*  From the Palm OS Programmer's API Reference:
-  
+
         Although the [...] spec is byte-oriented, the 16-bit algorithm is
         identical [to the 8-bit algorithm]: just substitute "word" for "byte".
     */
@@ -824,7 +825,7 @@ readPackBitsRow16(FILE *          const ifP,
     for (j = 0;  j < bytesPerRow; ) {
         char incount;
         pm_readchar(ifP, &incount);
-        if (incount < 0) { 
+        if (incount < 0) {
             /* How do we handle incount == -128 ? */
             unsigned int const runlength = (-incount + 1) * 2;
             unsigned int k;
@@ -846,13 +847,13 @@ readPackBitsRow16(FILE *          const ifP,
             }
             j += nonrunlength;
         }
-        if (j > bytesPerRow) 
+        if (j > bytesPerRow)
             pm_error("Bytes in PackBits compressed row exceed bytes per row.  "
                      "Bytes per row is %u.  "
                      "The bytes in this row were pushed up to %u bytes "
                      "(and then we gave up).", bytesPerRow, j);
     }
-} 
+}
 
 
 
@@ -866,7 +867,7 @@ readPackBitsRow(FILE *          const ifP,
     for (j = 0;  j < bytesPerRow; ) {
         char incount;
         pm_readchar(ifP, &incount);
-        if (incount < 0) { 
+        if (incount < 0) {
             /* How do we handle incount == -128 ? */
             unsigned int const runlength = -incount + 1;
             unsigned char inval;
@@ -884,13 +885,13 @@ readPackBitsRow(FILE *          const ifP,
             }
             j += nonrunlength;
         }
-        if (j > bytesPerRow) 
+        if (j > bytesPerRow)
             pm_error("Bytes in PackBits compressed row exceed bytes per row.  "
                      "Bytes per row is %u.  "
                      "The bytes in this row were pushed up to %u bytes "
                      "(and then we gave up).", bytesPerRow, j);
     }
-} 
+}
 
 
 
@@ -900,7 +901,7 @@ readUncompressedRow(FILE *          const ifP,
                     unsigned int    const bytesPerRow) {
 
     int bytesRead;
-    
+
     bytesRead = fread(palmrow, 1, bytesPerRow, ifP);
     if (bytesRead != bytesPerRow)
         pm_error("Error reading Palm file.  Short read.");
@@ -973,27 +974,27 @@ convertRowToPnmDirect(const unsigned char * const palmrow,
        blue=0x1F.  How do we promote those colors?  Simple
        shift would give us R=248,G=252,B=248; which is
        slightly green.  Hardly seems right.
-       
+
        So I've perverted the math a bit.  Each color value is
        multiplied by 255, then divided by either 31 (red or
        blue) or 63 (green).  That's the right way to do it
-       anyway.  
+       anyway.
     */
 
     const unsigned char *inbyte;
     unsigned int j;
-    
+
     for (inbyte = palmrow, j = 0;  j < cols;  ++j) {
         unsigned int inval;
         inval = *inbyte++ << 8;
         inval |= *inbyte++;
-        
+
         if (seen)
             ++seen[inval];
-        
-        PPM_ASSIGN(xelrow[j], 
-                   (((inval >> 11) & 0x1F) * maxval) / 0x1F, 
-                   (((inval >>  5) & 0x3F) * maxval) / 0x3F, 
+
+        PPM_ASSIGN(xelrow[j],
+                   (((inval >> 11) & 0x1F) * maxval) / 0x1F,
+                   (((inval >>  5) & 0x3F) * maxval) / 0x3F,
                    (((inval >>  0) & 0x1F) * maxval) / 0x1F
             );
     }
@@ -1017,21 +1018,21 @@ convertRowToPnmNotDirect(const unsigned char * const palmrow,
     unsigned int j;
 
     assert(pixelSize <= 8);
-    
+
     inbit = 8 - pixelSize;
     inbyteP = &palmrow[0];
     for (j = 0; j < cols; ++j) {
         short const color = (*inbyteP & (mask << inbit)) >> inbit;
         if (seen)
             ++seen[color];
-        
+
         if (colormapP) {
             ColormapEntry const searchTarget = color << 24;
             ColormapEntry * const foundEntryP =
                 bsearch(&searchTarget,
-                        colormapP->color_entries, 
+                        colormapP->color_entries,
                         colormapP->ncolors,
-                        sizeof(searchTarget), 
+                        sizeof(searchTarget),
                         palmcolor_compare_indices);
 
             if (!foundEntryP)
@@ -1040,13 +1041,13 @@ convertRowToPnmNotDirect(const unsigned char * const palmrow,
                          "in the colormap",
                          j, color, colormapP->ncolors);
 
-            PPM_ASSIGN(xelrow[j], 
-                       (*foundEntryP >> 16) & 0xFF, 
-                       (*foundEntryP >>  8) & 0xFF, 
+            PPM_ASSIGN(xelrow[j],
+                       (*foundEntryP >> 16) & 0xFF,
+                       (*foundEntryP >>  8) & 0xFF,
                        (*foundEntryP >>  0) & 0xFF);
         } else
             PNM_ASSIGN1(xelrow[j], graymap[color]);
-        
+
         if (!inbit) {
             ++inbyteP;
             inbit = 8 - pixelSize;
@@ -1076,22 +1077,22 @@ writePnm(FILE *            const ofP,
     xel *           xelrow;
     unsigned int *  seen;
     unsigned int    row;
-    
+
     pnm_writepnminit(ofP, cols, rows, maxval, format, 0);
     xelrow = pnm_allocrow(cols);
 
     /* Read the picture data, one row at a time */
     MALLOCARRAY_NOFAIL(palmrow, palmHeader.bytesPerRow);
-    MALLOCARRAY_NOFAIL(lastrow, palmHeader.bytesPerRow); 
-    
+    MALLOCARRAY_NOFAIL(lastrow, palmHeader.bytesPerRow);
+
     if (seenP) {
         createHistogram(nColors, &seen);
         *seenP = seen;
     } else
         seen = NULL;
 
-    /* We should actually use compressedDataSizeNN for checking the sanity 
-       of the data we're reading ... 
+    /* We should actually use compressedDataSizeNN for checking the sanity
+       of the data we're reading ...
     */
     if (palmHeader.compressionType != COMPRESSION_NONE) {
         if (palmHeader.version < 3) {
@@ -1104,8 +1105,8 @@ writePnm(FILE *            const ofP,
     }
 
     for (row = 0; row < rows; ++row) {
-        readDecompressedRow(ifP, palmrow, lastrow, 
-                            palmHeader.compressionType, 
+        readDecompressedRow(ifP, palmrow, lastrow,
+                            palmHeader.compressionType,
                             palmHeader.bytesPerRow,
                             palmHeader.pixelSize,
                             row == 0);
@@ -1133,18 +1134,18 @@ showHistogram(unsigned int * const seen,
               unsigned int   const ncolors) {
 
     unsigned int colorIndex;
-    
+
     for (colorIndex = 0;  colorIndex < ncolors; ++colorIndex) {
         if (!colormapP)
-            pm_message("%.3d -> %.3d:  %d", 
+            pm_message("%.3d -> %.3d:  %d",
                        colorIndex, graymap[colorIndex], seen[colorIndex]);
         else {
             ColormapEntry const searchTarget = colorIndex << 24;
             ColormapEntry * const foundEntryP =
                 bsearch(&searchTarget,
-                        colormapP->color_entries, 
+                        colormapP->color_entries,
                         colormapP->ncolors,
-                        sizeof(searchTarget), 
+                        sizeof(searchTarget),
                         palmcolor_compare_indices);
             if (foundEntryP)
                 pm_message("%.3d -> %ld,%ld,%ld:  %d", colorIndex,
@@ -1181,11 +1182,11 @@ main(int argc, const char **argv) {
     readHeader(ifP, cmdline.rendition, &palmHeader);
 
     readDirectInfoType(ifP, palmHeader, &directInfoType);
-   
+
     readColormap(ifP, palmHeader, &colormapFromImageP);
-    
+
     determineOutputFormat(palmHeader, &format, &maxval);
-    
+
     getColorInfo(palmHeader, directInfoType, colormapFromImageP,
                  &colormapP, &nColors, &directColorInfo);
 
@@ -1193,9 +1194,9 @@ main(int argc, const char **argv) {
         reportPalmHeader(palmHeader, directColorInfo);
 
     if (cmdline.transparent)
-        doTransparent(stdout, 
+        doTransparent(stdout,
                       palmHeader.hasTransparency, palmHeader.directColor,
-                      palmHeader.transparentIndex, 
+                      palmHeader.transparentIndex,
                       palmHeader.pixelSize, colormapP, directColorInfo);
     else {
         unsigned int * seen;
@@ -1204,12 +1205,12 @@ main(int argc, const char **argv) {
         graymap = createGraymap(nColors, maxval);
 
         writePnm(stdout,
-                 palmHeader, ifP, colormapP, graymap, nColors, format, maxval, 
+                 palmHeader, ifP, colormapP, graymap, nColors, format, maxval,
                  cmdline.showhist ? &seen : NULL);
-        
+
         if (cmdline.showhist)
             showHistogram(seen, colormapP, graymap, nColors);
-        
+
         free(graymap);
     }
     pm_close(ifP);
diff --git a/converter/other/pnmtopclxl.c b/converter/other/pnmtopclxl.c
index 8cabb614..f7db62ee 100644
--- a/converter/other/pnmtopclxl.c
+++ b/converter/other/pnmtopclxl.c
@@ -3,7 +3,7 @@
  *
  *  (C) 2002 Jochen Karrer, Linuxdata GbR
  *
- *      convert a pnm to PCL-XL image 
+ *      convert a pnm to PCL-XL image
  *
  * -------------------------------------------------------------
  */
@@ -44,7 +44,7 @@
 
 
 typedef struct InputSource {
-    const char *         name; 
+    const char *         name;
     struct InputSource * next;
 } InputSource;
 
@@ -82,7 +82,7 @@ parseCommandLine(int argc, char ** argv,
                  struct cmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    parse program command line described in Unix standard form by argc
-   and argv.  Return the information in the options as *cmdlineP.  
+   and argv.  Return the information in the options as *cmdlineP.
 
    If command line is internally inconsistent (invalid options, etc.),
    issue error message to stderr and abort program.
@@ -104,25 +104,25 @@ parseCommandLine(int argc, char ** argv,
     option_def_index = 0;   /* incremented by OPTENT3 */
     OPTENT3(0, "dpi",       OPT_UINT,    &cmdlineP->dpi,
             &dpiSpec,         0);
-    OPTENT3(0, "xoffs",     OPT_FLOAT,   &cmdlineP->xoffs, 
+    OPTENT3(0, "xoffs",     OPT_FLOAT,   &cmdlineP->xoffs,
             &xoffsSpec,        0);
-    OPTENT3(0, "yoffs",     OPT_FLOAT,   &cmdlineP->yoffs, 
+    OPTENT3(0, "yoffs",     OPT_FLOAT,   &cmdlineP->yoffs,
             &yoffsSpec,        0);
-    OPTENT3(0, "format",    OPT_STRING,  &formatOpt, 
+    OPTENT3(0, "format",    OPT_STRING,  &formatOpt,
             &formatSpec,        0);
-    OPTENT3(0, "duplex",    OPT_STRING,  &duplexOpt, 
+    OPTENT3(0, "duplex",    OPT_STRING,  &duplexOpt,
             &cmdlineP->duplexSpec,        0);
     OPTENT3(0, "copies",    OPT_UINT,    &cmdlineP->copies,
             &cmdlineP->copiesSpec,        0);
-    OPTENT3(0, "colorok",   OPT_FLAG,    NULL,                  
+    OPTENT3(0, "colorok",   OPT_FLAG,    NULL,
             &cmdlineP->colorok, 0);
-    OPTENT3(0, "center",    OPT_FLAG,    NULL,                  
+    OPTENT3(0, "center",    OPT_FLAG,    NULL,
             &cmdlineP->center, 0 );
     OPTENT3(0, "feeder",    OPT_UINT,    &cmdlineP->feeder,
             &cmdlineP->feederSpec,        0);
     OPTENT3(0, "outtray",   OPT_UINT,    &cmdlineP->outtray,
             &cmdlineP->outtraySpec,       0);
-    OPTENT3(0, "verbose",   OPT_FLAG,    NULL,                  
+    OPTENT3(0, "verbose",   OPT_FLAG,    NULL,
             &cmdlineP->verbose, 0);
     OPTENT3(0, "jobsetup",  OPT_STRING,  &cmdlineP->jobsetup,
             &jobsetupSpec,      0);
@@ -216,7 +216,7 @@ parseCommandLine(int argc, char ** argv,
 
 static void
 freeSource(InputSource * const firstSourceP) {
-    
+
     InputSource * sourceP;
 
     sourceP = firstSourceP;
@@ -284,7 +284,7 @@ pnmToPcllinePackbits(pclGenerator * const pclGeneratorP,
     unsigned int col, padCt;
     unsigned int const padsize =
         pclGeneratorP->paddedLinelen - pclGeneratorP->linelen;
-        
+
     tuplerow = pnm_allocpamrow(pamP);
 
     pnm_readpamrow(pamP, tuplerow);
@@ -297,7 +297,7 @@ pnmToPcllinePackbits(pclGenerator * const pclGeneratorP,
         if (bitmask == 0) {
             pclGeneratorP->data[pclGeneratorP->cursor++] = accum;
             bitmask = 0x80; accum = 0x0;
-        } 
+        }
     }
     if (bitmask != 0x80)
         pclGeneratorP->data[pclGeneratorP->cursor++] = accum;
@@ -351,7 +351,7 @@ createPclGeneratorPackbits(struct pam *    const pamP,
 
     pclGeneratorP->data =
         malloc(pclDatabuffSize(pclGeneratorP->paddedLinelen));
-    
+
     if (pclGeneratorP->data == NULL)
         pm_error("Unable to allocate row buffer.");
 
@@ -378,7 +378,7 @@ pnmToPcllineWholebytes(pclGenerator * const pclGeneratorP,
     for (col = 0; col < pamP->width; ++col) {
         unsigned int plane;
         for (plane = 0; plane < pamP->depth; ++plane) {
-            pclGeneratorP->data[pclGeneratorP->cursor++] = 
+            pclGeneratorP->data[pclGeneratorP->cursor++] =
                 pnm_scalesample(tuplerow[col][plane], pamP->maxval, 255);
         }
     }
@@ -399,7 +399,7 @@ createPclGeneratorWholebytes(struct pam *    const pamP,
     pclGenerator * pclGenP;
 
     MALLOCVAR_NOFAIL(pclGenP);
-    
+
     if (pamP->depth <  3)
         pclGenP->colorSpace = eGray;
     else
@@ -418,7 +418,7 @@ createPclGeneratorWholebytes(struct pam *    const pamP,
         if (pclGenP->data == NULL)
             pm_error("Unable to allocate row buffer.");
     }
-    
+
     pclGenP->getnextrow = pnmToPcllineWholebytes;
 
     *pclGenPP = pclGenP;
@@ -436,7 +436,7 @@ destroyPclGenerator(pclGenerator * const pclGenP) {
 
 
 
-static void 
+static void
 createPclGenerator(struct pam *        const pamP,
                    pclGenerator **     const pclGeneratorPP,
                    bool                const colorok) {
@@ -448,16 +448,16 @@ createPclGenerator(struct pam *        const pamP,
                    "through Ppmtopgm.  To suppress this warning, use the "
                    "-colorok option.");
 
-    if (pamP->depth == 1 && pamP->maxval == 1) 
+    if (pamP->depth == 1 && pamP->maxval == 1)
         createPclGeneratorPackbits(pamP, pclGeneratorPP);
-    else 
+    else
         createPclGeneratorWholebytes(pamP, pclGeneratorPP);
 }
 
 
 
 
-struct tPrinter { 
+struct tPrinter {
     const char *name;
     float topmargin;
     float bottommargin;
@@ -478,7 +478,7 @@ out_ubyte(int           const fd,
 
 
 
-static int 
+static int
 XL_Operator(int           const fd,
             enum Operator const data)  {
 
@@ -514,7 +514,7 @@ static int
 out_sint16(int          const fd,
            signed short const sdata ) {
 
-    unsigned short const data= (unsigned short)sdata;    
+    unsigned short const data= (unsigned short)sdata;
 
     unsigned char c[2];
 
@@ -559,7 +559,7 @@ xl_ubyte_array(int                   const fd,
 
     unsigned int i;
     unsigned char head[4];
-    
+
     head[0] = 0xc8;
     head[1] = 0xc1;
     head[2] = len & 0xff;
@@ -671,7 +671,7 @@ convertAndWriteRleBlock(int                  const outFd,
     pm_rlenc_compressbyte(pclGeneratorP->data, outbuf, PM_RLE_PACKBITS,
                           pclGeneratorP->paddedLinelen * lineCt, &rlelen);
 
-    xl_dataLength(outFd, rlelen); 
+    xl_dataLength(outFd, rlelen);
     XY_Write(outFd, outbuf, rlelen);
 }
 
@@ -680,10 +680,10 @@ convertAndWriteRleBlock(int                  const outFd,
 /*
  * ------------------------------------------------------------
  * XL_WriteImage
- *  Write a PCL-XL image to the datastream 
+ *  Write a PCL-XL image to the datastream
  * ------------------------------------------------------------
  */
-static void 
+static void
 convertAndWriteImage(int            const outFd,
                      pclGenerator * const pclGenP,
                      struct pam *   const pamP) {
@@ -695,10 +695,10 @@ convertAndWriteImage(int            const outFd,
 
     xl_ubyte(outFd, eDirectPixel); xl_attr_ubyte(outFd, aColorMapping);
     xl_ubyte(outFd, pclGenP->colorDepth); xl_attr_ubyte(outFd, aColorDepth);
-    xl_uint16(outFd, pclGenP->width); xl_attr_ubyte(outFd, aSourceWidth);  
-    xl_uint16(outFd, pclGenP->height); xl_attr_ubyte(outFd, aSourceHeight);    
-    xl_uint16_xy(outFd, pclGenP->width*1, pclGenP->height*1); 
-    xl_attr_ubyte(outFd, aDestinationSize);   
+    xl_uint16(outFd, pclGenP->width); xl_attr_ubyte(outFd, aSourceWidth);
+    xl_uint16(outFd, pclGenP->height); xl_attr_ubyte(outFd, aSourceHeight);
+    xl_uint16_xy(outFd, pclGenP->width*1, pclGenP->height*1);
+    xl_attr_ubyte(outFd, aDestinationSize);
     XL_Operator(outFd, oBeginImage);
 
     pm_rlenc_allocoutbuf(&outbuf, inSize, PM_RLE_PACKBITS);
@@ -707,13 +707,13 @@ convertAndWriteImage(int            const outFd,
         unsigned int const blockHeight =
             MIN(20, pclGenP->height-blockStartLine);
 
-        xl_uint16(outFd, blockStartLine); xl_attr_ubyte(outFd, aStartLine); 
+        xl_uint16(outFd, blockStartLine); xl_attr_ubyte(outFd, aStartLine);
         xl_uint16(outFd, blockHeight); xl_attr_ubyte(outFd, aBlockHeight);
         xl_ubyte(outFd, eRLECompression); xl_attr_ubyte(outFd, aCompressMode);
         /* In modern PCL-XL, we could use a PadBytesMultiple attribute
            here to avoid having to pad the data to a multiple of 4
            bytes.  But PCL-XL 1.1 didn't have PadBytesMultiple.
-           xl_ubyte(outFd, 1); xl_attr_ubyte(outFd, aPadBytesMultiple); 
+           xl_ubyte(outFd, 1); xl_attr_ubyte(outFd, aPadBytesMultiple);
         */
         XL_Operator(outFd, oReadImage);
         convertAndWriteRleBlock(outFd, pclGenP, pamP,
@@ -735,16 +735,16 @@ printEmbeddedImage(int                 const outFd,
     struct pam pam;
     pclGenerator * pclGeneratorP;
 
-    openDataSource(outFd, eBinaryLowByteFirst, eDefaultSource);
+    openDataSource(outFd, eBinaryLowByteFirst, eDefaultDataSource);
 
     ifP = pm_openr(sourceP->name);
 
     pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type));
-                
+
     createPclGenerator(&pam, &pclGeneratorP, colorok);
 
     convertAndWriteImage(outFd, pclGeneratorP, &pam);
-    
+
     destroyPclGenerator(pclGeneratorP);
 
     pm_close(ifP);
@@ -772,9 +772,9 @@ copyFile(const char * const sourceFileName,
         if (ferror(sourceFileP))
             pm_error("Read from file failed.  errno=%d (%s)",
                      errno, strerror(errno));
-        
+
         totalBytesWritten = 0;
-        
+
         while (totalBytesWritten < bytesRead) {
             ssize_t rc;
 
@@ -804,16 +804,16 @@ jobHead(int          const outFd,
    as opposed to e.g. Postscript.
 -----------------------------------------------------------------------------*/
     /* Reset */
-    XY_Puts(outFd,"\033%-12345X");  
+    XY_Puts(outFd,"\033%-12345X");
 
     if (userJobSetupFileName)
         copyFile(userJobSetupFileName, outFd);
 
     if (renderGray)
-        XY_Puts(outFd, "@PJL SET RENDERMODE=GRAYSCALE\n");  
+        XY_Puts(outFd, "@PJL SET RENDERMODE=GRAYSCALE\n");
 
-    XY_Puts(outFd, "@PJL ENTER LANGUAGE=PCLXL\n");  
-    XY_Puts(outFd, ") HP-PCL XL;1;1;Generated by Netpbm Pnmtopclxl\n");  
+    XY_Puts(outFd, "@PJL ENTER LANGUAGE=PCLXL\n");
+    XY_Puts(outFd, ") HP-PCL XL;1;1;Generated by Netpbm Pnmtopclxl\n");
 }
 
 
@@ -825,7 +825,7 @@ jobEnd(int const outFd) {
 
    Reset printer to quiescent mode.  Exit the printer language.
 -----------------------------------------------------------------------------*/
-    XY_Puts(outFd,"\033%-12345X");  
+    XY_Puts(outFd,"\033%-12345X");
 }
 
 
@@ -852,7 +852,7 @@ beginPage(int                 const outFd,
     }
 
     if (doMediaDestination) {
-        xl_ubyte(outFd, mediaDestination);  
+        xl_ubyte(outFd, mediaDestination);
         xl_attr_ubyte(outFd, aMediaDestination);
     }
 
@@ -898,11 +898,11 @@ setColorSpace(int                   const outFd,
    paletteDepth is not e8Bit.  Is each palette entry still a byte and only
    some of the byte gets used?  Or are there multiple entries per byte?
 -----------------------------------------------------------------------------*/
-    xl_ubyte(outFd, colorSpace); xl_attr_ubyte(outFd, aColorSpace);   
+    xl_ubyte(outFd, colorSpace); xl_attr_ubyte(outFd, aColorSpace);
     if (palette) {
-        xl_ubyte(outFd, paletteDepth); 
-        xl_attr_ubyte(outFd, aPaletteDepth);   
-        xl_ubyte_array(outFd, palette, paletteSize); 
+        xl_ubyte(outFd, paletteDepth);
+        xl_attr_ubyte(outFd, aPaletteDepth);
+        xl_ubyte_array(outFd, palette, paletteSize);
         xl_attr_ubyte(outFd, aPaletteData);
     }
     XL_Operator(outFd, oSetColorSpace);
@@ -925,8 +925,8 @@ positionCursor(int            const outFd,
     float xpos, ypos;
 
     if (center) {
-        float const width  = 1.0 * imageWidth/dpi;  
-        float const height = 1.0 * imageHeight/dpi;    
+        float const width  = 1.0 * imageWidth/dpi;
+        float const height = 1.0 * imageHeight/dpi;
         xpos = (PAPERWIDTH(format) - width)/2;
         ypos = (PAPERHEIGHT(format) - height)/2;
     } else {
@@ -985,11 +985,11 @@ convertAndPrintPage(int                  const outFd,
        an IllegalArraySize error from the printer on the SetColorSpace
        command.
 
-       So we don't use a palette at all now.  
+       So we don't use a palette at all now.
     */
     setColorSpace(outFd, pclGeneratorP->colorSpace, NULL, 0, 0);
 
-    positionCursor(outFd, center, xoffs, yoffs, 
+    positionCursor(outFd, center, xoffs, yoffs,
                    pclGeneratorP->width, pclGeneratorP->height, dpi, format);
 
     convertAndWriteImage(outFd, pclGeneratorP, pamP);
@@ -1007,7 +1007,7 @@ beginSession(int              const outFd,
              bool             const noReporting,
              enum ErrorReport const errorReport) {
 
-    xl_uint16_xy(outFd, xdpi, ydpi); xl_attr_ubyte(outFd, aUnitsPerMeasure); 
+    xl_uint16_xy(outFd, xdpi, ydpi); xl_attr_ubyte(outFd, aUnitsPerMeasure);
     xl_ubyte(outFd, measure);  xl_attr_ubyte(outFd, aMeasure);
     /* xl_ubyte(outFd,eNoReporting); xl_attr_ubyte(outFd,aErrorReport); */
     xl_ubyte(outFd,errorReport); xl_attr_ubyte(outFd,aErrorReport);
@@ -1015,8 +1015,8 @@ beginSession(int              const outFd,
 }
 
 
-             
-static void 
+
+static void
 endSession(int outFd) {
     XL_Operator(outFd,oEndSession);
 }
@@ -1046,9 +1046,9 @@ printPages(int                 const outFd,
     InputSource * sourceP;
     unsigned int sourceNum;
 
-    sourceP = firstSourceP;    
+    sourceP = firstSourceP;
 
-    openDataSource(outFd, eBinaryLowByteFirst, eDefaultSource);
+    openDataSource(outFd, eBinaryLowByteFirst, eDefaultDataSource);
 
     sourceNum = 0;   /* initial value */
 
@@ -1074,9 +1074,9 @@ printPages(int                 const outFd,
                 pm_message("Processing File %u, Page %u", sourceNum, pageNum);
 
                 pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type));
-                
+
                 createPclGenerator(&pam, &pclGeneratorP, colorok);
-                
+
                 convertAndPrintPage(
                     outFd, pclGeneratorP, &pam,
                     format, dpi, center, xoffs, yoffs, doDuplex, duplex,
@@ -1087,7 +1087,7 @@ printPages(int                 const outFd,
             }
         }
         pm_close(ifP);
-        sourceP = sourceP->next; 
+        sourceP = sourceP->next;
     }
     closeDataSource(outFd);
 }
@@ -1100,9 +1100,9 @@ main(int argc, char *argv[]) {
     int const outFd = STDOUT_FILENO;
 
     struct cmdlineInfo cmdline;
-    
+
     /* In case you're wondering why we do direct file descriptor I/O
-       instead of stream (FILE *), it's because Jochen originally 
+       instead of stream (FILE *), it's because Jochen originally
        wrote this code for an embedded system with diet-libc.  Without
        the stream library, the statically linked binary was only about
        5K big.
@@ -1116,7 +1116,7 @@ main(int argc, char *argv[]) {
     else {
         jobHead(outFd, cmdline.rendergray, cmdline.jobsetup);
 
-        beginSession(outFd, cmdline.dpi, cmdline.dpi, eInch, 
+        beginSession(outFd, cmdline.dpi, cmdline.dpi, eInch,
                      FALSE, eBackChAndErrPage);
 
         printPages(outFd, cmdline.sourceP,
diff --git a/converter/other/pstopnm.c b/converter/other/pstopnm.c
index 95a97440..d8e18e93 100644
--- a/converter/other/pstopnm.c
+++ b/converter/other/pstopnm.c
@@ -16,7 +16,7 @@
 
 #define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */
 #define _BSD_SOURCE 1   /* Make sure strdup() is in string.h */
-#define _XOPEN_SOURCE 500  
+#define _XOPEN_SOURCE 500
     /* Make sure fdopen() is in stdio.h and strdup() is in string.h */
 
 #include <assert.h>
@@ -25,7 +25,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <signal.h>
-#include <sys/wait.h>  
+#include <sys/wait.h>
 #include <sys/stat.h>
 
 #include "pm_c_util.h"
@@ -38,17 +38,32 @@ static bool verbose;
 
 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.
+    /* Description of a rectangle within an image; all coordinates
+       measured in points (1/72") with lower left corner of page being the
+       origin.  Negative values are OK.
     */
+    bool isDefined;
+
+    /* Nothing below is meaningful unless 'isDefined' is true */
     int llx;  /* lower left X coord */
-        /* -1 for llx means whole box is undefined. */
     int lly;  /* lower left Y coord */
     int urx;  /* upper right X coord */
     int ury;  /* upper right Y coord */
 };
 
+
+
+static void
+assertValidBox(struct Box const box) {
+
+    if (box.isDefined) {
+        assert(box.urx >= box.llx);
+        assert(box.ury >= box.lly);
+    }
+}
+
+
+
 struct Dimensions {
 /*----------------------------------------------------------------------------
   Horizontal and vertical dimensions of something, both in pixels and
@@ -107,7 +122,7 @@ parseCommandLine(int argc, char ** argv,
     unsigned int textalphabitsSpec;
 
     MALLOCARRAY_NOFAIL(option_def, 100);
-    
+
     option_def_index = 0;   /* incremented by OPTENTRY */
     OPTENT3(0, "forceplain", OPT_FLAG,  NULL, &cmdlineP->forceplain,     0);
     OPTENT3(0, "llx",        OPT_FLOAT, &llx, &llxSpec,                  0);
@@ -151,7 +166,7 @@ parseCommandLine(int argc, char ** argv,
     if (ymaxSpec) {
         if (cmdlineP->ymax == 0)
             pm_error("zero is not a valid value for -ymax");
-    } else 
+    } else
         cmdlineP->ymax = 792;
 
     if (xsizeSpec) {
@@ -163,7 +178,7 @@ parseCommandLine(int argc, char ** argv,
     if (ysizeSpec) {
         if (cmdlineP->ysize == 0)
             pm_error("zero is not a valid value for -ysize");
-    } else 
+    } else
         cmdlineP->ysize = 0;
 
     if (portraitOpt && !landscapeOpt)
@@ -185,9 +200,11 @@ parseCommandLine(int argc, char ** argv,
         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.  
+       command line, we default any of the 4 that aren't.
     */
     if (llxSpec || llySpec || urxSpec || urySpec) {
+        cmdlineP->extractBox.isDefined = true;
+
         if (!llxSpec) cmdlineP->extractBox.llx = 72;
         else cmdlineP->extractBox.llx = llx * 72;
         if (!llySpec) cmdlineP->extractBox.lly = 72;
@@ -197,7 +214,7 @@ parseCommandLine(int argc, char ** argv,
         if (!urySpec) cmdlineP->extractBox.ury = 720;
         else cmdlineP->extractBox.ury = ury * 72;
     } else {
-        cmdlineP->extractBox.llx = -1;
+        cmdlineP->extractBox.isDefined = false;
     }
 
     if (dpiSpec) {
@@ -225,7 +242,7 @@ parseCommandLine(int argc, char ** argv,
         cmdlineP->inputFileName = "-";  /* stdin */
     else if (argc-1 == 1)
         cmdlineP->inputFileName = argv[1];
-    else 
+    else
         pm_error("Too many arguments (%d).  "
                  "Only need one: the Postscript file name", argc-1);
 
@@ -249,7 +266,7 @@ addPsToFileName(char          const origFileName[],
     int statRc;
 
     statRc = lstat(origFileName, &statbuf);
-    
+
     if (statRc == 0)
         *newFileNameP = strdup(origFileName);
     else {
@@ -270,34 +287,62 @@ addPsToFileName(char          const origFileName[],
 
 
 
+static unsigned int
+resolution(unsigned int const dotCt,
+           unsigned int const pointCt) {
+/*----------------------------------------------------------------------------
+   The resolution in dots per inch when 'dotCt' dots print 'pointCt' points
+   long.
+
+   When this would round to zero, we return 1 dot per inch instead so it
+   doesn't play havoc with arithmetic - it's never going to happen unless
+   something is broken anyway.
+-----------------------------------------------------------------------------*/
+    return MAX(1, (unsigned int)((float)dotCt * 72 / pointCt + 0.5));
+}
+
+
+
 static void
 computeSizeResFromSizeSpec(unsigned int        const requestedXsize,
                            unsigned int        const requestedYsize,
                            unsigned int        const imageWidth,
                            unsigned int        const imageHeight,
                            struct Dimensions * const imageDimP) {
+/*----------------------------------------------------------------------------
+   Compute output image size and assumed Postscript input resolution, assuming
+   user requested a specific size for at least one of the dimensions and the
+   input is 'imageWidth' x 'imageHeight' points.
+
+   'requestedXsize' is what the user requested for output image width in
+   pixels, or zero if he made no request.  'requestedYsize' is analogous
+   for the height.
+-----------------------------------------------------------------------------*/
+    assert(requestedXsize || requestedYsize);
+
+    assert(imageWidth > 0);
 
     if (requestedXsize) {
         imageDimP->xsize = requestedXsize;
-        imageDimP->xres = (unsigned int)
-            (requestedXsize * 72 / imageWidth + 0.5);
+        imageDimP->xres = resolution(requestedXsize, imageWidth);
         if (!requestedYsize) {
             imageDimP->yres = imageDimP->xres;
             imageDimP->ysize = (unsigned int)
                 (imageHeight * (float)imageDimP->yres/72 + 0.5);
-            }
         }
+    }
+
+    assert(imageHeight > 0);
 
     if (requestedYsize) {
         imageDimP->ysize = requestedYsize;
-        imageDimP->yres = (unsigned int)
-            (requestedYsize * 72 / imageHeight + 0.5);
+        imageDimP->yres = resolution(requestedYsize, imageHeight);
         if (!requestedXsize) {
             imageDimP->xres = imageDimP->yres;
             imageDimP->xsize = (unsigned int)
                 (imageWidth * (float)imageDimP->xres/72 + 0.5);
         }
-    } 
+    }
 }
 
 
@@ -313,8 +358,9 @@ computeSizeResBlind(unsigned int        const xmax,
     if (imageWidth == 0 || imageHeight == 0) {
         imageDimP->xres = imageDimP->yres = 72;
     } else {
-        imageDimP->xres = imageDimP->yres = MIN(xmax * 72 / imageWidth,
-                                                ymax * 72 / imageHeight);
+        imageDimP->xres = imageDimP->yres =
+            MIN(resolution(xmax, imageWidth),
+                resolution(ymax, imageHeight));
     }
 
     if (nocrop) {
@@ -331,17 +377,17 @@ computeSizeResBlind(unsigned int        const xmax,
 
 
 static void
-computeSizeRes(struct CmdlineInfo  const cmdline, 
+computeSizeRes(struct CmdlineInfo  const cmdline,
                struct Box          const borderedBox,
                struct Dimensions * const imageDimP) {
 /*----------------------------------------------------------------------------
   Figure out how big the output image should be and what output device
   resolution Ghostscript should assume (return as *imageDimP).
 
-  A resolution number is the number of pixels per inch that the a
+  A resolution number is the number of pixels per inch that the
   printer prints.  Since we're emulating a printed page with a PNM
   image, and a PNM image has no spatial dimension (you can't say how
-  many inches wide a PNM image is), it's kind of confusing.  
+  many inches wide a PNM image is), it's kind of confusing.
 
   If the user doesn't select a resolution, we choose the resolution
   that causes the image to be a certain number of pixels, knowing how
@@ -350,8 +396,8 @@ computeSizeRes(struct CmdlineInfo  const cmdline,
   inches wide.  We want the PNM image to be 1000 pixels wide.  So we
   tell Ghostscript that our horizontal output device resolution is 500
   pixels per inch.
-  
-  X and Y in all returned values is with respect to the image, not the
+
+  X and Y in all returned values are with respect to the image, not the
   page.  Note that the image might be placed sideways on the page, so that
   page X and Y would be reversed from image X and Y.
 -----------------------------------------------------------------------------*/
@@ -361,6 +407,8 @@ computeSizeRes(struct CmdlineInfo  const cmdline,
     unsigned int const sx = borderedBox.urx - borderedBox.llx;
     unsigned int const sy = borderedBox.ury - borderedBox.lly;
 
+    assertValidBox(borderedBox); assert(borderedBox.isDefined);
+
     if (cmdline.dpi) {
         /* User gave resolution; we figure out output image size */
         imageDimP->xres = imageDimP->yres = cmdline.dpi;
@@ -370,6 +418,7 @@ computeSizeRes(struct CmdlineInfo  const cmdline,
         if (sx == 0 || sy == 0)
             pm_error("Input image is zero size; we cannot satisfy your "
                      "produce your requested output dimensions");
+
         computeSizeResFromSizeSpec(cmdline.xsize, cmdline.ysize, sx, sy,
                                    imageDimP);
     } else
@@ -398,7 +447,7 @@ languageDeclaration(char const inputFileName[]) {
     enum PostscriptLanguage language;
 
     if (streq(inputFileName, "-"))
-        /* Can't read stdin, because we need it to remain positioned for the 
+        /* Can't read stdin, because we need it to remain positioned for the
            Ghostscript interpreter to read it.
         */
         language = COMMON_POSTSCRIPT;
@@ -431,12 +480,57 @@ languageDeclaration(char const inputFileName[]) {
 
 
 static struct Box
+boundingBoxFmPostscriptFile(FILE * const ifP) {
+
+    struct Box retval;
+    bool eof;
+
+    for (retval.isDefined = false, eof = false; !retval.isDefined && !eof; ) {
+        char line[200];
+        char * fgetsRc;
+
+        fgetsRc = fgets(line, sizeof(line), ifP);
+
+        if (fgetsRc == NULL)
+            eof = true;
+        else {
+            int rc;
+            int llx, lly, urx, ury;
+
+            rc = sscanf(line, "%%%%BoundingBox: %d %d %d %d",
+                        &llx, &lly, &urx, &ury);
+            if (rc == 4) {
+                /* We found a BoundingBox statement */
+
+                if (llx > urx)
+                    pm_error("%%%%BoundingBox statement in input file has "
+                             "lower left corner to the right of the "
+                             "upper right corner");
+                if (lly > ury)
+                    pm_error("%%%%BoundingBox statement in input file has "
+                             "lower left corner above the "
+                             "upper right corner");
+
+                retval.llx = llx; retval.lly = lly;
+                retval.urx = urx; retval.ury = ury;
+                retval.isDefined = true;
+            }
+        }
+    }
+    fclose(ifP);
+
+    return retval;
+}
+
+
+
+static struct Box
 computeBoxToExtract(struct Box const cmdlineExtractBox,
                     char       const inputFileName[]) {
 
     struct Box retval;
 
-    if (cmdlineExtractBox.llx != -1)
+    if (cmdlineExtractBox.isDefined)
         /* User told us what box to extract, so that's what we'll do */
         retval = cmdlineExtractBox;
     else {
@@ -447,54 +541,37 @@ computeBoxToExtract(struct Box const cmdlineExtractBox,
 
         if (streq(inputFileName, "-"))
             /* Can't read stdin, because we need it to remain
-               positioned for the Ghostscript interpreter to read it.  
+               positioned for the Ghostscript interpreter to read it.
             */
-            psBb.llx = -1;
+            psBb.isDefined = false;
         else {
             FILE * ifP;
-            bool foundBb;
-            bool eof;
 
             ifP = pm_openr(inputFileName);
-            
-            for (foundBb = FALSE, eof = FALSE; !foundBb && !eof; ) {
-                char line[200];
-                char * fgetsRc;
-
-                fgetsRc = fgets(line, sizeof(line), ifP);
-
-                if (fgetsRc == NULL)
-                    eof = TRUE;
-                else {
-                    int rc;
-                    rc = sscanf(line, "%%%%BoundingBox: %d %d %d %d",
-                                &psBb.llx, &psBb.lly, 
-                                &psBb.urx, &psBb.ury);
-                    if (rc == 4) 
-                        foundBb = TRUE;
-                }
-            }
-            fclose(ifP);
 
-            if (!foundBb) {
-                psBb.llx = -1;
+            psBb = boundingBoxFmPostscriptFile(ifP);
+
+            if (!psBb.isDefined)
                 pm_message("Warning: no %%%%BoundingBox statement "
                            "in the input or command line.  "
                            "Will use defaults");
-            }
         }
-        if (psBb.llx != -1) {
+        if (psBb.isDefined) {
             if (verbose)
                 pm_message("Using %%%%BoundingBox statement from input.");
             retval = psBb;
-        } else { 
+        } else {
             /* Use the center of an 8.5" x 11" page with 1" border all around*/
+            retval.isDefined = true;
             retval.llx = 72;
             retval.lly = 72;
             retval.urx = 540;
             retval.ury = 720;
         }
     }
+
+    assert(retval.isDefined);
+
     if (verbose)
         pm_message("Extracting the box ((%d,%d),(%d,%d))",
                    retval.llx, retval.lly, retval.urx, retval.ury);
@@ -504,7 +581,7 @@ computeBoxToExtract(struct Box const cmdlineExtractBox,
 
 
 static enum Orientation
-computeOrientation(struct CmdlineInfo const cmdline, 
+computeOrientation(struct CmdlineInfo const cmdline,
                    struct Box         const extractBox) {
 /*----------------------------------------------------------------------------
    The proper orientation of the image on the page, given the user's
@@ -532,7 +609,7 @@ computeOrientation(struct CmdlineInfo const cmdline,
         /* Dimensions of image to print, in points */
         unsigned int const imageWidPt = extractBox.urx - extractBox.llx;
         unsigned int const imageHgtPt = extractBox.ury - extractBox.lly;
-        
+
         /* Dimensions of image to print, in pixels (possibly of assumed
            resolution)
         */
@@ -580,31 +657,30 @@ computeOrientation(struct CmdlineInfo const cmdline,
 
 
 static struct Box
-addBorders(struct Box const inputBox, 
+addBorders(struct Box const inputBox,
            float      const xborderScale,
            float      const yborderScale) {
 /*----------------------------------------------------------------------------
    Return a box which is 'inputBox' plus some borders.
 
    Add left and right borders that are the fraction 'xborderScale' of the
-   width of the input box; likewise for top and bottom borders with 
+   width of the input box; likewise for top and bottom borders with
    'yborderScale'.
 -----------------------------------------------------------------------------*/
-    unsigned int const leftRightBorderSize = 
+    unsigned int const leftRightBorderSize =
         ROUNDU((inputBox.urx - inputBox.llx) * xborderScale);
-    unsigned int const topBottomBorderSize = 
+    unsigned int const topBottomBorderSize =
         ROUNDU((inputBox.ury - inputBox.lly) * yborderScale);
 
     struct Box retval;
 
-
-    assert(inputBox.urx >= inputBox.llx);
-    assert(inputBox.ury >= inputBox.lly);
+    assertValidBox(inputBox); assert(inputBox.isDefined);
 
     retval.llx = inputBox.llx - (int)leftRightBorderSize;
     retval.lly = inputBox.lly - (int)topBottomBorderSize;
     retval.urx = inputBox.urx + (int)leftRightBorderSize;
     retval.ury = inputBox.ury + (int)topBottomBorderSize;
+    retval.isDefined = true;
 
     if (verbose)
         pm_message("With borders, extracted box is ((%d,%d),(%d,%d))",
@@ -628,6 +704,8 @@ writePstrans(struct Box        const box,
 
     const char * pstrans;
 
+    assert(xres > 0); assert(yres > 0);
+
     switch (orientation) {
     case PORTRAIT: {
         int llx, lly;
@@ -648,7 +726,7 @@ writePstrans(struct Box        const box,
     if (pstrans == pm_strsol)
         pm_error("Unable to allocate memory for pstrans");
 
-    if (verbose) 
+    if (verbose)
         pm_message("Postscript prefix command: '%s'", pstrans);
 
     fprintf(pipeToGsP, "%s\n", pstrans);
@@ -679,10 +757,10 @@ computeOutfileArg(struct CmdlineInfo const cmdline) {
     else {
         char * basename;
         const char * suffix;
-        
+
         basename  = strdup(cmdline.inputFileName);
-        if (strlen(basename) > 3 && 
-            streq(basename+strlen(basename)-3, ".ps")) 
+        if (strlen(basename) > 3 &&
+            streq(basename+strlen(basename)-3, ".ps"))
             /* The input file name ends in ".ps".  Chop it off. */
             basename[strlen(basename)-3] = '\0';
 
@@ -730,7 +808,7 @@ computeGsDevice(int  const formatType,
 
 static void
 findGhostscriptProg(const char ** const retvalP) {
-    
+
     *retvalP = NULL;  /* initial assumption */
     if (getenv("GHOSTSCRIPT"))
         *retvalP = strdup(getenv("GHOSTSCRIPT"));
@@ -740,7 +818,7 @@ findGhostscriptProg(const char ** const retvalP) {
             const char * candidate;
 
             pathwork = strdup(getenv("PATH"));
-            
+
             candidate = strtok(pathwork, ":");
 
             *retvalP = NULL;
@@ -774,7 +852,7 @@ findGhostscriptProg(const char ** const retvalP) {
 static void
 execGhostscript(int               const inputPipeFd,
                 char              const ghostscriptDevice[],
-                char              const outfileArg[], 
+                char              const outfileArg[],
                 struct Dimensions const pageDim,
                 unsigned int      const textalphabits) {
 /*----------------------------------------------------------------------------
@@ -817,13 +895,13 @@ execGhostscript(int               const inputPipeFd,
                    "'%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'",
                    ghostscriptProg, arg0,
                    deviceopt, outfileopt, gopt, ropt, textalphabitsopt,
-                   "-q", "-dNOPAUSE", 
+                   "-q", "-dNOPAUSE",
                    "-dSAFER", "-");
     }
 
     execl(ghostscriptProg, arg0, deviceopt, outfileopt, gopt, ropt, "-q",
           "-dNOPAUSE", "-dSAFER", "-", NULL);
-    
+
     pm_error("execl() of Ghostscript ('%s') failed, errno=%d (%s)",
              ghostscriptProg, errno, strerror(errno));
 }
@@ -852,26 +930,26 @@ feedPsToGhostScript(const char *            const inputFileName,
     bool eof;  /* End of file on input */
 
     pipeToGsP = fdopen(pipeToGhostscriptFd, "w");
-    if (pipeToGsP == NULL) 
+    if (pipeToGsP == NULL)
         pm_error("Unable to open stream on pipe to Ghostscript process.");
-    
+
     ifP = pm_openr(inputFileName);
     /*
       In encapsulated Postscript, we the encapsulator are supposed to
       handle showing the page (which we do by passing a showpage
-      statement to Ghostscript).  Any showpage statement in the 
+      statement to Ghostscript).  Any showpage statement in the
       input must be defined to have no effect.
-          
+
       See "Enscapsulated PostScript Format File Specification",
       v. 3.0, 1 May 1992, in particular Example 2, p. 21.  I found
-      it at 
+      it at
       http://partners.adobe.com/asn/developer/pdfs/tn/5002.EPSF_Spec.pdf
       The example given is a much fancier solution than we need
-      here, I think, so I boiled it down a bit.  JM 
+      here, I think, so I boiled it down a bit.  JM
     */
     if (language == ENCAPSULATED_POSTSCRIPT)
         fprintf(pipeToGsP, "\n/b4_Inc_state save def /showpage { } def\n");
- 
+
     writePstrans(borderedBox, imageDim, orientation, pipeToGsP);
 
     /* If our child dies, it closes the pipe and when we next write to it,
@@ -884,11 +962,11 @@ feedPsToGhostScript(const char *            const inputFileName,
     while (!eof) {
         char buffer[4096];
         size_t readCt;
-            
+
         readCt = fread(buffer, 1, sizeof(buffer), ifP);
-        if (readCt == 0) 
+        if (readCt == 0)
             eof = TRUE;
-        else 
+        else
             fwrite(buffer, 1, readCt, pipeToGsP);
     }
     pm_close(ifP);
@@ -897,7 +975,7 @@ feedPsToGhostScript(const char *            const inputFileName,
         fprintf(pipeToGsP, "\nb4_Inc_state restore showpage\n");
 
     fclose(pipeToGsP);
-}        
+}
 
 
 
@@ -940,7 +1018,7 @@ executeGhostscript(char                    const inputFileName[],
                    struct Dimensions       const imageDim,
                    enum Orientation        const orientation,
                    char                    const ghostscriptDevice[],
-                   char                    const outfileArg[], 
+                   char                    const outfileArg[],
                    unsigned int            const textalphabits,
                    enum PostscriptLanguage const language) {
 
@@ -949,12 +1027,12 @@ executeGhostscript(char                    const inputFileName[],
 
     if (strlen(outfileArg) > 80)
         pm_error("output file spec too long.");
-    
+
     rc = pm_pipe(pipefd);
     if (rc < 0)
         pm_error("Unable to create pipe to talk to Ghostscript process.  "
                  "errno = %d (%s)", errno, strerror(errno));
-    
+
     rc = fork();
     if (rc < 0)
         pm_error("Unable to fork a Ghostscript process.  errno=%d (%s)",
@@ -986,13 +1064,13 @@ executeGhostscript(char                    const inputFileName[],
 
         if (gsTermStatus != 0) {
             if (WIFEXITED(gsTermStatus))
-                pm_error("Ghostscript failed.  Exit code=%d\n", 
+                pm_error("Ghostscript failed.  Exit code=%d\n",
                          WEXITSTATUS(gsTermStatus));
             else if (WIFSIGNALED(gsTermStatus))
                 pm_error("Ghostscript process died because of a signal %d.",
                          WTERMSIG(gsTermStatus));
-            else 
-                pm_error("Ghostscript process died with exit code %d", 
+            else
+                pm_error("Ghostscript process died with exit code %d",
                          gsTermStatus);
         }
     }
@@ -1010,7 +1088,7 @@ main(int argc, char ** argv) {
         /* Size and resolution of the input image */
     struct Box extractBox;
         /* coordinates of the box within the input we are to extract; i.e.
-           that will become the output. 
+           that will become the output.
            */
     struct Box borderedBox;
         /* Same as above, but expanded to include borders */
@@ -1031,32 +1109,31 @@ main(int argc, char ** argv) {
     extractBox = computeBoxToExtract(cmdline.extractBox, inputFileName);
 
     language = languageDeclaration(inputFileName);
-    
+
     orientation = computeOrientation(cmdline, extractBox);
 
     borderedBox = addBorders(extractBox, cmdline.xborder, cmdline.yborder);
 
+    assertValidBox(borderedBox); assert(borderedBox.isDefined);
+
     computeSizeRes(cmdline, borderedBox, &imageDim);
 
-    if (imageDim.xres == 0)
-        imageDim.xres = 1;
-    if (imageDim.yres == 0)
-        imageDim.yres = 1;
-    
+    assert(imageDim.xres > 0); assert(imageDim.yres > 0);
+
     outfileArg = computeOutfileArg(cmdline);
 
-    ghostscriptDevice = 
+    ghostscriptDevice =
         computeGsDevice(cmdline.formatType, cmdline.forceplain);
-    
+
     pm_message("Writing %s format", ghostscriptDevice);
-    
+
     executeGhostscript(inputFileName, borderedBox, imageDim, orientation,
                        ghostscriptDevice, outfileArg, cmdline.textalphabits,
                        language);
 
     pm_strfree(ghostscriptDevice);
     pm_strfree(outfileArg);
-    
+
     return 0;
 }
 
diff --git a/converter/ppm/ilbmtoppm.c b/converter/ppm/ilbmtoppm.c
index 280ca939..92d4d6f2 100644
--- a/converter/ppm/ilbmtoppm.c
+++ b/converter/ppm/ilbmtoppm.c
@@ -99,10 +99,9 @@ static bool debug = FALSE;
 
 
 static char *
-ID2string(id)
-    IFF_ID id;
-{
-    static char str[] = "abcd";
+ID2string(IFF_ID const id) {
+
+    static char str[4];
 
     str[0] = (char)(id >> 24 & 0xff);
     str[1] = (char)(id >> 16 & 0xff);
@@ -141,16 +140,15 @@ alloc_cmap(void) {
 
 
 static rawtype *
-alloc_rawrow(cols)
-    int cols;
-{
-    rawtype *r;
-    int i;
+alloc_rawrow(unsigned int const cols) {
+
+    rawtype * r;
+    unsigned int col;
 
     MALLOCARRAY_NOFAIL(r, cols);
 
-    for( i = 0; i < cols; i++ )
-        r[i] = 0;
+    for (col = 0; col < cols; ++col)
+        r[col] = 0;
 
     return r;
 }
@@ -161,17 +159,17 @@ alloc_rawrow(cols)
  ****************************************************************************/
 
 static void
-readerr(f, iffid)
-    FILE *f;
-    IFF_ID iffid;
-{
-    if( ferror(f) )
+readerr(FILE * const fP,
+        IFF_ID const iffId) {
+
+    if (ferror(fP))
         pm_error("read error");
     else
-        pm_error("premature EOF in %s chunk", ID2string(iffid));
+        pm_error("premature EOF in %s chunk", ID2string(iffId));
 }
 
 
+
 static void
 read_bytes(FILE *          const ifP,
            int             const bytes,
@@ -191,21 +189,20 @@ read_bytes(FILE *          const ifP,
 
 
 static unsigned char
-get_byte(ifP, iffid, counter)
-    FILE* ifP;
-    IFF_ID iffid;
-    long *counter;
-{
+get_byte(FILE *          const ifP,
+         IFF_ID          const iffId,
+         unsigned long * const counterP) {
+
     int i;
 
-    if( counter ) {
-        if( *counter == 0 )
-            pm_error("insufficient data in %s chunk", ID2string(iffid));
-        --(*counter);
+    if (counterP) {
+        if (*counterP == 0 )
+            pm_error("insufficient data in %s chunk", ID2string(iffId));
+        --(*counterP);
     }
     i = getc(ifP);
-    if( i == EOF )
-        readerr(ifP, iffid);
+    if (i == EOF)
+        readerr(ifP, iffId);
 
     return (unsigned char) i;
 }
@@ -216,7 +213,7 @@ get_big_long(FILE *          const ifP,
              unsigned long * const counterP) {
 
     long l;
-    
+
     if (counterP) {
         if (*counterP < 4)
             pm_error("insufficient data in %s chunk", ID2string(iffid));
@@ -273,114 +270,117 @@ chunk_end(FILE *        const ifP,
 
 static void
 skip_chunk(FILE *        const ifP,
-           IFF_ID        const iffid,
-           unsigned long const chunksize) {
-    unsigned long remainingChunksize;
+           IFF_ID        const iffId,
+           unsigned long const chunkSize) {
 
-    remainingChunksize = chunksize;  /* initial value */
+    unsigned long remainingChunkSize;
 
-    while (remainingChunksize > 0)
-        get_byte(ifP, iffid, &remainingChunksize);
+    for (remainingChunkSize = chunkSize; remainingChunkSize > 0; )
+        get_byte(ifP, iffId, &remainingChunkSize);
 }
 
 
 
 static void
 display_chunk(FILE *        const ifP,
-              IFF_ID        const iffid,
-              unsigned long const chunksize) {
+              IFF_ID        const iffId,
+              unsigned long const chunkSize) {
 
     int byte;
-    unsigned long remainingChunksize;
+    unsigned long remainingChunkSize;
 
-    pm_message("contents of %s chunk:", ID2string(iffid));
+    pm_message("contents of %s chunk:", ID2string(iffId));
 
-    remainingChunksize = chunksize;  /* initial value */
-    byte = '\0';
+    for (remainingChunkSize = chunkSize, byte = '\0';
+         remainingChunkSize > 0; ) {
 
-    while (remainingChunksize > 0) {
-        byte = get_byte(ifP, iffid, &remainingChunksize);
+        byte = get_byte(ifP, iffId, &remainingChunkSize);
         if (fputc(byte, stderr) == EOF)
             pm_error("write error");
     }
-    if (byte != '\n')
-        if (fputc('\n', stderr) == EOF)
+    if (byte != '\n') {
+        int rc;
+        rc = fputc('\n', stderr);
+        if (rc == EOF)
             pm_error("write error");
+    }
 }
 
 
+
 static void
-read_cmap(FILE *     const ifP,
-          IFF_ID     const iffid,
-          long       const chunksize,
-          ColorMap * const cmap) {
+read_cmap(FILE *        const ifP,
+          IFF_ID        const iffId,
+          unsigned long const chunkSize,
+          ColorMap *    const cmapP) {
 
-    long colors;
+    unsigned long const colorCt = chunkSize / 3;
 
-    colors = chunksize / 3;
-    if( colors == 0 ) {
-        pm_error("warning - empty %s colormap", ID2string(iffid));
-        skip_chunk(ifP, iffid, chunksize);
+    if (colorCt == 0) {
+        pm_error("warning - empty %s colormap", ID2string(iffId));
+        skip_chunk(ifP, iffId, chunkSize);
     } else {
         unsigned int i;
-        if( cmap->color )               /* prefer CMAP-chunk over CMYK-chunk */
-            ppm_freerow(cmap->color);
-        cmap->color = ppm_allocrow(colors);
-        cmap->ncolors = colors;
-        
-        for( i = 0; i < colors; ++i ) {
-            int r, g, b;
-            r = get_byte(ifP, iffid, &chunksize);
-            g = get_byte(ifP, iffid, &chunksize);
-            b = get_byte(ifP, iffid, &chunksize);
-            PPM_ASSIGN(cmap->color[i], r, g, b);
+        unsigned long remainingChunkSize;
+
+        if (cmapP->color)               /* prefer CMAP-chunk over CMYK-chunk */
+            ppm_freerow(cmapP->color);
+        cmapP->color   = ppm_allocrow(colorCt);
+        cmapP->ncolors = colorCt;
+
+        for (i = 0, remainingChunkSize = chunkSize; i < colorCt; ++i ) {
+            int const r = get_byte(ifP, iffId, &remainingChunkSize);
+            int const g = get_byte(ifP, iffId, &remainingChunkSize);
+            int const b = get_byte(ifP, iffId, &remainingChunkSize);
+            PPM_ASSIGN(cmapP->color[i], r, g, b);
         }
-        chunk_end(ifP, iffid, chunksize);
+        chunk_end(ifP, iffId, remainingChunkSize);
     }
 }
 
 
 
 static void
-read_cmyk(FILE *     const ifP,
-          IFF_ID     const iffid,
-          long       const chunksize,
-          ColorMap * const cmap) {
+read_cmyk(FILE *        const ifP,
+          IFF_ID        const iffId,
+          unsigned long const chunkSize,
+          ColorMap *    const cmapP) {
 
-    if( HAS_COLORMAP(cmap) ) {      /* prefer RGB color map */
-        skip_chunk(ifP, iffid, chunksize);
+    if (HAS_COLORMAP(cmapP)) {      /* prefer RGB color map */
+        skip_chunk(ifP, iffId, chunkSize);
     } else {
-        long const colors = chunksize/4;
-        if( colors == 0 ) {
-            pm_error("warning - empty %s colormap", ID2string(iffid));
-            skip_chunk(ifP, iffid, chunksize);
+        unsigned long const colorCt = chunkSize / 4;
+        if (colorCt == 0 ) {
+            pm_error("warning - empty %s colormap", ID2string(iffId));
+            skip_chunk(ifP, iffId, chunkSize);
         } else {
             unsigned int i;
-            cmap->color = ppm_allocrow(colors);
-            cmap->ncolors = colors;
-            
-            for( i = 0; i < colors; ++i ) {
-                int c, m, y, k;
-                c = get_byte(ifP, iffid, &chunksize);
-                m = get_byte(ifP, iffid, &chunksize);
-                y = get_byte(ifP, iffid, &chunksize);
-                k = get_byte(ifP, iffid, &chunksize);
+            unsigned long remainingChunkSize;
+
+            cmapP->color   = ppm_allocrow(colorCt);
+            cmapP->ncolors = colorCt;
+
+            for (i = 0, remainingChunkSize = chunkSize; i < colorCt; ++i) {
+                int const c = get_byte(ifP, iffId, &remainingChunkSize);
+                int const m = get_byte(ifP, iffId, &remainingChunkSize);
+                int const y = get_byte(ifP, iffId, &remainingChunkSize);
+                int const k = get_byte(ifP, iffId, &remainingChunkSize);
 
                 {
-                    pixval const red = 
+                    pixval const red =
                         MAXCOLVAL - MIN(MAXCOLVAL,
-                                        c*(MAXCOLVAL-k)/MAXCOLVAL+k); 
-                    pixval const green = 
+                                        c * (MAXCOLVAL-k) / MAXCOLVAL+k);
+                    pixval const green =
                         MAXCOLVAL - MIN(MAXCOLVAL,
-                                        m*(MAXCOLVAL-k)/MAXCOLVAL+k);
-                    pixval const blue = 
+                                        m * (MAXCOLVAL-k) / MAXCOLVAL+k);
+                    pixval const blue =
                         MAXCOLVAL - MIN(MAXCOLVAL,
-                                        y*(MAXCOLVAL-k)/MAXCOLVAL+k);
+                                        y * (MAXCOLVAL-k) / MAXCOLVAL+k);
 
-                    PPM_ASSIGN(cmap->color[i], red, green, blue);
+                    PPM_ASSIGN(cmapP->color[i], red, green, blue);
                 }
             }
-            chunk_end(ifP, iffid, chunksize);
+            chunk_end(ifP, iffId, remainingChunkSize);
         }
     }
 }
@@ -389,45 +389,45 @@ read_cmyk(FILE *     const ifP,
 
 static void
 read_clut(FILE *        const ifP,
-          IFF_ID        const iffid,
-          unsigned long const chunksize,
-          ColorMap *    const cmap) {
-
-    if (chunksize != CLUTSize) {
-        pm_message("invalid size for %s chunk - skipping it", 
-                   ID2string(iffid));
-        skip_chunk(ifP, iffid, chunksize);
+          IFF_ID        const iffId,
+          unsigned long const chunkSize,
+          ColorMap *    const cmapP) {
+
+    if (chunkSize != CLUTSize) {
+        pm_message("invalid size for %s chunk - skipping it",
+                   ID2string(iffId));
+        skip_chunk(ifP, iffId, chunkSize);
     } else {
         long type;
         unsigned char * lut;
-        unsigned long remainingChunksize;
+        unsigned long remainingChunkSize;
         unsigned int i;
 
-        remainingChunksize = chunksize;  /* initial value */
+        remainingChunkSize = chunkSize;  /* initial value */
 
-        type = get_big_long(ifP, iffid, &remainingChunksize);
-        get_big_long(ifP, iffid, &remainingChunksize); /* skip reserved fld */
+        type = get_big_long(ifP, iffId, &remainingChunkSize);
+        get_big_long(ifP, iffId, &remainingChunkSize); /* skip reserved fld */
 
         MALLOCARRAY_NOFAIL(lut, 256);
         for( i = 0; i < 256; ++i )
-            lut[i] = get_byte(ifP, iffid, &remainingChunksize);
+            lut[i] = get_byte(ifP, iffId, &remainingChunkSize);
 
         switch( type ) {
         case CLUT_MONO:
-            cmap->monolut  = lut;
+            cmapP->monolut  = lut;
             break;
         case CLUT_RED:
-            cmap->redlut   = lut;
+            cmapP->redlut   = lut;
             break;
         case CLUT_GREEN:
-            cmap->greenlut = lut;
+            cmapP->greenlut = lut;
             break;
         case CLUT_BLUE:
-            cmap->bluelut  = lut;
+            cmapP->bluelut  = lut;
             break;
         default:
             pm_message("warning - %s type %ld not recognized",
-                       ID2string(iffid), type);
+                       ID2string(iffId), type);
             free(lut);
         }
     }
@@ -446,8 +446,8 @@ warnNonsquarePixels(uint8_t const xAspect,
             pm_message("%s; to fix do a 'pamscale -%cscale %g'",
                        baseMsg,
                        xAspect > yAspect ? 'x' : 'y',
-                       xAspect > yAspect ? 
-                       (float)xAspect/yAspect : 
+                       xAspect > yAspect ?
+                       (float)xAspect/yAspect :
                        (float)yAspect/xAspect);
         else
             pm_message("%s", baseMsg);
@@ -464,7 +464,7 @@ read_bmhd(FILE *        const ifP,
     BitMapHeader * bmhdP;
 
     if (chunksize != BitMapHeaderSize) {
-        pm_message("invalid size for %s chunk - skipping it", 
+        pm_message("invalid size for %s chunk - skipping it",
                    ID2string(iffid));
         skip_chunk(ifP, iffid, chunksize);
         bmhdP = NULL;
@@ -474,7 +474,7 @@ read_bmhd(FILE *        const ifP,
         MALLOCVAR_NOFAIL(bmhdP);
 
         remainingChunksize = chunksize;  /* initial value */
-        
+
         bmhdP->w = get_big_short(ifP, iffid, &remainingChunksize);
         bmhdP->h = get_big_short(ifP, iffid, &remainingChunksize);
         bmhdP->x = get_big_short(ifP, iffid, &remainingChunksize);
@@ -492,7 +492,7 @@ read_bmhd(FILE *        const ifP,
 
         if (verbose) {
             if (typeid == ID_ILBM)
-                pm_message("dimensions: %dx%d, %d planes", 
+                pm_message("dimensions: %dx%d, %d planes",
                            bmhdP->w, bmhdP->h, bmhdP->nPlanes);
             else
                 pm_message("dimensions: %dx%d", bmhdP->w, bmhdP->h);
@@ -509,11 +509,11 @@ read_bmhd(FILE *        const ifP,
                 case mskHasTransparentColor:
                     if (!maskfile)
                         pm_message("use '-maskfile <filename>' "
-                                   "to generate a PBM mask file from %s", 
+                                   "to generate a PBM mask file from %s",
                                    mskNAME[bmhdP->masking]);
                     break;
                 case mskLasso:
-                    pm_message("warning - masking type '%s' not recognized", 
+                    pm_message("warning - masking type '%s' not recognized",
                                mskNAME[bmhdP->masking]);
                     break;
                 default:
@@ -529,7 +529,7 @@ read_bmhd(FILE *        const ifP,
 
         /* fix aspect ratio */
         if (bmhdP->xAspect == 0 || bmhdP->yAspect == 0) {
-            pm_message("warning - illegal aspect ratio %d:%d, using 1:1", 
+            pm_message("warning - illegal aspect ratio %d:%d, using 1:1",
                        bmhdP->xAspect, bmhdP->yAspect);
             bmhdP->xAspect = bmhdP->yAspect = 1;
         }
@@ -647,7 +647,7 @@ decode_mask(FILE *          const ifP,
     case mskNone:
         break;
     case mskHasMask:        /* mask plane */
-        read_ilbm_plane(ifP, remainingChunksizeP, RowBytes(cols), 
+        read_ilbm_plane(ifP, remainingChunksizeP, RowBytes(cols),
                         bmhdP->compression);
         if (maskfile) {
             ilp = ilbmrow;
@@ -669,7 +669,7 @@ decode_mask(FILE *          const ifP,
     case mskHasTransparentColor:
         if (!chunkyrow)
             pm_error("decode_mask(): chunkyrow == NULL - can't happen");
-        
+
         if (maskfile) {
             for (col = 0; col < cols; ++col) {
                 if (chunkyrow[col] == bmhdP->transparentColor)
@@ -685,7 +685,7 @@ decode_mask(FILE *          const ifP,
         pm_error("This program does not know how to process Lasso masking");
         break;
     default:
-        pm_error("decode_mask(): unknown masking type %d - can't happen", 
+        pm_error("decode_mask(): unknown masking type %d - can't happen",
                  bmhdP->masking);
     }
 }
@@ -697,79 +697,82 @@ decode_mask(FILE *          const ifP,
 
 
 static void
-multi_adjust(cmap, row, palchange)
-    ColorMap *cmap;
-    int row;
-    PaletteChange *palchange;
-{
-    int i, reg;
-
-    for( i = 0; palchange[i].reg != MP_REG_END; i++ ) {
-        reg = palchange[i].reg;
-        if( reg >= cmap->ncolors ) {
+multi_adjust(ColorMap *            const cmapP,
+             unsigned int          const row,
+             const PaletteChange * const palchange) {
+
+    unsigned int i;
+
+    for (i = 0; palchange[i].reg != MP_REG_END; ++i) {
+        int const reg = palchange[i].reg;
+        if (reg >= cmapP->ncolors) {
             pm_message("warning - palette change register out of range");
-            pm_message("    row %d  change structure %d  reg=%d (max %d)", 
-                       row, i, reg, cmap->ncolors-1);
+            pm_message("    row %u  change structure %d  reg=%d (max %d)",
+                       row, i, reg, cmapP->ncolors-1);
             pm_message("    ignoring it...  "
                        "colors might get messed up from here");
-        }
-        else
-        if( reg != MP_REG_IGNORE ) {
-            PPM_ASSIGN(cmap->color[reg], 
-                       palchange[i].r, palchange[i].g, palchange[i].b);
+        } else {
+            if (reg != MP_REG_IGNORE) {
+                PPM_ASSIGN(cmapP->color[reg],
+                           palchange[i].r, palchange[i].g, palchange[i].b);
+            }
         }
     }
 }
 
+
+
 static void
-multi_init(cmap, viewportmodes)
-    ColorMap *cmap;
-    long viewportmodes;
-{
-    if( cmap->mp_init )
-        multi_adjust(cmap, -1, cmap->mp_init);
-    if( !(viewportmodes & vmLACE) )
-        cmap->mp_flags &= ~(MP_FLAGS_SKIPLACED);
+multi_init(ColorMap * const cmapP,
+           long       const viewportmodes) {
+
+    if (cmapP->mp_init)
+        multi_adjust(cmapP, -1, cmapP->mp_init);
+    if (!(viewportmodes & vmLACE) )
+        cmapP->mp_flags &= ~(MP_FLAGS_SKIPLACED);
 }
 
+
+
 static void
-multi_update(cmap, row)
-    ColorMap *cmap;
-    int row;
-{
-    if( cmap->mp_flags & MP_FLAGS_SKIPLACED ) {
-        if( ODD(row) )
+multi_update(ColorMap *   const cmapP,
+             unsigned int const row) {
+
+    if (cmapP->mp_flags & MP_FLAGS_SKIPLACED) {
+        if (ODD(row))
             return;
-        if( row/2 < cmap->mp_rows && cmap->mp_change[row/2] )
-            multi_adjust(cmap, row, cmap->mp_change[row/2]);
-    }
-    else {
-        if( row < cmap->mp_rows && cmap->mp_change[row] )
-            multi_adjust(cmap, row, cmap->mp_change[row]);
+        if (row/2 < cmapP->mp_rows && cmapP->mp_change[row/2])
+            multi_adjust(cmapP, row, cmapP->mp_change[row/2]);
+    } else {
+        if (row < cmapP->mp_rows && cmapP->mp_change[row])
+            multi_adjust(cmapP, row, cmapP->mp_change[row]);
     }
 }
 
+
+
 static void
-multi_free(cmap)
-    ColorMap *cmap;
-{
-    int i;
+multi_free(ColorMap * const cmapP) {
 
-    if( cmap->mp_init ) {
-        free(cmap->mp_init);
-        cmap->mp_init = NULL;
+    if (cmapP->mp_init) {
+        free(cmapP->mp_init);
+        cmapP->mp_init = NULL;
     }
-    if( cmap->mp_change ) {
-        for( i = 0; i < cmap->mp_rows; i++ ) {
-            if( cmap->mp_change[i] )
-                free(cmap->mp_change[i]);
+
+    if (cmapP->mp_change) {
+        unsigned int i;
+
+        for (i = 0; i < cmapP->mp_rows; ++i) {
+            if (cmapP->mp_change[i])
+                free(cmapP->mp_change[i]);
         }
-        free(cmap->mp_change);
-        cmap->mp_change = NULL;
+        free(cmapP->mp_change);
+        cmapP->mp_change = NULL;
     }
-    cmap->mp_rows = 0;
-    cmap->mp_type = 0;
-    cmap->mp_flags = 0;
+
+    cmapP->mp_rows  = 0;
+    cmapP->mp_type  = 0;
+    cmapP->mp_flags = 0;
 }
 
 
@@ -788,7 +791,7 @@ analyzeCmapSamples(const ColorMap * const cmapP,
     pixval       maxSample;
     bool         shifted;
     unsigned int i;
-        
+
     for (i = 0, maxSample = 0, shifted = true; i < cmapP->ncolors; ++i) {
         pixval const r = PPM_GETR(cmapP->color[i]);
         pixval const g = PPM_GETG(cmapP->color[i]);
@@ -857,7 +860,7 @@ transpColor(const BitMapHeader * const bmhdP,
     pixel * transpColorP;
 
     if (bmhdP) {
-        if (bmhdP->masking == mskHasTransparentColor || 
+        if (bmhdP->masking == mskHasTransparentColor ||
             bmhdP->masking == mskLasso) {
             MALLOCVAR_NOFAIL(transpColorP);
 
@@ -909,80 +912,83 @@ prepareCmap(const BitMapHeader * const bmhdP,
 
 
 static pixval
-lookup_red(cmap, oldval)
-    ColorMap *cmap;
-    int oldval;
-{
-    if( cmap && cmap->redlut && oldval < 256 )
-        return cmap->redlut[oldval];
+lookup_red(ColorMap *   const cmapP,
+           unsigned int const oldval) {
+
+    if (cmapP && cmapP->redlut && oldval < 256)
+        return cmapP->redlut[oldval];
     else
         return oldval;
 }
 
+
+
 static pixval
-lookup_green(cmap, oldval)
-    ColorMap *cmap;
-    int oldval;
-{
-    if( cmap && cmap->greenlut && oldval < 256 )
-        return cmap->greenlut[oldval];
+lookup_green(ColorMap *   const cmapP,
+             unsigned int const oldval) {
+
+    if (cmapP && cmapP->greenlut && oldval < 256)
+        return cmapP->greenlut[oldval];
     else
         return oldval;
 }
 
+
+
 static pixval
-lookup_blue(cmap, oldval)
-    ColorMap *cmap;
-    int oldval;
-{
-    if( cmap && cmap->bluelut && oldval < 256 )
-        return cmap->bluelut[oldval];
+lookup_blue(ColorMap *   const cmapP,
+            unsigned int const oldval) {
+
+    if (cmapP && cmapP->bluelut && oldval < 256)
+        return cmapP->bluelut[oldval];
     else
         return oldval;
 }
 
+
+
 static pixval
-lookup_mono(cmap, oldval)
-    ColorMap *cmap;
-    int oldval;
-{
-    if( cmap && cmap->monolut && oldval < 256 )
-        return cmap->monolut[oldval];
+lookup_mono(ColorMap *   const cmapP,
+            unsigned int const oldval) {
+
+    if (cmapP && cmapP->monolut && oldval < 256)
+        return cmapP->monolut[oldval];
     else
         return oldval;
 }
 
+
+
 static ColorMap *
-ehbcmap(cmap)
-    ColorMap *cmap;
-{
-    pixel *tempcolor = NULL;
-    int i, col;
-
-    col = cmap->ncolors;
-
-    tempcolor = ppm_allocrow(col * 2);
-    for( i = 0; i < col; i++ ) {
-        tempcolor[i] = cmap->color[i];
-        PPM_ASSIGN(tempcolor[col + i],  PPM_GETR(cmap->color[i]) / 2,
-                                        PPM_GETG(cmap->color[i]) / 2,
-                                        PPM_GETB(cmap->color[i]) / 2 );
+ehbcmap(ColorMap * const cmapP) {
+
+    pixel * tempcolor;
+    unsigned int i;
+
+    tempcolor = ppm_allocrow(cmapP->ncolors * 2);
+
+    for (i = 0; i < cmapP->ncolors; ++i) {
+        tempcolor[i] = cmapP->color[i];
+        PPM_ASSIGN(tempcolor[cmapP->ncolors + i],
+                   PPM_GETR(cmapP->color[i]) / 2,
+                   PPM_GETG(cmapP->color[i]) / 2,
+                   PPM_GETB(cmapP->color[i]) / 2);
     }
-    ppm_freerow(cmap->color);
-    cmap->color = tempcolor;
-    cmap->ncolors *= 2;
+    ppm_freerow(cmapP->color);
+    cmapP->color = tempcolor;
+    cmapP->ncolors *= 2;
 
-    return cmap;
+    return cmapP;
 }
 
 
 
 static pixval
-lut_maxval(ColorMap * const cmap, 
+lut_maxval(ColorMap * const cmap,
            pixval     const maxval) {
 
     pixval retval;
-    
+
     if (maxval >= 255)
         retval = maxval;
     else {
@@ -993,16 +999,16 @@ lut_maxval(ColorMap * const cmap,
             unsigned char maxlut;
             maxlut = maxval;
             for( i = 0; i < maxval; i++ ) {
-                if( cmap->redlut   && cmap->redlut[i]   > maxlut ) 
+                if( cmap->redlut   && cmap->redlut[i]   > maxlut )
                     maxlut = cmap->redlut[i];
-                if( cmap->greenlut && cmap->greenlut[i] > maxlut ) 
+                if( cmap->greenlut && cmap->greenlut[i] > maxlut )
                     maxlut = cmap->greenlut[i];
-                if( cmap->bluelut  && cmap->bluelut[i]  > maxlut ) 
+                if( cmap->bluelut  && cmap->bluelut[i]  > maxlut )
                     maxlut = cmap->bluelut[i];
             }
             pm_message("warning - "
                        "%d-bit index into 8-bit color lookup table, "
-                       "table maxval=%d", 
+                       "table maxval=%d",
                        pm_maxvaltobits(maxval), maxlut);
             if( maxlut != maxval )
                 retval = 255;
@@ -1017,49 +1023,49 @@ lut_maxval(ColorMap * const cmap,
 
 
 static void
-get_color(cmap, idx, red, green, blue)
-    ColorMap *cmap;
-    int idx;
-    pixval *red, *green, *blue;
-{
-    if( HAS_COLORMAP(cmap) ) {
-        pixval r, g, b;
-
-        if( idx >= cmap->ncolors )
-            pm_error("color index out of range: %d (max %d)", 
-                     idx, cmap->ncolors);
-        r = PPM_GETR(cmap->color[idx]);
-        g = PPM_GETG(cmap->color[idx]);
-        b = PPM_GETB(cmap->color[idx]);
-
-        *red    = lookup_red(cmap, r);
-        *green  = lookup_green(cmap, g);
-        *blue   = lookup_blue(cmap, b);
-    }
-    else {
-        *red = *green = *blue = lookup_mono(cmap, idx);
-    }
+get_color(ColorMap *   const cmapP,
+          unsigned int const idx,
+          pixval *     const redP,
+          pixval *     const greenP,
+          pixval *     const blueP) {
+
+    if (HAS_COLORMAP(cmapP)) {
+        if (idx >= cmapP->ncolors)
+            pm_error("color index out of range: %u (max %u)",
+                     idx, cmapP->ncolors);
+        else {
+            pixval const r = PPM_GETR(cmapP->color[idx]);
+            pixval const g = PPM_GETG(cmapP->color[idx]);
+            pixval const b = PPM_GETB(cmapP->color[idx]);
+
+            *redP    = lookup_red   (cmapP, r);
+            *greenP  = lookup_green (cmapP, g);
+            *blueP   = lookup_blue  (cmapP, b);
+        }
+    } else
+        *redP = *greenP = *blueP = lookup_mono(cmapP, idx);
 }
 
 
+
 /****************************************************************************
  Conversion functions
  ****************************************************************************/
 
 static void
-std_to_ppm(FILE *         const ifP, 
-           long           const chunksize, 
-           BitMapHeader * const bmhdP, 
-           ColorMap *     const cmap, 
+std_to_ppm(FILE *         const ifP,
+           long           const chunksize,
+           BitMapHeader * const bmhdP,
+           ColorMap *     const cmap,
            long           const viewportmodes);
 
 
 
 static void
-ham_to_ppm(FILE *         const ifP, 
-           long           const chunksize, 
-           BitMapHeader * const bmhdP, 
-           ColorMap *     const cmap, 
+ham_to_ppm(FILE *         const ifP,
+           long           const chunksize,
+           BitMapHeader * const bmhdP,
+           ColorMap *     const cmap,
            long           const viewportmodes) {
 
     int cols, rows, hambits, hammask, hamshift, hammask2, col, row;
@@ -1077,7 +1083,7 @@ ham_to_ppm(FILE *         const ifP,
     if( hambits > 8 || hambits < 1 ) {
         int const assumed_viewportmodes = viewportmodes & ~(vmHAM);
 
-        pm_message("%d-plane HAM?? - interpreting image as a normal ILBM", 
+        pm_message("%d-plane HAM?? - interpreting image as a normal ILBM",
                    bmhdP->nPlanes);
         std_to_ppm(ifP, chunksize, bmhdP, cmap, assumed_viewportmodes);
         return;
@@ -1085,8 +1091,8 @@ ham_to_ppm(FILE *         const ifP,
         unsigned long remainingChunksize;
         pixel * transpColorP;
 
-        pm_message("input is a %sHAM%d file", 
-                   HAS_MULTIPALETTE(cmap) ? "multipalette " : "", 
+        pm_message("input is a %sHAM%d file",
+                   HAS_MULTIPALETTE(cmap) ? "multipalette " : "",
                    bmhdP->nPlanes);
 
         if( HAS_COLORLUT(cmap) || HAS_MONOLUT(cmap) ) {
@@ -1095,7 +1101,7 @@ ham_to_ppm(FILE *         const ifP,
             if( cmap->greenlut )    free(cmap->greenlut);
             if( cmap->bluelut )     free(cmap->bluelut);
             if( cmap->monolut )     free(cmap->monolut);
-            cmap->redlut = cmap->greenlut = cmap->bluelut = 
+            cmap->redlut = cmap->greenlut = cmap->bluelut =
                 cmap->monolut = NULL;
         }
         if( !HAS_COLORMAP(cmap) ) {
@@ -1165,10 +1171,10 @@ ham_to_ppm(FILE *         const ifP,
 
 
 static void
-std_to_ppm(FILE *         const ifP, 
-           long           const chunksize, 
-           BitMapHeader * const bmhdP, 
-           ColorMap *     const cmap, 
+std_to_ppm(FILE *         const ifP,
+           long           const chunksize,
+           BitMapHeader * const bmhdP,
+           ColorMap *     const cmap,
            long           const viewportmodes) {
 
     if (viewportmodes & vmHAM) {
@@ -1213,7 +1219,7 @@ std_to_ppm(FILE *         const ifP,
         ppm_writeppminit( stdout, cols, rows, maxval, 0 );
 
         remainingChunksize = chunksize;  /* initial value */
-    
+
         for (row = 0; row < rows; ++row) {
 
             if( HAS_MULTIPALETTE(cmap) )
@@ -1240,9 +1246,9 @@ std_to_ppm(FILE *         const ifP,
 
 
 static void
-deep_to_ppm(FILE *         const ifP, 
-            long           const chunksize, 
-            BitMapHeader * const bmhdP, 
+deep_to_ppm(FILE *         const ifP,
+            long           const chunksize,
+            BitMapHeader * const bmhdP,
             ColorMap *     const cmap) {
 
     unsigned int const cols = bmhdP->w;
@@ -1259,9 +1265,9 @@ deep_to_ppm(FILE *         const ifP,
     if( planespercolor > MAXPLANES )
         pm_error("too many planes (max %d)", MAXPLANES * 3);
 
-    if( bmhdP->masking == mskHasTransparentColor || 
+    if( bmhdP->masking == mskHasTransparentColor ||
         bmhdP->masking == mskLasso ) {
-        pm_message("masking type '%s' in a deep ILBM?? - ignoring it", 
+        pm_message("masking type '%s' in a deep ILBM?? - ignoring it",
                    mskNAME[bmhdP->masking]);
         bmhdP->masking = mskNone;
     }
@@ -1271,7 +1277,7 @@ deep_to_ppm(FILE *         const ifP,
         pm_error("nPlanes is too large");
 
     transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
-        
+
     Rrow = alloc_rawrow(cols);
     Grow = alloc_rawrow(cols);
     Brow = alloc_rawrow(cols);
@@ -1313,7 +1319,7 @@ dcol_to_ppm(FILE *         const ifP,
     unsigned int const redplanes   = dcol->r;
     unsigned int const greenplanes = dcol->g;
     unsigned int const blueplanes  = dcol->b;
-    
+
     int col, row;
     rawtype *Rrow, *Grow, *Brow;
     pixval maxval, redmaxval, greenmaxval, bluemaxval;
@@ -1324,16 +1330,16 @@ dcol_to_ppm(FILE *         const ifP,
     pm_message("input is a %d:%d:%d direct color ILBM",
                 redplanes, greenplanes, blueplanes);
 
-    if( redplanes > MAXPLANES || 
-        blueplanes > MAXPLANES || 
+    if( redplanes > MAXPLANES ||
+        blueplanes > MAXPLANES ||
         greenplanes > MAXPLANES )
         pm_error("too many planes (max %d per color component)", MAXPLANES);
 
     if( bmhdP->nPlanes != (redplanes + greenplanes + blueplanes) )
-        pm_error("%s/%s plane number mismatch", 
+        pm_error("%s/%s plane number mismatch",
                  ID2string(ID_BMHD), ID2string(ID_DCOL));
 
-    if( bmhdP->masking == mskHasTransparentColor || 
+    if( bmhdP->masking == mskHasTransparentColor ||
         bmhdP->masking == mskLasso ) {
         pm_message("masking type '%s' in a direct color ILBM?? - ignoring it",
                    mskNAME[bmhdP->masking]);
@@ -1356,7 +1362,7 @@ dcol_to_ppm(FILE *         const ifP,
 
     if( redmaxval != maxval || greenmaxval != maxval || bluemaxval != maxval )
         pm_message("scaling colors to %d bits", pm_maxvaltobits(maxval));
-    
+
     MALLOCARRAY_NOFAIL(redtable,   redmaxval   +1);
     MALLOCARRAY_NOFAIL(greentable, greenmaxval +1);
     MALLOCARRAY_NOFAIL(bluetable,  bluemaxval  +1);
@@ -1403,7 +1409,7 @@ dcol_to_ppm(FILE *         const ifP,
 
 static void
 cmapToPpm(FILE *     const ofP,
-            ColorMap * const cmapP) {
+          ColorMap * const cmapP) {
 
     ppm_colorrowtomapfile(ofP, cmapP->color, cmapP->ncolors, MAXCOLVAL);
 }
@@ -1425,11 +1431,11 @@ ipbm_to_ppm(FILE *         const ifP,
     unsigned long remainingChunksize;
     pixel * transpColorP;
 
-    pm_message("input is a %sPBM ", 
+    pm_message("input is a %sPBM ",
                HAS_MULTIPALETTE(cmap) ? "multipalette " : "");
 
     if( bmhdP->nPlanes != 8 )
-        pm_error("invalid number of planes for IFF-PBM: %d (must be 8)", 
+        pm_error("invalid number of planes for IFF-PBM: %d (must be 8)",
                  bmhdP->nPlanes);
 
     if( bmhdP->masking == mskHasMask )
@@ -1456,7 +1462,7 @@ ipbm_to_ppm(FILE *         const ifP,
     for( row = 0; row < rows; row++ ) {
         if( HAS_MULTIPALETTE(cmap) )
             multi_update(cmap, row);
-        
+
         read_ilbm_plane(ifP, &remainingChunksize, cols, bmhdP->compression);
 
         for( col = 0; col < cols; col++ ) {
@@ -1494,24 +1500,24 @@ rgbn_to_ppm(FILE *         const ifP,
     pm_message("input is a %d-bit RGB image", (typeid == ID_RGB8 ? 8 : 4));
 
     if (bmhdP->compression != 4)
-        pm_error("invalid compression mode for %s: %d (must be 4)", 
+        pm_error("invalid compression mode for %s: %d (must be 4)",
                  ID2string(typeid), bmhdP->compression);
-    
+
     switch (typeid) {
     case ID_RGBN:
         if (bmhdP->nPlanes != 13)
-            pm_error("invalid number of planes for %s: %d (must be 13)", 
+            pm_error("invalid number of planes for %s: %d (must be 13)",
                      ID2string(typeid), bmhdP->nPlanes);
         maxval = lut_maxval(cmap, 15);
         break;
     case ID_RGB8:
         if (bmhdP->nPlanes != 25)
-            pm_error("invalid number of planes for %s: %d (must be 25)", 
+            pm_error("invalid number of planes for %s: %d (must be 25)",
                      ID2string(typeid), bmhdP->nPlanes);
         maxval = 255;
         break;
     default:
-        pm_error("rgbn_to_ppm(): invalid IFF ID %s - can't happen", 
+        pm_error("rgbn_to_ppm(): invalid IFF ID %s - can't happen",
                  ID2string(typeid));
     }
 
@@ -1533,7 +1539,7 @@ rgbn_to_ppm(FILE *         const ifP,
             tries = 0;
             while (count == 0) {
                 if (typeid == ID_RGB8) {
-                    r = lookup_red(cmap,   get_byte(ifP, ID_BODY, 
+                    r = lookup_red(cmap,   get_byte(ifP, ID_BODY,
                                                     &remainingChunksize));
                     g = lookup_green(cmap, get_byte(ifP, ID_BODY,
                                                     &remainingChunksize));
@@ -1675,40 +1681,46 @@ read_4bit_mp(FILE *     const ifP,
 
 
 static void
-PCHG_DecompHuff(src, dest, tree, origsize)
-    unsigned char *src, *dest;
-    short *tree;
-    unsigned long origsize;
-{
-    unsigned long i = 0, bits = 0;
+PCHG_DecompHuff(const unsigned char * const src,
+                unsigned char *       const dst,
+                short *               const tree,
+                unsigned long         const origsize) {
+
+    const unsigned char * srcCursor;
+    unsigned char * dstCursor;
+    unsigned long i;
+    unsigned long bits;
     unsigned char thisbyte;
-    short *p;
+    short * p;
 
-    p = tree;
-    while( i < origsize ) {
-        if( bits == 0 ) {
-            thisbyte = *src++;
+    srcCursor = &src[0];  /* initial value */
+    dstCursor = &dst[0];  /* initial value */
+    i = 0;     /* initial value */
+    bits = 0;  /* initial value */
+    p = tree;  /* initial value */
+
+    while (i < origsize) {
+        if (bits == 0)  {
+            thisbyte = *srcCursor++;
             bits = 8;
         }
-        if( thisbyte & (1 << 7) ) {
-            if( *p >= 0 ) {
-                *dest++ = (unsigned char)*p;
-                i++;
+        if (thisbyte & (1 << 7)) {
+            if (*p >= 0) {
+                *dstCursor++ = (unsigned char)*p;
+                ++i;
                 p = tree;
-            }
-            else
+            } else
                 p += (*p / 2);
-        }
-        else {
-            p--;
-            if( *p > 0 && (*p & 0x100) ) {
-                *dest++ = (unsigned char )*p;
-                i++;
+        } else {
+            --p;
+            if (*p > 0 && (*p & 0x100)) {
+                *dstCursor++ = (unsigned char )*p;
+                ++i;
                 p = tree;
             }
         }
         thisbyte <<= 1;
-        bits--;
+        --bits;
     }
 }
 
@@ -1743,9 +1755,9 @@ PCHG_Decompress(PCHGHeader *     const PCHG,
             hufftree[i] = pm_uintFromBigend16(bigendComptree[i]);
 
         /* decompress the change structure data */
-        PCHG_DecompHuff(compdata, data, &hufftree[huffsize-1], 
+        PCHG_DecompHuff(compdata, data, &hufftree[huffsize-1],
                         CompHdr->OriginalDataSize);
-        
+
         free(hufftree);
     } break;
         default:
@@ -1755,99 +1767,103 @@ PCHG_Decompress(PCHGHeader *     const PCHG,
 
 
 static void
-PCHG_ConvertSmall(PCHG, cmap, mask, datasize)
-    PCHGHeader *PCHG;
-    ColorMap *cmap;
-    unsigned char *mask;
-    unsigned long datasize;
-{
+PCHG_ConvertSmall(PCHGHeader *    const pchgP,
+                  ColorMap *      const cmapP,
+                  unsigned char * const mask,
+                  unsigned long   const dataSize) {
+
     unsigned char *data;
+    unsigned long remDataSize;
     unsigned char thismask;
     int bits, row, i, changes, masklen, reg;
     unsigned char ChangeCount16, ChangeCount32;
     unsigned short SmallChange;
-    unsigned long totalchanges = 0;
-    int changedlines = PCHG->ChangedLines;
+    unsigned long totalchanges;
+    int changedlines;
+    unsigned char * maskCursor;
 
-    masklen = 4 * MaskLongWords(PCHG->LineCount);
-    data = mask + masklen; datasize -= masklen;
+    totalchanges = 0;  /* initial value */
+    changedlines = pchgP->ChangedLines;  /* initial value */
+    masklen = 4 * MaskLongWords(pchgP->LineCount);
+    maskCursor = mask;
+    data = maskCursor + masklen; remDataSize = dataSize - masklen;
 
     bits = 0;
-    for( row = PCHG->StartLine; changedlines && row < 0; row++ ) {
-        if( bits == 0 ) {
-            if( masklen == 0 ) goto fail2;
-            thismask = *mask++;
+    for (row = pchgP->StartLine; changedlines && row < 0; ++row) {
+        if (bits == 0) {
+            if (masklen == 0) goto fail2;
+            thismask = *maskCursor++;
             --masklen;
             bits = 8;
         }
-        if( thismask & (1<<7) ) {
-            if( datasize < 2 ) goto fail;
+        if (thismask & (1<<7)) {
+            if (remDataSize < 2) goto fail;
             ChangeCount16 = *data++;
             ChangeCount32 = *data++;
-            datasize -= 2;
+            remDataSize -= 2;
 
             changes = ChangeCount16 + ChangeCount32;
-            for( i = 0; i < changes; i++ ) {
-                if( totalchanges >= PCHG->TotalChanges ) goto fail;
-                if( datasize < 2 ) goto fail;
-                SmallChange = BIG_WORD(data); data += 2; datasize -= 2;
-                reg = ((SmallChange & 0xf000) >> 12) + 
+            for (i = 0; i < changes; ++i) {
+                if (totalchanges >= pchgP->TotalChanges) goto fail;
+                if (remDataSize < 2) goto fail;
+                SmallChange = BIG_WORD(data); data += 2; remDataSize -= 2;
+                reg = ((SmallChange & 0xf000) >> 12) +
                     (i >= ChangeCount16 ? 16 : 0);
-                cmap->mp_init[reg - PCHG->MinReg].reg = reg;
-                cmap->mp_init[reg - PCHG->MinReg].r = 
+                cmapP->mp_init[reg - pchgP->MinReg].reg = reg;
+                cmapP->mp_init[reg - pchgP->MinReg].r =
                     ((SmallChange & 0x0f00) >> 8) * FACTOR_4BIT;
-                cmap->mp_init[reg - PCHG->MinReg].g = 
+                cmapP->mp_init[reg - pchgP->MinReg].g =
                     ((SmallChange & 0x00f0) >> 4) * FACTOR_4BIT;
-                cmap->mp_init[reg - PCHG->MinReg].b = 
+                cmapP->mp_init[reg - pchgP->MinReg].b =
                     ((SmallChange & 0x000f) >> 0) * FACTOR_4BIT;
                 ++totalchanges;
             }
             --changedlines;
         }
         thismask <<= 1;
-        bits--;
+        --bits;
     }
 
-    for( row = PCHG->StartLine; changedlines && row < cmap->mp_rows; row++ ) {
-        if( bits == 0 ) {
-            if( masklen == 0 ) goto fail2;
-            thismask = *mask++;
+    for (row = pchgP->StartLine; changedlines && row < cmapP->mp_rows; row++) {
+        if (bits == 0) {
+            if (masklen == 0) goto fail2;
+            thismask = *maskCursor++;
             --masklen;
             bits = 8;
         }
-        if( thismask & (1<<7) ) {
-            if( datasize < 2 ) goto fail;
+        if(thismask & (1<<7)) {
+            if (remDataSize < 2) goto fail;
             ChangeCount16 = *data++;
             ChangeCount32 = *data++;
-            datasize -= 2;
+            remDataSize -= 2;
 
             changes = ChangeCount16 + ChangeCount32;
-            MALLOCARRAY_NOFAIL(cmap->mp_change[row], changes + 1);
-            for( i = 0; i < changes; i++ ) {
-                if( totalchanges >= PCHG->TotalChanges ) goto fail;
-                if( datasize < 2 ) goto fail;
-                SmallChange = BIG_WORD(data); data += 2; datasize -= 2;
-                reg = ((SmallChange & 0xf000) >> 12) + 
+            MALLOCARRAY_NOFAIL(cmapP->mp_change[row], changes + 1);
+            for (i = 0; i < changes; ++i) {
+                if (totalchanges >= pchgP->TotalChanges) goto fail;
+                if (remDataSize < 2) goto fail;
+                SmallChange = BIG_WORD(data); data += 2; remDataSize -= 2;
+                reg = ((SmallChange & 0xf000) >> 12) +
                     (i >= ChangeCount16 ? 16 : 0);
-                cmap->mp_change[row][i].reg = reg;
-                cmap->mp_change[row][i].r = 
+                cmapP->mp_change[row][i].reg = reg;
+                cmapP->mp_change[row][i].r =
                     ((SmallChange & 0x0f00) >> 8) * FACTOR_4BIT;
-                cmap->mp_change[row][i].g = 
+                cmapP->mp_change[row][i].g =
                     ((SmallChange & 0x00f0) >> 4) * FACTOR_4BIT;
-                cmap->mp_change[row][i].b = 
+                cmapP->mp_change[row][i].b =
                     ((SmallChange & 0x000f) >> 0) * FACTOR_4BIT;
                 ++totalchanges;
             }
-            cmap->mp_change[row][changes].reg = MP_REG_END;
+            cmapP->mp_change[row][changes].reg = MP_REG_END;
             --changedlines;
         }
         thismask <<= 1;
-        bits--;
+        --bits;
     }
-    if( totalchanges != PCHG->TotalChanges )
+    if (totalchanges != pchgP->TotalChanges)
         pm_message("warning - got %ld change structures, "
-                   "chunk header reports %ld", 
-                   totalchanges, PCHG->TotalChanges);
+                   "chunk header reports %ld",
+                   totalchanges, pchgP->TotalChanges);
     return;
 fail:
     pm_error("insufficient data in SmallLineChanges structures");
@@ -1872,16 +1888,16 @@ PCHG_ConvertBig(PCHGHeader *    const PCHG,
     int reg;
     unsigned long totalchanges;
     int changedlines;
-    unsigned long dataRemaining;
+    unsigned long remDataSize;
     unsigned char * mask;
 
     mask = maskStart;  /* initial value */
-    dataRemaining = datasize;  /* initial value */
+    remDataSize = datasize;  /* initial value */
     changedlines = PCHG->ChangedLines;  /* initial value */
     totalchanges = 0;  /* initial value */
 
     masklen = 4 * MaskLongWords(PCHG->LineCount);
-    data = mask + masklen; dataRemaining -= masklen;
+    data = mask + masklen; remDataSize -= masklen;
 
     for (row = PCHG->StartLine, bits = 0; changedlines && row < 0; ++row) {
         if (bits == 0) {
@@ -1894,16 +1910,16 @@ PCHG_ConvertBig(PCHGHeader *    const PCHG,
         if (thismask & (1<<7)) {
             unsigned int i;
 
-            if (dataRemaining < 2)
+            if (remDataSize < 2)
                 pm_error("insufficient data in BigLineChanges structures");
 
-            changes = BIG_WORD(data); data += 2; dataRemaining -= 2;
+            changes = BIG_WORD(data); data += 2; remDataSize -= 2;
 
             for (i = 0; i < changes; ++i) {
                 if (totalchanges >= PCHG->TotalChanges)
                     pm_error("insufficient data in BigLineChanges structures");
 
-                if (dataRemaining < 6)
+                if (remDataSize < 6)
                     pm_error("insufficient data in BigLineChanges structures");
 
                 reg = BIG_WORD(data); data += 2;
@@ -1912,7 +1928,7 @@ PCHG_ConvertBig(PCHGHeader *    const PCHG,
                 cmap->mp_init[reg - PCHG->MinReg].r = *data++;
                 cmap->mp_init[reg - PCHG->MinReg].b = *data++;  /* yes, RBG */
                 cmap->mp_init[reg - PCHG->MinReg].g = *data++;
-                dataRemaining -= 6;
+                remDataSize -= 6;
                 ++totalchanges;
             }
             --changedlines;
@@ -1933,17 +1949,17 @@ PCHG_ConvertBig(PCHGHeader *    const PCHG,
         if (thismask & (1<<7)) {
             unsigned int i;
 
-            if (dataRemaining < 2)
+            if (remDataSize < 2)
                 pm_error("insufficient data in BigLineChanges structures");
 
-            changes = BIG_WORD(data); data += 2; dataRemaining -= 2;
+            changes = BIG_WORD(data); data += 2; remDataSize -= 2;
 
             MALLOCARRAY_NOFAIL(cmap->mp_change[row], changes + 1);
             for (i = 0; i < changes; ++i) {
                 if (totalchanges >= PCHG->TotalChanges)
                     pm_error("insufficient data in BigLineChanges structures");
 
-                if (dataRemaining < 6)
+                if (remDataSize < 6)
                     pm_error("insufficient data in BigLineChanges structures");
 
                 reg = BIG_WORD(data); data += 2;
@@ -1952,7 +1968,7 @@ PCHG_ConvertBig(PCHGHeader *    const PCHG,
                 cmap->mp_change[row][i].r = *data++;
                 cmap->mp_change[row][i].b = *data++;    /* yes, RBG */
                 cmap->mp_change[row][i].g = *data++;
-                dataRemaining -= 6;
+                remDataSize -= 6;
                 ++totalchanges;
             }
             cmap->mp_change[row][changes].reg = MP_REG_END;
@@ -1963,7 +1979,7 @@ PCHG_ConvertBig(PCHGHeader *    const PCHG,
     }
     if (totalchanges != PCHG->TotalChanges)
         pm_message("warning - got %ld change structures, "
-                   "chunk header reports %ld", 
+                   "chunk header reports %ld",
                    totalchanges, PCHG->TotalChanges);
 }
 
@@ -2027,7 +2043,7 @@ read_pchg(FILE *     const ifP,
 
             datasize = CompHdr.OriginalDataSize;
             MALLOCARRAY_NOFAIL(data, datasize);
-            PCHG_Decompress(&PCHG, &CompHdr, compdata, 
+            PCHG_Decompress(&PCHG, &CompHdr, compdata,
                             compsize, comptree, data);
 
             free(comptree);
@@ -2073,7 +2089,7 @@ read_pchg(FILE *     const ifP,
             }
             else
                 pm_error("unknown palette changes structure "
-                         "format in %s chunk", 
+                         "format in %s chunk",
                          ID2string(iffid));
         }
         free(data);
@@ -2101,7 +2117,7 @@ ignored_iffid(IFF_ID       const iffid,
 
 
 
-static void 
+static void
 process_body( FILE *          const ifP,
               long            const chunksize,
               BitMapHeader *  const bmhdP,
@@ -2111,9 +2127,9 @@ process_body( FILE *          const ifP,
               int             const isdeepopt,
               DirectColor *   const dcol,
               int *           const viewportmodesP) {
-    
+
     if (bmhdP == NULL)
-        pm_error("%s chunk without %s chunk", 
+        pm_error("%s chunk without %s chunk",
                  ID2string(ID_BODY), ID2string(ID_BMHD));
 
     prepareCmap(bmhdP, cmap);
@@ -2132,12 +2148,12 @@ process_body( FILE *          const ifP,
 
         if( isdeepopt > 0 && (bmhdP->nPlanes % 3 != 0) ) {
             pm_message("cannot interpret %d-plane image as 'deep' "
-                       "(# of planes must be divisible by 3)", 
+                       "(# of planes must be divisible by 3)",
                        bmhdP->nPlanes);
             isdeep = 0;
         } else
             isdeep = isdeepopt;
-        
+
         if (isdeep > 0)
             deep_to_ppm(ifP, chunksize, bmhdP, cmap);
         else if (dcol)
@@ -2151,7 +2167,7 @@ process_body( FILE *          const ifP,
                 /* will be interpreted as grayscale */
                 std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP);
             else
-                pm_error("don't know how to interpret %d-plane image", 
+                pm_error("don't know how to interpret %d-plane image",
                          bmhdP->nPlanes);
         } else
             std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP);
@@ -2163,7 +2179,7 @@ process_body( FILE *          const ifP,
 
 
 
-static void 
+static void
 processChunk(FILE *          const ifP,
              long            const formsize,
              IFF_ID          const ignorelist[],
@@ -2200,7 +2216,7 @@ processChunk(FILE *          const ifP,
     } else if (iffid == ID_END) {
         /* END chunks are not officially valid in IFF, but
            suggested as a future expansion for stream-writing,
-           see Amiga RKM Devices, 3rd Ed, page 376 
+           see Amiga RKM Devices, 3rd Ed, page 376
         */
         if (chunksize != 0 ) {
             pm_message("warning - non-0 %s chunk", ID2string(iffid));
@@ -2212,7 +2228,7 @@ processChunk(FILE *          const ifP,
                        ID2string(iffid), formsize, 0xffffffff);
         *endchunkP = 1;
     } else if (*bodyChunkProcessedP) {
-        pm_message("%s chunk found after %s chunk - skipping", 
+        pm_message("%s chunk found after %s chunk - skipping",
                    ID2string(iffid), ID2string(ID_BODY));
         skip_chunk(ifP, iffid, chunksize);
     } else
@@ -2251,11 +2267,11 @@ processChunk(FILE *          const ifP,
             (*dcolP)->b = get_byte(ifP, iffid, NULL);
             get_byte(ifP, iffid, NULL);       /* skip pad byte */
             break;
-        case ID_BODY: 
+        case ID_BODY:
             if (cmaponly || (*bmhdP && (*bmhdP)->nPlanes == 0))
                 skip_chunk(ifP, ID_BODY,  chunksize);
             else {
-                process_body(ifP, chunksize, *bmhdP, cmap, 
+                process_body(ifP, chunksize, *bmhdP, cmap,
                              maskfile, fakeviewport, isdeepopt, *dcolP,
                              viewportmodesP);
 
@@ -2280,11 +2296,11 @@ processChunk(FILE *          const ifP,
             x = get_big_short(ifP, ID_DPI, NULL);
             y = get_big_short(ifP, ID_DPI, NULL);
             if (verbose)
-                pm_message("%s chunk:  dpi_x = %d    dpi_y = %d", 
+                pm_message("%s chunk:  dpi_x = %d    dpi_y = %d",
                            ID2string(ID_DPI), x, y);
         } break;
         default:
-            pm_message("unknown chunk type %s - skipping", 
+            pm_message("unknown chunk type %s - skipping",
                        ID2string(iffid));
             skip_chunk(ifP, iffid, chunksize);
             break;
@@ -2295,7 +2311,7 @@ processChunk(FILE *          const ifP,
     if (ODD(chunksize)) {
         get_byte(ifP, iffid, NULL);
         bytesread += 1;
-    } 
+    }
     *bytesReadP = bytesread;
 }
 
@@ -2338,7 +2354,7 @@ maybeWriteColorMap(FILE *               const ofP,
             prepareCmap(bmhdP, cmapP);
             cmapToPpm(ofP, cmapP);
         } else
-            pm_error("ILBM has neither %s or %s chunk", 
+            pm_error("ILBM has neither %s or %s chunk",
                      ID2string(ID_BODY), ID2string(ID_CMAP));
     }
 }
@@ -2413,13 +2429,13 @@ main(int argc, char *argv[]) {
                          "as argument");
             if( ignorecount >= MAX_IGNORE )
                 pm_error("max %d chunk IDs to ignore", MAX_IGNORE);
-            ignorelist[ignorecount++] = 
-                MAKE_ID(argv[argn][0], argv[argn][1], argv[argn][2], 
+            ignorelist[ignorecount++] =
+                MAKE_ID(argv[argn][0], argv[argn][1], argv[argn][2],
                         argv[argn][3]);
         } else
             pm_usage(usage);
         ++argn;
-    }    
+    }
 
     if( argn < argc ) {
         ifP = pm_openr( argv[argn] );
@@ -2439,7 +2455,7 @@ main(int argc, char *argv[]) {
         pm_error("input is not a FORM type IFF file");
     formsize = get_big_long(ifP, ID_FORM, NULL);
     typeid = get_big_long(ifP, ID_FORM, NULL);
-    if (typeid != ID_ILBM && typeid != ID_RGBN && typeid != ID_RGB8 && 
+    if (typeid != ID_ILBM && typeid != ID_RGBN && typeid != ID_RGB8 &&
         typeid != ID_PBM)
         pm_error("input is not an ILBM, RGBN, RGB8 or PBM "
                  "type FORM IFF file");
@@ -2474,7 +2490,7 @@ main(int argc, char *argv[]) {
 
     {
         unsigned int skipped;
-        
+
         for (skipped = 0; fgetc(ifP) != EOF; ++skipped)
             ++bytesread;
 
@@ -2492,3 +2508,6 @@ main(int argc, char *argv[]) {
 
     return 0;
 }
+
+
+
diff --git a/doc/HISTORY b/doc/HISTORY
index b1553f60..f26ccb32 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -4,10 +4,17 @@ Netpbm.
 CHANGE HISTORY 
 --------------
 
-18.06.28 BJH  Release 10.82.03
+18.06.30 BJH  Release 10.83.00
 
-              pbmmask: Fix invalid memory reference with zero-dimension
-              input image.  Broken in primordial Netpbm, ca 1989.
+              Add pamlevels.  Thanks Anton Shepelev <anton.txt@gmail.com>.
+
+              Add pamgetcolor.  Thanks Anton Shepelev <anton.txt@gmail.com>.
+
+              Add rgb-<maxval>:r/g/b color specification format.
+
+              pngtopam: Fix bogus warning of non-square pixels when image does
+              not contain pixel resolution information.  Introduced in Netpbm
+              10.48 (September 2009).
 
               pstopnm: Fix divide-by-zero crash when Postscript input says
               the image has zero size.
@@ -15,13 +22,21 @@ CHANGE HISTORY
               pstopnm: Fix divide-by-zero crash when computed resolution
               rounds down to zero dots per inch.
 
-18.06.27 BJH  Release 10.82.02
+              pbmmask: Fix invalid memory reference with zero-dimension
+              input image.  Broken in primordial Netpbm, ca 1989.
 
-              Pngtopam: Fix bogus warning of non-square pixels when image does
-              not contain pixel resolution information.  Introduced in Netpbm
-              10.48 (September 2009)
+              libnetpbm: Add pnm_colorspec_rgb_integer,
+              pnm_colorspec_rgb_norm, pnm_colorspec_rgb_x11,
+              pnm_colorspec_dict, pnm_colorspec_dict_close.
 
-18.04.28 BJH  Release 10.82.01
+              libnetpbm: Add pnm_parsecolor2.
+
+              libnetpbm: Add pnm_allocpamtuplen, pnm_freepamtuplen.
+              
+              libnetpbm: Make the normalized tuple functions respect the
+              allocation depth specified in struct pam (member
+              'allocation_depth') instead of using the actual tuple depth
+              (member 'depth').
 
               ilbmtoppm: Fix bug: may fail with bogus error message about an
               invalid CLUT chunk if image has a CLUT chunk.  Introduced after
@@ -156,6 +171,8 @@ CHANGE HISTORY
 
               ppmshadow: eliminate extraneous messages from pnmconvol.
 
+              libnetpbm: Add pnm_parsecolorn().
+
               libnetpbm: Improve error message for purported image that is
               exactly 1 byte long (so ends in the middle of what would be the
               magic number).
diff --git a/doc/TESTS b/doc/TESTS
index d2225164..ca4930a2 100644
--- a/doc/TESTS
+++ b/doc/TESTS
@@ -1,3 +1,5 @@
+Please cut and paste from below:
+---------------------------------------------------------------------------
 Contents
 ========
 
@@ -91,6 +93,7 @@ The tests use the following utilities:
  - grep
  - file
  - head
+ - iconv
  - mkdir
  - mktemp
  - rm
@@ -208,18 +211,23 @@ test/Execute-Tests:
 
   vg_command_base="valgrind --trace-children=yes"
 
-To run "valgrind --track-origins=yes", you must make two changes in
-config.mk:
+To get useful information from "--trace-origins=yes", you must make
+two changes to config.mk before compilation:
 
   - Add -g to CFLAGS
   - Turn stripping off: STRIPFLAG =
 
+Without these changes valgrind will report how many errors were
+detected, of what kind, and at what addresses (in binary).  With the
+above "-g" turned on during compilation valgrind reports source file
+and line numbers of detected problems.
+
 Valgrind significantly increases execution time.  If ordinary
 "make check" requires 10 seconds, "make check VALGRIND_TESTS=on"
 will require roughly 12 minutes, maybe more.  You should consider
 either setting "target=..." or paring down the items in Test-Order.
 In the latter case, you probably don't need to run "all-in-place.test"
-and "legacy-names.test".
+and "legacy-names.test"; consider commenting them out.
 
 The option "--trace-children-skip" is used to prevent valgrind from
 stepping into child processes that are not relevant.  This option
@@ -255,8 +263,8 @@ won't know and quite certainly you'll get failure messages.
 If you run the tests as "make check-install" information about
 configuration choices is deliberately ignored.  This is because the
 post-install check is typically run on systems with multiple versions
-of Netpbm and in this case users want to get a clear idea of absent
-components.
+of Netpbm and in this case most users would want to get a clear idea
+of absent components.
 
 For details on the effects of missing libraries, read
 'Netpbm Library Prerequisites':
@@ -281,6 +289,9 @@ When a test fails, a ".out" file will be produced in the
 can tell exactly what went wrong.  Often one does not need to
 go this far; the error messages tell enough.
 
+In some cases the ".ok" file is generated dynamically.  See "2.5
+System Dependent Issues."
+
 
 
 2.3 Color dictionary file
@@ -345,22 +356,33 @@ the tests on installed Netpbm programs, regardless of the version:
    ./configure           # accept the defaults
    make check-install
 
+As of this writing (April 2018) Debian is working on resolving the
+fork.  A new version, tagged as "experimental", based on the Sourceforge
+line of source files is available.
+
+
 
 2.5 System dependent issues
 ===========================
 
-The tests have worked on x86 and x86_64 GNU/Linux systems, with several
-versions of GCC and Clang.  Reports from users of other systems including Mac
-OS, Sun SPARC and BSD and compilers other than GCC are highly welcome.
+The tests have worked on x86 and x86_64 GNU/Linux systems and with several
+versions of GCC and Clang and also Mac OS/Clang.  Reports from users of
+other systems including OS, Sun SPARC and BSD and compilers other than
+GCC are highly welcome.
 
 Floating point math precision seems to be an issue.  Some discrepancies
 have been observed between x86 32 bit and 64 bit; the tests are written to
 work around them as much as possible.  The use of the "--fast-math"
-flag by default may also be a factor.
+c compiler flag by default may also be a factor.
+
+Another cause of discrepancies is the qsort function.  The tests are
+written to circumvent this issue at some cost to accuracy and
+coverage.
 
-The current test framework checks whether the random number generator
-is the one from glibc and skips certain tests if a different one is
-detected.
+The test directory Makefile checks whether the random number generator
+is the one from glibc or Mac OS and automatically generates the proper
+".ok" files from master files with the suffix ".rand-ok".  If some other
+random number generator is detected the affected tests are skipped.
 
 
 
@@ -370,3 +392,7 @@ detected.
 When reporting problems with the tests, please give both
 the output of "make check" and the contents of the "netpbm-test"
 directory.
+
+
+
+
diff --git a/editor/Makefile b/editor/Makefile
index 39329f00..d7d71bf6 100644
--- a/editor/Makefile
+++ b/editor/Makefile
@@ -19,7 +19,7 @@ SUBDIRS = pamflip specialty
 PORTBINARIES = pamaddnoise pambackground pamcomp pamcut \
 	       pamdice pamditherbw pamedge \
 	       pamenlarge \
-	       pamfunc pammasksharpen \
+	       pamfunc pamlevels pammasksharpen \
 	       pamperspective pamrecolor pamrubber \
 	       pamscale pamsistoaglyph pamstretch pamthreshold pamundice \
 	       pamwipeout \
diff --git a/editor/pamcomp.c b/editor/pamcomp.c
index 332acac3..0732b92f 100644
--- a/editor/pamcomp.c
+++ b/editor/pamcomp.c
@@ -6,13 +6,13 @@
    This program is derived from (and replaces) Pnmcomp, whose origin is
    as follows:
 
-       Copyright 1992, David Koblas.                                    
-         Permission to use, copy, modify, and distribute this software  
+       Copyright 1992, David Koblas.
+         Permission to use, copy, modify, and distribute this software
          and its documentation for any purpose and without fee is hereby
          granted, provided that the above copyright notice appear in all
-         copies and that both that copyright notice and this permission 
-         notice appear in supporting documentation.  This software is   
-         provided "as is" without express or implied warranty.          
+         copies and that both that copyright notice and this permission
+         notice appear in supporting documentation.  This software is
+         provided "as is" without express or implied warranty.
 
    No code from the original remains in the present version.  The
    January 2004 version was coded entirely by Bryan Henderson.
@@ -40,11 +40,11 @@ enum vertPos {ABOVE, TOP, MIDDLE, BOTTOM, BELOW};
 
 enum sampleScale {INTENSITY_SAMPLE, GAMMA_SAMPLE};
     /* This indicates a scale for a PAM sample value.  INTENSITY_SAMPLE means
-       the value is proportional to light intensity; GAMMA_SAMPLE means the 
+       the value is proportional to light intensity; GAMMA_SAMPLE means the
        value is gamma-adjusted as defined in the PGM/PPM spec.  In both
        scales, the values are continuous and normalized to the range 0..1.
-       
-       This scale has no meaning if the PAM is not a visual image.  
+
+       This scale has no meaning if the PAM is not a visual image.
     */
 
 enum alphaMix {AM_KEEPUNDER, AM_OVERLAY};
@@ -84,12 +84,12 @@ struct cmdlineInfo {
 
 
 static void
-parseCommandLine(int                        argc, 
+parseCommandLine(int                        argc,
                  const char **              argv,
                  struct cmdlineInfo * const cmdlineP ) {
 /*----------------------------------------------------------------------------
    Parse program command line described in Unix standard form by argc
-   and argv.  Return the information in the options as *cmdlineP.  
+   and argv.  Return the information in the options as *cmdlineP.
 
    If command line is internally inconsistent (invalid options, etc.),
    issue error message to stderr and abort program.
@@ -111,11 +111,11 @@ parseCommandLine(int                        argc,
     MALLOCARRAY_NOFAIL(option_def, 100);
 
     option_def_index = 0;   /* incremented by OPTENT3 */
-    OPTENT3(0, "invert",             OPT_FLAG,   NULL,                  
+    OPTENT3(0, "invert",             OPT_FLAG,   NULL,
             &cmdlineP->alphaInvert,       0);
-    OPTENT3(0, "xoff",               OPT_INT,    &cmdlineP->xoff,       
+    OPTENT3(0, "xoff",               OPT_INT,    &cmdlineP->xoff,
             &xoffSpec,                    0);
-    OPTENT3(0, "yoff",               OPT_INT,    &cmdlineP->yoff,       
+    OPTENT3(0, "yoff",               OPT_INT,    &cmdlineP->yoff,
             &yoffSpec,                    0);
     OPTENT3(0, "opacity",            OPT_FLOAT,  &cmdlineP->opacity,
             &opacitySpec,                 0);
@@ -125,9 +125,9 @@ parseCommandLine(int                        argc,
             &alignSpec,                   0);
     OPTENT3(0, "valign",             OPT_STRING, &valign,
             &valignSpec,                  0);
-    OPTENT3(0, "linear",             OPT_FLAG,   NULL,       
+    OPTENT3(0, "linear",             OPT_FLAG,   NULL,
             &cmdlineP->linear,            0);
-    OPTENT3(0, "mixtransparency",    OPT_FLAG,   NULL,       
+    OPTENT3(0, "mixtransparency",    OPT_FLAG,   NULL,
             &cmdlineP->mixtransparency,   0);
 
     opt.opt_table = option_def;
@@ -158,9 +158,9 @@ parseCommandLine(int                        argc,
             cmdlineP->align = BEYONDRIGHT;
         else
             pm_error("Invalid value for align option: '%s'.  Only LEFT, "
-                     "RIGHT, CENTER, BEYONDLEFT, and BEYONDRIGHT are valid.", 
+                     "RIGHT, CENTER, BEYONDLEFT, and BEYONDRIGHT are valid.",
                      align);
-    } else 
+    } else
         cmdlineP->align = LEFT;
 
     if (valignSpec) {
@@ -176,12 +176,12 @@ parseCommandLine(int                        argc,
             cmdlineP->valign = BELOW;
         else
             pm_error("Invalid value for valign option: '%s'.  Only TOP, "
-                     "BOTTOM, MIDDLE, ABOVE, and BELOW are valid.", 
+                     "BOTTOM, MIDDLE, ABOVE, and BELOW are valid.",
                      align);
-    } else 
+    } else
         cmdlineP->valign = TOP;
 
-    if (!opacitySpec) 
+    if (!opacitySpec)
         cmdlineP->opacity = 1.0;
 
     if (argc-1 < 1)
@@ -219,7 +219,7 @@ commonFormat(int const formatA,
 
     int const typeA = PAM_FORMAT_TYPE(formatA);
     int const typeB = PAM_FORMAT_TYPE(formatB);
-    
+
     if (typeA == PAM_TYPE || typeB == PAM_TYPE)
         retval = PAM_FORMAT;
     else if (typeA == PPM_TYPE || typeB == PPM_TYPE)
@@ -242,7 +242,7 @@ typedef enum { TT_BLACKANDWHITE, TT_GRAYSCALE, TT_RGB } BaseTupletype;
 
 
 static BaseTupletype
-commonTupletype(const char * const tupletypeA, 
+commonTupletype(const char * const tupletypeA,
                 const char * const tupletypeB) {
 
     if (strneq(tupletypeA, "RGB", 3) ||
@@ -300,11 +300,11 @@ determineOutputType(const struct pam * const underlayPamP,
     composedPamP->height = underlayPamP->height;
     composedPamP->width  = underlayPamP->width;
 
-    composedPamP->format = commonFormat(underlayPamP->format, 
+    composedPamP->format = commonFormat(underlayPamP->format,
                                         overlayPamP->format);
     composedPamP->plainformat = FALSE;
 
-    composedPamP->maxval = pm_lcm(underlayPamP->maxval, overlayPamP->maxval, 
+    composedPamP->maxval = pm_lcm(underlayPamP->maxval, overlayPamP->maxval,
                                   1, PNM_OVERALLMAXVAL);
 
     composedPamP->visual = true;
@@ -325,7 +325,7 @@ determineOutputType(const struct pam * const underlayPamP,
 
 static void
 warnOutOfFrame(int const originLeft,
-               int const originTop, 
+               int const originTop,
                int const overCols,
                int const overRows,
                int const underCols,
@@ -362,7 +362,7 @@ warnOutOfFrame(int const originLeft,
 
 
 static void
-validateComputableHeight(int const originTop, 
+validateComputableHeight(int const originTop,
                          int const overRows) {
 
     if (originTop < 0) {
@@ -381,11 +381,11 @@ validateComputableHeight(int const originTop,
 
 
 static void
-computeOverlayPosition(int                const underCols, 
+computeOverlayPosition(int                const underCols,
                        int                const underRows,
-                       int                const overCols, 
+                       int                const overCols,
                        int                const overRows,
-                       struct cmdlineInfo const cmdline, 
+                       struct cmdlineInfo const cmdline,
                        int *              const originLeftP,
                        int *              const originTopP) {
 /*----------------------------------------------------------------------------
@@ -421,8 +421,8 @@ computeOverlayPosition(int                const underCols,
 
     validateComputableHeight(*originTopP, overRows);
 
-    warnOutOfFrame(*originLeftP, *originTopP, 
-                   overCols, overRows, underCols, underRows);    
+    warnOutOfFrame(*originLeftP, *originTopP,
+                   overCols, overRows, underCols, underRows);
 }
 
 
@@ -484,7 +484,7 @@ computeOverlayPosition(int                const underCols,
 
 
 static sample
-composeComponents(sample           const compA, 
+composeComponents(sample           const compA,
                   sample           const compB,
                   float            const distrib,
                   float            const bFactor,
@@ -508,7 +508,7 @@ composeComponents(sample           const compA,
   useful.
 
   The inputs and result are based on a maxval of 'maxval'.
-  
+
   Note that while 'distrib' in the straightforward case is always in
   [0,1], it can in fact be negative or greater than 1.  We clip the
   result as required to return a legal sample value.
@@ -520,7 +520,7 @@ composeComponents(sample           const compA,
         retval = compA;
     else {
         if (sampleScale == INTENSITY_SAMPLE) {
-            sample const mix = 
+            sample const mix =
                 ROUNDU(compA * distrib + compB * bFactor *(1.0 - distrib));
             retval = MIN(maxval, MAX(0, mix));
         } else {
@@ -529,7 +529,7 @@ composeComponents(sample           const compA,
             float const compALinear = pm_ungamma709(compANormalized);
             float const compBLinear = pm_ungamma709(compBNormalized);
             float const compBLinearAdj = compBLinear * bFactor;
-            float const mix = 
+            float const mix =
                 compALinear * distrib + compBLinearAdj * (1.0 - distrib)
                 * composedFactor;
             sample const sampleValue = ROUNDU(pm_gamma709(mix) * maxval);
@@ -624,13 +624,13 @@ overlayPixel(tuple            const overlayTuple,
         /* Part of formula for AM_OVERLAY -- see explanation above */
 
     overlayWeight = masterOpacity;  /* initial value */
-    
+
     if (overlayPamP->have_opacity)
         overlayWeight *= (float)
             overlayTuple[overlayPamP->opacity_plane] / overlayPamP->maxval;
-    
+
     if (alphaTuplen) {
-        float const alphaval = 
+        float const alphaval =
             invertAlpha ? (1.0 - alphaTuplen[0]) : alphaTuplen[0];
         overlayWeight *= alphaval;
     }
@@ -645,7 +645,7 @@ overlayPixel(tuple            const overlayTuple,
         float  const uOpacityN = uOpacity / uMaxval;
         float  const oOpacityN = oOpacity / oMaxval;
         float  const composedTrans = (1.0 - uOpacityN) * (1.0 * oOpacityN);
-        
+
         if (composedTrans > .999) {
             underlayWeight = 1.0;
             composedWeight = 1.0;
@@ -659,10 +659,10 @@ overlayPixel(tuple            const overlayTuple,
     }
     {
         unsigned int plane;
-        
+
         for (plane = 0; plane < composedPamP->color_depth; ++plane)
-            composedTuple[plane] = 
-                composeComponents(overlayTuple[plane], underlayTuple[plane], 
+            composedTuple[plane] =
+                composeComponents(overlayTuple[plane], underlayTuple[plane],
                                   overlayWeight, underlayWeight,
                                   composedWeight,
                                   composedPamP->maxval,
@@ -707,7 +707,7 @@ adaptRowFormat(struct pam * const inpamP,
 
 
 static void
-composeRow(int              const originleft, 
+composeRow(int              const originleft,
            struct pam *     const underlayPamP,
            struct pam *     const overlayPamP,
            bool             const invertAlpha,
@@ -732,7 +732,7 @@ composeRow(int              const originleft,
         int const ovlcol = col - originleft;
 
         if (ovlcol >= 0 && ovlcol < overlayPamP->width) {
-            tuplen const alphaTuplen = 
+            tuplen const alphaTuplen =
                 alphaTuplerown ? alphaTuplerown[ovlcol] : NULL;
 
             overlayPixel(overlayTuplerow[ovlcol], overlayPamP,
@@ -799,8 +799,8 @@ determineInputAdaptations(const struct pam * const underlayPamP,
 
 
 static void
-composite(int          const originleft, 
-          int          const origintop, 
+composite(int          const originleft,
+          int          const origintop,
           struct pam * const underlayPamP,
           struct pam * const overlayPamP,
           struct pam * const alphaPamP,
@@ -829,7 +829,7 @@ composite(int          const originleft,
    We assume that the span from the topmost row of the two images to
    the bottommost row is less than INT_MAX.
 -----------------------------------------------------------------------------*/
-    enum sampleScale const sampleScale = 
+    enum sampleScale const sampleScale =
         assumeLinear ? INTENSITY_SAMPLE : GAMMA_SAMPLE;
     enum alphaMix const alphaMix =
         mixTransparency ? AM_OVERLAY : AM_KEEPUNDER;
@@ -859,7 +859,7 @@ composite(int          const originleft,
     assert(INT_MAX - overlayPamP->height > origintop); /* arg constraint */
 
     for (underlayRow = MIN(0, origintop), overlayRow = MIN(0, -origintop);
-         underlayRow < MAX(underlayPamP->height, 
+         underlayRow < MAX(underlayPamP->height,
                            origintop + overlayPamP->height);
          ++underlayRow, ++overlayRow) {
 
@@ -872,19 +872,19 @@ composite(int          const originleft,
         if (underlayRow >= 0 && underlayRow < underlayPamP->height) {
             pnm_readpamrow(underlayPamP, underlayTuplerow);
             adaptRowFormat(underlayPamP, &adaptUnderlayPam, underlayTuplerow);
-            if (underlayRow < origintop || 
+            if (underlayRow < origintop ||
                 underlayRow >= origintop + overlayPamP->height) {
-            
+
                 /* Overlay image does not touch this underlay row. */
 
                 pnm_writepamrow(composedPamP, underlayTuplerow);
             } else {
                 composeRow(originleft, &adaptUnderlayPam, &adaptOverlayPam,
-                           invertAlpha, masterOpacity, 
+                           invertAlpha, masterOpacity,
                            composedPamP, sampleScale, alphaMix,
                            underlayTuplerow, overlayTuplerow, alphaTuplerown,
                            composedTuplerow);
-                
+
                 pnm_writepamrow(composedPamP, composedTuplerow);
             }
         }
@@ -905,13 +905,13 @@ initAlphaFile(struct cmdlineInfo const cmdline,
               struct pam *       const pamP) {
 
     FILE * fileP;
-    
+
     if (cmdline.alphaFilespec) {
         fileP = pm_openr(cmdline.alphaFilespec);
         pamP->comment_p = NULL;
         pnm_readpaminit(fileP, pamP, PAM_STRUCT_SIZE(opacity_plane));
 
-        if (overlayPamP->width != pamP->width || 
+        if (overlayPamP->width != pamP->width ||
             overlayPamP->height != pamP->height)
             pm_error("Opacity map and overlay image are not the same size");
     } else
@@ -942,7 +942,7 @@ main(int argc, const char *argv[]) {
     overlayFileP = pm_openr(cmdline.overlayFilespec);
 
     overlayPam.comment_p = NULL;
-    pnm_readpaminit(overlayFileP, &overlayPam, 
+    pnm_readpaminit(overlayFileP, &overlayPam,
                     PAM_STRUCT_SIZE(opacity_plane));
 
     if (overlayPam.len < PAM_STRUCT_SIZE(opacity_plane))
@@ -959,7 +959,7 @@ main(int argc, const char *argv[]) {
     underlayFileP = pm_openr(cmdline.underlyingFilespec);
 
     underlayPam.comment_p = NULL;
-    pnm_readpaminit(underlayFileP, &underlayPam, 
+    pnm_readpaminit(underlayFileP, &underlayPam,
                     PAM_STRUCT_SIZE(opacity_plane));
 
     assert(underlayPam.len >= PAM_STRUCT_SIZE(opacity_plane));
@@ -968,8 +968,8 @@ main(int argc, const char *argv[]) {
         pm_error("Overlay image has tuple type '%s', which is not a "
                  "standard visual type.  We don't know how to compose.",
                  overlayPam.tuple_type);
-    
-    computeOverlayPosition(underlayPam.width, underlayPam.height, 
+
+    computeOverlayPosition(underlayPam.width, underlayPam.height,
                            overlayPam.width,  overlayPam.height,
                            cmdline, &originLeft, &originTop);
 
@@ -983,7 +983,7 @@ main(int argc, const char *argv[]) {
 
     pnm_setminallocationdepth(&underlayPam, composedPam.depth);
     pnm_setminallocationdepth(&overlayPam,  composedPam.depth);
-    
+
     composite(originLeft, originTop,
               &underlayPam, &overlayPam, alphaFileP ? &alphaPam : NULL,
               cmdline.alphaInvert, cmdline.opacity,
diff --git a/editor/pamflip/flip.h b/editor/pamflip/flip.h
index 612a7f84..ace93044 100644
--- a/editor/pamflip/flip.h
+++ b/editor/pamflip/flip.h
@@ -1,7 +1,7 @@
 #ifndef FLIP_H_INCLUDED
 #define FLIP_H_INCLUDED
 
-struct xformCore {
+struct XformCore {
     /* a b
        c d
     */
diff --git a/editor/pamflip/pamflip.c b/editor/pamflip/pamflip.c
index e6f1d6ed..bc752208 100644
--- a/editor/pamflip/pamflip.c
+++ b/editor/pamflip/pamflip.c
@@ -13,9 +13,9 @@
 /*
    transformNonPbmChunk() is the general transformation function.
    It can transform anything, albeit slowly and expensively.
-   
+
    The following are enhancements for specific cases:
-   
+
      transformRowByRowPbm():
        PBM image with left-right or null transformation
      transformRowsBottomTopPbm()
@@ -77,12 +77,12 @@
 #include "flip.h"
 #include "pamflip_sse.h"
 
-enum xformType {LEFTRIGHT, TOPBOTTOM, TRANSPOSE};
+enum XformType {LEFTRIGHT, TOPBOTTOM, TRANSPOSE};
 
 static void
 parseXformOpt(const char *     const xformOpt,
               unsigned int  *  const xformCountP,
-              enum xformType * const xformList) {
+              enum XformType * const xformList) {
 /*----------------------------------------------------------------------------
    Translate the -xform option string into an array of transform types.
 
@@ -93,10 +93,10 @@ parseXformOpt(const char *     const xformOpt,
     char * xformOptWork;
     char * cursor;
     bool eol;
-    
+
     xformOptWork = strdup(xformOpt);
     cursor = &xformOptWork[0];
-    
+
     eol = FALSE;    /* initial value */
     xformCount = 0; /* initial value */
     while (!eol && xformCount < 10) {
@@ -125,13 +125,13 @@ parseXformOpt(const char *     const xformOpt,
 
 
 /* See transformPoint() for an explanation of the transform matrix types.  The
-   difference between xformCore and xformMatrix is that 'xformCore' is
+   difference between XformCore and XformMatrix is that 'XformCore' is
    particular to the source image dimensions and can be used to do the
-   transformation, while 'xformCore' is independent of the source image and
+   transformation, while 'XformCore' is independent of the source image and
    just tells what kind of transformation.
 */
 
-struct xformMatrix {
+struct XformMatrix {
     /* a b 0
        c d 0
        e f 1
@@ -147,7 +147,7 @@ struct xformMatrix {
 
 
 static void
-leftright(struct xformCore * const xformP) {
+leftright(struct XformCore * const xformP) {
     xformP->a = - xformP->a;
     xformP->c = - xformP->c;
 }
@@ -155,7 +155,7 @@ leftright(struct xformCore * const xformP) {
 
 
 static void
-topbottom(struct xformCore * const xformP) {
+topbottom(struct XformCore * const xformP) {
     xformP->b = - xformP->b;
     xformP->d = - xformP->d;
 }
@@ -174,7 +174,7 @@ swap(int * const xP, int * const yP) {
 
 
 static void
-transpose(struct xformCore * const xformP) {
+transpose(struct XformCore * const xformP) {
     swap(&xformP->a, &xformP->b);
     swap(&xformP->c, &xformP->d);
 }
@@ -183,18 +183,18 @@ transpose(struct xformCore * const xformP) {
 
 static void
 computeXformCore(unsigned int       const xformCount,
-                 enum xformType     const xformType[],
-                 struct xformCore * const xformP) {
-    
-    struct xformCore const nullTransform = {1, 0, 0, 1};
+                 enum XformType     const XformType[],
+                 struct XformCore * const xformP) {
+
+    struct XformCore const nullTransform = {1, 0, 0, 1};
 
     unsigned int i;
 
     *xformP = nullTransform;   /* initial value */
 
     for (i = 0; i < xformCount; ++i) {
-        switch (xformType[i]) {
-        case LEFTRIGHT: 
+        switch (XformType[i]) {
+        case LEFTRIGHT:
             leftright(xformP);
             break;
         case TOPBOTTOM:
@@ -210,7 +210,7 @@ computeXformCore(unsigned int       const xformCount,
 
 
 static void
-xformDimensions(struct xformCore const xform,
+xformDimensions(struct XformCore const xform,
                 unsigned int     const inCols,
                 unsigned int     const inRows,
                 unsigned int *   const outColsP,
@@ -222,25 +222,25 @@ xformDimensions(struct xformCore const xform,
    E.g. if it's a 90 degree rotation of a 10 x 20 image, the output is
    a 20 x 10 image.
 -----------------------------------------------------------------------------*/
-    *outColsP = abs(xform.a * inCols + xform.c * inRows);
-    *outRowsP = abs(xform.b * inCols + xform.d * inRows);
+    *outColsP = abs(xform.a * (int)inCols + xform.c * (int)inRows);
+    *outRowsP = abs(xform.b * (int)inCols + xform.d * (int)inRows);
 }
 
 
 
 static void
-computeXformMatrix(struct xformMatrix * const xformP, 
+computeXformMatrix(struct XformMatrix * const xformP,
                    unsigned int         const sourceCols,
                    unsigned int         const sourceRows,
-                   struct xformCore     const xformCore) {
+                   struct XformCore     const XformCore) {
 
-    int colMax = xformCore.a * (sourceCols-1) + xformCore.c * (sourceRows-1);
-    int rowMax = xformCore.b * (sourceCols-1) + xformCore.d * (sourceRows-1);
+    int colMax = XformCore.a * (sourceCols-1) + XformCore.c * (sourceRows-1);
+    int rowMax = XformCore.b * (sourceCols-1) + XformCore.d * (sourceRows-1);
 
-    xformP->a = xformCore.a;
-    xformP->b = xformCore.b;
-    xformP->c = xformCore.c;
-    xformP->d = xformCore.d;
+    xformP->a = XformCore.a;
+    xformP->b = XformCore.b;
+    xformP->c = XformCore.c;
+    xformP->d = XformCore.d;
     xformP->e = colMax < 0 ? -colMax : 0;
     xformP->f = rowMax < 0 ? -rowMax : 0;
 }
@@ -252,7 +252,7 @@ struct cmdlineInfo {
        in a form easy for the program to use.
     */
     const char * inputFilespec;  /* Filespec of input file */
-    struct xformCore xform;
+    struct XformCore xform;
         /* Handy mathematical representation of all of transform options */
     size_t availableMemory;
     unsigned int pageSize;
@@ -272,7 +272,7 @@ interpretMemorySize(unsigned int const memsizeSpec,
     if (memsizeSpec) {
         if (memsizeOpt > sizeMax / Meg)
             pm_error("-memsize value too large: %u MiB.  Maximum this program "
-                     "can handle is %u MiB", 
+                     "can handle is %u MiB",
                      memsizeOpt, (unsigned)sizeMax / Meg);
         *availableMemoryP = memsizeOpt * Meg;
     } else
@@ -300,8 +300,8 @@ parseCommandLine(int argc, char ** const argv,
     unsigned int memsizeOpt;
     const char * xformOpt;
     unsigned int xformCount;
-        /* Number of transforms in the 'xformType' array */
-    enum xformType xformList[10];
+        /* Number of transforms in the 'XformType' array */
+    enum XformType xformList[10];
         /* Array of transforms to be applied, in order */
 
     MALLOCARRAY(option_def, 100);
@@ -323,11 +323,11 @@ parseCommandLine(int argc, char ** const argv,
     OPTENT3(0, "cw",        OPT_FLAG,    NULL, &r270,    0);
     OPTENT3(0, "null",      OPT_FLAG,    NULL, &null,    0);
     OPTENT3(0, "verbose",   OPT_FLAG,    NULL, &cmdlineP->verbose,       0);
-    OPTENT3(0, "memsize",   OPT_UINT,    &memsizeOpt, 
+    OPTENT3(0, "memsize",   OPT_UINT,    &memsizeOpt,
             &memsizeSpec,       0);
     OPTENT3(0, "pagesize",  OPT_UINT,    &cmdlineP->pageSize,
             &pagesizeSpec,      0);
-    OPTENT3(0, "xform",     OPT_STRING,  &xformOpt, 
+    OPTENT3(0, "xform",     OPT_STRING,  &xformOpt,
             &xformSpec, 0);
 
     opt.opt_table = option_def;
@@ -364,20 +364,20 @@ parseCommandLine(int argc, char ** const argv,
         } else if (null) {
             xformCount = 0;
         }
-    } else if (xformSpec) 
+    } else if (xformSpec)
         parseXformOpt(xformOpt, &xformCount, xformList);
     else
         pm_error("You must specify an option such as -topbottom to indicate "
                  "what kind of flip you want.");
 
     computeXformCore(xformCount, xformList, &cmdlineP->xform);
-    
+
     interpretMemorySize(memsizeSpec, memsizeOpt, &cmdlineP->availableMemory);
 
     if (!pagesizeSpec)
-        cmdlineP->pageSize = 4*1024;         
+        cmdlineP->pageSize = 4*1024;
 
-    if (argc-1 == 0) 
+    if (argc-1 == 0)
         cmdlineP->inputFilespec = "-";
     else if (argc-1 != 1)
         pm_error("Program takes zero or one argument (filename).  You "
@@ -391,7 +391,7 @@ parseCommandLine(int argc, char ** const argv,
 
 
 static void
-bitOrderReverse(unsigned char * const bitrow, 
+bitOrderReverse(unsigned char * const bitrow,
                 unsigned int    const cols) {
 /*----------------------------------------------------------------------------
   Reverse the bits in a packed pbm row (1 bit per pixel).  I.e. the leftmost
@@ -413,12 +413,12 @@ bitOrderReverse(unsigned char * const bitrow,
             if ((bitrow[j] | bitrow[i]) == 0) {
                 /* Both are 0x00 - skip */
             } else {
-                unsigned char const t = bitreverse[bitrow[j]]; 
+                unsigned char const t = bitreverse[bitrow[j]];
                 bitrow[j] = bitreverse[bitrow[i]];
                 bitrow[i] = t;
             }
     } else {
-        unsigned int const m = cols % 8; 
+        unsigned int const m = cols % 8;
 
         unsigned int i, j;
             /* Cursors into bitrow[].  i moves from left to center;
@@ -431,7 +431,7 @@ bitOrderReverse(unsigned char * const bitrow,
                 /* Skip if both are 0x00 */
                 th = bitreverse[bitrow[i]];
                 bitrow[i] =
-                    bitreverse[0xff & ((bitrow[j-1] << 8 
+                    bitreverse[0xff & ((bitrow[j-1] << 8
                                         | bitrow[j]) >> (8-m))];
                 bitrow[j] = 0xff & ((th << 8 | tl) >> m);
                 tl = th;
@@ -450,7 +450,7 @@ bitOrderReverse(unsigned char * const bitrow,
 
 
 static void
-transformRowByRowPbm(struct pam * const inpamP, 
+transformRowByRowPbm(struct pam * const inpamP,
                      struct pam * const outpamP,
                      bool         const reverse) {
 /*----------------------------------------------------------------------------
@@ -464,7 +464,7 @@ transformRowByRowPbm(struct pam * const inpamP,
     unsigned char * bitrow;
     unsigned int row;
 
-    bitrow = pbm_allocrow_packed(outpamP->width); 
+    bitrow = pbm_allocrow_packed(outpamP->width);
 
     for (row = 0; row < inpamP->height; ++row) {
         pbm_readpbmrow_packed(inpamP->file,  bitrow, inpamP->width,
@@ -481,7 +481,7 @@ transformRowByRowPbm(struct pam * const inpamP,
 
 
 static void
-transformRowByRowNonPbm(struct pam * const inpamP, 
+transformRowByRowNonPbm(struct pam * const inpamP,
                         struct pam * const outpamP,
                         bool         const reverse) {
 /*----------------------------------------------------------------------------
@@ -500,20 +500,20 @@ transformRowByRowNonPbm(struct pam * const inpamP,
            itself.
         */
     tuple * scratchTuplerow;
-    
+
     unsigned int row;
-    
+
     tuplerow = pnm_allocpamrow(inpamP);
-    
+
     if (reverse) {
         /* Set up newtuplerow[] to point to the tuples of tuplerow[] in
            reverse order.
         */
         unsigned int col;
-        
+
         MALLOCARRAY_NOFAIL(scratchTuplerow, inpamP->width);
 
-        for (col = 0; col < inpamP->width; ++col) 
+        for (col = 0; col < inpamP->width; ++col)
             scratchTuplerow[col] = tuplerow[inpamP->width - col - 1];
         newtuplerow = scratchTuplerow;
     } else {
@@ -524,7 +524,7 @@ transformRowByRowNonPbm(struct pam * const inpamP,
         pnm_readpamrow(inpamP, tuplerow);
         pnm_writepamrow(outpamP, newtuplerow);
     }
-    
+
     if (scratchTuplerow)
         free(scratchTuplerow);
     pnm_freepamrow(tuplerow);
@@ -535,7 +535,7 @@ transformRowByRowNonPbm(struct pam * const inpamP,
 static void
 transformRowsBottomTopPbm(struct pam * const inpamP,
                           struct pam * const outpamP,
-                          bool         const reverse) { 
+                          bool         const reverse) {
 /*----------------------------------------------------------------------------
   Flip a PBM raster top for bottom; read the raster from *inpamP;
   write the flipped raster to *outpamP.
@@ -547,15 +547,15 @@ transformRowsBottomTopPbm(struct pam * const inpamP,
 
     unsigned char ** bitrow;
     unsigned int row;
-        
+
     bitrow = pbm_allocarray_packed(outpamP->width, outpamP->height);
-        
+
     for (row = 0; row < rows; ++row)
-        pbm_readpbmrow_packed(inpamP->file, bitrow[row], 
+        pbm_readpbmrow_packed(inpamP->file, bitrow[row],
                               inpamP->width, inpamP->format);
 
     for (row = 0; row < rows; ++row) {
-        if (reverse) 
+        if (reverse)
             bitOrderReverse(bitrow[rows-row-1], inpamP->width);
 
         pbm_writepbmrow_packed(outpamP->file, bitrow[rows - row - 1],
@@ -567,7 +567,7 @@ transformRowsBottomTopPbm(struct pam * const inpamP,
 
 
 static void
-transformRowsBottomTopNonPbm(struct pam * const inpamP, 
+transformRowsBottomTopNonPbm(struct pam * const inpamP,
                              struct pam * const outpamP) {
 /*----------------------------------------------------------------------------
   Do a simple vertical flip.  Read the raster from *inpamP; write the
@@ -593,17 +593,17 @@ transformRowsBottomTopNonPbm(struct pam * const inpamP,
 
         pnm_writepamrow(outpamP, tuplerow);
     }
-    
+
     pnm_freepamarray(tuplerows, outpamP);
 }
 
 
 
 static void __inline__
-transformPoint(int                const col, 
-               int                const row, 
-               struct xformMatrix const xform, 
-               unsigned int *     const newcolP, 
+transformPoint(int                const col,
+               int                const row,
+               struct XformMatrix const xform,
+               unsigned int *     const newcolP,
                unsigned int *     const newrowP ) {
 /*----------------------------------------------------------------------------
    Compute the location in the output of a pixel that is at row 'row',
@@ -613,7 +613,7 @@ transformPoint(int                const col,
    Return the output image location of the pixel as *newcolP and *newrowP.
 -----------------------------------------------------------------------------*/
     /* The transformation is:
-     
+
                  [ a b 0 ]
        [ x y 1 ] [ c d 0 ] = [ x2 y2 1 ]
                  [ e f 1 ]
@@ -653,9 +653,9 @@ writeRaster(struct pam *    const pamP,
 static void
 transformPbmGen(struct pam *     const inpamP,
                 struct pam *     const outpamP,
-                struct xformCore const xformCore) { 
+                struct XformCore const XformCore) {
 /*----------------------------------------------------------------------------
-   This is the same as transformGen, except that it uses less 
+   This is the same as transformGen, except that it uses less
    memory, since the PBM buffer format uses one bit per pixel instead
    of twelve bytes + pointer space
 
@@ -665,28 +665,28 @@ transformPbmGen(struct pam *     const inpamP,
 -----------------------------------------------------------------------------*/
     bit * bitrow;
     bit ** newbits;
-    struct xformMatrix xform;
+    struct XformMatrix xform;
     unsigned int row;
-            
-    computeXformMatrix(&xform, inpamP->width, inpamP->height, xformCore);
-    
+
+    computeXformMatrix(&xform, inpamP->width, inpamP->height, XformCore);
+
     bitrow = pbm_allocrow_packed(inpamP->width);
     newbits = pbm_allocarray_packed( outpamP->width, outpamP->height );
-            
+
     /* Initialize entire array to zeroes.  One bits will be or'ed in later */
     for (row = 0; row < outpamP->height; ++row) {
         unsigned int col;
-        for (col = 0; col < pbm_packed_bytes(outpamP->width); ++col) 
-            newbits[row][col] = 0; 
+        for (col = 0; col < pbm_packed_bytes(outpamP->width); ++col)
+            newbits[row][col] = 0;
     }
-    
+
     for (row = 0; row < inpamP->height; ++row) {
         unsigned int col;
 
         pbm_readpbmrow_packed(inpamP->file, bitrow,
                               inpamP->width, inpamP->format);
         for (col = 0; col < inpamP->width; ) {
-            if (bitrow[col/8] == 0x00) 
+            if (bitrow[col/8] == 0x00)
                 col += 8;  /* Blank.   Skip to next byte. */
             else {      /* Examine each pixel. */
                 unsigned int const colLimit = MIN(col+8, inpamP->width);
@@ -695,7 +695,7 @@ transformPbmGen(struct pam *     const inpamP,
                 for (i = 0; col < colLimit; ++i, ++col) {
                     bool const bitIsOne = (bitrow[col/8] >> (7-i)) & 0x01;
                     if (bitIsOne) {
-                        /* Write in only the one bits. */  
+                        /* Write in only the one bits. */
                         unsigned int newcol, newrow;
                         transformPoint(col, row, xform, &newcol, &newrow);
                         newbits[newrow][newcol/8] |= 0x01 << (7 - newcol % 8);
@@ -710,7 +710,7 @@ transformPbmGen(struct pam *     const inpamP,
 
     for (row = 0; row < outpamP->height; ++row)
         pbm_writepbmrow_packed(outpamP->file, newbits[row], outpamP->width, 0);
-    
+
     pbm_freearray(newbits, outpamP->height);
     pbm_freerow(bitrow);
 }
@@ -720,7 +720,7 @@ transformPbmGen(struct pam *     const inpamP,
 static void
 transformNonPbmWhole(struct pam *     const inpamP,
                      struct pam *     const outpamP,
-                     struct xformCore const xformCore,
+                     struct XformCore const XformCore,
                      bool             const verbose) {
 /*----------------------------------------------------------------------------
   Do the transform using "pam" library functions, as opposed to "pbm"
@@ -738,18 +738,18 @@ transformNonPbmWhole(struct pam *     const inpamP,
 -----------------------------------------------------------------------------*/
     tuple * tuplerow;
     tuple ** newtuples;
-    struct xformMatrix xform;
+    struct XformMatrix xform;
     unsigned int row;
 
-    computeXformMatrix(&xform, inpamP->width, inpamP->height, xformCore);
-    
+    computeXformMatrix(&xform, inpamP->width, inpamP->height, XformCore);
+
     tuplerow = pnm_allocpamrow(inpamP);
     newtuples = pnm_allocpamarray(outpamP);
-    
+
     for (row = 0; row < inpamP->height; ++row) {
         unsigned int col;
         pnm_readpamrow(inpamP, tuplerow);
-        
+
         for (col = 0; col < inpamP->width; ++col) {
             unsigned int newcol, newrow;
 
@@ -762,9 +762,9 @@ transformNonPbmWhole(struct pam *     const inpamP,
                             tuplerow[col]);
         }
     }
-    
+
     writeRaster(outpamP, newtuples);
-    
+
     pnm_freepamarray(newtuples, outpamP);
     pnm_freepamrow(tuplerow);
 }
@@ -798,7 +798,7 @@ initOutCell(struct pam *     const outCellPamP,
             unsigned int     const inCellWidth,
             unsigned int     const inCellHeight,
             struct pam *     const inpamP,
-            struct xformCore const xformCore) {
+            struct XformCore const XformCore) {
 /*----------------------------------------------------------------------------
    Set up an output cell.  Create and open a temporary file to hold its
    raster.  Figure out the dimensions of the cell.  Return a PAM structure
@@ -812,7 +812,7 @@ initOutCell(struct pam *     const outCellPamP,
 
     outCellPamP->file = pm_tmpfile();
 
-    xformDimensions(xformCore, inCellWidth, inCellHeight,
+    xformDimensions(XformCore, inCellWidth, inCellHeight,
                     &outCellFileCt, &outCellRankCt);
 
     outCellPamP->width = outCellFileCt;
@@ -824,8 +824,8 @@ initOutCell(struct pam *     const outCellPamP,
 static outputMap *
 createOutputMap(struct pam *       const inpamP,
                 unsigned int       const maxRows,
-                struct xformMatrix const cellXform,
-                struct xformCore   const xformCore) {
+                struct XformMatrix const cellXform,
+                struct XformCore   const XformCore) {
 /*----------------------------------------------------------------------------
    Create and return the output map.  That's a map of all the output cells
    (from which the output image can be assembled, once those cells are filled
@@ -853,7 +853,7 @@ createOutputMap(struct pam *       const inpamP,
 
     MALLOCVAR_NOFAIL(mapP);
 
-    xformDimensions(xformCore, inCellFileCt, inCellRankCt,
+    xformDimensions(XformCore, inCellFileCt, inCellRankCt,
                     &mapP->fileCt, &mapP->rankCt);
 
     MALLOCARRAY(mapP->pam, mapP->rankCt);
@@ -879,14 +879,14 @@ createOutputMap(struct pam *       const inpamP,
         unsigned int outCellFile, outCellRank;
         transformPoint(inCellFile, inCellRank, cellXform,
                        &outCellFile, &outCellRank);
-    
+
         initOutCell(&mapP->pam[outCellRank][outCellFile],
                     inpamP->width, inCellRowCt,
-                    inpamP, xformCore);
+                    inpamP, XformCore);
     }
     return mapP;
 }
-                
+
 
 
 static void
@@ -935,14 +935,14 @@ closeCellFiles(outputMap * const outputMapP) {
 static void
 transformCell(struct pam *     const inpamP,
               struct pam *     const outpamP,
-              struct xformCore const xformCore) {
+              struct XformCore const XformCore) {
 
-    struct xformMatrix xform;
+    struct XformMatrix xform;
     tuple * inTupleRow;
     tuple ** outTuples;
     unsigned int inRow;
 
-    computeXformMatrix(&xform, inpamP->width, inpamP->height, xformCore);
+    computeXformMatrix(&xform, inpamP->width, inpamP->height, XformCore);
 
     inTupleRow = pnm_allocpamrow(inpamP);
 
@@ -952,7 +952,7 @@ transformCell(struct pam *     const inpamP,
         unsigned int inCol;
 
         pnm_readpamrow(inpamP, inTupleRow);
-        
+
         for (inCol = 0; inCol < inpamP->width; ++inCol) {
             unsigned int outCol, outRow;
 
@@ -996,7 +996,7 @@ stitchCellsToOutput(outputMap *  const outputMapP,
             outCol = 0;
 
             for (outFile = 0; outFile < outputMapP->fileCt; ++outFile) {
-                struct pam * const outCellPamP = 
+                struct pam * const outCellPamP =
                     &outputMapP->pam[outRank][outFile];
 
                 assert(outCellPamP->height == cellRows);
@@ -1020,7 +1020,7 @@ stitchCellsToOutput(outputMap *  const outputMapP,
 static void
 transformNonPbmChunk(struct pam *     const inpamP,
                      struct pam *     const outpamP,
-                     struct xformCore const xformCore,
+                     struct XformCore const XformCore,
                      unsigned int     const maxRows,
                      bool             const verbose) {
 /*----------------------------------------------------------------------------
@@ -1032,11 +1032,11 @@ transformNonPbmChunk(struct pam *     const inpamP,
   header).
 
   We call the strip of 'maxRows' rows that we read a source cell.  We
-  transform that cell according to 'xformCore' to create a
+  transform that cell according to 'XformCore' to create a
   target cell.  We store all the target cells in temporary files.
   We consider the target cells to be arranged in a column matrix the
   same as the source cells within the source image; we transform that
-  matrix according to 'xformCore'.  The resulting cell matrix is the
+  matrix according to 'XformCore'.  The resulting cell matrix is the
   target image.
 -----------------------------------------------------------------------------*/
     /* The cells of the source image ("inCell") are in a 1-column matrix.
@@ -1046,7 +1046,7 @@ transformNonPbmChunk(struct pam *     const inpamP,
     unsigned int const inCellFileCt = 1;
     unsigned int const inCellRankCt = (inpamP->height + maxRows - 1) / maxRows;
 
-    struct xformMatrix cellXform;
+    struct XformMatrix cellXform;
     unsigned int inCellRank;
     outputMap * outputMapP;
 
@@ -1054,9 +1054,9 @@ transformNonPbmChunk(struct pam *     const inpamP,
         pm_message("Transforming in %u chunks, using temp files",
                    inCellRankCt);
 
-    computeXformMatrix(&cellXform, inCellFileCt, inCellRankCt, xformCore);
+    computeXformMatrix(&cellXform, inCellFileCt, inCellRankCt, XformCore);
 
-    outputMapP = createOutputMap(inpamP, maxRows, cellXform, xformCore);
+    outputMapP = createOutputMap(inpamP, maxRows, cellXform, XformCore);
 
     for (inCellRank = 0; inCellRank < inCellRankCt; ++inCellRank) {
         unsigned int const inCellFile = 0;
@@ -1070,15 +1070,15 @@ transformNonPbmChunk(struct pam *     const inpamP,
 
         transformPoint(inCellFile, inCellRank, cellXform,
                        &outCellFile, &outCellRank);
-    
+
         outCellPamP = &outputMapP->pam[outCellRank][outCellFile];
 
         /* Input cell is just the next 'inCellRows' rows of input image */
         inCellPam = *inpamP;
         inCellPam.height = inCellRows;
 
-        transformCell(&inCellPam, outCellPamP, xformCore);
-    }    
+        transformCell(&inCellPam, outCellPamP, XformCore);
+    }
 
     rewindCellFiles(outputMapP);
 
@@ -1122,7 +1122,7 @@ maxRowsThatFit(struct pam * const pamP,
 static void
 transformPbm(struct pam *     const inpamP,
              struct pam *     const outpamP,
-             struct xformCore const xform,
+             struct XformCore const xform,
              bool             const verbose) {
 
     if (xform.b == 0 && xform.c == 0) {
@@ -1155,7 +1155,7 @@ transformPbm(struct pam *     const inpamP,
 static void
 transformNonPbm(struct pam *     const inpamP,
                 struct pam *     const outpamP,
-                struct xformCore const xform,
+                struct XformCore const xform,
                 unsigned int     const availableMemory,
                 bool             const verbose) {
 
@@ -1212,7 +1212,7 @@ main(int argc, char * argv[]) {
         ifP = pm_openr_seekable(cmdline.inputFilespec);
     else
         ifP = pm_openr(cmdline.inputFilespec);
-    
+
     pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
 
     outpam = inpam;  /* initial value */
@@ -1233,6 +1233,6 @@ main(int argc, char * argv[]) {
     }
     pm_close(inpam.file);
     pm_close(outpam.file);
-    
+
     return 0;
 }
diff --git a/editor/pamflip/pamflip_sse.c b/editor/pamflip/pamflip_sse.c
index e0929f65..c4e51751 100644
--- a/editor/pamflip/pamflip_sse.c
+++ b/editor/pamflip/pamflip_sse.c
@@ -37,7 +37,7 @@
 
 /*----------------------------------------------------------------------------
    This is a specialized routine for row-for-column PBM transformations.
-   (-cw, -ccw, -xy).  It requires GCC (>= v. 4.2.0) and SSE2. 
+   (-cw, -ccw, -xy).  It requires GCC (>= v. 4.2.0) and SSE2.
 
    In each cycle, we read sixteen rows from the input.  We process this band
    left to right in blocks 8 pixels wide.  We use the SSE2 instruction
@@ -70,7 +70,7 @@
    It is possible to write a non-SSE version by providing a generic
    version of transpose16Bitrows() or one tuned for a specific
    architecture.  Use 8x8 blocks to avoid endian issues.
- 
+
    Further enhancement should be possible by employing wider bands,
    larger blocks as wider SIMD registers become available.  Clearing
    the white parts after instead of before transposition is also a
@@ -149,7 +149,7 @@ transpose16Bitrows(unsigned int const cols,
 
         register v16qi vReg = {
             block[0][col8],  block[1][col8],
-            block[2][col8],  block[3][col8],  
+            block[2][col8],  block[3][col8],
             block[4][col8],  block[5][col8],
             block[6][col8],  block[7][col8],
             block[8][col8],  block[9][col8],
@@ -163,14 +163,14 @@ transpose16Bitrows(unsigned int const cols,
         if (_mm_movemask_epi8(compare) != 0xffff) {
 
             /* There is some black content in this block; write to outplane */
-            
+
             unsigned int outrow;
             unsigned int i;
 
             outrow = col;  /* initial value */
 
             for (i = 0; i < 7; ++i) {
-                /* GCC (>=4.2) automatically unrolls this loop */  
+                /* GCC (>=4.2) automatically unrolls this loop */
                 outplane[outrow++][outcol16] =
                     _mm_movemask_epi8((__m128i)vReg);
                 vReg = (v16qi)_mm_slli_epi32((__m128i)vReg, 1);
@@ -197,7 +197,7 @@ analyzeBlock(const struct pam * const inpamP,
   "twists" brought about by Intel byte ordering which occur when:
     (1) 16 bytes are loaded to a SSE register
     (2) 16 bits are written to memory.
- 
+
   If 'rows' is not a multiple of 8, a partial input band appears at one edge.
   Set *topOfFullBlockP accordingly.  blockPartial[] is an adjusted "block" for
   this partial band, brought up to a size of 8 rows.  The extra pointers point
@@ -227,7 +227,7 @@ analyzeBlock(const struct pam * const inpamP,
                 : block[i];
         }
         *topOfFullBlockP = inpamP->height % 16;
-    
+
         if (inpamP->height >= 16) {
             *outcol16P = inpamP->height/16 - 1;
         } else
@@ -243,7 +243,7 @@ doPartialBlockTop(const struct pam * const inpamP,
                   const bit *        const blockPartial[16],
                   unsigned int       const topOfFullBlock,
                   uint16_t **        const outplane) {
-    
+
     if (topOfFullBlock > 0) {
         unsigned int colChar, row;
         unsigned int pad = 16 - topOfFullBlock;
@@ -267,7 +267,7 @@ doPartialBlockTop(const struct pam * const inpamP,
                            outplane, inpamP->height /16);
             /* Transpose partial rows on top of input.  Place on right edge of
                output.
-            */ 
+            */
     }
 }
 
@@ -303,7 +303,7 @@ doFullBlocks(const struct pam * const inpamP,
         ++modrow;
         if (modrow == 16) {
             /* 16 row buffer is full.  Transpose. */
-            modrow = 0; 
+            modrow = 0;
 
             transpose16Bitrows(inpamP->width, inpamP->height,
                                block, outplane, outcol16);
@@ -320,7 +320,7 @@ doPartialBlockBottom(const struct pam * const inpamP,
                      int                const xdir,
                      const bit *        const blockPartial[16],
                      uint16_t **        const outplane) {
-    
+
     if (xdir > 0 && inpamP->height % 16 > 0) {
         unsigned int colChar;
 
@@ -331,7 +331,7 @@ doPartialBlockBottom(const struct pam * const inpamP,
                            outplane, inpamP->height/16);
             /* Transpose partial rows on bottom of input.  Place on right edge
                of output.
-            */ 
+            */
     }
 }
 
@@ -341,7 +341,7 @@ static void
 writeOut(const struct pam * const outpamP,
          uint16_t **        const outplane,
          int                const ydir) {
-             
+
     unsigned int row;
 
     for (row = 0; row < outpamP->height; ++row) {
@@ -357,23 +357,23 @@ writeOut(const struct pam * const outpamP,
 
 static void
 clearOutplane(const struct pam * const outpamP,
-              uint16_t **        const outplane) { 
-    
+              uint16_t **        const outplane) {
+
     unsigned int row;
-    
+
     for (row = 0; row < outpamP->height; ++row) {
         unsigned int col16;  /* column divided by 16 */
         for (col16 = 0; col16 < (outpamP->width + 15)/16; ++col16)
             outplane[row][col16] = 0x0000;
     }
-} 
+}
 
 
 
 void
 pamflip_transformRowsToColumnsPbmSse(const struct pam * const inpamP,
                                      const struct pam * const outpamP,
-                                     struct xformCore const xformCore) { 
+                                     struct XformCore   const xformCore) {
 /*----------------------------------------------------------------------------
   This is a specialized routine for row-for-column PBM transformations.
   (-cw, -ccw, -xy).
@@ -397,11 +397,11 @@ pamflip_transformRowsToColumnsPbmSse(const struct pam * const inpamP,
         pm_error("Could not allocate %u x %u array of 16 bit units",
                  blocksPerRow, outpamP->height + 7);
 
-    /* We write to the output array in 16 bit units.  Add margin. */  
+    /* We write to the output array in 16 bit units.  Add margin. */
 
     clearOutplane(outpamP, outplane);
 
-    analyzeBlock(inpamP, inrow, xdir, block, blockPartial, 
+    analyzeBlock(inpamP, inrow, xdir, block, blockPartial,
                  &topOfFullBlock, &outcol16);
 
     doPartialBlockTop(inpamP, inrow, blockPartial, topOfFullBlock, outplane);
@@ -421,9 +421,9 @@ pamflip_transformRowsToColumnsPbmSse(const struct pam * const inpamP,
 void
 pamflip_transformRowsToColumnsPbmSse(const struct pam * const inpamP,
                                      const struct pam * const outpamP,
-                                     struct xformCore   const xformCore) { 
+                                     struct XformCore   const xformCore) {
 
     /* Nobody is supposed to call this */
     assert(false);
 }
-#endif 
+#endif
diff --git a/editor/pamflip/pamflip_sse.h b/editor/pamflip/pamflip_sse.h
index 59e7c026..cd1267b7 100644
--- a/editor/pamflip/pamflip_sse.h
+++ b/editor/pamflip/pamflip_sse.h
@@ -7,6 +7,6 @@ struct pam;
 void
 pamflip_transformRowsToColumnsPbmSse(const struct pam *     const inpamP,
                                      const struct pam *     const outpamP,
-                                     struct xformCore       const xformCore);
+                                     struct XformCore       const xformCore);
 
 #endif
diff --git a/editor/pamlevels.c b/editor/pamlevels.c
new file mode 100644
index 00000000..fbbb2c0b
--- /dev/null
+++ b/editor/pamlevels.c
@@ -0,0 +1,515 @@
+#include <stdbool.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "netpbm/pam.h"
+#include "netpbm/pm_system.h"
+#include "netpbm/pm_gamma.h"
+#include "netpbm/nstring.h"
+#include "netpbm/ppm.h"
+
+#include "shhopt.h"
+#include "mallocvar.h"
+
+/* ----------------------------- Type aliases ------------------------------ */
+
+typedef unsigned char uchar;
+typedef unsigned int  uint;
+typedef struct   pam  pam;
+
+typedef struct {
+/*----------------------------------------------------------------------------
+  An RGB triple, in linear intensity or linear brightness; user's choice.
+-----------------------------------------------------------------------------*/
+    double _[3];
+} Rgb;
+
+typedef struct {
+/*----------------------------------------------------------------------------
+  A quadratic polynomial
+-----------------------------------------------------------------------------*/
+    double coeff[3];
+} Polynomial;
+
+typedef struct {
+/*----------------------------------------------------------------------------
+  A set of source or target sample values, in some plane.
+
+  These are either intensity-linear or brightness-linear; user's choice.
+
+  There could be two or three values; user must know which.
+-----------------------------------------------------------------------------*/
+    double _[3];
+} SampleSet;
+
+/* ------------------------- Parse transformations ------------------------- */
+
+typedef struct {
+/*----------------------------------------------------------------------------
+  A mapping of one source color to one target color, encoded in linear RGB
+-----------------------------------------------------------------------------*/
+    tuplen from;
+    tuplen to;
+} Trans;
+
+typedef struct {
+    const char * from;  /* color specifications  */
+    const char * to;    /*   as they appear on commandline */
+    unsigned int  hasFrom;      /* "from" part is present */
+    unsigned int  hasTo;        /* "to" part is present */
+    char  nameFromS[3]; /* short option name */
+    char  nameToS  [3];
+    char  nameFromL[6]; /* long option name */
+    char  nameToL  [6];
+} TransArg;
+
+typedef struct {
+    TransArg _[3];
+} TransArgSet;
+
+typedef struct {
+    unsigned int n;
+        /* Number of elements in 't', 2 for linear transformation; 3 for
+           quadratic.
+        */
+    Trans t[3];
+} TransSet;
+
+typedef struct {
+    unsigned int linear;
+    unsigned int fitbrightness;
+    TransSet     xlats; /* color mappings (-from1, -to1, etc.) */
+    const char * inputFileName;  /* the input file name, "-" for stdin     */
+} CmdlineInfo;
+
+
+
+static void
+optAddTrans (optEntry *     const option_def,
+             unsigned int * const option_def_indexP,
+             TransArg *     const xP,
+             char           const index) {
+
+    char indexc;
+    uint option_def_index;
+
+    option_def_index = *option_def_indexP;
+
+    indexc = '0' + index;
+
+    STRSCPY(xP->nameFromL, "from "); xP->nameFromL[4] = indexc;
+    STRSCPY(xP->nameToL,   "to "  ); xP->nameToL  [2] = indexc;
+    STRSCPY(xP->nameFromS, "f "   ); xP->nameFromS[1] = indexc;
+    STRSCPY(xP->nameToS,   "t "   ); xP->nameToS  [1] = indexc;
+
+    OPTENT3(0, xP->nameFromL, OPT_STRING, &xP->from, &xP->hasFrom, 0);
+    OPTENT3(0, xP->nameFromS, OPT_STRING, &xP->from, &xP->hasFrom, 0);
+    OPTENT3(0, xP->nameToL,   OPT_STRING, &xP->to,   &xP->hasTo,   0);
+    OPTENT3(0, xP->nameToS,   OPT_STRING, &xP->to,   &xP->hasTo,   0);
+
+    *option_def_indexP = option_def_index;
+}
+
+
+
+static void
+parseColor(const char * const text,
+           tuplen *     const colorP) {
+/*----------------------------------------------------------------------------
+  Parses color secification in <text>, converts it into linear RGB,
+  and stores the result in <colorP>.
+-----------------------------------------------------------------------------*/
+    const char * const lastsc = strrchr(text, ':');
+
+    const char * colorname;
+    double mul;
+    tuplen unmultipliedColor;
+    tuplen color;
+
+    if (lastsc) {
+        /* Specification contains a colon.  It might be the colon that
+           introduces the optional multiplier, or it might just be the colon
+           after the type specifier, e.g. "rgbi:...".
+        */
+
+        if (strstr(text, "rgb") == text && strchr(text, ':') == lastsc) {
+            /* The only colon present is the one on the type specifier.
+               So there is no multiplier.
+            */
+            mul = 1.0;
+            colorname = pm_strdup(text);
+        } else {
+            /* There is a multiplier (possibly invalid, though). */
+            const char * const mulstart = lastsc + 1;
+
+            char * endP;
+            char colorbuf[50];
+
+            errno = 0;
+            mul = strtod(mulstart, &endP);
+            if (errno != 0 || endP == mulstart)
+                pm_error("Invalid sample multiplier: '%s'", mulstart);
+
+            strncpy(colorbuf, text, lastsc - text);
+            colorbuf[lastsc - text] = '\0';
+            colorname = pm_strdup(colorbuf);
+        }
+    } else {
+        mul = 1.0;
+        colorname = pm_strdup(text);
+    }
+
+    unmultipliedColor = pnm_parsecolorn(colorname);
+
+    pm_strfree(colorname);
+
+    MALLOCARRAY_NOFAIL(color, 3);
+
+    {
+        /* Linearize and apply multiplier */
+        unsigned int i;
+        for (i = 0; i < 3; ++i)
+            color[i] = pm_ungamma709(unmultipliedColor[i]) * mul;
+    }
+    free(unmultipliedColor);
+
+    *colorP = color;
+}
+
+
+
+static void
+parseTran (TransArg const transArg,
+           Trans *  const rP) {
+
+    parseColor(transArg.from, &rP->from);
+    parseColor(transArg.to,   &rP->to);
+}
+
+
+
+static void
+calcTrans(TransArgSet   const transArgs,
+          TransSet *    const transP) {
+/*----------------------------------------------------------------------------
+   Interpret transformation option (-from1, etc.) values 'transArg'
+   as transformations, *transP.
+-----------------------------------------------------------------------------*/
+    unsigned int xi;
+
+    for (transP->n = 0, xi = 0; xi < 3; ++xi) {
+        const TransArg * const xformP = &transArgs._[xi];
+
+        if (xformP->hasFrom || xformP->hasTo) {
+            if (!xformP->hasFrom || !xformP->hasTo)
+                pm_error("Mapping %u incompletely specified - "
+                         "you specified -fromN or -toN but not the other",
+                    xi + 1);
+            parseTran(*xformP, &transP->t[transP->n++]);
+        }
+    }
+    if (transP->n < 2)
+        pm_error("You must specify at least two mappings with "
+                 "-from1, -to1, etc.  You specified %u", transP->n);
+}
+
+
+
+static void
+parseCommandLine(int                 argc,
+                 const char **       argv,
+                 CmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Parse program command line described in Unix standard form by argc
+   and argv.  Return the information in the options as *cmdlineP.
+
+   If command line is internally inconsistent (invalid options, etc.),
+   issue error message to stderr and abort program.
+
+   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;
+        /* Instructions to pm_optParseOptions3 on how to parse our options.
+         */
+    optStruct3 opt;
+
+    unsigned int option_def_index;
+
+    TransArgSet xlations; /* color mapping as read from command line */
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;  /* incremented by OPTENT3 */
+
+    OPTENT3(0, "fitbrightness",          OPT_FLAG, NULL,
+            &cmdlineP->fitbrightness, 0);
+    OPTENT3(0, "linear",                 OPT_FLAG, NULL,
+            &cmdlineP->linear,        0);
+
+    {
+        unsigned int i;
+        for (i = 0; i < 3; ++i)
+            optAddTrans(option_def, &option_def_index,
+                        &xlations._[i], i + 1);
+    }
+
+    opt.opt_table     = option_def;
+    opt.short_allowed = 0;
+    opt.allowNegNum   = 0;
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+
+    if (cmdlineP->linear && cmdlineP->fitbrightness) {
+        pm_error("You cannot use -linear and -fitbrightness together");
+        /* Note: It actually makes sense to use them together; we're just not
+           willing to put the effort into something it's unlikely anyone will
+           want.
+        */
+    }
+
+    calcTrans(xlations, &cmdlineP->xlats);
+
+    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 void
+errResolve(void) {
+    pm_error( "Cannot resolve the transformations");
+}
+
+
+
+static double
+sqr(double const x) {
+    return x * x;
+}
+
+
+
+static void
+solveOnePlane(SampleSet    const f,
+              SampleSet    const t,
+              unsigned int const n,
+              Polynomial * const solutionP) {
+/*----------------------------------------------------------------------------
+  Find the transformation that maps f[i] to t[i] for 0 <= i < n.
+-----------------------------------------------------------------------------*/
+    double const eps = 0.00001;
+
+    double a, b, c;
+
+    /* I have decided against generic methods of solving systems of linear
+       equations in favour of simple explicit formulas, with no memory
+       allocation and tedious matrix processing.
+    */
+
+    switch (n) {
+    case 3: {
+        double const aDenom =
+            sqr( f._[0] ) * ( f._[1] - f._[2] ) -
+            sqr( f._[2] ) * ( f._[1] - f._[0] ) -
+            sqr( f._[1] ) * ( f._[0] - f._[2] );
+
+        if (fabs(aDenom) < eps)
+            errResolve();
+
+        a = (t._[1] * (f._[2] - f._[0]) - t._[0] * (f._[2] - f._[1]) -
+             t._[2] * (f._[1] - f._[0]))
+            / aDenom;
+    } break;
+    case 2:
+        a = 0.0;
+        break;
+    default:
+        a = 0.0; /* to avoid a warning that <a> "may be uninitialized". */
+        pm_error("INTERNAL ERROR: solve(): impossible value of n: %u", n);
+    }
+
+    {
+        double const bDenom = f._[1] - f._[0];
+
+        if (fabs(bDenom) < eps)
+            errResolve();
+
+        b = (t._[1] - t._[0] + a * (sqr(f._[0]) - sqr(f._[1]))) / bDenom;
+    }
+
+    c = -a * sqr(f._[0]) - b * f._[0] + t._[0];
+
+    solutionP->coeff[0] = a; solutionP->coeff[1] = b; solutionP->coeff[2] = c;
+}
+
+
+
+static void
+chanData(TransSet     const ta,
+         bool         const fittingBrightness,
+         unsigned int const plane,
+         SampleSet *  const fromP,
+         SampleSet *  const toP) {
+/*----------------------------------------------------------------------------
+  Collate transformations from 'ta' for plane 'plane'.
+-----------------------------------------------------------------------------*/
+    unsigned int i;
+
+    for (i = 0; i < ta.n; ++i) {
+        if (fittingBrightness) { /* working with gamma-compressed values */
+            fromP->_[i] = pm_gamma709(ta.t[i].from[plane]);
+            toP->  _[i] = pm_gamma709(ta.t[i].to  [plane]);
+        } else { /* working in linear RGB */
+            fromP->_[i] = ta.t[i].from[plane];
+            toP->  _[i] = ta.t[i].to  [plane];
+        }
+    }
+}
+
+
+
+typedef struct {
+    Polynomial _[3];  /* One per plane */
+} Solution;
+
+
+
+static void
+solveFmCmdlineOpts(CmdlineInfo  const cmdline,
+                   unsigned int const depth,
+                   Solution *   const solutionP) {
+/*----------------------------------------------------------------------------
+   Compute the function that will transform the tuples, based on what the user
+   requested ('cmdline').
+
+   The function takes intensity-linear tuples for the normal levels function,
+   or brightness-linear for the brightness approximation levels function.
+
+   The transformed image has 'depth' planes.
+-----------------------------------------------------------------------------*/
+    unsigned int plane;
+    SampleSet from, to;
+    /* This initialization to bypass the "may be uninitialized" warning: */
+    to  ._[0] = 0; to.  _[1] = 0; to  ._[2] = 0;
+    from._[0] = 1; from._[1] = 0; from._[2] = 0;
+
+    for (plane = 0; plane < depth; ++plane) {
+
+        chanData(cmdline.xlats, cmdline.fitbrightness, plane, &from, &to);
+        solveOnePlane(from, to, cmdline.xlats.n, &solutionP->_[plane]);
+    }
+}
+
+
+
+static samplen
+xformedSample(samplen    const value,
+              Polynomial const polynomial) {
+/*----------------------------------------------------------------------------
+  'sample' transformed by 'polynomial'.
+-----------------------------------------------------------------------------*/
+    double const res =
+        (polynomial.coeff[0] * value + polynomial.coeff[1]) * value +
+        polynomial.coeff[2];
+
+    return MAX(0.0f, MIN(1.0f, res));
+}
+
+
+
+static void
+pamlevels(CmdlineInfo const cmdline) {
+
+    unsigned int row;
+    pam      inPam, outPam;
+    Solution solution;
+    tuplen * tuplerown;
+    FILE   * ifP;
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    pnm_readpaminit(ifP, &inPam, PAM_STRUCT_SIZE(tuple_type));
+
+    outPam = inPam;
+    outPam.file = stdout;
+
+    solveFmCmdlineOpts(cmdline, inPam.depth, &solution);
+
+    tuplerown = pnm_allocpamrown(&inPam);
+
+    pnm_writepaminit(&outPam);
+
+    for (row = 0; row < inPam.height; ++row) {
+        unsigned int col;
+
+        pnm_readpamrown(&inPam, tuplerown);
+
+        if (!cmdline.linear && !cmdline.fitbrightness)
+            pnm_ungammarown(&inPam, tuplerown);
+
+        for (col = 0; col < inPam.width; ++col) {
+            unsigned int plane;
+
+            for (plane = 0; plane < inPam.depth; ++plane) {
+                tuplerown[col][plane] =
+                    xformedSample(tuplerown[col][plane], solution._[plane]);
+            }
+        }
+        if (!cmdline.linear && !cmdline.fitbrightness)
+            pnm_gammarown(&inPam, tuplerown);
+
+        pnm_writepamrown(&outPam, tuplerown);
+    }
+    pnm_freepamrown(tuplerown);
+    pm_close(ifP);
+}
+
+
+
+static void
+freeCmdLineInfo(CmdlineInfo cmdline) {
+/*----------------------------------------------------------------------------
+  Free any memory that has been dynamically allcoated in <cmdline>.
+-----------------------------------------------------------------------------*/
+    TransSet * const xxP = &cmdline.xlats;
+
+    uint x;
+
+    for (x = 0; x < xxP->n; ++x) {
+        free(xxP->t[x].from);
+        free(xxP->t[x].to);
+    }
+}
+
+
+
+int main(int    argc, const char * argv[]) {
+
+    CmdlineInfo cmdline;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    pamlevels(cmdline);
+
+    freeCmdLineInfo(cmdline);
+
+    return 0;
+}
+
+
+
diff --git a/editor/pamrecolor.c b/editor/pamrecolor.c
index 6937fd8d..8c5bce12 100644
--- a/editor/pamrecolor.c
+++ b/editor/pamrecolor.c
@@ -404,7 +404,7 @@ parseCommandLine(int argc, const char ** const argv,
             cmdlineP->color2gray.rfrac +
             cmdlineP->color2gray.gfrac +
             cmdlineP->color2gray.bfrac;
-        if (fabsf(1.0 - maxLuminance) > REAL_EPSILON)
+        if (fabsf(1.0f - maxLuminance) > REAL_EPSILON)
             pm_error("The values given for --rmult, --gmult, and --bmult must "
                      "sum to 1.0, not %.10g", maxLuminance);
     } else if (csSpec)
diff --git a/editor/pamscale.c b/editor/pamscale.c
index 0456d15a..433d5cee 100644
--- a/editor/pamscale.c
+++ b/editor/pamscale.c
@@ -11,9 +11,9 @@
    people contributed code changes over the years.
 
    Copyright (C) 2003 by Michael Reinelt <reinelt@eunet.at>
-  
+
    Copyright (C) 1989, 1991 by Jef Poskanzer.
-  
+
    Permission to use, copy, modify, and distribute this software and its
    documentation for any purpose and without fee is hereby granted, provided
    that the above copyright notice appear in all copies and that both that
@@ -54,14 +54,14 @@
 
 
 /* x^2 and x^3 helper functions */
-static __inline__ double 
+static __inline__ double
 pow2(double const x) {
     return x * x;
 }
 
 
 
-static __inline__ double 
+static __inline__ double
 pow3(double const x) {
     return x * x * x;
 }
@@ -75,7 +75,7 @@ pow3(double const x) {
 #define radius_point (0.0)
 #define radius_box (0.5)
 
-static double 
+static double
 filter_box(double const x) {
 
     double const absx = x < 0.0 ? -x : x;
@@ -91,7 +91,7 @@ filter_box(double const x) {
 
 #define radius_triangle (1.0)
 
-static double 
+static double
 filter_triangle(double const x) {
 
     double const absx = x < 0.0 ? -x : x;
@@ -105,7 +105,7 @@ filter_triangle(double const x) {
 
 #define radius_quadratic (1.5)
 
-static double 
+static double
 filter_quadratic(double const x) {
 
     double const absx = x < 0.0 ? -x : x;
@@ -122,7 +122,7 @@ filter_quadratic(double const x) {
 
 #define radius_cubic (2.0)
 
-static double 
+static double
 filter_cubic(double const x) {
 
     double const absx = x < 0.0 ? -x : x;
@@ -139,7 +139,7 @@ filter_cubic(double const x) {
 
 #define radius_catrom (2.0)
 
-static double 
+static double
 filter_catrom(double const x) {
 
     double const absx = x < 0.0 ? -x : x;
@@ -158,7 +158,7 @@ filter_catrom(double const x) {
 
 #define radius_mitchell (2.0)
 
-static double 
+static double
 filter_mitchell(double x)
 {
 
@@ -187,7 +187,7 @@ filter_mitchell(double x)
 
 #define radius_gauss (1.25)
 
-static double 
+static double
 filter_gauss(double const x) {
 
     return exp(-2.0*pow2(x)) * sqrt(2.0/M_PI);
@@ -199,14 +199,14 @@ filter_gauss(double const x) {
 
 #define radius_sinc (4.0)
 
-static double 
+static double
 filter_sinc(double const x) {
     /* Note: Some people say sinc(x) is sin(x)/x.  Others say it's
        sin(PI*x)/(PI*x), a horizontal compression of the former which is
        zero at integer values.  We use the latter, whose Fourier transform
        is a canonical rectangle function (edges at -1/2, +1/2, height 1).
     */
-    return 
+    return
         x == 0.0 ? 1.0 :
         sin(M_PI*x)/(M_PI*x);
 }
@@ -218,10 +218,10 @@ filter_sinc(double const x) {
 
 #define radius_bessel (3.2383)
 
-static double 
+static double
 filter_bessel(double const x) {
 
-    return 
+    return
         x == 0.0 ? M_PI/4.0 :
         j1(M_PI * x) / (2.0 * x);
 }
@@ -232,7 +232,7 @@ filter_bessel(double const x) {
 
 #define radius_hanning (1.0)
 
-static double 
+static double
 filter_hanning(double const x) {
 
     return 0.5 * cos(M_PI * x) + 0.5;
@@ -244,7 +244,7 @@ filter_hanning(double const x) {
 
 #define radius_hamming (1.0)
 
-static double 
+static double
 filter_hamming(double const x) {
     return 0.46 * cos(M_PI * x) + 0.54;
 }
@@ -255,7 +255,7 @@ filter_hamming(double const x) {
 
 #define radius_blackman (1.0)
 
-static double 
+static double
 filter_blackman(double const x) {
     return 0.5 * cos(M_PI * x) + 0.08 * cos(2.0 * M_PI * x) + 0.42;
 }
@@ -268,12 +268,12 @@ filter_blackman(double const x) {
 #define radius_kaiser (1.0)
 
 /* modified zeroth order Bessel function of the first kind. */
-static double 
+static double
 bessel_i0(double const x) {
-  
+
     int i;
     double sum, y, t;
-  
+
     sum = 1.0;
     y = pow2(x)/4.0;
     t = y;
@@ -286,15 +286,15 @@ bessel_i0(double const x) {
 
 
 
-static double 
+static double
 filter_kaiser(double const x) {
     /* typically 4 < a < 9 */
     /* param a trades off main lobe width (sharpness) */
     /* for side lobe amplitude (ringing) */
-  
+
     double const a   = 6.5;
     double const i0a = 1.0/bessel_i0(a);
-  
+
     return i0a * bessel_i0(a * sqrt(1.0-pow2(x)));
 }
 
@@ -305,7 +305,7 @@ filter_kaiser(double const x) {
 
 #define radius_normal (1.0)
 
-static double 
+static double
 filter_normal(double const x) {
     return exp(-pow2(x)/2.0) / sqrt(2.0*M_PI);
 }
@@ -316,7 +316,7 @@ filter_normal(double const x) {
 
 #define radius_hermite  (1.0)
 
-static double 
+static double
 filter_hermite(double const x) {
     /* f(x) = 2|x|^3 - 3|x|^2 + 1, -1 <= x <= 1 */
 
@@ -333,7 +333,7 @@ filter_hermite(double const x) {
 
 #define radius_lanczos (3.0)
 
-static double 
+static double
 filter_lanczos(double const x) {
 
     double const absx = x < 0.0 ? -x : x;
@@ -352,7 +352,7 @@ typedef struct {
         /* This is how far from the Y axis (on either side) the
            function has significant value.  (You can use this to limit
            how much of your domain you bother to compute the function
-           over).  
+           over).
         */
     bool windowed;
 } filter;
@@ -420,25 +420,25 @@ struct CmdlineInfo {
     basicFunction_t filterFunction; /* NULL if not using resample method */
     basicFunction_t windowFunction;
         /* Meaningful only when filterFunction != NULL */
-    double filterRadius;           
+    double filterRadius;
         /* Meaningful only when filterFunction != NULL */
     enum scaleType scaleType;
     /* 'xsize' and 'ysize' are numbers of pixels.  Their meaning depends upon
-       'scaleType'.  for SCALE_BOXFIT and SCALE_BOXFILL, they are the box 
+       'scaleType'.  for SCALE_BOXFIT and SCALE_BOXFILL, they are the box
        dimensions.  For SCALE_SEPARATE, they are the separate dimensions, or
        zero to indicate unspecified.  For SCALE_PIXELMAX, they are
        meaningless.
     */
     unsigned int xsize;
     unsigned int ysize;
-    /* 'xscale' and 'yscale' are meaningful only for scaleType == 
+    /* 'xscale' and 'yscale' are meaningful only for scaleType ==
        SCALE_SEPARATE and only where the corresponding xsize/ysize is
        unspecified.  0.0 means unspecified.
     */
     float xscale;
     float yscale;
     /* 'pixels' is meaningful only for scaleType == SCALE_PIXELMAX */
-    unsigned int pixels; 
+    unsigned int pixels;
     unsigned int linear;
     unsigned int verbose;
 };
@@ -466,7 +466,7 @@ lookupFilterByName(const char * const filtername,
         strcpy(known_filters, "");
         for (i = 0; Filters[i].name; ++i) {
             const char * const name = Filters[i].name;
-            if (strlen(known_filters) + strlen(name) + 1 + 1 < 
+            if (strlen(known_filters) + strlen(name) + 1 + 1 <
                 sizeof(known_filters)) {
                 strcat(known_filters, name);
                 strcat(known_filters, " ");
@@ -489,13 +489,13 @@ processFilterOptions(unsigned int const         filterSpec,
     if (filterSpec) {
         filter baseFilter;
         lookupFilterByName(filterOpt, &baseFilter);
-        cmdlineP->filterFunction = baseFilter.function; 
+        cmdlineP->filterFunction = baseFilter.function;
         cmdlineP->filterRadius   = baseFilter.radius;
 
         if (windowSpec) {
             filter windowFilter;
             lookupFilterByName(windowOpt, &windowFilter);
-            
+
             if (cmdlineP->windowFunction == filter_box)
                 cmdlineP->windowFunction = NULL;
             else
@@ -526,28 +526,28 @@ parseSizeParm(const char *   const sizeString,
 
     sizeLong = strtol(sizeString, &endptr, 10);
     if (strlen(sizeString) > 0 && *endptr != '\0')
-        pm_error("%s size argument not an integer: '%s'", 
+        pm_error("%s size argument not an integer: '%s'",
                  description, sizeString);
     else if (sizeLong > INT_MAX - 2)
         pm_error("%s size argument is too large "
-                 "for computations: %ld", 
+                 "for computations: %ld",
                  description, sizeLong);
     else if (sizeLong <= 0)
-        pm_error("%s size argument is not positive: %ld", 
+        pm_error("%s size argument is not positive: %ld",
                  description, sizeLong);
     else
         *sizeP = (unsigned int) sizeLong;
-}        
+}
 
 
 
 static void
-parseXyParms(int                  const argc, 
+parseXyParms(int                  const argc,
              const char **        const argv,
              struct CmdlineInfo * const cmdlineP) {
 
     /* parameters are box width (columns), box height (rows), and
-       optional filespec 
+       optional filespec
     */
     if (argc-1 < 2)
         pm_error("You must supply at least two parameters with "
@@ -571,7 +571,7 @@ parseXyParms(int                  const argc,
 
 
 static void
-parseScaleParms(int                   const argc, 
+parseScaleParms(int                   const argc,
                 const char **         const argv,
                 struct CmdlineInfo  * const cmdlineP) {
 /*----------------------------------------------------------------------------
@@ -583,7 +583,7 @@ parseScaleParms(int                   const argc,
                  "one parameter: the scale factor.");
     else {
         cmdlineP->xscale = cmdlineP->yscale = atof(argv[1]);
-        
+
         if (cmdlineP->xscale <= 0.0)
             pm_error("The scale parameter %s is not a positive number.",
                      argv[1]);
@@ -592,7 +592,7 @@ parseScaleParms(int                   const argc,
                 cmdlineP->inputFileName = "-";
             else {
                 cmdlineP->inputFileName = argv[2];
-                
+
                 if (argc-1 > 2)
                     pm_error("Too many arguments.  There are at most two "
                              "arguments with this set of options: "
@@ -606,7 +606,7 @@ parseScaleParms(int                   const argc,
 
 
 static void
-parseFilespecOnlyParms(int                   const argc, 
+parseFilespecOnlyParms(int                   const argc,
                        const char **         const argv,
                        struct CmdlineInfo  * const cmdlineP) {
 
@@ -618,13 +618,13 @@ parseFilespecOnlyParms(int                   const argc,
 }
 
 
-static void 
-parseCommandLine(int argc, 
-                 const char ** argv, 
+static void
+parseCommandLine(int argc,
+                 const char ** argv,
                  struct CmdlineInfo  * const cmdlineP) {
 /* --------------------------------------------------------------------------
    Parse program command line described in Unix standard form by argc
-   and argv.  Return the information in the options as *cmdlineP.  
+   and argv.  Return the information in the options as *cmdlineP.
 
    If command line is internally inconsistent (invalid options, etc.),
    issue error message to stderr and abort program.
@@ -635,7 +635,7 @@ parseCommandLine(int argc,
     optEntry * option_def;
     optStruct3 opt;
         /* Instructions to pm_optParseOptions3 on how to parse our options. */
-  
+
     unsigned int option_def_index;
     unsigned int xyfit, xyfill;
     int xsize, ysize, pixels;
@@ -665,7 +665,7 @@ parseCommandLine(int argc,
     OPTENT3(0, "window",    OPT_STRING,  &window,    &windowSpec,          0);
     OPTENT3(0, "nomix",     OPT_FLAG,    NULL,       &cmdlineP->nomix,     0);
     OPTENT3(0, "linear",    OPT_FLAG,    NULL,       &cmdlineP->linear,    0);
-  
+
     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 */
@@ -673,7 +673,7 @@ parseCommandLine(int argc,
     pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
     /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
-    if (cmdlineP->nomix && filterSpec) 
+    if (cmdlineP->nomix && filterSpec)
         pm_error("You cannot specify both -nomix and -filter.");
 
     processFilterOptions(filterSpec, filterOpt, windowSpec, window,
@@ -694,19 +694,19 @@ parseCommandLine(int argc,
         pm_error("Cannot specify both -xsize/width and -xscale.");
     if (ysizeSpec && yscaleSpec)
         pm_error("Cannot specify both -ysize/height and -yscale.");
-    
+
     if ((xyfit || xyfill) &&
-        (xsizeSpec || xscaleSpec || ysizeSpec || yscaleSpec || 
+        (xsizeSpec || xscaleSpec || ysizeSpec || yscaleSpec ||
          reduceSpec || pixelsSpec) )
         pm_error("Cannot specify -xyfit/xyfill/xysize with other "
                  "dimension options.");
     if (xyfit && xyfill)
         pm_error("Cannot specify both -xyfit and -xyfill");
-    if (pixelsSpec && 
+    if (pixelsSpec &&
         (xsizeSpec || xscaleSpec || ysizeSpec || yscaleSpec ||
          reduceSpec) )
         pm_error("Cannot specify -pixels with other dimension options.");
-    if (reduceSpec && 
+    if (reduceSpec &&
         (xsizeSpec || xscaleSpec || ysizeSpec || yscaleSpec) )
         pm_error("Cannot specify -reduce with other dimension options.");
 
@@ -722,9 +722,9 @@ parseCommandLine(int argc,
         cmdlineP->scaleType = SCALE_SEPARATE;
         parseFilespecOnlyParms(argc, argv, cmdlineP);
         cmdlineP->xsize = cmdlineP->ysize = 0;
-        cmdlineP->xscale = cmdlineP->yscale = 
+        cmdlineP->xscale = cmdlineP->yscale =
             ((double) 1.0) / ((double) reduce);
-        pm_message("reducing by %d gives scale factor of %f.", 
+        pm_message("reducing by %d gives scale factor of %f.",
                    reduce, cmdlineP->xscale);
     } else if (pixelsSpec) {
         cmdlineP->scaleType = SCALE_PIXELMAX;
@@ -746,12 +746,12 @@ parseCommandLine(int argc,
 
 
 
-static void 
-computeOutputDimensions(struct CmdlineInfo  const cmdline, 
-                        unsigned int        const cols, 
-                        unsigned int        const rows, 
+static void
+computeOutputDimensions(struct CmdlineInfo  const cmdline,
+                        unsigned int        const cols,
+                        unsigned int        const rows,
                         int *               const newcolsP,
-                        int *               const newrowsP) { 
+                        int *               const newrowsP) {
 
     double newcolsD, newrowsD;
         /* Intermediate calculation of the output dimensions, in double
@@ -775,10 +775,10 @@ computeOutputDimensions(struct CmdlineInfo  const cmdline,
     case SCALE_BOXFIT:
     case SCALE_BOXFILL: {
         double const aspect_ratio = (float) cols / (float) rows;
-        double const box_aspect_ratio = 
+        double const box_aspect_ratio =
             (float) cmdline.xsize / (float) cmdline.ysize;
-        
-        if ((box_aspect_ratio > aspect_ratio && 
+
+        if ((box_aspect_ratio > aspect_ratio &&
              cmdline.scaleType == SCALE_BOXFIT) ||
             (box_aspect_ratio < aspect_ratio &&
              cmdline.scaleType == SCALE_BOXFILL)) {
@@ -809,7 +809,7 @@ computeOutputDimensions(struct CmdlineInfo  const cmdline,
             newrowsD = rows;
     }
     }
-    
+
     /* If the rounding yields a zero dimension, we fudge it up to 1.  We do
        this rather than considering it a specification error (and dying)
        because it's friendlier to automated processes that work on arbitrary
@@ -898,9 +898,9 @@ typedef struct {
            at index 0.
         */
     unsigned int allocWeight;
-        /* Number of allocated frames in 'Weight' */ 
+        /* Number of allocated frames in 'Weight' */
     WEIGHT *Weight;
-        /* The terms of the linear combination.  Has 'nWeight' elements. 
+        /* The terms of the linear combination.  Has 'nWeight' elements.
            The coefficients (weights) of each add up to unity.
         */
 } WLIST;
@@ -911,7 +911,7 @@ typedef struct {
         /* The row number in the input image of the row.
            -1 means no row.
         */
-    tuple *tuplerow;  
+    tuple *tuplerow;
         /* The tuples of the row.
            If rowNumber = -1, these are arbitrary, but allocated, tuples.
         */
@@ -957,7 +957,7 @@ appendWeight(WLIST * const WList,
         unsigned int const n = WList->nWeight;
 
         assert(WList->allocWeight >= n+1);
-        
+
         WList->Weight[n].position = index;
         WList->Weight[n].weight   = weight;
         ++WList->nWeight;
@@ -977,7 +977,7 @@ unnormalize(double const normalized,
        wrong thing in actual practice, EG on Darwin PowerPC (my iBook
        running OS X) negative values clamp to maxval.  We get negative
        values because some of the filters (EG catrom) have negative
-       weights.  
+       weights.
     */
 
     return MIN(maxval, (sample)(MAX(0.0, (normalized*maxval + 0.5))));
@@ -1007,10 +1007,10 @@ createWeightList(unsigned int          const targetPos,
                  WLIST *               const weightListP) {
 /*----------------------------------------------------------------------------
    Create a weight list for computing target pixel number 'targetPos' from
-   a set of source pixels.  These pixels are a line of pixels either 
+   a set of source pixels.  These pixels are a line of pixels either
    horizontally or vertically.  The weight list is a list of weights to give
    each source pixel in the set.
-   
+
    The source pixel set is a window of source pixels centered on some
    point.  The weights are defined by the function 'filter' of
    the position within the window, and normalized to add up to 1.0.
@@ -1034,7 +1034,7 @@ createWeightList(unsigned int          const targetPos,
 
    We want to calculate 3 weights, one to be applied to each source pixel
    in computing the target pixel.  Ideally, we would compute the average
-   height of the filter function over each source pixel region.  But 
+   height of the filter function over each source pixel region.  But
    that's too hard.  So we approximate by assuming that the filter function
    is constant within each region, at the value the function has at the
    _center_ of the region.
@@ -1064,12 +1064,12 @@ createWeightList(unsigned int          const targetPos,
        'leftPixel' and 'rightPixel' are the pixel positions of the
        pixels at the edges of that window.  Note that if we're
        doing vertical weights, "left" and "right" mean top and
-       bottom.  
+       bottom.
     */
     double const windowCenter = ((double)targetPos + 0.5) / scale;
     double left = MAX(0.0, windowCenter - filter.radius - EPSILON);
     unsigned int const leftPixel = floor(left);
-    double right = MIN((double)sourceSize - EPSILON, 
+    double right = MIN((double)sourceSize - EPSILON,
                        windowCenter + filter.radius + EPSILON);
     unsigned int const rightPixel = floor(right);
 
@@ -1082,7 +1082,7 @@ createWeightList(unsigned int          const targetPos,
     norm = 0.0;  /* initial value */
 
     for (j = leftPixel; j <= rightPixel; ++j) {
-        /* Calculate the weight that source pixel 'j' will have in the 
+        /* Calculate the weight that source pixel 'j' will have in the
            value of target pixel 'targetPos'.
         */
         double const regionLeft   = MAX(left, (double)j);
@@ -1132,7 +1132,7 @@ createWeightListSet(unsigned int          const sourceSize,
    pixels in a region to effect a resampling.  Multiplying by these
    factors effects all of the following transformations on the
    original pixels:
-   
+
    1) Filter out any frequencies that are artifacts of the
       original sampling.  We assume a perfect sampling was done,
       which means the original continuous dataset had a maximum
@@ -1140,12 +1140,12 @@ createWeightListSet(unsigned int          const sourceSize,
       above that is an artifact of the sampling.  So we filter out
       anything above 1/2 of the original sample rate (sample rate
       == pixel resolution).
-      
+
    2) Filter out any frequencies that are too high to be captured
       by the new sampling -- i.e. frequencies above 1/2 the new
       sample rate.  This is the information we must lose because of low
       sample rate.
-      
+
    3) Sample the result at the new sample rate.
 
    We do all three of these steps in a single convolution of the
@@ -1154,7 +1154,7 @@ createWeightListSet(unsigned int          const sourceSize,
    rectangle function is a pixel domain sinc function, which is
    what we assume 'filterFunction' is.  We get Step 3 by computing
    the convolution only at the new sample points.
-   
+
    I don't know what any of this means when 'filterFunction' is
    not sinc.  Maybe it just means some approximation or additional
    filtering steps are happening.
@@ -1164,7 +1164,7 @@ createWeightListSet(unsigned int          const sourceSize,
     unsigned int targetPos;
 
     MALLOCARRAY_NOFAIL(weightListSet, targetSize);
-    
+
     for (targetPos = 0; targetPos < targetSize; ++targetPos)
         createWeightList(targetPos, sourceSize, scale, filterFunction,
                          &weightListSet[targetPos]);
@@ -1210,7 +1210,7 @@ makeFilterFunction(double          const scale,
 
     retval.basicFunction = basicFunction;
     retval.windowFunction = windowFunction;
-    
+
     retval.horizontalScaler = freqLimit;
 
     /* Our 'windowFunction' argument is a function normalized to the
@@ -1235,11 +1235,11 @@ makeFilterFunction(double          const scale,
 
     return retval;
 }
-                   
 
-                   
+
+
 static void
-destroyWeightListSet(WLIST *      const weightListSet, 
+destroyWeightListSet(WLIST *      const weightListSet,
                      unsigned int const size) {
 
     unsigned int i;
@@ -1264,14 +1264,14 @@ createScanBuf(struct pam * const pamP,
     scanbuf.width = pamP->width;
     scanbuf.height = maxRowWeights;
     MALLOCARRAY_NOFAIL(scanbuf.line, scanbuf.height);
-  
+
     for (lineNumber = 0; lineNumber < scanbuf.height; ++lineNumber) {
         scanbuf.line[lineNumber].rowNumber = -1;
         scanbuf.line[lineNumber].tuplerow = pnm_allocpamrow(pamP);
     }
-  
+
     if (verbose)
-        pm_message("scanline buffer: %d lines of %d pixels", 
+        pm_message("scanline buffer: %d lines of %d pixels",
                    scanbuf.height, scanbuf.width);
 
     *scanbufP = scanbuf;
@@ -1296,10 +1296,10 @@ static void
 resampleDimensionMessage(struct pam * const inpamP,
                          struct pam * const outpamP) {
 
-    pm_message ("resampling from %d*%d to %d*%d (%f, %f)", 
-                inpamP->width, inpamP->height, 
+    pm_message ("resampling from %d*%d to %d*%d (%f, %f)",
+                inpamP->width, inpamP->height,
                 outpamP->width, outpamP->height,
-                (double)outpamP->width/inpamP->width, 
+                (double)outpamP->width/inpamP->width,
                 (double)outpamP->height/inpamP->height);
 }
 
@@ -1325,12 +1325,12 @@ addInPixel(const struct pam * const pamP,
     for (plane = 0; plane < pamP->depth; ++plane) {
         double const normalizedSample = (double)tuple[plane]/pamP->maxval;
         double opacityAdjustment;
-        
+
         if (haveOpacity && plane != opacityPlane)
             opacityAdjustment = (double)tuple[opacityPlane]/pamP->maxval;
         else
             opacityAdjustment = 1;
-        
+
         accum[plane] += opacityAdjustment * normalizedSample * weight;
     }
 }
@@ -1340,7 +1340,7 @@ addInPixel(const struct pam * const pamP,
 static void
 generateOutputTuple(const struct pam * const pamP,
                     double             const accum[],
-                    bool               const haveOpacity, 
+                    bool               const haveOpacity,
                     unsigned int       const opacityPlane,
                     tuple *            const tupleP) {
 /*----------------------------------------------------------------------------
@@ -1358,7 +1358,7 @@ generateOutputTuple(const struct pam * const pamP,
         if (haveOpacity && plane != opacityPlane) {
             if (accum[opacityPlane] < EPSILON) {
                 opacityAdjustedSample = 0.0;
-            } else 
+            } else
                 opacityAdjustedSample = accum[plane] / accum[opacityPlane];
         } else
             opacityAdjustedSample = accum[plane];
@@ -1377,7 +1377,7 @@ outputOneResampledRow(const struct pam * const outpamP,
                       tuple *            const line,
                       double *           const accum) {
 /*----------------------------------------------------------------------------
-   From the data in 'scanbuf' and weights in 'YW' and 'XWeight', 
+   From the data in 'scanbuf' and weights in 'YW' and 'XWeight',
    generate one output row for the image described by *outpamP and
    output it.
 
@@ -1411,24 +1411,24 @@ outputOneResampledRow(const struct pam * const outpamP,
             for (plane = 0; plane < outpamP->depth; ++plane)
                 accum[plane] = 0.0;
         }
-        
+
         for (i = 0; i < YW.nWeight; ++i) {
             int   const yp   = YW.Weight[i].position;
             float const yw   = YW.Weight[i].weight;
             int   const slot = yp % scanbuf.height;
 
             unsigned int j;
-            
+
             for (j = 0; j < XW.nWeight; ++j) {
                 int   const xp    = XW.Weight[j].position;
                 tuple const tuple = scanbuf.line[slot].tuplerow[xp];
-                
-                addInPixel(outpamP, tuple, yw * XW.Weight[j].weight, 
+
+                addInPixel(outpamP, tuple, yw * XW.Weight[j].weight,
                            haveOpacity, opacityPlane,
                            accum);
             }
         }
-        generateOutputTuple(outpamP, accum, haveOpacity, opacityPlane, 
+        generateOutputTuple(outpamP, accum, haveOpacity, opacityPlane,
                             &line[col]);
     }
     pnm_writepamrow(outpamP, line);
@@ -1447,7 +1447,7 @@ scanbufContainsTheRows(SCAN  const scanbuf,
 -----------------------------------------------------------------------------*/
     bool missingRow;
     unsigned int i;
-    
+
     for (i = 0, missingRow = FALSE;
          i < rowWeights.nWeight && !missingRow;
         ++i) {
@@ -1481,7 +1481,7 @@ createWeightLists(struct pam *     const inpamP,
 /*----------------------------------------------------------------------------
    This is the function that actually does the resampling.  Note that it
    does it without ever looking at the source or target pixels!  It produces
-   a simple set of numbers that Caller can blindly apply to the source 
+   a simple set of numbers that Caller can blindly apply to the source
    pixels to get target pixels.
 -----------------------------------------------------------------------------*/
     struct filterFunction horizFilter, vertFilter;
@@ -1490,14 +1490,14 @@ createWeightLists(struct pam *     const inpamP,
         (double)outpamP->width/inpamP->width,
         filterFunction, filterRadius, windowFunction);
 
-    createWeightListSet(inpamP->width, outpamP->width, horizFilter, 
+    createWeightListSet(inpamP->width, outpamP->width, horizFilter,
                         horizWeightP);
-    
+
     vertFilter = makeFilterFunction(
         (double)outpamP->height/inpamP->height,
         filterFunction, filterRadius, windowFunction);
 
-    createWeightListSet(inpamP->height, outpamP->height, vertFilter, 
+    createWeightListSet(inpamP->height, outpamP->height, vertFilter,
                         vertWeightP);
 
     *maxRowWeightsP = ceil(2.0*(vertFilter.radius+EPSILON) + 1 + EPSILON);
@@ -1516,12 +1516,12 @@ resample(struct pam *     const inpamP,
 /*---------------------------------------------------------------------------
   Resample the image in the input file, described by *inpamP,
   so as to create the image in the output file, described by *outpamP.
-  
+
   Input and output differ by height, width, and maxval only.
 
   Use the resampling filter function 'filterFunction', applied over
   radius 'filterRadius'.
-  
+
   The input file is positioned past the header, to the beginning of the
   raster.  The output file is too.
 ---------------------------------------------------------------------------*/
@@ -1539,7 +1539,7 @@ resample(struct pam *     const inpamP,
     if (linear)
         pm_error("You cannot use the resampling scaling method on "
                  "linear input.");
-  
+
     createWeightLists(inpamP, outpamP, filterFunction, filterRadius,
                       windowFunction, &horizWeight, &vertWeight,
                       &maxRowWeights);
@@ -1576,10 +1576,10 @@ resample(struct pam *     const inpamP,
                    i.e. what fractions of which input rows combine to create
                    this output row.
                 */
-            assert(rowWeights.nWeight <= scanbuf.height); 
+            assert(rowWeights.nWeight <= scanbuf.height);
 
             if (scanbufContainsTheRows(scanbuf, rowWeights)) {
-                outputOneResampledRow(outpamP, scanbuf, rowWeights, 
+                outputOneResampledRow(outpamP, scanbuf, rowWeights,
                                       horizWeight, line, weight);
                 ++outputRow;
             } else
@@ -1609,7 +1609,7 @@ resample(struct pam *     const inpamP,
 static void
 zeroNewRow(struct pam * const pamP,
            tuplen *     const tuplenrow) {
-    
+
     unsigned int col;
 
     for (col = 0; col < pamP->width; ++col) {
@@ -1625,7 +1625,7 @@ zeroNewRow(struct pam * const pamP,
 static void
 accumOutputCol(struct pam * const pamP,
                tuplen       const intuplen,
-               float        const fraction, 
+               float        const fraction,
                tuplen       const accumulator) {
 /*----------------------------------------------------------------------------
    Add fraction 'fraction' of the pixel indicated by 'intuplen' to the
@@ -1645,7 +1645,7 @@ accumOutputCol(struct pam * const pamP,
 
 
 static void
-horizontalScale(tuplen *     const inputtuplenrow, 
+horizontalScale(tuplen *     const inputtuplenrow,
                 tuplen *     const newtuplenrow,
                 struct pam * const inpamP,
                 struct pam * const outpamP,
@@ -1683,7 +1683,7 @@ horizontalScale(tuplen *     const inputtuplenrow,
             /* Generate one output pixel in 'newtuplerow'.  It will
                consist of anything accumulated from prior input pixels
                in accumulator[], plus a fraction of the current input
-               pixel.  
+               pixel.
             */
             assert(newcol < outpamP->width);
             accumOutputCol(inpamP, inputtuplenrow[col], fraccoltofill,
@@ -1695,7 +1695,7 @@ horizontalScale(tuplen *     const inputtuplenrow,
             ++newcol;
             fraccoltofill = 1.0;
         }
-        /* There's not enough left in the current input pixel to fill up 
+        /* There's not enough left in the current input pixel to fill up
            a whole output column, so just accumulate the remainder of the
            pixel into the current output column.  Because of rounding, we may
            have a tiny bit of pixel left and have run out of output pixels.
@@ -1714,17 +1714,17 @@ horizontalScale(tuplen *     const inputtuplenrow,
                  newcol, outpamP->width-1);
 
     if (newcol < outpamP->width) {
-        /* We were still working on the last output column when we 
+        /* We were still working on the last output column when we
            ran out of input columns.  This would be because of rounding
            down, and we should be missing only a tiny fraction of that
            last output column.  Just fill in the missing color with the
            color of the rightmost input pixel.
         */
-        accumOutputCol(inpamP, inputtuplenrow[inpamP->width-1], 
+        accumOutputCol(inpamP, inputtuplenrow[inpamP->width-1],
                        fraccoltofill, newtuplenrow[newcol]);
-        
+
         *stretchP = fraccoltofill;
-    } else 
+    } else
         *stretchP = 0.0;
 }
 
@@ -1747,11 +1747,11 @@ zeroAccum(struct pam * const pamP,
 
 static void
 accumOutputRow(struct pam * const pamP,
-               tuplen *     const tuplenrow, 
-               float        const fraction, 
+               tuplen *     const tuplenrow,
+               float        const fraction,
                tuplen *     const accumulator) {
 /*----------------------------------------------------------------------------
-   Take 'fraction' times the samples in row 'tuplenrow' and add it to 
+   Take 'fraction' times the samples in row 'tuplenrow' and add it to
    'accumulator' in the same way as accumOutputCol().
 
    'fraction' is less than 1.0.
@@ -1838,7 +1838,7 @@ writeARow(struct pam *             const pamP,
 
 
 static void
-issueStretchWarning(bool   const verbose, 
+issueStretchWarning(bool   const verbose,
                     double const fracrowtofill) {
 
     /* We need another input row to fill up this
@@ -1847,11 +1847,11 @@ issueStretchWarning(bool   const verbose,
        scaling arithmetic.  So we go ahead with
        the data from the last row we read, which
        amounts to stretching out the last output
-       row.  
+       row.
     */
     if (verbose)
         pm_message("%f of bottom row stretched because of "
-                   "arithmetic imprecision", 
+                   "arithmetic imprecision",
                    fracrowtofill);
 }
 
@@ -1873,21 +1873,21 @@ scaleHorizontallyAndOutputRow(struct pam *             const inpamP,
    'newtuplenrow' is work space Caller provides us.  It is at least
    wide enough to hold one output row.
 -----------------------------------------------------------------------------*/
-    if (outpamP->width == inpamP->width)    
+    if (outpamP->width == inpamP->width)
         /* shortcut X scaling */
         writeARow(outpamP, rowAccumulator, transform);
             /* This destroys 'rowAccumulator' */
     else {
         float stretch;
-            
+
         horizontalScale(rowAccumulator, newtuplenrow, inpamP, outpamP,
                         xscale, &stretch);
-            
+
         if (verbose && row == 0)
             pm_message("%f of right column stretched because of "
-                       "arithmetic imprecision", 
+                       "arithmetic imprecision",
                        stretch);
-            
+
         writeARow(outpamP, newtuplenrow, transform);
             /* This destroys 'newtuplenrow' */
     }
@@ -1919,7 +1919,7 @@ destroyTransforms(const pnm_transformMap * const inputTransform,
 
     if (inputTransform)
         free((void*)inputTransform);
-    
+
     if (outputTransform)
         free((void*)outputTransform);
 }
@@ -1929,7 +1929,7 @@ destroyTransforms(const pnm_transformMap * const inputTransform,
 static void
 scaleWithMixing(struct pam * const inpamP,
                 struct pam * const outpamP,
-                float        const xscale, 
+                float        const xscale,
                 float        const yscale,
                 bool         const assumeLinear,
                 bool         const verbose) {
@@ -1950,8 +1950,8 @@ scaleWithMixing(struct pam * const inpamP,
   approximate but fast results).
 
 -----------------------------------------------------------------------------*/
-    /* Here's how we think of the color mixing scaling operation:  
-       
+    /* Here's how we think of the color mixing scaling operation:
+
        First, I'll describe scaling in one dimension.  Assume we have
        a one row image.  A raster row is ordinarily a sequence of
        discrete pixels which have no width and no distance between
@@ -1973,7 +1973,7 @@ scaleWithMixing(struct pam * const inpamP,
        look the same.
 
        This works for all scale factors, both scaling up and scaling down.
-       
+
        For images with an opacity plane, imagine Input Pixel 0's
        foreground is fully opaque red (1,0,0,1), and Input Pixel 1 is
        fully transparent (foreground irrelevant) (0,0,0,0).  We make
@@ -1994,14 +1994,14 @@ scaleWithMixing(struct pam * const inpamP,
        stretch the image vertically first (same process as above, but
        in place of a single-color pixels, we have a vector of colors).
        Then we take each row this vertical stretching generates and
-       stretch it horizontally.  
+       stretch it horizontally.
     */
 
     tuplen * tuplenrow;     /* An input row */
     tuplen * newtuplenrow;  /* Working space */
     float rowsleft;
     /* The number of rows of output that need to be formed from the
-       current input row (the one in tuplerow[]), less the number that 
+       current input row (the one in tuplerow[]), less the number that
        have already been formed (either in accumulator[]
        or output to the file).  This can be fractional because of the
        way we define rows as having height.
@@ -2021,8 +2021,8 @@ scaleWithMixing(struct pam * const inpamP,
     int row;
     const pnm_transformMap * inputTransform;
     const pnm_transformMap * outputTransform;
-    
-    tuplenrow = pnm_allocpamrown(inpamP); 
+
+    tuplenrow = pnm_allocpamrown(inpamP);
     rowAccumulator = pnm_allocpamrown(inpamP);
 
     rowsread = 0;
@@ -2087,7 +2087,7 @@ scaleWithMixing(struct pam * const inpamP,
 static void
 scaleWithoutMixing(const struct pam * const inpamP,
                    const struct pam * const outpamP,
-                   float              const xscale, 
+                   float              const xscale,
                    float              const yscale) {
 /*----------------------------------------------------------------------------
   Scale the image described by *inpamP by xscale horizontally and
@@ -2096,9 +2096,9 @@ scaleWithoutMixing(const struct pam * const inpamP,
 
   The input file is positioned past the header, to the beginning of the
   raster.  The output file is too.
-  
+
   Don't mix colors from different input pixels together in the output
-  pixels.  Each output pixel is an exact copy of some corresponding 
+  pixels.  Each output pixel is an exact copy of some corresponding
   input pixel.
 -----------------------------------------------------------------------------*/
     tuple * tuplerow;  /* An input row */
@@ -2109,22 +2109,22 @@ scaleWithoutMixing(const struct pam * const inpamP,
     assert(outpamP->maxval == inpamP->maxval);
     assert(outpamP->depth  == inpamP->depth);
 
-    tuplerow = pnm_allocpamrow(inpamP); 
+    tuplerow = pnm_allocpamrow(inpamP);
     rowInInput = -1;
 
     newtuplerow = pnm_allocpamrow(outpamP);
 
     for (row = 0; row < outpamP->height; ++row) {
         int col;
-        
+
         int const inputRow = (int) (row / yscale);
 
-        for (; rowInInput < inputRow; ++rowInInput) 
+        for (; rowInInput < inputRow; ++rowInInput)
             pnm_readpamrow(inpamP, tuplerow);
-        
+
         for (col = 0; col < outpamP->width; ++col) {
             int const inputCol = (int) (col / xscale);
-            
+
             pnm_assigntuple(inpamP, newtuplerow[col], tuplerow[inputCol]);
         }
 
@@ -2140,7 +2140,7 @@ static void
 pamscale(FILE *             const ifP,
          FILE *             const ofP,
          struct CmdlineInfo const cmdline) {
-    
+
     struct pam inpam, outpam;
     float xscale, yscale;
 
@@ -2158,21 +2158,21 @@ pamscale(FILE *             const ifP,
         outpam.maxval = inpam.maxval;
     }
 
-    computeOutputDimensions(cmdline, inpam.width, inpam.height, 
+    computeOutputDimensions(cmdline, inpam.width, inpam.height,
                             &outpam.width, &outpam.height);
 
     xscale = (float) outpam.width / inpam.width;
     yscale = (float) outpam.height / inpam.height;
 
     if (cmdline.verbose) {
-        pm_message("Scaling by %f horizontally to %d columns.", 
+        pm_message("Scaling by %f horizontally to %d columns.",
                    xscale, outpam.width);
-        pm_message("Scaling by %f vertically to %d rows.", 
+        pm_message("Scaling by %f vertically to %d rows.",
                    yscale, outpam.height);
     }
 
     if (xscale * inpam.width < outpam.width - 1 ||
-        yscale * inpam.height < outpam.height - 1) 
+        yscale * inpam.height < outpam.height - 1)
         pm_error("Arithmetic precision of this program is inadequate to "
                  "do the specified scaling.  Use a smaller input image "
                  "or a slightly different scale factor.");
@@ -2186,7 +2186,7 @@ pamscale(FILE *             const ifP,
     } else if (!cmdline.filterFunction) {
         if (cmdline.verbose)
             pm_message("Using simple pixel mixing rescaling method");
-        scaleWithMixing(&inpam, &outpam, xscale, yscale, 
+        scaleWithMixing(&inpam, &outpam, xscale, yscale,
                         cmdline.linear, cmdline.verbose);
     } else {
         if (cmdline.verbose)
@@ -2221,6 +2221,6 @@ main(int argc, const char **argv ) {
 
     pm_close(ifP);
     pm_close(stdout);
-    
+
     return 0;
 }
diff --git a/editor/pbmclean.c b/editor/pbmclean.c
index 46e7dee6..08f410c0 100644
--- a/editor/pbmclean.c
+++ b/editor/pbmclean.c
@@ -6,13 +6,14 @@
 =============================================================================*/
 #include <assert.h>
 #include <stdio.h>
+#include <stdbool.h>
 
 #include "pm_c_util.h"
 #include "mallocvar.h"
 #include "shhopt.h"
 #include "pbm.h"
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
@@ -28,7 +29,7 @@ struct cmdlineInfo {
 
 static void
 parseCommandLine(int argc, const char ** argv,
-                 struct cmdlineInfo *cmdlineP) {
+                 struct CmdlineInfo *cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that the file spec array we return is stored in the storage that
    was passed to us as the argv array.
@@ -46,13 +47,13 @@ parseCommandLine(int argc, const char ** argv,
     OPTENT3(0,   "verbose",          OPT_FLAG, NULL, &cmdlineP->verbose, 0);
     OPTENT3(0,   "black",            OPT_FLAG, NULL, &black, 0);
     OPTENT3(0,   "white",            OPT_FLAG, NULL, &white, 0);
-    OPTENT3(0,   "minneighbors",     OPT_UINT, &cmdlineP->minneighbors, 
+    OPTENT3(0,   "minneighbors",     OPT_UINT, &cmdlineP->minneighbors,
             &minneighborsSpec, 0);
     OPTENT3(0,   "extended",         OPT_FLAG, NULL, &cmdlineP->extended, 0);
 
     opt.opt_table = option_def;
-    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
-    opt.allowNegNum = TRUE;  /* We sort of allow negative numbers as parms */
+    opt.short_allowed = false;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = true;  /* We sort of allow negative numbers as parms */
 
     pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
@@ -64,8 +65,8 @@ parseCommandLine(int argc, const char ** argv,
             pm_error("With -extended, you cannot specify both "
                      "-black and -white");
         else if (!black & !white) {
-            cmdlineP->flipBlack = TRUE;
-            cmdlineP->flipWhite = FALSE;
+            cmdlineP->flipBlack = true;
+            cmdlineP->flipWhite = false;
         } else {
             cmdlineP->flipBlack = !!black;
             cmdlineP->flipWhite = !!white;
@@ -77,7 +78,7 @@ parseCommandLine(int argc, const char ** argv,
         } else {
             cmdlineP->flipBlack = !!black;
             cmdlineP->flipWhite = !!white;
-        }    
+        }
     }
     if (!minneighborsSpec) {
         /* Now we do a sleazy tour through the parameters to see if
@@ -86,7 +87,7 @@ parseCommandLine(int argc, const char ** argv,
            unconventional syntax where a -N option was used instead of
            the current -minneighbors option.  The only reason -N didn't
            get processed by pm_pm_optParseOptions3() is that it looked
-           like a negative number parameter instead of an option.  
+           like a negative number parameter instead of an option.
            If we find a -N, we make like it was a -minneighbors=N option.
         */
         int i;
@@ -109,7 +110,7 @@ parseCommandLine(int argc, const char ** argv,
             --argc;
     }
 
-    if (argc-1 < 1) 
+    if (argc-1 < 1)
         cmdlineP->inputFileName = "-";
     else if (argc-1 == 1)
         cmdlineP->inputFileName = argv[1];
@@ -160,7 +161,7 @@ bitpop24(uint32_t const w){
 -----------------------------------------------------------------------------*/
     return (bitpop8((w >> 16) & 0xff) +
             bitpop8((w >>  8) & 0xff) +
-            bitpop8((w >>  0) & 0xff));  
+            bitpop8((w >>  0) & 0xff));
 }
 
 
@@ -204,11 +205,11 @@ and written to outrow at the byte boundary.
 
 
 static unsigned int
-likeNeighbors(uint32_t     const blackSample, 
+likeNeighbors(uint32_t     const blackSample,
               unsigned int const offset) {
 
     bool const thispoint = ( blackSample >> (18-offset) ) & 0x01;
-    uint32_t const sample = (thispoint == PBM_BLACK ) 
+    uint32_t const sample = (thispoint == PBM_BLACK )
                           ?   blackSample
                           : ~ blackSample ;
     uint32_t const selection = 0x701407;
@@ -238,7 +239,7 @@ setSample(const bit *  const prevrow,
         ((nextrow[col8 - 1] & 0x01)  <<  9) |
         ((nextrow[col8]           )  <<  1) |
         ((nextrow[col8 + 1] & 0x80)  >>  7);
-    
+
     return sample;
 }
 
@@ -277,7 +278,7 @@ cleanrow(const bit *    const prevrow,
 /* ----------------------------------------------------------------------
   Work through row, scanning for bits that require flipping, and write
   the results to 'outrow'.
-  
+
   Returns the number of bits flipped within this one row as *nFlippedP.
 -------------------------------------------------------------------------*/
     uint32_t sample;
@@ -350,9 +351,9 @@ setupInputBuffers(FILE *       const ifP,
 
     for (i = 0; i < pbm_packed_bytes(cols+16); ++i)
         edgeRow[i] = 0x00;
-        
+
     for (i = 0; i < 3; ++i) {
-        /* Add blank (all white) bytes beside the edges */ 
+        /* Add blank (all white) bytes beside the edges */
         buffer[i][0] = buffer[i][ pbm_packed_bytes( cols +16 ) - 1] = 0x00;
     }
     nextRow = &buffer[0][1];
@@ -374,7 +375,7 @@ setupInputBuffers(FILE *       const ifP,
 static void
 cleanSimple(FILE *             const ifP,
             FILE *             const ofP,
-            struct cmdlineInfo const cmdline,
+            struct CmdlineInfo const cmdline,
             double *           const nFlippedP) {
 /*----------------------------------------------------------------------------
    Do the traditional clean where you look only at the immediate neighboring
@@ -412,7 +413,7 @@ cleanSimple(FILE *             const ifP,
         if (row < rows -1){
             nextRow = &buffer[(row+1)%3][1];
             /* We take the address directly instead of shuffling the rows
-               with the help of a temporary.  This provision is for proper 
+               with the help of a temporary.  This provision is for proper
                handling of the initial edgerow.
             */
             pbm_readpbmrow_packed(ifP, nextRow, cols, format);
@@ -423,7 +424,7 @@ cleanSimple(FILE *             const ifP,
 
         cleanrow(prevRow, thisRow, nextRow, outRow, cols, cmdline.minneighbors,
                  cmdline.flipWhite, cmdline.flipBlack, &nFlipped);
-        
+
         *nFlippedP += nFlipped;
 
         pbm_writepbmrow_packed(ofP, outRow, cols, 0) ;
@@ -446,7 +447,7 @@ typedef struct {
    A queue of pixel locations.
 -----------------------------------------------------------------------------*/
     unsigned int size;
-    
+
     struct PixQueueElt * headP;
     struct PixQueueElt * tailP;
 } PixQueue;
@@ -495,7 +496,7 @@ pixQueue_push(PixQueue *    const queueP,
     newEltP->nextP = NULL;
     if (queueP->tailP)
         queueP->tailP->nextP = newEltP;
-    
+
     queueP->tailP = newEltP;
 
     if (!queueP->headP)
@@ -538,7 +539,7 @@ pixQueue_term(PixQueue * const queueP) {
 
     struct PixQueueElt * p;
     struct PixQueueElt * nextP;
-    
+
     for (p = queueP->headP; p; p = nextP) {
         nextP = p->nextP;
         free(p);
@@ -720,9 +721,9 @@ cleanPixels(bit **       const pixels,
         for (thisPix.col = 0; thisPix.col < cols; ++thisPix.col) {
             if (pixels[thisPix.row][thisPix.col] == foregroundColor
                 && !visited[thisPix.row][thisPix.col]) {
-                
+
                 double nFlipped;
-                
+
                 processBlob(thisPix, pixels, cols, rows, trivialSize,
                             visited, &nFlipped);
 
@@ -772,7 +773,7 @@ cleanExtended(FILE *             const ifP,
 static void
 pbmclean(FILE *             const ifP,
          FILE *             const ofP,
-         struct cmdlineInfo const cmdline,
+         struct CmdlineInfo const cmdline,
          double *           const nFlippedP) {
 
     if (cmdline.extended) {
@@ -791,7 +792,7 @@ pbmclean(FILE *             const ifP,
 int
 main(int argc, const char *argv[]) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     FILE * ifP;
     double nFlipped;
         /* Number of pixels we have flipped so far.  Use type double to
diff --git a/editor/pbmmask.c b/editor/pbmmask.c
index 25c71226..0be10435 100644
--- a/editor/pbmmask.c
+++ b/editor/pbmmask.c
@@ -10,13 +10,57 @@
 ** implied warranty.
 */
 
+#include <stdbool.h>
+#include <assert.h>
+
 #include "pbm.h"
+#include "shhopt.h"
 #include "mallocvar.h"
 
-static bit ** bits;
-static bit ** mask;
-static bit backcolor;
-static int rows, cols;
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFileName;  /* File name of input file */
+    unsigned int expand;
+};
+
+
+
+static void
+parseCommandLine(int argc, const char ** argv,
+                 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.
+-----------------------------------------------------------------------------*/
+    optStruct3 opt;  /* set by OPTENT3 */
+    optEntry * option_def;
+    unsigned int option_def_index;
+
+    MALLOCARRAY(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0,   "expand",          OPT_FLAG, NULL, &cmdlineP->expand, 0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = false;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = true;  /* We sort of allow negative numbers as parms */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    free(option_def);
+
+    if (argc-1 < 1)
+        cmdlineP->inputFileName = "-";
+    else if (argc-1 == 1)
+        cmdlineP->inputFileName = argv[1];
+    else
+        pm_error("You specified too many arguments (%u).  The only "
+                 "possible argument is the optional input file specification.",
+                 argc-1);
+}
 
 
 
@@ -28,25 +72,78 @@ static int fstackp = 0;
 
 
 static void
-addflood(int const col,
-         int const row) {
+clearMask(bit ** const mask,
+          unsigned int const cols,
+          unsigned int const rows) {
+
+    /* Clear out the mask. */
+    unsigned int row;
 
-    if ( bits[row][col] == backcolor && mask[row][col] == PBM_BLACK ) {
-        if ( fstackp >= fstacksize ) {
-            if ( fstacksize == 0 ) {
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+
+        for (col = 0; col < cols; ++col)
+            mask[row][col] = PBM_BLACK;
+    }
+}
+
+
+
+static bit
+backcolorFmImage(bit **       const bits,
+                 unsigned int const cols,
+                 unsigned int const rows) {
+
+    /* Figure out the background color, by counting along the edge. */
+
+    unsigned int row;
+    unsigned int col;
+    unsigned int wcount;
+
+    assert(cols > 0); assert(rows > 0);
+
+    wcount = 0;
+    for (row = 0; row < rows; ++row) {
+        if (bits[row][0] == PBM_WHITE)
+            ++wcount;
+        if (bits[row][cols - 1] == PBM_WHITE)
+            ++wcount;
+    }
+    for (col = 1; col < cols - 1; ++col) {
+        if (bits[0][col] == PBM_WHITE)
+            ++wcount;
+        if (bits[rows - 1][col] == PBM_WHITE)
+            ++wcount;
+    }
+
+    return (wcount >= rows + cols - 2) ? PBM_WHITE : PBM_BLACK;
+}
+
+
+
+static void
+addflood(bit **       const bits,
+         bit **       const mask,
+         unsigned int const col,
+         unsigned int const row,
+         bit          const backcolor) {
+
+    if (bits[row][col] == backcolor && mask[row][col] == PBM_BLACK) {
+        if (fstackp >= fstacksize) {
+            if (fstacksize == 0) {
                 fstacksize = 1000;
                 MALLOCARRAY(fcols, fstacksize);
                 MALLOCARRAY(frows, fstacksize);
-                if ( fcols == NULL || frows == NULL )
-                    pm_error( "out of memory" );
+                if (fcols == NULL || frows == NULL)
+                    pm_error("out of memory");
             } else {
                 fstacksize *= 2;
                 fcols = (short*) realloc(
-                    (char*) fcols, fstacksize * sizeof(short) );
+                    (char*) fcols, fstacksize * sizeof(short));
                 frows = (short*) realloc(
-                    (char*) frows, fstacksize * sizeof(short) );
-                if ( fcols == (short*) 0 || frows == (short*) 0 )
-                    pm_error( "out of memory" );
+                    (char*) frows, fstacksize * sizeof(short));
+                if (fcols == (short*) 0 || frows == (short*)0)
+                    pm_error("out of memory");
             }
         }
         fcols[fstackp] = col;
@@ -58,46 +155,81 @@ addflood(int const col,
 
 
 static void
-flood(void) {
+floodEdge(bit **       const bits,
+          unsigned int const cols,
+          unsigned int const rows,
+          bit          const backcolor,
+          bit **       const mask) {
+
+    int col;
+    int row;
+
+    /* Flood the entire edge.  Probably the first call will be enough, but
+       might as well be sure.
+    */
+    assert(cols > 0); assert(rows > 0);
+
+    for (col = cols - 3; col >= 2; col -= 2) {
+        addflood(bits, mask, col, rows - 1, backcolor);
+        addflood(bits, mask, col, 0, backcolor);
+    }
+    for (row = rows - 1; row >= 0; row -= 2) {
+        addflood(bits, mask, cols - 1, row, backcolor);
+        addflood(bits, mask, 0, row, backcolor);
+    }
+}
+
+
+
+static void
+flood(bit **       const bits,
+      unsigned int const cols,
+      unsigned int const rows,
+      bit          const backcolor,
+      bit **       const mask) {
+
+    assert(cols > 0); assert(rows > 0);
 
-    while ( fstackp > 0 ) {
+    floodEdge(bits, cols, rows, backcolor, mask);
+
+    while (fstackp > 0) {
         int col, row;
         --fstackp;
         col = fcols[fstackp];
         row = frows[fstackp];
-        if ( bits[row][col] == backcolor && mask[row][col] == PBM_BLACK ) {
+        if (bits[row][col] == backcolor && mask[row][col] == PBM_BLACK) {
             int c;
             mask[row][col] = PBM_WHITE;
-            if ( row - 1 >= 0 )
-                addflood( col, row - 1 );
-            if ( row + 1 < rows )
-                addflood( col, row + 1 );
-            for ( c = col + 1; c < cols; ++c ) {
-                if ( bits[row][c] == backcolor && mask[row][c] == PBM_BLACK ) {
+            if (row - 1 >= 0)
+                addflood(bits, mask, col, row - 1, backcolor);
+            if (row + 1 < rows)
+                addflood(bits, mask, col, row + 1, backcolor);
+            for (c = col + 1; c < cols; ++c) {
+                if (bits[row][c] == backcolor && mask[row][c] == PBM_BLACK) {
                     mask[row][c] = PBM_WHITE;
-                    if ( row - 1 >= 0 && 
-                         ( bits[row - 1][c - 1] != backcolor || 
-                           mask[row - 1][c - 1] != PBM_BLACK ) )
-                        addflood( c, row - 1 );
-                    if ( row + 1 < rows && 
-                         ( bits[row + 1][c - 1] != backcolor || 
-                           mask[row + 1][c - 1] != PBM_BLACK ) )
-                        addflood( c, row + 1 );
+                    if (row - 1 >= 0 &&
+                        (bits[row - 1][c - 1] != backcolor ||
+                         mask[row - 1][c - 1] != PBM_BLACK))
+                        addflood(bits, mask, c, row - 1, backcolor);
+                    if (row + 1 < rows &&
+                         (bits[row + 1][c - 1] != backcolor ||
+                          mask[row + 1][c - 1] != PBM_BLACK))
+                        addflood(bits, mask, c, row + 1, backcolor);
                 }
                 else
                     break;
             }
-            for ( c = col - 1; c >= 0; --c ) {
-                if ( bits[row][c] == backcolor && mask[row][c] == PBM_BLACK ) {
+            for (c = col - 1; c >= 0; --c) {
+                if (bits[row][c] == backcolor && mask[row][c] == PBM_BLACK) {
                     mask[row][c] = PBM_WHITE;
-                    if ( row - 1 >= 0 && 
-                         ( bits[row - 1][c + 1] != backcolor || 
-                           mask[row - 1][c + 1] != PBM_BLACK ) )
-                        addflood( c, row - 1 );
-                    if ( row + 1 < rows && 
-                         ( bits[row + 1][c + 1] != backcolor || 
-                           mask[row + 1][c + 1] != PBM_BLACK ) )
-                        addflood( c, row + 1 );
+                    if (row - 1 >= 0 &&
+                        (bits[row - 1][c + 1] != backcolor ||
+                         mask[row - 1][c + 1] != PBM_BLACK))
+                        addflood(bits, mask, c, row - 1, backcolor);
+                    if (row + 1 < rows &&
+                         (bits[row + 1][c + 1] != backcolor ||
+                          mask[row + 1][c + 1] != PBM_BLACK))
+                        addflood(bits, mask, c, row + 1, backcolor);
                 } else
                     break;
             }
@@ -107,121 +239,103 @@ flood(void) {
 
 
 
-int
-main(int argc, char * argv[]) {
-
-    FILE* ifp;
-    int argn, expand, wcount;
-    register int row, col;
-    const char* const usage = "[-expand] [pbmfile]";
-
-    pbm_init( &argc, argv );
-
-    argn = 1;
-    expand = 0;
-
-    if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
-    {
-        if ( pm_keymatch( argv[argn], "-expand", 2 ) )
-            expand = 1;
-        else if ( pm_keymatch( argv[argn], "-noexpand", 2 ) )
-            expand = 0;
-        else
-            pm_usage( usage );
-        ++argn;
-    }
+static bit **
+expandedByOnePixel(bit **       const mask,
+                   unsigned int const cols,
+                   unsigned int const rows) {
 
-    if ( argn == argc )
-        ifp = stdin;
-    else
-    {
-        ifp = pm_openr( argv[argn] );
-        ++argn;
+    /* Expand by one pixel. */
+
+    bit ** const emask = pbm_allocarray(cols, rows);
+
+    unsigned int row;
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            if (mask[row][col] == PBM_BLACK)
+                emask[row][col] = PBM_BLACK;
+            else {
+                unsigned int srow;
+
+                emask[row][col] = PBM_WHITE;
+
+                for (srow = row - 1; srow <= row + 1; ++srow) {
+                    unsigned int scol;
+
+                    for (scol = col - 1; scol <= col + 1; ++scol) {
+                        if (srow >= 0 && srow < rows &&
+                            scol >= 0 && scol < cols &&
+                            mask[srow][scol] == PBM_BLACK) {
+
+                            emask[row][col] = PBM_BLACK;
+                            break;
+                        }
+                    }
+                }
+            }
     }
+    return emask;
+}
+
+
 
-    if ( argn != argc )
-        pm_usage( usage );
+static void
+pbmmask(FILE *             const ifP,
+        FILE *             const ofP,
+        struct CmdlineInfo const cmdline) {
+
+    int cols, rows;
+    bit ** mask;
+    bit ** bits;
+    bit backcolor;
 
-    bits = pbm_readpbm( ifp, &cols, &rows );
+    bits = pbm_readpbm(ifP, &cols, &rows);
 
     if (cols == 0 || rows == 0)
         pm_error("Image contains no pixels, so there is no such thing "
                  "as background and foreground");
 
-    pm_close( ifp );
-    mask = pbm_allocarray( cols, rows );
+    mask = pbm_allocarray(cols, rows);
 
-    /* Clear out the mask. */
-    for ( row = 0; row < rows; ++row )
-        for ( col = 0; col < cols; ++col )
-            mask[row][col] = PBM_BLACK;
+    clearMask(mask, cols, rows);
 
-    /* Figure out the background color, by counting along the edge. */
-    wcount = 0;
-    for ( row = 0; row < rows; ++row ) {
-        if ( bits[row][0] == PBM_WHITE )
-            ++wcount;
-        if ( bits[row][cols - 1] == PBM_WHITE )
-            ++wcount;
-    }
-    for ( col = 1; col < cols - 1; ++col ) {
-        if ( bits[0][col] == PBM_WHITE )
-            ++wcount;
-        if ( bits[rows - 1][col] == PBM_WHITE )
-            ++wcount;
-    }
-    if ( wcount >= rows + cols - 2 )
-        backcolor = PBM_WHITE;
-    else
-        backcolor = PBM_BLACK;
+    backcolor = backcolorFmImage(bits, cols, rows);
 
-    /* Flood the entire edge.  Probably the first call will be enough, but
-       might as well be sure.
-    */
-    for ( col = cols - 3; col >= 2; col -= 2 ) {
-        addflood( col, rows - 1 );
-        addflood( col, 0 );
-    }
-    for ( row = rows - 1; row >= 0; row -= 2 ) {
-        addflood( cols - 1, row );
-        addflood( 0, row );
-    }
-    flood( );
+    flood(bits, cols, rows, backcolor, mask);
 
-    if ( ! expand )
+    if (!cmdline.expand) {
         /* Done. */
-        pbm_writepbm( stdout, mask, cols, rows, 0 );
-    else {
-        /* Expand by one pixel. */
-        int srow, scol;
-        unsigned int row;
-        bit ** emask;
-
-        emask = pbm_allocarray( cols, rows );
-
-        for ( row = 0; row < rows; ++row ) {
-            unsigned int col;
-            for ( col = 0; col < cols; ++col )
-                if ( mask[row][col] == PBM_BLACK )
-                    emask[row][col] = PBM_BLACK;
-                else {
-                    emask[row][col] = PBM_WHITE;
-                    for ( srow = row - 1; srow <= row + 1; ++srow )
-                        for ( scol = col - 1; scol <= col + 1; ++scol )
-                            if ( srow >= 0 && srow < rows &&
-                                 scol >= 0 && scol < cols &&
-                                 mask[srow][scol] == PBM_BLACK ) {
-
-                                emask[row][col] = PBM_BLACK;
-                                break;
-                            }
-                }
-        }
-        pbm_writepbm( stdout, emask, cols, rows, 0 );
+        pbm_writepbm(stdout, mask, cols, rows, 0);
+    } else {
+        bit ** const emask = expandedByOnePixel(mask, cols, rows);
+
+        pbm_writepbm(stdout, emask, cols, rows, 0);
+
+        pbm_freearray(emask, rows);
     }
+}
+
+
+
+int
+main(int argc, const char ** argv) {
 
-    pm_close( stdout );
+    struct CmdlineInfo cmdline;
+    FILE * ifP;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    pbmmask(ifP, stdout, cmdline);
+
+    pm_close(ifP);
+    pm_close(stdout);
 
     return 0;
 }
 
+
diff --git a/editor/pnmremap.c b/editor/pnmremap.c
index 59b1e84b..0038f4d7 100644
--- a/editor/pnmremap.c
+++ b/editor/pnmremap.c
@@ -501,9 +501,10 @@ fserr_init(struct pam *   const pamP,
 
 
 static void
-floydInitRow(struct pam * const pamP, struct Fserr * const fserrP) {
+floydInitRow(struct pam *   const pamP,
+             struct Fserr * const fserrP) {
 
-    int col;
+    unsigned int col;
 
     for (col = 0; col < pamP->width + 2; ++col) {
         unsigned int plane;
@@ -571,7 +572,8 @@ floydPropagateErr(struct pam *   const pamP,
 
 
 static void
-floydSwitchDir(struct pam * const pamP, struct Fserr * const fserrP) {
+floydSwitchDir(struct pam *   const pamP,
+               struct Fserr * const fserrP) {
 
     unsigned int plane;
 
diff --git a/editor/specialty/pammixinterlace.c b/editor/specialty/pammixinterlace.c
index 1392777e..28dace25 100644
--- a/editor/specialty/pammixinterlace.c
+++ b/editor/specialty/pammixinterlace.c
@@ -2,7 +2,7 @@
                              pammixinterlace
 *******************************************************************************
   De-interlace an image by merging adjacent rows.
-   
+
   Copyright (C) 2007 Bruce Guenter, FutureQuest, Inc.
 
   Permission to use, copy, modify, and distribute this software and its
@@ -37,9 +37,9 @@ clamp(sample const val,
 
 
 static bool
-distant(long const above,
-        long const mid,
-        long const below) {
+distant(int const above,
+        int const mid,
+        int const below) {
 
     return abs(mid - (above + below) / 2) > abs(above - below);
 }
@@ -60,9 +60,9 @@ filterLinearBlend(tuple *      const outputrow,
         unsigned int plane;
 
         for (plane = 0; plane < depth; ++plane) {
-            long const above = tuplerowWindow[0][col][plane];
-            long const mid   = tuplerowWindow[1][col][plane];
-            long const below = tuplerowWindow[2][col][plane];
+            int const above = tuplerowWindow[0][col][plane];
+            int const mid   = tuplerowWindow[1][col][plane];
+            int const below = tuplerowWindow[2][col][plane];
 
             sample out;
 
@@ -70,7 +70,7 @@ filterLinearBlend(tuple *      const outputrow,
                 out = (above + mid * 2 + below) / 4;
             else
                 out = mid;
-            
+
             outputrow[col][plane] = out;
         }
     }
@@ -87,23 +87,23 @@ filterFfmpeg(tuple *      const outputrow,
              sample       const maxval) {
 
     unsigned int col;
-    
+
     for (col = 0; col < width; ++col) {
         unsigned int plane;
-        
+
         for (plane = 0; plane < depth; ++plane) {
-            long const above = tuplerowWindow[1][col][plane];
-            long const mid   = tuplerowWindow[2][col][plane];
-            long const below = tuplerowWindow[3][col][plane];
+            int const above = tuplerowWindow[1][col][plane];
+            int const mid   = tuplerowWindow[2][col][plane];
+            int const below = tuplerowWindow[3][col][plane];
 
             sample out;
-            
+
             if (!adaptive || distant(above, mid, below)) {
-                long const a = (- (long)tuplerowWindow[0][col][plane]
+                int const a = (- (int)tuplerowWindow[0][col][plane]
                                 + above * 4
                                 + mid * 2
                                 + below * 4
-                                - (long)tuplerowWindow[4][col][plane]) / 8;
+                                - (int)tuplerowWindow[4][col][plane]) / 8;
                 out = clamp(a, maxval);
             } else
                 out = mid;
@@ -130,22 +130,22 @@ filterFIR(tuple *      const outputrow,
 
         for (plane = 0; plane < depth; ++plane) {
 
-            long const above = tuplerowWindow[1][col][plane];
-            long const mid   = tuplerowWindow[2][col][plane];
-            long const below = tuplerowWindow[3][col][plane];
+            int const above = tuplerowWindow[1][col][plane];
+            int const mid   = tuplerowWindow[2][col][plane];
+            int const below = tuplerowWindow[3][col][plane];
 
             sample out;
 
             if (!adaptive || distant(above, mid, below)) {
-                long const a = (- (long)tuplerowWindow[0][col][plane]
+                int const a = (- (int)tuplerowWindow[0][col][plane]
                                 + above * 2
                                 + mid * 6
                                 + below * 2
-                                - (long)tuplerowWindow[4][col][plane]) / 8;
+                                - (int)tuplerowWindow[4][col][plane]) / 8;
                 out = clamp(a, maxval);
             } else
                 out = mid;
-            
+
             outputrow[col][plane] = out;
         }
     }
@@ -218,7 +218,7 @@ parseCommandLine(int argc, char ** argv,
         if (!cmdlineP->filterP)
             pm_error("The filter name '%s' is not known.", filterName);
     }
-    
+
     if (argc-1 < 1)
         cmdlineP->inputFileName = "-";
     else if (argc-1 == 1)
@@ -280,12 +280,12 @@ main(int argc, char *argv[]) {
 
     FILE * ifP;
     struct cmdlineInfo cmdline;
-    struct pam inpam;  
+    struct pam inpam;
     struct pam outpam;
     tuple * tuplerowWindow[5];
     tuple * outputrow;
     unsigned int rows;
-    
+
     pnm_init(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
@@ -293,7 +293,7 @@ main(int argc, char *argv[]) {
     rows = cmdline.filterP->rows;
 
     ifP = pm_openr(cmdline.inputFileName);
-    
+
     pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
 
     outpam = inpam;    /* Initial value -- most fields should be same */
@@ -328,10 +328,10 @@ main(int argc, char *argv[]) {
                                 inpam.width, inpam.depth,
                                 cmdline.adaptive, inpam.maxval);
         pnm_writepamrow(&outpam, outputrow);
-        
+
         slideWindowDown(tuplerowWindow, rows);
     }
-    
+
     /* Pass through last rows */
     for (row = rows/2; row < rows-1; ++row)
         pnm_writepamrow(&outpam, tuplerowWindow[row]);
@@ -341,6 +341,9 @@ main(int argc, char *argv[]) {
     pnm_freepamrow(outputrow);
     pm_close(inpam.file);
     pm_close(outpam.file);
-    
+
     return 0;
 }
+
+
+
diff --git a/generator/pbmmake.c b/generator/pbmmake.c
index 600440f0..0352d007 100644
--- a/generator/pbmmake.c
+++ b/generator/pbmmake.c
@@ -61,7 +61,7 @@ parseCommandLine(int argc, char ** argv,
 
     if (blackOpt + whiteOpt + grayOpt > 1)
         pm_error("You can specify only one of -black, -white, and -gray");
-    
+
     if (blackOpt)
         cmdlineP->color = COLOR_BLACK;
     else if (whiteOpt)
@@ -83,8 +83,8 @@ parseCommandLine(int argc, char ** argv,
 
 
 
-static void 
-writeGrayRaster(unsigned int const cols, 
+static void
+writeGrayRaster(unsigned int const cols,
                 unsigned int const rows,
                 FILE *       const ofP) {
 
@@ -96,7 +96,7 @@ writeGrayRaster(unsigned int const cols,
     bitrow0 = pbm_allocrow_packed(cols);
     bitrow1 = pbm_allocrow_packed(cols);
 
-    for (i=0; i <= lastCol; ++i) { 
+    for (i=0; i <= lastCol; ++i) {
         bitrow0[i] = (PBM_WHITE*0xaa) | (PBM_BLACK*0x55);
         bitrow1[i] = (PBM_WHITE*0x55) | (PBM_BLACK*0xaa);
         /* 0xaa = 10101010 ; 0x55 = 01010101 */
@@ -119,7 +119,7 @@ writeGrayRaster(unsigned int const cols,
     pbm_freerow(bitrow1);
 }
 
-    
+
 
 static void
 writeSingleColorRaster(unsigned int const cols,
@@ -134,7 +134,7 @@ writeSingleColorRaster(unsigned int const cols,
 
     bitrow0 = pbm_allocrow_packed(cols);
 
-    for (i = 0; i <= lastCol; ++i) 
+    for (i = 0; i <= lastCol; ++i)
         bitrow0[i] = color*0xff;
 
     if (color != 0)
@@ -161,7 +161,7 @@ main(int argc, char * argv[]) {
     parseCommandLine(argc, argv, &cmdline);
 
     pbm_writepbminit(stdout, cmdline.width, cmdline.height, 0);
-    
+
     if (cmdline.color == COLOR_GRAY)
         writeGrayRaster(cmdline.width, cmdline.height, stdout);
     else {
@@ -169,6 +169,6 @@ main(int argc, char * argv[]) {
         writeSingleColorRaster(cmdline.width, cmdline.height, color, stdout);
     }
     pm_close(stdout);
-    
+
     return 0;
 }
diff --git a/generator/pbmtext.c b/generator/pbmtext.c
index 0fe8ad6a..7d9f7cf7 100644
--- a/generator/pbmtext.c
+++ b/generator/pbmtext.c
@@ -828,55 +828,140 @@ truncateText(struct Text    const inputText,
 
 
 static void
-fgetNarrowWideString(PM_WCHAR *    const widestring,
-                     unsigned int  const size,
-                     FILE *        const ifP,
-                     const char ** const errorP) {
-/*----------------------------------------------------------------------------
-  Return the next line from file *ifP, up to 'size' characters, as
-  *widestring.
+fgetWideString(PM_WCHAR *    const widestring,
+               unsigned int  const size,
+               FILE *        const ifP,
+               bool *        const eofP,
+               const char ** const errorP) {
 
-  Return error if we can't read the file, or file is at EOF.
------------------------------------------------------------------------------*/
-    int wideCode;
-        /* Width orientation for *ifP: positive means wide, negative means
-           byte, zero means undecided.
-        */
+    wchar_t * rc;
 
     assert(widestring);
     assert(size > 0);
 
-    wideCode = fwide(ifP, 0);
-    if (wideCode > 0) {
-        /* *ifP is wide-oriented */
-        wchar_t * rc;
-        rc = fgetws(widestring, size, ifP);
-        if (rc == NULL)
+    rc = fgetws(widestring, size, ifP);
+
+    if (rc == NULL) {
+        if (feof(ifP)) {
+            *eofP   = true;
+            *errorP = NULL;
+        } else if (ferror(ifP) && errno == EILSEQ)
             pm_asprintf(errorP,
-                        "fgetws() of max %u bytes failed or end of stream",
-                        size);
+                        "fgetws(): conversion error: sequence is "
+                        "invalid for locale '%s'",
+                        setlocale(LC_CTYPE, NULL));
         else
-            *errorP = NULL;
+            pm_asprintf(errorP,
+                        "fgetws() of max %u bytes failed",
+                        size);
     } else {
-        char * bufNarrow;
-        char * rc;
+        *eofP   = false;
+        *errorP = NULL;
+    }
+}
 
-        MALLOCARRAY_NOFAIL(bufNarrow, MAXLINECHARS+1);
 
-        rc = fgets(bufNarrow, size, ifP);
-        if (rc == NULL)
-            pm_asprintf(errorP, "EOF or error reading file");
-        else {
-            size_t cnt;
 
-            for (cnt = 0; cnt < size && bufNarrow[cnt] != '\0'; ++cnt)
-                widestring[cnt] = (PM_WCHAR)(unsigned char) bufNarrow[cnt];
+static void
+fgetNarrowString(PM_WCHAR *    const widestring,
+                 unsigned int  const size,
+                 FILE *        const ifP,
+                 bool *        const eofP,
+                 const char ** const errorP) {
+
+    char * bufNarrow;
+    char * rc;
 
-            widestring[cnt] = L'\0';
+    assert(widestring);
+    assert(size > 0);
+
+    MALLOCARRAY_NOFAIL(bufNarrow, MAXLINECHARS+1);
+
+    rc = fgets(bufNarrow, size, ifP);
+
+    if (rc == NULL) {
+        if (feof(ifP)) {
+            *eofP   = true;
             *errorP = NULL;
-        }
-        free(bufNarrow);
+        } else
+            pm_asprintf(errorP, "Error reading file");
+    } else {
+        size_t cnt;
+
+        for (cnt = 0; cnt < size && bufNarrow[cnt] != '\0'; ++cnt)
+            widestring[cnt] = (PM_WCHAR)(unsigned char) bufNarrow[cnt];
+
+        widestring[cnt] = L'\0';
+
+        *eofP   = false;
+        *errorP = NULL;
     }
+    free(bufNarrow);
+}
+
+
+
+static void
+fgetNarrowWideString(PM_WCHAR *    const widestring,
+                     unsigned int  const size,
+                     FILE *        const ifP,
+                     bool *        const eofP,
+                     const char ** const errorP) {
+/*----------------------------------------------------------------------------
+  Return the next line from file *ifP, as *widestring.
+
+  Lines are delimited by newline characters and EOF.
+
+  'size' is the size in characters of the buffer at *widestring.  If the line
+  to which the file is positioned is longer than that minus 1, we consider it
+  to be only that long and consider the next character of the actual line to
+  be the first character of the next line.  We leave the file positioned
+  to that character.
+
+  Return *eofP == true iff we encounter end of file (and therefore don't read
+  a line).
+
+  If we can't read the file (or sense EOF), return as *errorP a text
+  explanation of why; otherwise, return *errorP = NULL.
+
+  The line we return is null-terminated.  But it also includes any embedded
+  null characters that are within the line in the file.  It is not strictly
+  possible for Caller to tell whether a null character in *widestring comes
+  from the file or is the one we put there, so Caller should just ignore any
+  null character and anything after it.  It is also not possible for Caller to
+  tell if we trunctaed the actual line because of 'size' if there is a null
+  character in the line.  This means there just isn't any way to get
+  reasonable behavior from this function if the input file contains null
+  characters (but at least the damage is limited to presenting arbitrary text
+  as the contents of the file - the program won't crash).
+
+  Null characters never appear within normal text (including wide-character
+  text).  If there is one in the input file, it is probably because the input
+  is corrupted.
+
+  The line we return may or may not end in a newline character.  It ends in a
+  newline character unless it doesn't fit in 'size' characters or it is the
+  last line in the file and doesn't end in newline.
+-----------------------------------------------------------------------------*/
+    /* The limitations described above with respect to null characters in
+       *ifP are derived from the same limitations in POSIX 'fgets' and
+       'fgetws'.  To avoid them, we would have to read *ifP one character
+       at a time with 'fgetc' and 'fgetwc'.
+    */
+
+    int const wideCode = fwide(ifP, 0);
+        /* Width orientation for *ifP: positive means wide, negative means
+           byte, zero means undecided.
+        */
+
+    assert(widestring);
+    assert(size > 0);
+
+    if (wideCode > 0)
+        /* *ifP is wide-oriented */
+        fgetWideString(widestring, size, ifP, eofP, errorP);
+    else
+        fgetNarrowString(widestring, size, ifP, eofP, errorP);
 }
 
 
@@ -898,6 +983,10 @@ getText(PM_WCHAR       const cmdlineText[],
    But we return text as only renderable characters - characters in *fontP -
    with control characters interpreted or otherwise fixed, according to
    'fixMode'.
+
+   If *inputTextP indicates Standard Input and Standard Input contains null
+   characters, we will truncate lines or consider a single line to be multiple
+   lines.
 -----------------------------------------------------------------------------*/
     struct Text inputText;
 
@@ -934,30 +1023,31 @@ getText(PM_WCHAR       const cmdlineText[],
 
         for (lineCount = 0, eof = false; !eof; ) {
             const char * error;
-            fgetNarrowWideString(buf, MAXLINECHARS, stdin, &error);
-            if (error) {
-                /* We're lazy, so we treat any error as EOF */
-                pm_strfree(error);
-                eof = true;
-            } else {
-                if (wcslen(buf) + 1 >= MAXLINECHARS)
-                    pm_error(
-                        "Line %u (starting at zero) of input text "
-                        "is longer than %u characters."
-                        "Cannot process",
-                        lineCount, (unsigned int) MAXLINECHARS-1);
-                if (lineCount >= maxlines) {
-                    maxlines *= 2;
-                    REALLOCARRAY(textArray, maxlines);
-                    if (textArray == NULL)
+            fgetNarrowWideString(buf, MAXLINECHARS, stdin, &eof, &error);
+            if (error)
+                pm_error("Unable to read line %u from file.  %s",
+                         lineCount, error);
+            else {
+                if (!eof) {
+                    if (wcslen(buf) + 1 >= MAXLINECHARS)
+                        pm_error(
+                            "Line %u (starting at zero) of input text "
+                            "is longer than %u characters."
+                            "Cannot process",
+                            lineCount, (unsigned int) MAXLINECHARS-1);
+                    if (lineCount >= maxlines) {
+                        maxlines *= 2;
+                        REALLOCARRAY(textArray, maxlines);
+                        if (textArray == NULL)
+                            pm_error("out of memory");
+                    }
+                    fixControlChars(buf, fontP,
+                                    (const PM_WCHAR **)&textArray[lineCount],
+                                    fixMode);
+                    if (textArray[lineCount] == NULL)
                         pm_error("out of memory");
+                    ++lineCount;
                 }
-                fixControlChars(buf, fontP,
-                                (const PM_WCHAR **)&textArray[lineCount],
-                                fixMode);
-                if (textArray[lineCount] == NULL)
-                    pm_error("out of memory");
-                ++lineCount;
             }
         }
         inputText.textArray = textArray;
@@ -1305,7 +1395,7 @@ main(int argc, const char *argv[]) {
         char * newLocale;
         newLocale = setlocale(LC_ALL, "");
         if (!newLocale)
-            pm_error("Failed to set locale (LC_ALL) from environemt");
+            pm_error("Failed to set locale (LC_ALL) from environment");
 
         /* Orient standard input stream to wide */
         fwide(stdin,  1);
diff --git a/generator/pbmtextps.c b/generator/pbmtextps.c
index 68df2b15..f543618d 100644
--- a/generator/pbmtextps.c
+++ b/generator/pbmtextps.c
@@ -25,9 +25,8 @@
  * http://partners.adobe.com/public/developer/ps/index_specs.html
  */
 
-#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */
-#define _XOPEN_SOURCE   /* Make sure popen() is in stdio.h */
-#define _BSD_SOURCE     /* Make sure stdrup() is in string.h */
+#define _XOPEN_SOURCE 500
+  /* Make sure popen() is in stdio.h, strdup() is in string.h */
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -54,11 +53,11 @@ validateFontName(const char * const name) {
     unsigned int idx;
 
     for (idx = 0; name[idx] != '\0'; ++idx) {
-        char const c = name[idx]; 
+        char const c = name[idx];
 
         if (c < 32 || c > 125)
             pm_error("Invalid character in font name");
-        else 
+        else
             switch (c) {
               case '[':   case ']':   case '(':   case ')':
               case '{':   case '}':   case '/':   case '\\':
@@ -85,7 +84,7 @@ asciiHexEncode(char *          const inbuff,
     unsigned int idx;
 
     for (idx = 0; inbuff[idx] != '\0'; ++idx) {
-        unsigned int const item = (unsigned char) inbuff[idx]; 
+        unsigned int const item = (unsigned char) inbuff[idx];
 
         outbuff[idx*2]   = hexits[item >> 4];
         outbuff[idx*2+1] = hexits[item & 0xF];
@@ -127,7 +126,7 @@ buildTextFromArgs(int           const argc,
             if (text == NULL)
                 pm_error("out of memory");
             strcat(text, " ");
-        } 
+        }
         totalTextSize += strlen(argv[i]);
         text = realloc(text, totalTextSize);
         if (text == NULL)
@@ -135,7 +134,7 @@ buildTextFromArgs(int           const argc,
         strcat(text, argv[i]);
     }
 
-    { 
+    {
         char * asciiHexText;
 
         MALLOCARRAY(asciiHexText, totalTextSize * 2);
@@ -263,7 +262,7 @@ parseCommandLine(int argc, const char ** argv,
     if (cropSpec == TRUE) {
         if (ascentSpec || descentSpec ||
             leftmarginSpec || rightmarginSpec ||
-            topmarginSpec || bottommarginSpec || 
+            topmarginSpec || bottommarginSpec ||
             cmdlineP->pad)
               pm_error("-crop cannot be specified with -ascent, -descent, "
                        "-leftmargin, -rightmargin, "
@@ -346,7 +345,7 @@ postscriptProgram(struct CmdlineInfo const cmdline) {
         "  {/padbottom 0 def /padtop 0 def}\n"
         "  ifelse\n"
         "setfont\n";
-    
+
     const char * const psFixed2 =
         "0 0 moveto\n"
         "textstring false charpath flattenpath pathbbox\n"
@@ -359,7 +358,7 @@ postscriptProgram(struct CmdlineInfo const cmdline) {
         "/xorigin leftmargin BBleft max def\n"
         "/width xorigin BBright add rightmargin add def\n"
         "/height ascent BBtop max padtop max topmargin add yorigin add def\n";
-    
+
     const char * const psFixed3 =
         "<</PageSize [width height]>> setpagedevice\n"
         "xorigin yorigin moveto\n"
@@ -369,7 +368,7 @@ postscriptProgram(struct CmdlineInfo const cmdline) {
         "  textstring true charpath stroke}\n"
         "  ifelse\n"
         "showpage\n";
-    
+
     const char * const psFixed4 =
         "verbose\n"
         "  {xorigin yorigin moveto\n"
@@ -383,7 +382,7 @@ postscriptProgram(struct CmdlineInfo const cmdline) {
         "       {pop (anonymous)}\n"
         "       ifelse]  ==}\n"
         "  if";
-    
+
     const char * retval;
     const char * psVariable;
 
@@ -399,27 +398,27 @@ postscriptProgram(struct CmdlineInfo const cmdline) {
                 psFixed1, psFixed2, psFixed3, psFixed4);
 
     pm_strfree(psVariable);
-        
+
     return retval;
 }
 
 
 
 static const char **
-gsArgList(const char *       const outputFilename, 
+gsArgList(const char *       const outputFilename,
           struct CmdlineInfo const cmdline) {
 
     unsigned int const maxArgCt = 50;
-    
+
     const char ** retval;
     unsigned int argCt;  /* Number of arguments in 'retval' so far */
 
     if (cmdline.res <= 0)
          pm_error("Resolution (dpi) must be positive.");
-    
+
     if (cmdline.fontsize <= 0)
          pm_error("Font size must be positive.");
-  
+
     MALLOCARRAY_NOFAIL(retval, maxArgCt+2);
 
     argCt = 0;  /* initial value */
@@ -491,7 +490,7 @@ reportMetrics(float const  width,
               float const  BBoxright,
               float const  BBoxtop) {
 
-    pm_message("-- Metrics in points.  Bottom left is (0,0) --");  
+    pm_message("-- Metrics in points.  Bottom left is (0,0) --");
     pm_message("Width:   %f", width);
     pm_message("Height:  %f", height);
     pm_message("Ascent:  %f", ascent);
@@ -537,7 +536,7 @@ acceptGSoutput(int             const pipetosuckFd,
     widthHeightReported   = FALSE; /* Initial value */
     ascentDescentReported = FALSE; /* Initial value */
     BBoxReported          = FALSE; /* Initial value */
-    
+
     MALLOCARRAY_NOFAIL(lineBuff, lineBuffSize);
 
     while (fgets(lineBuff, lineBuffSize, inFileP) != NULL) {
@@ -567,7 +566,7 @@ acceptGSoutput(int             const pipetosuckFd,
     }
 
     if (fontnameReported) {
-        fontname[strlen(fontname)-1] = 0; 
+        fontname[strlen(fontname)-1] = 0;
         reportFontName(fontname);
 
         if (widthHeightReported && ascentDescentReported && BBoxReported)
@@ -581,7 +580,7 @@ acceptGSoutput(int             const pipetosuckFd,
 
 
 static void
-executeProgram(const char *       const psProgram, 
+executeProgram(const char *       const psProgram,
                const char *       const outputFname,
                struct CmdlineInfo const cmdline) {
 
@@ -633,19 +632,19 @@ writePbm(const char * const fileName,
     FILE * ifP;
     int format;
     int cols, rows, row ;
-    unsigned char * bitrow; 
-    
+    unsigned char * bitrow;
+
     ifP = pm_openr(fileName);
     pbm_readpbminit(ifP, &cols, &rows, &format);
 
     if (cols == 0 || rows == 0 || cols > INT_MAX - 10 || rows > INT_MAX - 10)
         pm_error("Abnormal output from gs program.  "
                  "width x height = %u x %u", cols, rows);
-               
-    pbm_writepbminit(ofP, cols, rows, 0);           
-               
+
+    pbm_writepbminit(ofP, cols, rows, 0);
+
     bitrow = pbm_allocrow_packed(cols);
-    
+
     for (row = 0; row < rows; ++row) {
         pbm_readpbmrow_packed(ifP, bitrow, cols, format);
         pbm_writepbmrow_packed(ofP, bitrow, cols, 0);
@@ -699,7 +698,7 @@ dumpPsProgram(struct CmdlineInfo const cmdline) {
 
 
 
-int 
+int
 main(int argc, const char *argv[]) {
 
     struct CmdlineInfo cmdline;
diff --git a/generator/pgmnoise.c b/generator/pgmnoise.c
index 442edc59..40d0e189 100644
--- a/generator/pgmnoise.c
+++ b/generator/pgmnoise.c
@@ -56,7 +56,7 @@ parseCommandLine(int argc, const char ** const argv,
 
     if (maxvalSpec) {
         if (cmdlineP->maxval > PGM_OVERALLMAXVAL)
-            pm_error("Maxval too large: %u.  Maximu is %u", 
+            pm_error("Maxval too large: %u.  Maximu is %u",
                      cmdlineP->maxval, PGM_OVERALLMAXVAL);
         else if (cmdlineP->maxval == 0)
             pm_error("Maxval must not be zero");
@@ -70,7 +70,7 @@ parseCommandLine(int argc, const char ** const argv,
     else {
         int const width  = atoi(argv[1]);
         int const height = atoi(argv[2]);
-        
+
         if (width <= 0)
             pm_error("Width must be positive, not %d", width);
         else
@@ -90,12 +90,12 @@ randPool(unsigned int const digits) {
 /*----------------------------------------------------------------------------
   Draw 'digits' bits from pool of random bits.  If the number of random bits
   in pool is insufficient, call rand() and add 31 bits to it.
-  
+
   'digits' must be at most 16.
 
   We assume that each call to rand() generates 31 bits, or RAND_MAX ==
   2147483647.
-  
+
   The underlying logic is flexible and endian-free.  The above conditions
   can be relaxed.
 -----------------------------------------------------------------------------*/
@@ -114,7 +114,7 @@ randPool(unsigned int const digits) {
         hold >>= digits;
         len   -= digits;
     } else {              /* Load another 31 bits into hold */
-        hold    = rand(); 
+        hold    = rand();
         retval |= (hold << len);
         hold >>=  (digits - len);
         len = 31 - digits + len;
@@ -164,11 +164,11 @@ pgmnoise(FILE *       const ofP,
             unsigned int col;
             for (col = 0; col < cols; ++col)
                 destrow[col] = randPool(bitLen);
-        } 
-        else { 
+        }
+        else {
             unsigned int col;
             for (col = 0; col < cols; ++col)
-                destrow[col] = rand() % (maxval + 1); 
+                destrow[col] = rand() % (maxval + 1);
         }
         pgm_writepgmrow(ofP, destrow, cols, maxval, 0);
     }
@@ -181,7 +181,7 @@ pgmnoise(FILE *       const ofP,
 int
 main(int          argc,
      const char * argv[]) {
-    
+
     struct cmdlineInfo cmdline;
 
     pm_proginit(&argc, argv);
@@ -194,3 +194,6 @@ main(int          argc,
 
     return 0;
 }
+
+
+
diff --git a/generator/pgmramp.c b/generator/pgmramp.c
index 225542fe..db32b9f0 100644
--- a/generator/pgmramp.c
+++ b/generator/pgmramp.c
@@ -35,7 +35,7 @@ static void
 parseCommandLine(int argc, char ** argv,
                  struct cmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
-  Convert program invocation arguments (argc,argv) into a format the 
+  Convert program invocation arguments (argc,argv) into a format the
   program can use easily, struct cmdlineInfo.  Validate arguments along
   the way and exit program with message if invalid.
 
@@ -111,12 +111,23 @@ parseCommandLine(int argc, char ** argv,
 
 
 
+static int
+diffu(unsigned int const subtrahend,
+      unsigned int const subtractor) {
+
+    return (int)subtrahend - (int)subtractor;
+
+    /* (Not the conventional terminology, but better) */
+}
+
+
+
 int
 main(int argc, char *argv[]) {
 
     struct cmdlineInfo cmdline;
     gray *grayrow;
-    int rowso2, colso2;
+    unsigned int rowso2, colso2;
     unsigned int row;
 
     pgm_init( &argc, argv );
@@ -149,20 +160,17 @@ main(int argc, char *argv[]) {
                         MAX((float) cmdline.cols + cmdline.rows-2, 1);
                 break;
             case RT_RECT: {
-                float const r = fabs((int)(rowso2 - row)) / rowso2;
-                float const c = fabs((int)(colso2 - col)) / colso2;
+                float const r = fabs((float)diffu(rowso2, row)) / rowso2;
+                float const c = fabs((float)diffu(colso2, col)) / colso2;
                 grayrow[col] =
                     cmdline.maxval - (r + c) / 2.0 * cmdline.maxval;
             } break;
 
             case RT_ELLIP: {
-                float const r = fabs((int)(rowso2 - row)) / rowso2;
-                float const c = fabs((int)(colso2 - col)) / colso2;
-                float v;
+                float const r = fabs((float)diffu(rowso2, row)) / rowso2;
+                float const c = fabs((float)diffu(colso2, col)) / colso2;
+                float const v = MAX(0.0f, MIN(1.0f, SQR(r) + SQR(c)));
 
-                v = r * r + c * c;
-                if ( v < 0.0 ) v = 0.0;
-                else if ( v > 1.0 ) v = 1.0;
                 grayrow[col] = cmdline.maxval - v * cmdline.maxval;
             } break;
             }
@@ -174,3 +182,6 @@ main(int argc, char *argv[]) {
     pm_close(stdout);
     return 0;
 }
+
+
+
diff --git a/lib/colorname.c b/lib/colorname.c
index b2bc4a83..596d8788 100644
--- a/lib/colorname.c
+++ b/lib/colorname.c
@@ -32,7 +32,7 @@ static int lineNo;
 
 
 
-void 
+void
 pm_canonstr(char * const arg) {
 /*----------------------------------------------------------------------------
    Modify string 'arg' to canonical form: lower case, no white space.
@@ -93,7 +93,7 @@ pm_openColornameFile(const char * const fileName, const int must_open) {
    environment variable whose name is RGB_ENV (e.g. "RGBDEF").  Except
    if that environment variable is not set, it is the first file found,
    if any, in the search path RGB_DB_PATH.
-   
+
    'must_open' is a logical: we must get the file open or die.  If
    'must_open' is true and we can't open the file (e.g. it doesn't
    exist), exit the program with an error message.  If 'must_open' is
@@ -111,7 +111,7 @@ pm_openColornameFile(const char * const fileName, const int must_open) {
                          "named %s, per the %s environment variable.  "
                          "errno = %d (%s)",
                          rgbdef, RGBENV, errno, strerror(errno));
-        } else {            
+        } else {
             /* The environment variable isn't set, so try the hardcoded
                default color name dictionary locations.
             */
@@ -122,7 +122,7 @@ pm_openColornameFile(const char * const fileName, const int must_open) {
                          "path '%s' "
                          "and Environment variable %s not set.  Set %s to "
                          "the pathname of your rgb.txt file or don't use "
-                         "color names.", 
+                         "color names.",
                          RGB_DB_PATH, RGBENV, RGBENV);
             }
         }
@@ -131,7 +131,7 @@ pm_openColornameFile(const char * const fileName, const int must_open) {
         if (f == NULL && must_open)
             pm_error("Can't open the color names dictionary file '%s'.  "
                      "errno = %d (%s)", fileName, errno, strerror(errno));
-        
+
     }
     lineNo = 0;
     return(f);
@@ -154,7 +154,7 @@ pm_colorget(FILE * const f) {
     bool eof;
     struct colorfile_entry retval;
     char * rc;
-    
+
     gotOne = FALSE;  /* initial value */
     eof = FALSE;
     while (!gotOne && !eof) {
@@ -165,15 +165,15 @@ pm_colorget(FILE * const f) {
         else {
             if (buf[0] != '#' && buf[0] != '\n' && buf[0] != '!' &&
                 buf[0] != '\0') {
-                if (sscanf(buf, "%ld %ld %ld %[^\n]", 
-                           &retval.r, &retval.g, &retval.b, colorname) 
+                if (sscanf(buf, "%ld %ld %ld %[^\n]",
+                           &retval.r, &retval.g, &retval.b, colorname)
                     == 4 )
                     gotOne = TRUE;
                 else {
                     if (buf[strlen(buf)-1] == '\n')
                         buf[strlen(buf)-1] = '\0';
                     pm_message("can't parse color names dictionary Line %d:  "
-                               "'%s'", 
+                               "'%s'",
                                lineNo, buf);
                 }
             }
@@ -189,7 +189,7 @@ pm_colorget(FILE * const f) {
 
 
 void
-pm_parse_dictionary_namen(char   const colorname[], 
+pm_parse_dictionary_namen(char   const colorname[],
                           tuplen const color) {
 
     FILE * fP;
@@ -213,7 +213,7 @@ pm_parse_dictionary_namen(char   const colorname[],
             colorfileExhausted = TRUE;
     }
     fclose(fP);
-    
+
     if (!gotit)
         pm_error("unknown color '%s'", colorname);
 
@@ -227,7 +227,7 @@ pm_parse_dictionary_namen(char   const colorname[],
 
 
 void
-pm_parse_dictionary_name(char    const colorname[], 
+pm_parse_dictionary_name(char    const colorname[],
                          pixval  const maxval,
                          int     const closeOk,
                          pixel * const colorP) {
@@ -244,7 +244,7 @@ pm_parse_dictionary_name(char    const colorname[],
     r = ROUNDU(color[PAM_RED_PLANE] * maxval);
     g = ROUNDU(color[PAM_GRN_PLANE] * maxval);
     b = ROUNDU(color[PAM_BLU_PLANE] * maxval);
-    
+
     if (!closeOk) {
         if (maxval != PAM_COLORFILE_MAXVAL) {
             if (fabs((double)r / maxval - color[PAM_RED_PLANE]) > epsilon ||
diff --git a/lib/colorname.h b/lib/colorname.h
index 86c3d585..492df951 100644
--- a/lib/colorname.h
+++ b/lib/colorname.h
@@ -28,7 +28,7 @@ struct colorfile_entry {
 
 
 
-void 
+void
 pm_canonstr(char * const str);
 
 FILE *
@@ -38,11 +38,11 @@ struct colorfile_entry
 pm_colorget(FILE * const f);
 
 void
-pm_parse_dictionary_namen(char   const colorname[], 
+pm_parse_dictionary_namen(char   const colorname[],
                           tuplen const color);
 
 void
-pm_parse_dictionary_name(const char       colorname[], 
+pm_parse_dictionary_name(const char       colorname[],
                          pixval     const maxval,
                          int        const closeOk,
                          pixel *    const colorP);
diff --git a/lib/libpam.h b/lib/libpam.h
index 9f8a34d0..2d4f29d7 100644
--- a/lib/libpam.h
+++ b/lib/libpam.h
@@ -7,9 +7,9 @@
 #include "pgm.h"
 
 void
-pnm_readpaminitrestaspnm(FILE * const fileP, 
-                         int *  const colsP, 
-                         int *  const rowsP, 
+pnm_readpaminitrestaspnm(FILE * const fileP,
+                         int *  const colsP,
+                         int *  const rowsP,
                          gray * const maxvalP,
                          int *  const formatP);
 
diff --git a/lib/libpamcolor.c b/lib/libpamcolor.c
index c0a57dee..49abd063 100644
--- a/lib/libpamcolor.c
+++ b/lib/libpamcolor.c
@@ -12,7 +12,7 @@
    offset stuff.
 */
 #define _FILE_OFFSET_BITS 64
-#define _LARGE_FILES  
+#define _LARGE_FILES
 
 #define _DEFAULT_SOURCE 1  /* New name for SVID & BSD source defines */
 #define _BSD_SOURCE 1      /* Make sure strdup() is in string.h */
@@ -20,6 +20,7 @@
 
 #include <string.h>
 #include <limits.h>
+#include <math.h>
 
 #include "netpbm/pm_c_util.h"
 #include "netpbm/mallocvar.h"
@@ -91,7 +92,7 @@ parseHexDigits(const char *   const string,
 
 
 static void
-parseNewHexX11(char   const colorname[], 
+parseNewHexX11(char   const colorname[],
                tuplen const color) {
 /*----------------------------------------------------------------------------
    Determine what color colorname[] specifies in the new style hex
@@ -131,11 +132,11 @@ isNormal(samplen const arg) {
 
 
 static void
-parseNewDecX11(const char * const colorname, 
+parseNewDecX11(const char * const colorname,
                tuplen       const color) {
 
     int rc;
-    
+
     rc = sscanf(colorname, "rgbi:%f/%f/%f",
                 &color[PAM_RED_PLANE],
                 &color[PAM_GRN_PLANE],
@@ -155,7 +156,51 @@ parseNewDecX11(const char * const colorname,
 
 
 static void
-parseOldX11(const char * const colorname, 
+parseInteger(const char * const colorname,
+             tuplen       const color) {
+
+    unsigned int maxval;
+    unsigned int r, g, b;
+    int rc;
+
+    rc = sscanf(colorname, "rgb-%u:%u/%u/%u", &maxval, &r, &g, &b);
+
+    if (rc != 4)
+        pm_error("invalid color specifier '%s'.  "
+                 "If it starts with \"rgb-\", then it must have the format "
+                 "rgb-<MAXVAL>:<RED>:<GRN>:<BLU>, "
+                 "where <MAXVAL>, <RED>, <GRN>, and <BLU> are "
+                 "unsigned integers",
+                 colorname);
+
+    if (maxval < 1 || maxval > PNM_OVERALLMAXVAL)
+        pm_error("Maxval in color specification '%s' is %u, "
+                 "which is invalid because it is not between "
+                 "1 and %u, inclusive",
+                 colorname, maxval, PNM_OVERALLMAXVAL);
+
+    if (r > maxval)
+        pm_error("Red value in color specification '%s' is %u, "
+                 "whcih is invalid because the specified maxval is %u",
+                 colorname, r, maxval);
+    if (g > maxval)
+        pm_error("Green value in color specification '%s' is %u, "
+                 "whcih is invalid because the specified maxval is %u",
+                 colorname, g, maxval);
+    if (b > maxval)
+        pm_error("Blue value in color specification '%s' is %u, "
+                 "whcih is invalid because the specified maxval is %u",
+                 colorname, b, maxval);
+
+    color[PAM_RED_PLANE] = (float)r/maxval;
+    color[PAM_GRN_PLANE] = (float)g/maxval;
+    color[PAM_BLU_PLANE] = (float)b/maxval;
+}
+
+
+
+static void
+parseOldX11(const char * const colorname,
             tuplen       const color) {
 /*----------------------------------------------------------------------------
    Return as *colorP the color specified by the old X11 style color
@@ -181,7 +226,7 @@ parseOldX11(const char * const colorname,
              (samplen)(hexDigitValue(colorname[4]) << 0))
              / 255;
         color[PAM_BLU_PLANE] =
-            ((samplen)(hexDigitValue(colorname[5]) << 4) + 
+            ((samplen)(hexDigitValue(colorname[5]) << 4) +
              (samplen)(hexDigitValue(colorname[6]) << 0))
              / 255;
         break;
@@ -193,12 +238,12 @@ parseOldX11(const char * const colorname,
              (samplen)(hexDigitValue(colorname[3]) << 0))
             / 4095;
         color[PAM_GRN_PLANE] =
-            ((samplen)(hexDigitValue(colorname[4]) << 8) + 
+            ((samplen)(hexDigitValue(colorname[4]) << 8) +
              (samplen)(hexDigitValue(colorname[5]) << 4) +
              (samplen)(hexDigitValue(colorname[6]) << 0))
             / 4095;
         color[PAM_BLU_PLANE] =
-            ((samplen)(hexDigitValue(colorname[7]) << 8) + 
+            ((samplen)(hexDigitValue(colorname[7]) << 8) +
              (samplen)(hexDigitValue(colorname[8]) << 4) +
              (samplen)(hexDigitValue(colorname[9]) << 0))
             / 4095;
@@ -206,19 +251,19 @@ parseOldX11(const char * const colorname,
 
     case 12:
         color[PAM_RED_PLANE] =
-            ((samplen)(hexDigitValue(colorname[1]) << 12) + 
+            ((samplen)(hexDigitValue(colorname[1]) << 12) +
              (samplen)(hexDigitValue(colorname[2]) <<  8) +
-             (samplen)(hexDigitValue(colorname[3]) <<  4) + 
+             (samplen)(hexDigitValue(colorname[3]) <<  4) +
              (samplen)(hexDigitValue(colorname[4]) <<  0))
             / 65535;
         color[PAM_GRN_PLANE] =
-            ((samplen)(hexDigitValue(colorname[5]) << 12) + 
+            ((samplen)(hexDigitValue(colorname[5]) << 12) +
              (samplen)(hexDigitValue(colorname[6]) <<  8) +
              (samplen)(hexDigitValue(colorname[7]) <<  4) +
              (samplen)(hexDigitValue(colorname[8]) <<  0))
             / 65535;
         color[PAM_BLU_PLANE] =
-            ((samplen)(hexDigitValue(colorname[ 9]) << 12) + 
+            ((samplen)(hexDigitValue(colorname[ 9]) << 12) +
              (samplen)(hexDigitValue(colorname[10]) << 8) +
              (samplen)(hexDigitValue(colorname[11]) << 4) +
              (samplen)(hexDigitValue(colorname[12]) << 0))
@@ -233,7 +278,7 @@ parseOldX11(const char * const colorname,
 
 
 static void
-parseOldX11Dec(const char* const colorname, 
+parseOldX11Dec(const char* const colorname,
                tuplen      const color) {
 
     int rc;
@@ -260,15 +305,18 @@ tuplen
 pnm_parsecolorn(const char * const colorname) {
 
     tuplen retval;
-    
+
     MALLOCARRAY_NOFAIL(retval, 3);
 
-    if (strncmp(colorname, "rgb:", 4) == 0)
+    if (strneq(colorname, "rgb:", 4))
         /* It's a new-X11-style hexadecimal rgb specifier. */
         parseNewHexX11(colorname, retval);
-    else if (strncmp(colorname, "rgbi:", 5) == 0)
+    else if (strneq(colorname, "rgbi:", 5))
         /* It's a new-X11-style decimal/float rgb specifier. */
         parseNewDecX11(colorname, retval);
+    else if (strneq(colorname, "rgb-", 4))
+        /* It's a Netpbm-native decimal integer rgb specifier */
+        parseInteger(colorname, retval);
     else if (colorname[0] == '#')
         /* It's an old-X11-style hexadecimal rgb specifier. */
         parseOldX11(colorname, retval);
@@ -276,7 +324,7 @@ pnm_parsecolorn(const char * const colorname) {
              colorname[0] == '.')
         /* It's an old-style decimal/float rgb specifier. */
         parseOldX11Dec(colorname, retval);
-    else 
+    else
         /* Must be a name from the X-style rgb file. */
         pm_parse_dictionary_namen(colorname, retval);
 
@@ -285,9 +333,29 @@ pnm_parsecolorn(const char * const colorname) {
 
 
 
+static void
+warnIfNotExact(const char * const colorname,
+               tuple        const rounded,
+               tuplen       const exact,
+               sample       const maxval,
+               unsigned int const plane) {
+
+    float const epsilon = 1.0/65536.0;
+
+    if (fabs((float)(rounded[plane] / maxval) - exact[plane]) > epsilon) {
+        pm_message("WARNING: Component %u of color '%s' is %f, "
+                   "which cannot be represented precisely with maxval %lu.  "
+                   "Approximating as %lu.",
+                   plane, colorname, exact[plane], maxval, rounded[plane]);
+    }
+}
+
+
+
 tuple
-pnm_parsecolor(const char * const colorname,
-               sample       const maxval) {
+pnm_parsecolor2(const char * const colorname,
+                sample       const maxval,
+                int          const closeOk) {
 
     tuple retval;
     tuplen color;
@@ -306,6 +374,12 @@ pnm_parsecolor(const char * const colorname,
     retval[PAM_GRN_PLANE] = ROUNDU(color[PAM_GRN_PLANE] * maxval);
     retval[PAM_BLU_PLANE] = ROUNDU(color[PAM_BLU_PLANE] * maxval);
 
+    if (!closeOk) {
+        warnIfNotExact(colorname, retval, color, maxval, PAM_RED_PLANE);
+        warnIfNotExact(colorname, retval, color, maxval, PAM_GRN_PLANE);
+        warnIfNotExact(colorname, retval, color, maxval, PAM_BLU_PLANE);
+    }
+
     free(color);
 
     return retval;
@@ -313,6 +387,15 @@ pnm_parsecolor(const char * const colorname,
 
 
 
+tuple
+pnm_parsecolor(const char * const colorname,
+               sample       const maxval) {
+
+    return pnm_parsecolor2(colorname, maxval, true);
+}
+
+
+
 const char *
 pnm_colorname(struct pam * const pamP,
               tuple        const color,
@@ -324,7 +407,7 @@ pnm_colorname(struct pam * const pamP,
 
     if (pamP->depth < 3)
         PPM_ASSIGN(colorp, color[0], color[0], color[0]);
-    else 
+    else
         PPM_ASSIGN(colorp,
                    color[PAM_RED_PLANE],
                    color[PAM_GRN_PLANE],
@@ -341,21 +424,279 @@ pnm_colorname(struct pam * const pamP,
 
 
 
+static tuple
+scaledRgb(struct pam * const pamP,
+          tuple        const color,
+          sample       const maxval) {
+
+    tuple scaledColor;
+
+    struct pam pam;
+
+    pam.size             = sizeof(pam);
+    pam.len              = PAM_STRUCT_SIZE(allocation_depth);
+    pam.maxval           = pamP->maxval;
+    pam.depth            = pamP->depth;
+    pam.allocation_depth = 3;
+
+    scaledColor = pnm_allocpamtuple(&pam);
+
+    pnm_scaletuple(&pam, scaledColor, color, maxval);
+
+    pnm_maketuplergb(&pam, scaledColor);
+
+    return scaledColor;
+}
+
+
+
+const char *
+pnm_colorspec_rgb_integer(struct pam * const pamP,
+                          tuple        const color,
+                          sample       const maxval) {
+
+    const char * retval;
+
+    tuple scaledColor = scaledRgb(pamP, color, maxval);
+
+    pm_asprintf(&retval, "rgb-%lu:%lu/%lu/%lu",
+                maxval,
+                scaledColor[PAM_RED_PLANE],
+                scaledColor[PAM_GRN_PLANE],
+                scaledColor[PAM_BLU_PLANE]
+        );
+
+    pnm_freepamtuple(scaledColor);
+
+    return retval;
+}
+
+
+
+const char *
+pnm_colorspec_rgb_norm(struct pam * const pamP,
+                       tuple        const color,
+                       unsigned int const digitCt) {
+
+    const char * retval;
+
+    tuple rgbColor;
+
+    tuplen normColor;
+
+    struct pam rgbPam;
+
+    rgbPam.size             = sizeof(rgbPam);
+    rgbPam.len              = PAM_STRUCT_SIZE(allocation_depth);
+    rgbPam.maxval           = pamP->maxval;
+    rgbPam.depth            = pamP->depth;
+    rgbPam.allocation_depth = 3;
+
+    rgbColor = pnm_allocpamtuple(&rgbPam);
+
+    pnm_assigntuple(&rgbPam, rgbColor, color);  /* initial value */
+
+    pnm_maketuplergb(&rgbPam, rgbColor);
+
+    normColor = pnm_allocpamtuplen(&rgbPam);
+
+    rgbPam.depth = 3;
+
+    pnm_normalizetuple(&rgbPam, rgbColor, normColor);
+
+    {
+        const char * format;
+        pm_asprintf(&format, "rgbi:%%.%uf/%%.%uf/%%.%uf",
+                    digitCt, digitCt, digitCt);
+
+        pm_asprintf(&retval, format,
+                    normColor[PAM_RED_PLANE],
+                    normColor[PAM_GRN_PLANE],
+                    normColor[PAM_BLU_PLANE]
+            );
+        pm_strfree(format);
+    }
+
+    pnm_freepamtuplen(normColor);
+    pnm_freepamtuple(rgbColor);
+
+    return retval;
+}
+
+
+
+const char *
+pnm_colorspec_rgb_x11(struct pam * const pamP,
+                      tuple        const color,
+                      unsigned int const hexDigitCt) {
+
+    const char * retval;
+
+    sample maxval;
+    const char * format;
+
+    switch(hexDigitCt) {
+    case 1:
+        maxval =    15;
+        format = "rgb:%01x:%01x:%01x";
+        break;
+    case 2:
+        maxval =   255;
+        format = "rgb:%02x:%02x:%02x";
+        break;
+    case 3:
+        maxval =  4095;
+        format = "rgb:%03x:%03x:%03x";
+        break;
+    case 4:
+        maxval = 65535;
+        format = "rgb:%04x:%04x:%04x";
+        break;
+    default:
+        pm_error("Invalid number of hex digits "
+                 "for X11 color specification: %u.  "
+                 "Must be 1, 2, 3, or 4", hexDigitCt);
+    }
+
+    {
+        tuple const scaledColor = scaledRgb(pamP, color, maxval);
+
+        pm_asprintf(&retval, format,
+                    scaledColor[PAM_RED_PLANE],
+                    scaledColor[PAM_GRN_PLANE],
+                    scaledColor[PAM_BLU_PLANE]
+            );
+
+        pnm_freepamtuple(scaledColor);
+    }
+    return retval;
+}
+
+
+
+const char *
+pnm_colorspec_dict(struct pam * const pamP,
+                   tuple        const color) {
+/*----------------------------------------------------------------------------
+   Return the name from the color dictionary of color 'color'.
+
+   Return it in newly allocated pm_strdrup storage.
+
+   If the color is not in the dictionary, or the dictionary doesn't even
+   exist (file not found in any of the possible places), return NULL.
+
+   The color dictionary uses maxval 255, so we match to that precision.
+   E.g. if a component of 'color' is 1000 out of maxval 65535 (which would be
+   3.9 out of maxval 255), we consider it a match to a component value of 4
+   in the color dictionary.
+-----------------------------------------------------------------------------*/
+    tuple scaledColor = scaledRgb(pamP, color, PAM_COLORFILE_MAXVAL);
+
+    FILE * dictFileP;
+    const char * colorname;
+
+    dictFileP = pm_openColornameFile(NULL, false);
+
+    if (dictFileP) {
+        bool eof;
+        for (colorname = NULL, eof = false; !colorname && !eof; ) {
+            struct colorfile_entry const ce = pm_colorget(dictFileP);
+
+            if (ce.colorname)  {
+                if (scaledColor[PAM_RED_PLANE] == (sample)ce.r &&
+                    scaledColor[PAM_GRN_PLANE] == (sample)ce.g &&
+                    scaledColor[PAM_BLU_PLANE] == (sample)ce.b) {
+                    colorname = pm_strdup(ce.colorname);
+                }
+            } else
+                eof = TRUE;
+        }
+
+        fclose(dictFileP);
+    } else
+        colorname = NULL;
+
+    pnm_freepamtuple(scaledColor);
+
+    return colorname;
+}
+
+
+
+const char *
+pnm_colorspec_dict_close(struct pam * const pamP,
+                         tuple        const color) {
+/*----------------------------------------------------------------------------
+   Return the name from the color dictionary of the color closst to 'color'.
+
+   Return it in newly allocated pm_strdrup storage.
+
+   If the color dictionary is empty, or the dictionary doesn't even exist
+   (file not found in any of the possible places), return a null string.
+   This is the only case in which we would return a null string, as the
+   color dictionary cannot define a null string color name.
+-----------------------------------------------------------------------------*/
+    tuple scaledColor = scaledRgb(pamP, color, PAM_COLORFILE_MAXVAL);
+
+    FILE * dictFileP;
+    static char colorname[200];
+
+    dictFileP = pm_openColornameFile(NULL, false);
+
+    if (dictFileP) {
+        unsigned int bestDiff;
+        bool eof;
+
+        for (bestDiff = 32767, eof = FALSE; !eof && bestDiff > 0; ) {
+            struct colorfile_entry const ce = pm_colorget(dictFileP);
+
+            if (ce.colorname)  {
+                unsigned int const thisDiff =
+                    abs((int)scaledColor[PAM_RED_PLANE] - (int)ce.r) +
+                    abs((int)scaledColor[PAM_GRN_PLANE] - (int)ce.g) +
+                    abs((int)scaledColor[PAM_BLU_PLANE] - (int)ce.b);
+
+                if (thisDiff < bestDiff) {
+                    bestDiff = thisDiff;
+                    STRSCPY(colorname, ce.colorname);
+                }
+            } else
+                eof = TRUE;
+        }
+
+        fclose(dictFileP);
+
+        if (bestDiff == 32767) {
+            /* Color file contain no entries, so we can't even pick a close
+               one
+            */
+            STRSCPY(colorname, "");
+        }
+    } else
+        STRSCPY(colorname, "");
+
+    pnm_freepamtuple(scaledColor);
+
+    return pm_strdup(colorname);
+}
+
+
+
 double pnm_lumin_factor[3] = {PPM_LUMINR, PPM_LUMING, PPM_LUMINB};
 
 void
-pnm_YCbCrtuple(tuple    const tuple, 
-               double * const YP, 
-               double * const CbP, 
+pnm_YCbCrtuple(tuple    const tuple,
+               double * const YP,
+               double * const CbP,
                double * const CrP) {
 /*----------------------------------------------------------------------------
-   Assuming that the tuple 'tuple' is of tupletype RGB, return the 
+   Assuming that the tuple 'tuple' is of tupletype RGB, return the
    Y/Cb/Cr representation of the color represented by the tuple.
 -----------------------------------------------------------------------------*/
     int const red = (int)tuple[PAM_RED_PLANE];
     int const grn = (int)tuple[PAM_GRN_PLANE];
     int const blu = (int)tuple[PAM_BLU_PLANE];
-    
+
     *YP  = (+ PPM_LUMINR * red + PPM_LUMING * grn + PPM_LUMINB * blu);
     *CbP = (- 0.16874 * red - 0.33126 * grn + 0.50000 * blu);
     *CrP = (+ 0.50000 * red - 0.41869 * grn - 0.08131 * blu);
@@ -363,11 +704,11 @@ pnm_YCbCrtuple(tuple    const tuple,
 
 
 
-void 
+void
 pnm_YCbCr_to_rgbtuple(const struct pam * const pamP,
                       tuple              const tuple,
                       double             const Y,
-                      double             const Cb, 
+                      double             const Cb,
                       double             const Cr,
                       int *              const overflowP) {
 
@@ -388,7 +729,7 @@ pnm_YCbCr_to_rgbtuple(const struct pam * const pamP,
         } else if (rgb[plane] < 0.0) {
             overflow = TRUE;
             tuple[plane] = 0;
-        } else 
+        } else
             tuple[plane] = (sample)rgb[plane];
     }
     if (overflowP)
diff --git a/lib/libpamn.c b/lib/libpamn.c
index 26dbbfe3..65c8979f 100644
--- a/lib/libpamn.c
+++ b/lib/libpamn.c
@@ -23,6 +23,43 @@
 
 
 
+static unsigned int
+allocationDepth(const struct pam * const pamP) {
+
+    unsigned int retval;
+
+    if (pamP->len >= PAM_STRUCT_SIZE(allocation_depth)) {
+        if (pamP->allocation_depth == 0)
+            retval = pamP->depth;
+        else {
+            if (pamP->depth > pamP->allocation_depth)
+                pm_error("'allocationDepth' (%u) is smaller than 'depth' (%u)",
+                         pamP->allocation_depth, pamP->depth);
+            retval = pamP->allocation_depth;
+        }
+    } else
+        retval = pamP->depth;
+    return retval;
+}
+
+
+
+tuplen
+pnm_allocpamtuplen(const struct pam * const pamP) {
+
+    tuplen retval;
+
+    retval = malloc(allocationDepth(pamP) * sizeof(retval[0]));
+
+    if (retval == NULL)
+        pm_error("Out of memory allocating %u-plane normalized tuple",
+                 allocationDepth(pamP));
+
+    return retval;
+}
+
+
+
 static void
 allocpamrown(const struct pam * const pamP,
              tuplen **          const tuplerownP,
@@ -32,7 +69,7 @@ allocpamrown(const struct pam * const pamP,
    overflow will not occur in our calculations.  NOTE: pnm_readpaminit()
    ensures this assumption is valid.
 -----------------------------------------------------------------------------*/
-    int const bytes_per_tuple = pamP->depth * sizeof(samplen);
+    int const bytes_per_tuple = allocationDepth(pamP) * sizeof(samplen);
 
     tuplen * tuplerown;
     const char * error;
@@ -47,15 +84,16 @@ allocpamrown(const struct pam * const pamP,
         pm_asprintf(&error, "Out of memory allocating space for a tuple row of"
                     "%u tuples by %u samples per tuple "
                     "by %u bytes per sample.",
-                    pamP->width, pamP->depth, (unsigned)sizeof(samplen));
+                    pamP->width, allocationDepth(pamP),
+                    (unsigned)sizeof(samplen));
     else {
         /* Now we initialize the pointers to the individual tuples to make this
            a regulation C two dimensional array.
         */
-        
+
         unsigned char * p;
         unsigned int i;
-        
+
         p = (unsigned char*) (tuplerown + pamP->width);
             /* location of Tuple 0 */
         for (i = 0; i < pamP->width; ++i) {
@@ -93,7 +131,7 @@ pnm_allocpamrown(const struct pam * const pamP) {
 
 
 static void
-readpbmrow(const struct pam * const pamP, 
+readpbmrow(const struct pam * const pamP,
            tuplen *           const tuplenrow) {
 
     bit * bitrow;
@@ -101,7 +139,7 @@ readpbmrow(const struct pam * const pamP,
     jmp_buf * origJmpbufP;
 
     bitrow = pbm_allocrow(pamP->width);
-    
+
     if (setjmp(jmpbuf) != 0) {
         pbm_freerow(bitrow);
         pm_setjmpbuf(origJmpbufP);
@@ -123,15 +161,15 @@ readpbmrow(const struct pam * const pamP,
 
 
 static void
-readpamrow(const struct pam * const pamP, 
+readpamrow(const struct pam * const pamP,
            tuplen *           const tuplenrow) {
 
     jmp_buf jmpbuf;
     jmp_buf * origJmpbufP;
     tuple * tuplerow;
-    
+
     tuplerow = pnm_allocpamrow(pamP);
-    
+
     if (setjmp(jmpbuf) != 0) {
         pnm_freepamrow(tuplerow);
         pm_setjmpbuf(origJmpbufP);
@@ -159,13 +197,13 @@ readpamrow(const struct pam * const pamP,
 
 
 
-void 
-pnm_readpamrown(const struct pam * const pamP, 
+void
+pnm_readpamrown(const struct pam * const pamP,
                 tuplen *           const tuplenrow) {
 
-    /* For speed, we don't check any of the inputs for consistency 
+    /* For speed, we don't check any of the inputs for consistency
        here (unless it's necessary to avoid crashing).  Any consistency
-       checking should have been done by a prior call to 
+       checking should have been done by a prior call to
        pnm_writepaminit().
     */
     assert(pamP->maxval != 0);
@@ -186,7 +224,7 @@ pnm_readpamrown(const struct pam * const pamP,
 
 
 static void
-writepbmrow(const struct pam * const pamP, 
+writepbmrow(const struct pam * const pamP,
             const tuplen *     const tuplenrow) {
 
     jmp_buf jmpbuf;
@@ -206,26 +244,26 @@ writepbmrow(const struct pam * const pamP,
 
         for (col = 0; col < pamP->width; ++col)
             bitrow[col] = tuplenrow[col][0] < 0.5 ? PBM_BLACK : PBM_WHITE;
-        pbm_writepbmrow(pamP->file, bitrow, pamP->width, 
+        pbm_writepbmrow(pamP->file, bitrow, pamP->width,
                         pamP->format == PBM_FORMAT);
 
         pm_setjmpbuf(origJmpbufP);
     }
     pbm_freerow(bitrow);
-} 
+}
 
 
 
 static void
-writepamrow(const struct pam * const pamP, 
+writepamrow(const struct pam * const pamP,
             const tuplen *     const tuplenrow) {
 
     jmp_buf jmpbuf;
     jmp_buf * origJmpbufP;
     tuple * tuplerow;
-    
+
     tuplerow = pnm_allocpamrow(pamP);
-    
+
     if (setjmp(jmpbuf) != 0) {
         pnm_freepamrow(tuplerow);
         pm_setjmpbuf(origJmpbufP);
@@ -240,7 +278,7 @@ writepamrow(const struct pam * const pamP,
             for (plane = 0; plane < pamP->depth; ++plane)
                 tuplerow[col][plane] = (sample)
                     (tuplenrow[col][plane] * pamP->maxval + 0.5);
-        }    
+        }
         pnm_writepamrow(pamP, tuplerow);
 
         pm_setjmpbuf(origJmpbufP);
@@ -250,13 +288,13 @@ writepamrow(const struct pam * const pamP,
 
 
 
-void 
-pnm_writepamrown(const struct pam * const pamP, 
+void
+pnm_writepamrown(const struct pam * const pamP,
                  const tuplen *     const tuplenrow) {
 
-    /* For speed, we don't check any of the inputs for consistency 
+    /* For speed, we don't check any of the inputs for consistency
        here (unless it's necessary to avoid crashing).  Any consistency
-       checking should have been done by a prior call to 
+       checking should have been done by a prior call to
        pnm_writepaminit().
     */
     assert(pamP->maxval != 0);
@@ -274,16 +312,16 @@ pnm_writepamrown(const struct pam * const pamP,
 
 tuplen **
 pnm_allocpamarrayn(const struct pam * const pamP) {
-    
+
     tuplen ** tuplenarray;
     const char * error;
 
     /* If the speed of this is ever an issue, it might be sped up a little
        by allocating one large chunk.
     */
-    
+
     MALLOCARRAY(tuplenarray, pamP->height);
-    if (tuplenarray == NULL) 
+    if (tuplenarray == NULL)
         pm_asprintf(&error,
                     "Out of memory allocating the row pointer section of "
                     "a %u row array", pamP->height);
@@ -317,7 +355,7 @@ pnm_allocpamarrayn(const struct pam * const pamP) {
 
 
 void
-pnm_freepamarrayn(tuplen **          const tuplenarray, 
+pnm_freepamarrayn(tuplen **          const tuplenarray,
                   const struct pam * const pamP) {
 
     int row;
@@ -329,9 +367,9 @@ pnm_freepamarrayn(tuplen **          const tuplenarray,
 
 
 
-tuplen** 
-pnm_readpamn(FILE *       const file, 
-             struct pam * const pamP, 
+tuplen**
+pnm_readpamn(FILE *       const file,
+             struct pam * const pamP,
              int          const size) {
 
     tuplen **tuplenarray;
@@ -339,9 +377,9 @@ pnm_readpamn(FILE *       const file,
     jmp_buf * origJmpbufP;
 
     pnm_readpaminit(file, pamP, size);
-    
+
     tuplenarray = pnm_allocpamarrayn(pamP);
-    
+
     if (setjmp(jmpbuf) != 0) {
         pnm_freepamarrayn(tuplenarray, pamP);
         pm_setjmpbuf(origJmpbufP);
@@ -351,7 +389,7 @@ pnm_readpamn(FILE *       const file,
 
         pm_setjmpbufsave(&jmpbuf, &origJmpbufP);
 
-        for (row = 0; row < pamP->height; ++row) 
+        for (row = 0; row < pamP->height; ++row)
             pnm_readpamrown(pamP, tuplenarray[row]);
 
         pm_setjmpbuf(origJmpbufP);
@@ -361,15 +399,15 @@ pnm_readpamn(FILE *       const file,
 
 
 
-void 
-pnm_writepamn(struct pam * const pamP, 
+void
+pnm_writepamn(struct pam * const pamP,
               tuplen **    const tuplenarray) {
 
     unsigned int row;
 
     pnm_writepaminit(pamP);
-    
-    for (row = 0; row < pamP->height; ++row) 
+
+    for (row = 0; row < pamP->height; ++row)
         pnm_writepamrown(pamP, tuplenarray[row]);
 }
 
@@ -382,7 +420,7 @@ pnm_normalizetuple(struct pam * const pamP,
 
     unsigned int plane;
 
-    for (plane = 0; plane < pamP->depth; ++plane) 
+    for (plane = 0; plane < pamP->depth; ++plane)
         tuplen[plane] = (samplen)tuple[plane] / pamP->maxval;
 }
 
@@ -395,7 +433,7 @@ pnm_unnormalizetuple(struct pam * const pamP,
 
     unsigned int plane;
 
-    for (plane = 0; plane < pamP->depth; ++plane) 
+    for (plane = 0; plane < pamP->depth; ++plane)
         tuple[plane] = tuplen[plane] * pamP->maxval + 0.5;
 }
 
@@ -412,7 +450,7 @@ pnm_normalizeRow(struct pam *             const pamP,
            once here so we can multiply many times later.
         */
     unsigned int plane;
-    
+
     for (plane = 0; plane < pamP->depth; ++plane) {
         if (transform && transform[plane]) {
             unsigned int col;
@@ -437,14 +475,14 @@ reversemap(samplen          const samplen,
 /*----------------------------------------------------------------------------
    Find the integer sample value that maps to the normalized samplen value
    'samplen' through the map 'transformMap'.  We interpret the map as
-   mapping the value N+1 to all the values transformMap[N] through 
+   mapping the value N+1 to all the values transformMap[N] through
    transformMap[N+1], and we expect transformMap[N+1] to be greater than
    transformMap[N] for all N.
 -----------------------------------------------------------------------------*/
     /* Do a binary search, since the values are in sorted (increasing)
        order
     */
-    
+
     sample low, high;
 
     low = 0; high = maxval;  /* Consider whole range to start */
@@ -471,18 +509,18 @@ pnm_unnormalizeRow(struct pam *             const pamP,
                    tuple *                  const tuplerow) {
 
     unsigned int plane;
-    
+
     for (plane = 0; plane < pamP->depth; ++plane) {
         if (transform && transform[plane]) {
             unsigned int col;
             for (col = 0; col < pamP->width; ++col)
-                tuplerow[col][plane] = 
-                    reversemap(tuplenrow[col][plane], 
+                tuplerow[col][plane] =
+                    reversemap(tuplenrow[col][plane],
                                transform[plane], pamP->maxval);
         } else {
             unsigned int col;
             for (col = 0; col < pamP->width; ++col)
-                tuplerow[col][plane] = 
+                tuplerow[col][plane] =
                     tuplenrow[col][plane] * pamP->maxval + 0.5;
         }
     }
@@ -500,13 +538,13 @@ gammaCommon(struct pam *  const pamP,
     unsigned int plane;
     unsigned int opacityPlane;
     int haveOpacity;
-    
+
     pnm_getopacity(pamP, &haveOpacity, &opacityPlane);
 
     for (plane = 0; plane < pamP->depth; ++plane) {
         if (haveOpacity && plane == opacityPlane) {
             /* It's an opacity (alpha) plane, which means there is
-               no gamma adjustment in it.  
+               no gamma adjustment in it.
             */
         } else {
             unsigned int col;
@@ -550,7 +588,7 @@ applyopacityCommon(enum applyUnapply const applyUnapply,
 -----------------------------------------------------------------------------*/
     unsigned int opacityPlane;
     int haveOpacity;
-    
+
     pnm_getopacity(pamP, &haveOpacity, &opacityPlane);
 
     if (haveOpacity) {
@@ -657,7 +695,7 @@ createUngammaMapOffset(const struct pam * const pamP,
                     retval[plane] = NULL;
                 else
                     retval[plane] = ungammaTransformMap;
-            }            
+            }
             fillInMap(ungammaTransformMap, pamP->maxval, offset);
         } else {
             free(retval);
diff --git a/lib/libpbm2.c b/lib/libpbm2.c
index f199c51a..a35004f9 100644
--- a/lib/libpbm2.c
+++ b/lib/libpbm2.c
@@ -18,7 +18,7 @@
 #include "fileio.h"
 #include "pam.h"
 
-static bit 
+static bit
 getbit (FILE * const file) {
     char ch;
 
@@ -28,7 +28,7 @@ getbit (FILE * const file) {
 
     if ( ch != '0' && ch != '1' )
         pm_error( "junk in file where bits should be" );
-    
+
     return ( ch == '1' ) ? 1 : 0;
 }
 
@@ -157,9 +157,9 @@ pbm_readpbmrow( FILE * const file,
 
 
 void
-pbm_readpbmrow_packed(FILE *          const fileP, 
+pbm_readpbmrow_packed(FILE *          const fileP,
                       unsigned char * const packedBits,
-                      int             const cols, 
+                      int             const cols,
                       int             const format) {
 
     switch(format) {
@@ -182,20 +182,20 @@ pbm_readpbmrow_packed(FILE *          const fileP,
     case RPBM_FORMAT: {
         unsigned int bytesReadCt;
         bytesReadCt = fread(packedBits, 1, pbm_packed_bytes(cols), fileP);
-             
+
         if (bytesReadCt < pbm_packed_bytes(cols)) {
-            if (feof(fileP)) 
-                if (bytesReadCt == 0) 
+            if (feof(fileP))
+                if (bytesReadCt == 0)
                     pm_error("Attempt to read a raw PBM image row, but "
                              "no more rows left in file.");
                 else
                     pm_error("EOF in the middle of a raw PBM row.");
-            else 
+            else
                 pm_error("I/O error reading raw PBM row");
         }
     }
     break;
-    
+
     default:
         pm_error("Internal error in pbm_readpbmrow_packed.");
     }
@@ -205,7 +205,7 @@ pbm_readpbmrow_packed(FILE *          const fileP,
 
 void
 pbm_readpbmrow_bitoffset(FILE *          const ifP,
-                         unsigned char * const packedBits, 
+                         unsigned char * const packedBits,
                          int             const cols,
                          int             const format,
                          unsigned int    const offset) {
@@ -237,7 +237,7 @@ pbm_readpbmrow_bitoffset(FILE *          const ifP,
         /* Target slot doesn't start on byte boundary; right-shift. */
         unsigned char carryover;
         unsigned int i;
-  
+
         carryover = (origHead >> lsh) << lsh;
 
         for (i = 0; i <= last; ++i) {
@@ -246,7 +246,7 @@ pbm_readpbmrow_bitoffset(FILE *          const ifP,
             carryover = t;
         }
     }
-  
+
     if ((cols + rsh) % 8 > 0) {
         /* Adjust rightmost char */
         unsigned int  const trs = (cols + rsh) % 8;
diff --git a/lib/libpm.c b/lib/libpm.c
index f9aa1aef..b335debb 100644
--- a/lib/libpm.c
+++ b/lib/libpm.c
@@ -45,7 +45,7 @@ const char * pm_progname;
 int pm_plain_output;
     /* Boolean: programs should produce output in plain format */
 
-static bool pm_showmessages;  
+static bool pm_showmessages;
     /* Programs should display informational messages (because the user didn't
        specify the --quiet option).
     */
@@ -249,7 +249,7 @@ pm_errormsg(const char format[], ...) {
     va_start(args, format);
 
     pm_vasprintf(&msg, format, args);
-    
+
     errormsg(msg);
 
     pm_strfree(msg);
@@ -267,7 +267,7 @@ pm_error(const char format[], ...) {
     va_start(args, format);
 
     pm_vasprintf(&msg, format, args);
-    
+
     errormsg(msg);
 
     pm_strfree(msg);
@@ -356,7 +356,7 @@ pm_allocarray(int const cols,
 
 
 void
-pm_freearray(char ** const rowIndex, 
+pm_freearray(char ** const rowIndex,
              int     const rows) {
 
     void * const rowIndexVoid = rowIndex;
@@ -369,8 +369,8 @@ pm_freearray(char ** const rowIndex,
 /* Case-insensitive keyword matcher. */
 
 int
-pm_keymatch(const char *       const strarg, 
-            const char * const keywordarg, 
+pm_keymatch(const char *       const strarg,
+            const char * const keywordarg,
             int          const minchars) {
     int len;
     const char * keyword;
@@ -449,7 +449,7 @@ pm_bitstomaxval(int const bits) {
 
 
 unsigned int PURE_FN_ATTR
-pm_lcm(unsigned int const x, 
+pm_lcm(unsigned int const x,
        unsigned int const y,
        unsigned int const z,
        unsigned int const limit) {
@@ -472,7 +472,7 @@ pm_lcm(unsigned int const x,
            candidate <= limit)
         candidate += biggest;
 
-    if (candidate > limit) 
+    if (candidate > limit)
         candidate = limit;
 
     return candidate;
@@ -499,7 +499,7 @@ pm_init(const char * const progname,
 #ifdef HAVE_SETMODE
     /* Set the stdin and stdout mode to binary.  This means nothing on Unix,
        but matters on Windows.
-       
+
        Note that stdin and stdout aren't necessarily image files.  In
        particular, stdout is sometimes text for human consumption,
        typically printed on the terminal.  Binary mode isn't really
@@ -507,7 +507,7 @@ pm_init(const char * const progname,
        any knowledge of how stdin and stdout are being used because it is
        easy.  But we do make an exception for the case that we know the
        file is a terminal, to get a little closer to doing the right
-       thing.  
+       thing.
     */
     if (!isatty(0)) setmode(0,O_BINARY);  /* Standard Input */
     if (!isatty(1)) setmode(1,O_BINARY);  /* Standard Output */
@@ -525,7 +525,7 @@ dtMsg(time_t const dateTime) {
     struct tm * const brokenTimeP = localtime(&dateTime);
 
     char buffer[100];
-    
+
     strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", brokenTimeP);
 
     return pm_strdup(buffer);
@@ -579,7 +579,7 @@ showVersion(void) {
         pm_message( "RGB_ENV='%s'", RGBENV );
         rgbdef = getenv(RGBENV);
         if( rgbdef )
-            pm_message( "RGBENV= '%s' (env vbl set to '%s')", 
+            pm_message( "RGBENV= '%s' (env vbl set to '%s')",
                         RGBENV, rgbdef );
         else
             pm_message( "RGBENV= '%s' (env vbl is unset)", RGBENV);
@@ -592,7 +592,7 @@ static void
 showNetpbmHelp(const char progname[]) {
 /*----------------------------------------------------------------------------
   Tell the user where to get help for this program, assuming it is a Netpbm
-  program (a program that comes with the Netpbm package, as opposed to a 
+  program (a program that comes with the Netpbm package, as opposed to a
   program that just uses the Netpbm libraries).
 
   Tell him to go to the URL listed in the Netpbm configuration file.
@@ -610,9 +610,9 @@ showNetpbmHelp(const char progname[]) {
 
     if (getenv("NETPBM_CONF"))
         netpbmConfigFileName = getenv("NETPBM_CONF");
-    else 
+    else
         netpbmConfigFileName = "/etc/netpbm";
-    
+
     netpbmConfigFile = fopen(netpbmConfigFileName, "r");
     if (netpbmConfigFile == NULL) {
         pm_message("Unable to open Netpbm configuration file '%s'.  "
@@ -666,14 +666,14 @@ parseCommonOptions(int *         const argcP,
 
     for (inCursor = 1, outCursor = 1; inCursor < *argcP; ++inCursor) {
             if (strcaseeq(argv[inCursor], "-quiet") ||
-                strcaseeq(argv[inCursor], "--quiet")) 
+                strcaseeq(argv[inCursor], "--quiet"))
                 *showMessagesP = false;
             else if (strcaseeq(argv[inCursor], "-version") ||
-                     strcaseeq(argv[inCursor], "--version")) 
+                     strcaseeq(argv[inCursor], "--version"))
                 *showVersionP = true;
             else if (strcaseeq(argv[inCursor], "-help") ||
                      strcaseeq(argv[inCursor], "--help") ||
-                     strcaseeq(argv[inCursor], "-?")) 
+                     strcaseeq(argv[inCursor], "-?"))
                 *showHelpP = true;
             else if (strcaseeq(argv[inCursor], "-plain") ||
                      strcaseeq(argv[inCursor], "--plain"))
@@ -728,7 +728,7 @@ pm_proginit(int *         const argcP,
         exit(0);
     } else if (justShowHelp) {
         pm_error("Use 'man %s' for help.", progname);
-        /* If we can figure out a way to distinguish Netpbm programs from 
+        /* If we can figure out a way to distinguish Netpbm programs from
            other programs using the Netpbm libraries, we can do better here.
         */
         if (0)
@@ -742,7 +742,7 @@ pm_proginit(int *         const argcP,
 void
 pm_setMessage(int   const newState,
               int * const oldStateP) {
-    
+
     if (oldStateP)
         *oldStateP = pm_showmessages;
 
@@ -763,7 +763,7 @@ static void
 extractAfterLastSlash(const char * const fullPath,
                       char *       const retval,
                       size_t       const retvalSize) {
-    
+
     char * slashPos;
 
     /* Chop any directories off the left end */
@@ -794,13 +794,13 @@ chopOffExe(char * const arg) {
 char *
 pm_arg0toprogname(const char arg0[]) {
 /*----------------------------------------------------------------------------
-   Given a value for argv[0] (a command name or file name passed to a 
+   Given a value for argv[0] (a command name or file name passed to a
    program in the standard C calling sequence), return the name of the
    Netpbm program to which it refers.
 
    In the most ordinary case, this is simply the argument itself.
 
-   But if the argument contains a slash, it is the part of the argument 
+   But if the argument contains a slash, it is the part of the argument
    after the last slash, and if there is a .exe on it (as there is for
    DJGPP), that is removed.
 
@@ -848,7 +848,7 @@ pm_parse_width(const char * const arg) {
     unsigned int width;
     const char * error;
 
-    pm_interpret_uint(arg, &width, &error);
+    pm_string_to_uint(arg, &width, &error);
 
     if (error) {
         pm_error("'%s' is invalid as an image width.  %s", arg, error);
@@ -873,7 +873,7 @@ pm_parse_height(const char * const arg) {
     unsigned int height;
     const char * error;
 
-    pm_interpret_uint(arg, &height, &error);
+    pm_string_to_uint(arg, &height, &error);
 
     if (error) {
         pm_error("'%s' is invalid as an image height.  %s", arg, error);
diff --git a/lib/libppmcolor.c b/lib/libppmcolor.c
index 3378e076..27340d5f 100644
--- a/lib/libppmcolor.c
+++ b/lib/libppmcolor.c
@@ -23,376 +23,31 @@
 #include "netpbm/nstring.h"
 #include "ppm.h"
 #include "colorname.h"
+#include "pam.h"
 
 
-static void
-computeHexTable(int hexit[]) {
-
-    unsigned int i;
-
-    for ( i = 0; i < 256; ++i )
-        hexit[i] = -1;
-
-    hexit['0'] = 0;
-    hexit['1'] = 1;
-    hexit['2'] = 2;
-    hexit['3'] = 3;
-    hexit['4'] = 4;
-    hexit['5'] = 5;
-    hexit['6'] = 6;
-    hexit['7'] = 7;
-    hexit['8'] = 8;
-    hexit['9'] = 9;
-    hexit['a'] = hexit['A'] = 10;
-    hexit['b'] = hexit['B'] = 11;
-    hexit['c'] = hexit['C'] = 12;
-    hexit['d'] = hexit['D'] = 13;
-    hexit['e'] = hexit['E'] = 14;
-    hexit['f'] = hexit['F'] = 15;
-}
-
+pixel
+ppm_parsecolor2(const char * const colorname,
+                pixval       const maxval,
+                int          const closeOk) {
 
+    tuple const color = pnm_parsecolor2(colorname, maxval, closeOk);
 
-static long
-invRgbnorm(pixval       const rgb,
-           pixval       const maxval,
-           unsigned int const hexDigits) {
-/*----------------------------------------------------------------------------
-  This is the inverse of 'rgbnorm', below.
------------------------------------------------------------------------------*/
-    long retval;
-
-    switch (hexDigits) {
-    case 1:
-        retval = (long)((double) rgb * 15 / maxval + 0.5);
-        break;
-    case 2:
-        retval = (long) ((double) rgb * 255 / maxval + 0.5);
-        break;
-    case 3:
-        retval = (long) ((double) rgb * 4095 / maxval + 0.5);
-        break;
-    case 4:
-        retval = (long) ((double) rgb * 65535UL / maxval + 0.5);
-        break;
-    default:
-        pm_message("Internal error in invRgbnorm()");
-        abort();
-    }
-    return retval;
-}
-
+    pixel retval;
 
+    PPM_PUTR(retval, color[PAM_RED_PLANE]);
+    PPM_PUTG(retval, color[PAM_GRN_PLANE]);
+    PPM_PUTB(retval, color[PAM_BLU_PLANE]);
 
-static pixval
-rgbnorm(long         const rgb, 
-        pixval       const maxval, 
-        unsigned int const hexDigitCount, 
-        bool         const closeOk,
-        const char * const colorname) {
-/*----------------------------------------------------------------------------
-   Normalize the color (r, g, or b) value 'rgb', which was specified
-   with 'hexDigitCount' digits, to a maxval of 'maxval'.  If the
-   number of digits isn't valid, issue an error message and identify
-   the complete color color specification in error as 'colorname'.
-
-   For example, if the user says "0ff" and the maxval is 100,
-   then rgb is 0xff, n is 3, and our result is 
-   0xff / (16**3-1) * 100 = 6.
------------------------------------------------------------------------------*/
-    pixval retval;
-
-    switch (hexDigitCount) {
-    case 0:
-        pm_error("A hexadecimal color specifier in color '%s' is "
-                 "an empty string", colorname);
-        break;
-    case 1:
-        retval = (pixval)((double) rgb * maxval / 15 + 0.5);
-        break;
-    case 2:
-        retval = (pixval) ((double) rgb * maxval / 255 + 0.5);
-        break;
-    case 3:
-        retval = (pixval) ((double) rgb * maxval / 4095 + 0.5);
-        break;
-    case 4:
-        retval = (pixval) ((double) rgb * maxval / 65535L + 0.5);
-        break;
-    default:
-        pm_error("color specifier '%s' has too many digits", colorname);
-    }
+    free(color);
 
-    if (!closeOk) {
-        long const newrgb = invRgbnorm(retval, maxval, hexDigitCount);
-        if (newrgb != rgb)
-            pm_message("WARNING: Component 0x%lx of color '%s' "
-                       "cannot be represented precisely with maxval %u.  "
-                       "Approximating as %u.",
-                       rgb, colorname, maxval, retval);
-    }
     return retval;
 }
 
 
 
-static void
-parseHexDigits(const char *   const string,
-               char           const delim,
-               int            const hexit[],
-               pixval *       const nP,
-               unsigned int * const digitCountP) {
-
-    unsigned int digitCount;
-    pixval n;
-    
-    digitCount = 0;  /* initial value */
-    n = 0;           /* initial value */
-    while (string[digitCount] != delim) {
-        char const digit = string[digitCount];
-        if (digit == '\0')
-            pm_error("rgb: color spec ends prematurely");
-        else {
-            int const hexval = hexit[(unsigned int)digit];
-            if (hexval == -1)
-                pm_error("Invalid hex digit in rgb: color spec: 0x%02x",
-                         digit);
-            n = n * 16 + hexval;
-            ++digitCount;
-        }
-    }
-    *nP = n;
-    *digitCountP = digitCount;
-}
-
-
-
-static void
-parseNewHexX11(char       const colorname[], 
-               pixval     const maxval,
-               bool       const closeOk,
-               pixel *    const colorP) {
-/*----------------------------------------------------------------------------
-   Determine what color colorname[] specifies in the new style hex
-   color specification format (e.g. rgb:55/40/55).
-
-   Return that color as *colorP.
-
-   Assume colorname[] starts with "rgb:", but otherwise it might be
-   gibberish.
------------------------------------------------------------------------------*/
-    int hexit[256];
-
-    const char * cp;
-    pixval n;
-    unsigned int digitCount;
-    pixval rNorm, gNorm, bNorm;
-
-    computeHexTable(hexit);
-
-    cp = &colorname[4];
-
-    parseHexDigits(cp, '/', hexit, &n, &digitCount);
-
-    rNorm = rgbnorm(n, maxval, digitCount, closeOk, colorname);
-
-    cp += digitCount;
-    ++cp;  /* Skip the slash */
-
-    parseHexDigits(cp, '/', hexit, &n, &digitCount);
-
-    gNorm = rgbnorm(n, maxval, digitCount, closeOk, colorname);
-
-    cp += digitCount;
-    ++cp;  /* Skip the slash */
-
-    parseHexDigits(cp, '\0', hexit, &n, &digitCount);
-
-    bNorm = rgbnorm(n, maxval, digitCount, closeOk, colorname);
-
-    PPM_ASSIGN(*colorP, rNorm, gNorm, bNorm);
-}
-
-
-
-static void
-parseNewDecX11(char       const colorname[], 
-               pixval     const maxval,
-               bool       const closeOk,
-               pixel *    const colorP) {
-
-    float const epsilon = 1.0/65536.0;
-    float fr, fg, fb;
-    pixval rNorm, gNorm, bNorm;
-
-    if (sscanf( colorname, "rgbi:%f/%f/%f", &fr, &fg, &fb) != 3)
-        pm_error("invalid color specifier '%s'", colorname);
-    if (fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 
-        || fb < 0.0 || fb > 1.0)
-        pm_error("invalid color specifier '%s' - "
-                 "values must be between 0.0 and 1.0", colorname );
-
-    rNorm = fr * maxval + 0.5;
-    gNorm = fg * maxval + 0.5;
-    bNorm = fb * maxval + 0.5;
-
-    if (!closeOk) {
-        if (fabs((double)rNorm/maxval - fr) > epsilon ||
-            fabs((double)gNorm/maxval - fg) > epsilon ||
-            fabs((double)bNorm/maxval - fb) > epsilon)
-            pm_message("WARNING: Color '%s' cannot be represented "
-                       "precisely with maxval %u.  "
-                       "Approximating as (%u,%u,%u).",
-                       colorname, maxval, rNorm, gNorm, bNorm);
-    }
-    PPM_ASSIGN(*colorP, rNorm, gNorm, bNorm);
-}
-
-
-
-static void
-parseOldX11(char       const colorname[], 
-            pixval     const maxval,
-            bool       const closeOk,
-            pixel *    const colorP) {
-/*----------------------------------------------------------------------------
-   Return as *colorP the color specified by the old X11 style color
-   specififier colorname[] (e.g. #554055).
------------------------------------------------------------------------------*/
-    int hexit[256];
-    long r,g,b;
-    pixval rNorm, gNorm, bNorm;
-    
-    computeHexTable(hexit);
-
-    if (!pm_strishex(&colorname[1]))
-        pm_error("Non-hexadecimal characters in #-type color specification");
-
-    switch (strlen(colorname) - 1 /* (Number of hex digits) */) {
-    case 3:
-        r = hexit[(int)colorname[1]];
-        g = hexit[(int)colorname[2]];
-        b = hexit[(int)colorname[3]];
-        rNorm = rgbnorm(r, maxval, 1, closeOk, colorname);
-        gNorm = rgbnorm(g, maxval, 1, closeOk, colorname);
-        bNorm = rgbnorm(b, maxval, 1, closeOk, colorname);
-        break;
-
-    case 6:
-        r = (hexit[(int)colorname[1]] << 4 ) + hexit[(int)colorname[2]];
-        g = (hexit[(int)colorname[3]] << 4 ) + hexit[(int)colorname[4]];
-        b = (hexit[(int)colorname[5]] << 4 ) + hexit[(int)colorname[6]];
-        rNorm = rgbnorm(r, maxval, 2, closeOk, colorname);
-        gNorm = rgbnorm(g, maxval, 2, closeOk, colorname);
-        bNorm = rgbnorm(b, maxval, 2, closeOk, colorname);
-        break;
-
-    case 9:
-        r = (hexit[(int)colorname[1]] << 8) +
-            (hexit[(int)colorname[2]] << 4) +
-            (hexit[(int)colorname[3]] << 0);
-        g = (hexit[(int)colorname[4]] << 8) + 
-            (hexit[(int)colorname[5]] << 4) +
-            (hexit[(int)colorname[6]] << 0);
-        b = (hexit[(int)colorname[7]] << 8) + 
-            (hexit[(int)colorname[8]] << 4) +
-            (hexit[(int)colorname[9]] << 0);
-        rNorm = rgbnorm(r, maxval, 3, closeOk, colorname);
-        gNorm = rgbnorm(g, maxval, 3, closeOk, colorname);
-        bNorm = rgbnorm(b, maxval, 3, closeOk, colorname);
-        break;
-
-    case 12:
-        r = (hexit[(int)colorname[1]] << 12) + 
-            (hexit[(int)colorname[2]] <<  8) +
-            (hexit[(int)colorname[3]] <<  4) + hexit[(int)colorname[4]];
-        g = (hexit[(int)colorname[5]] << 12) + 
-            (hexit[(int)colorname[6]] <<  8) +
-            (hexit[(int)colorname[7]] <<  4) + hexit[(int)colorname[8]];
-        b = (hexit[(int)colorname[9]] << 12) + 
-            (hexit[(int)colorname[10]] << 8) +
-            (hexit[(int)colorname[11]] << 4) + hexit[(int)colorname[12]];
-        rNorm = rgbnorm(r, maxval, 4, closeOk, colorname);
-        gNorm = rgbnorm(g, maxval, 4, closeOk, colorname);
-        bNorm = rgbnorm(b, maxval, 4, closeOk, colorname);
-        break;
-
-    default:
-        pm_error("invalid color specifier '%s'", colorname);
-    }
-    PPM_ASSIGN(*colorP, rNorm, gNorm, bNorm);
-}
-
-
-
-
-static void
-parseOldX11Dec(const char       colorname[], 
-               pixval     const maxval,
-               bool       const closeOk,
-               pixel *    const colorP) {
-
-    float const epsilon = 1.0/65536.0;
-
-    float fr, fg, fb;
-    pixval rNorm, gNorm, bNorm;
-
-    if (sscanf(colorname, "%f,%f,%f", &fr, &fg, &fb) != 3)
-        pm_error("invalid color specifier '%s'", colorname);
-    if (fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 
-        || fb < 0.0 || fb > 1.0)
-        pm_error("invalid color specifier '%s' - "
-                 "values must be between 0.0 and 1.0", colorname );
-
-    rNorm = fr * maxval + 0.5;
-    gNorm = fg * maxval + 0.5;
-    bNorm = fb * maxval + 0.5;
-
-    if (!closeOk) {
-        if (fabs((float)rNorm/maxval - fr) > epsilon ||
-            fabs((float)gNorm/maxval - fg) > epsilon ||
-            fabs((float)bNorm/maxval - fb) > epsilon)
-            pm_message("WARNING: Color '%s' cannot be represented "
-                       "precisely with maxval %u.  "
-                       "Approximating as (%u,%u,%u).",
-                       colorname, maxval, rNorm, gNorm, bNorm);
-    }
-    PPM_ASSIGN(*colorP, rNorm, gNorm, bNorm);
-}
-
-
-
-pixel
-ppm_parsecolor2(const char * const colorname,
-                pixval       const maxval,
-                int          const closeOk) {
-
-    pixel color;
-    
-    if (strncmp(colorname, "rgb:", 4) == 0)
-        /* It's a new-X11-style hexadecimal rgb specifier. */
-        parseNewHexX11(colorname, maxval, closeOk, &color);
-    else if (strncmp(colorname, "rgbi:", 5) == 0)
-        /* It's a new-X11-style decimal/float rgb specifier. */
-        parseNewDecX11(colorname, maxval, closeOk, &color);
-    else if (colorname[0] == '#')
-        /* It's an old-X11-style hexadecimal rgb specifier. */
-        parseOldX11(colorname, maxval, closeOk, &color);
-    else if ((colorname[0] >= '0' && colorname[0] <= '9') ||
-             colorname[0] == '.')
-        /* It's an old-style decimal/float rgb specifier. */
-        parseOldX11Dec(colorname, maxval, closeOk, &color);
-    else 
-        /* Must be a name from the X-style rgb file. */
-        pm_parse_dictionary_name(colorname, maxval, closeOk, &color);
-    
-    return color;
-}
-
-
-
 pixel
-ppm_parsecolor(const char * const colorname, 
+ppm_parsecolor(const char * const colorname,
                pixval       const maxval) {
 
     return ppm_parsecolor2(colorname, maxval, TRUE);
@@ -401,13 +56,14 @@ ppm_parsecolor(const char * const colorname,
 
 
 char *
-ppm_colorname(const pixel * const colorP, 
-              pixval        const maxval, 
+ppm_colorname(const pixel * const colorP,
+              pixval        const maxval,
               int           const hexok)   {
 
     int r, g, b;
     FILE * f;
     static char colorname[200];
+        /* Null string means no suitable name so far */
 
     if (maxval == 255) {
         r = PPM_GETR(*colorP);
@@ -420,33 +76,57 @@ ppm_colorname(const pixel * const colorP,
     }
 
     f = pm_openColornameFile(NULL, !hexok);
-    if (f != NULL) {
-        int best_diff, this_diff;
+
+    if (!f)
+        STRSCPY(colorname, "");
+    else {
+        int bestDiff;
         bool eof;
 
-        best_diff = 32767;
-        eof = FALSE;
-        while (!eof && best_diff > 0 ) {
+        for (bestDiff = 32767, eof = FALSE;
+             !eof && bestDiff > 0; ) {
             struct colorfile_entry const ce = pm_colorget(f);
             if (ce.colorname)  {
-                this_diff = abs(r - ce.r) + abs(g - ce.g) + abs(b - ce.b);
-                if (this_diff < best_diff) {
-                    best_diff = this_diff;
-                    strcpy(colorname, ce.colorname);
+                int const thisDiff =
+                    abs(r - (int)ce.r) +
+                    abs(g - (int)ce.g) +
+                    abs(b - (int)ce.b);
+
+                if (thisDiff < bestDiff) {
+                    bestDiff = thisDiff;
+                    STRSCPY(colorname, ce.colorname);
                 }
             } else
                 eof = TRUE;
         }
         fclose(f);
-        if (best_diff != 32767 && (best_diff == 0 || ! hexok))
-            return colorname;
+
+        if (bestDiff == 32767) {
+            /* Color file contain no entries, so we can't even pick a close
+               one
+            */
+            STRSCPY(colorname, "");
+        } else if (bestDiff > 0 && hexok) {
+            /* We didn't find an exact match and user is willing to accept
+               hex, so we don't have to use an approximate match.
+            */
+            STRSCPY(colorname, "");
+        }
     }
 
-    /* Color lookup failed, but caller is willing to take an X11-style
-       hex specifier, so return that.
-    */
-    sprintf(colorname, "#%02x%02x%02x", r, g, b);
-    return colorname;}
+    if (streq(colorname, "")) {
+        if (hexok) {
+            /* Color lookup failed, but caller is willing to take an X11-style
+               hex specifier, so return that.
+            */
+            sprintf(colorname, "#%02x%02x%02x", r, g, b);
+        } else {
+            pm_error("Couldn't find any name colors at all");
+        }
+    }
+
+    return colorname;
+}
 
 
 
@@ -509,7 +189,7 @@ processColorfileEntry(struct colorfile_entry const ce,
             /* The color is already in the hash, which means we saw it
                earlier in the file.  We prefer the first name that the
                file gives for each color, so we just ignore the
-               current entry.  
+               current entry.
             */
             *errorP = NULL;
         } else {
@@ -576,15 +256,15 @@ readOpenColorFile(FILE *          const colorFileP,
 
     while (!done && !*errorP) {
         struct colorfile_entry const ce = pm_colorget(colorFileP);
-        
-        if (!ce.colorname)  
+
+        if (!ce.colorname)
             done = TRUE;
-        else 
+        else
             processColorfileEntry(ce, cht, colornames, colors,
                                   &nColorsDone, errorP);
     }
     *nColorsP = nColorsDone;
-    
+
     if (*errorP) {
         unsigned int colorIndex;
 
@@ -630,13 +310,13 @@ readColorFile(const char *    const fileName,
         } else {
             readOpenColorFile(colorFileP, nColorsP, colornames, colors, cht,
                               errorP);
-            
+
             fclose(colorFileP);
         }
     }
 }
 
-    
+
 
 static void
 readcolordict(const char *      const fileName,
@@ -657,14 +337,14 @@ readcolordict(const char *      const fileName,
         pixel * colors;
 
         MALLOCARRAY(colors, MAXCOLORNAMES);
-        
+
         if (colors == NULL)
             pm_asprintf(errorP, "Unable to allocate space for color table.");
         else {
             colorhash_table cht;
 
             cht = allocColorHash();
-            
+
             if (cht == NULL)
                 pm_asprintf(errorP, "Unable to allocate space for color hash");
             else {
@@ -754,9 +434,9 @@ ppm_readcolordict(const char *      const fileName,
 
 
 void
-ppm_readcolornamefile(const char *      const fileName, 
+ppm_readcolornamefile(const char *      const fileName,
                       int               const mustOpen,
-                      colorhash_table * const chtP, 
+                      colorhash_table * const chtP,
                       const char ***    const colornamesP) {
 
     ppm_readcolordict(fileName, mustOpen, NULL, colornamesP, NULL, chtP);
@@ -778,7 +458,7 @@ ppm_freecolornames(const char ** const colornames) {
 
 
 
-static unsigned int 
+static unsigned int
 nonnegative(unsigned int const arg) {
 
     if ((int)(arg) < 0)
@@ -790,8 +470,8 @@ nonnegative(unsigned int const arg) {
 
 
 pixel
-ppm_color_from_ycbcr(unsigned int const y, 
-                     int          const cb, 
+ppm_color_from_ycbcr(unsigned int const y,
+                     int          const cb,
                      int          const cr) {
 /*----------------------------------------------------------------------------
    Return the color that has luminance 'y', blue chrominance 'cb', and
@@ -805,12 +485,12 @@ ppm_color_from_ycbcr(unsigned int const y,
 -----------------------------------------------------------------------------*/
     pixel retval;
 
-    PPM_ASSIGN(retval, 
+    PPM_ASSIGN(retval,
                y + 1.4022 * cr,
                nonnegative(y - 0.7145 * cr - 0.3456 * cb),
                y + 1.7710 * cb
         );
-    
+
     return retval;
 }
 
@@ -876,7 +556,7 @@ ppm_color_from_hsv(struct hsv const hsv,
             pm_error("Invalid H value passed to color_from_HSV: %f", hsv.h);
         }
     }
-    PPM_ASSIGN(retval, 
+    PPM_ASSIGN(retval,
                ROUNDU(R * maxval),
                ROUNDU(G * maxval),
                ROUNDU(B * maxval));
diff --git a/lib/libsystem.c b/lib/libsystem.c
index 57073dce..bf2416a4 100644
--- a/lib/libsystem.c
+++ b/lib/libsystem.c
@@ -18,7 +18,6 @@
    Contributed to the public domain.
 =============================================================================*/
 #define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */
-#define _XOPEN_SOURCE
 #define _BSD_SOURCE  /* Make SIGWINCH defined on OpenBSD */
 
 #include <stdarg.h>
diff --git a/lib/pam.h b/lib/pam.h
index d8d0e5c7..c2cfb4c7 100644
--- a/lib/pam.h
+++ b/lib/pam.h
@@ -401,6 +401,11 @@ typedef float samplen;
 typedef samplen *tuplen;
     /* Same as 'tuple', except using normalized samples. */
 
+tuplen
+pnm_allocpamtuplen(const struct pam * const pamP);
+
+#define pnm_freepamtuplen(tuplen) pm_freerow((char*) tuplen)
+
 tuplen *
 pnm_allocpamrown(const struct pam * const pamP);
 
@@ -490,6 +495,11 @@ pnm_createungammatransform(const struct pam * const pamP);
 #define pnm_freeungammatransform pnm_freegammatransform;
 
 tuple
+pnm_parsecolor2(const char * const colorname,
+                sample       const maxval,
+                int          const closeOk);
+
+tuple
 pnm_parsecolor(const char * const colorname,
                sample       const maxval);
 
@@ -501,6 +511,29 @@ pnm_colorname(struct pam * const pamP,
               tuple        const color,
               int          const hexok);
 
+const char *
+pnm_colorspec_rgb_integer(struct pam * const pamP,
+                          tuple        const color,
+                          sample       const maxval);
+
+const char *
+pnm_colorspec_rgb_norm(struct pam * const pamP,
+                       tuple        const color,
+                       unsigned int const digitCt);
+
+const char *
+pnm_colorspec_rgb_x11(struct pam * const pamP,
+                      tuple        const color,
+                      unsigned int const hexDigitCt);
+
+const char *
+pnm_colorspec_dict(struct pam * const pamP,
+                   tuple        const color);
+
+const char *
+pnm_colorspec_dict_close(struct pam * const pamP,
+                         tuple        const color);
+
 extern double
 pnm_lumin_factor[3];
 
diff --git a/lib/util/mallocvar.c b/lib/util/mallocvar.c
index 339d5d61..f75bd94d 100644
--- a/lib/util/mallocvar.c
+++ b/lib/util/mallocvar.c
@@ -30,7 +30,7 @@ allocarrayNoHeap(void **      const rowIndex,
         void * rowSpace;
 
         mallocProduct(&rowSpace, cols, elementSize);
-        
+
         if (rowSpace == NULL) {
             unsigned int row;
 
@@ -123,7 +123,7 @@ pm_mallocarray2(void **      const resultP,
 
             if (rowheap) {
                 unsigned int row;
-                
+
                 for (row = 0; row < rows; ++row)
                     rowIndex[row] = &(rowheap[row * cols * elementSize]);
             }
@@ -133,7 +133,7 @@ pm_mallocarray2(void **      const resultP,
                format.
             */
             rowIndex[rows+1] = NULL;   /* Declare it fragmented format */
-            
+
             allocarrayNoHeap(rowIndex, rows, cols, elementSize, &failed);
         }
         rowIndex[rows+0] = NULL;   /* mark end of rows */
@@ -151,7 +151,7 @@ array2RowCount(void ** const rowIndex) {
 /*----------------------------------------------------------------------------
    Return the number of rows in the 2-dimensional array.
 -----------------------------------------------------------------------------*/
-    /* The end of the rows is marked by a null pointer where a row 
+    /* The end of the rows is marked by a null pointer where a row
        pointer otherwise would be.
     */
 
diff --git a/lib/util/mallocvar.h b/lib/util/mallocvar.h
index e92e3fe4..00ba6484 100644
--- a/lib/util/mallocvar.h
+++ b/lib/util/mallocvar.h
@@ -1,5 +1,5 @@
 /* These are some dynamic memory allocation facilities.  They are essentially
-   an extension to C, as they do allocations with a cognizance of C 
+   an extension to C, as they do allocations with a cognizance of C
    variables.  You can use them to make C read more like a high level
    language.
 
@@ -23,7 +23,7 @@ extern "C" {
 #endif
 
 static __inline__ void
-mallocProduct(void **      const resultP, 
+mallocProduct(void **      const resultP,
               unsigned int const factor1,
               unsigned int const factor2) {
 /*----------------------------------------------------------------------------
@@ -44,10 +44,10 @@ mallocProduct(void **      const resultP,
     if (factor1 == 0 || factor2 == 0)
         *resultP = malloc(1);
     else {
-        if (UINT_MAX / factor2 < factor1) 
+        if (UINT_MAX / factor2 < factor1)
             *resultP = NULL;
-        else 
-            *resultP = malloc(factor1 * factor2); 
+        else
+            *resultP = malloc(factor1 * factor2);
     }
 }
 
@@ -61,11 +61,11 @@ reallocProduct(void **      const blockP,
     void * const oldBlockP = *blockP;
 
     void * newBlockP;
-    
-    if (UINT_MAX / factor2 < factor1) 
+
+    if (UINT_MAX / factor2 < factor1)
         newBlockP = NULL;
-    else 
-        newBlockP = realloc(oldBlockP, factor1 * factor2); 
+    else
+        newBlockP = realloc(oldBlockP, factor1 * factor2);
 
     if (newBlockP)
         *blockP = newBlockP;
diff --git a/lib/util/nstring.c b/lib/util/nstring.c
index 8cff4d56..7ef9fcfb 100644
--- a/lib/util/nstring.c
+++ b/lib/util/nstring.c
@@ -1007,43 +1007,6 @@ pm_strishex(const char * const subject) {
 
 
 void
-pm_interpret_uint(const char *   const string,
-                  unsigned int * const valueP,
-                  const char **  const errorP) {
-
-    if (string[0] == '\0')
-        pm_asprintf(errorP, "Null string.");
-    else {
-        /* strtoul() does a bizarre thing where if the number is out
-           of range, it returns a clamped value but tells you about it
-           by setting errno = ERANGE.  If it is not out of range,
-           strtoul() leaves errno alone.
-        */
-        char * tail;
-        unsigned long ulongValue;
-
-        errno = 0;  /* So we can tell if strtoul() overflowed */
-
-        ulongValue = strtoul(string, &tail, 10);
-
-        if (tail[0] != '\0')
-            pm_asprintf(errorP, "Non-digit stuff in string: %s", tail);
-        else if (errno == ERANGE)
-            pm_asprintf(errorP, "Number too large");
-        else if (ulongValue > UINT_MAX)
-            pm_asprintf(errorP, "Number too large");
-        else if (string[0] == '-')
-            pm_asprintf(errorP, "Negative number");
-            /* Sleazy code; string may have leading spaces. */
-        else {
-            *valueP = ulongValue;
-            *errorP = NULL;
-        }
-    }
-}
-
-
-void
 pm_string_to_uint(const char *   const string,
                   unsigned int * const uintP,
                   const char **  const errorP) {
@@ -1052,31 +1015,39 @@ pm_string_to_uint(const char *   const string,
         pm_asprintf(errorP, "Value is a null string");
     else {
         char * tailptr;
+        long longValue;
 
-        /* We can't use 'strtoull'.  Contrary to expectations, though as
+        /* We can't use 'strtoul'.  Contrary to expectations, though as
            designed, it returns junk if there is a minus sign.
         */
 
-        long longValue;
+        /* strtol() does a bizarre thing where if the number is out
+           of range, it returns a clamped value but tells you about it
+           by setting errno = ERANGE.  If it is not out of range,
+           strtol() leaves errno alone.
+        */
+        errno = 0;  /* So we can tell if strtoul() overflowed */
 
         longValue = strtol(string, &tailptr, 10);
 
-
-        *uintP = strtoul(string, &tailptr, 10);
-
         if (*tailptr != '\0')
             pm_asprintf(errorP, "Non-numeric crap in string: '%s'", tailptr);
         else {
-            if (longValue < 0)
-                pm_asprintf(errorP, "Number is negative");
-            else {
-                if ((unsigned int)longValue != longValue)
-                    pm_asprintf(errorP, "Number is too large for computation");
-                else {
-                    *uintP = (unsigned int)longValue;
-                    *errorP = NULL;
-                }
-            }
+             if (errno == ERANGE)
+                 pm_asprintf(errorP, "Number is too large for computation");
+             else {
+                 if (longValue < 0)
+                     pm_asprintf(errorP, "Number is negative");
+                 else {
+                     if ((unsigned int)longValue != longValue)
+                         pm_asprintf(errorP,
+                                     "Number is too large for computation");
+                     else {
+                         *uintP = (unsigned int)longValue;
+                         *errorP = NULL;
+                     }
+                 }
+             }
         }
     }
 }
diff --git a/lib/util/nstring.h b/lib/util/nstring.h
index bded8417..5159277c 100644
--- a/lib/util/nstring.h
+++ b/lib/util/nstring.h
@@ -60,15 +60,21 @@ static __inline__ int
 memeq(const void * const comparand,
       const void * const comparator,
       size_t       const size) {
-    
+
     return memcmp(comparand, comparator, size) == 0;
 }
 
-/* The Standard C Library may not declare strcasecmp() if the including
-   source file doesn't request BSD functions, with _BSD_SOURCE.  So
-   we don't define functions that use strcasecmp() in that case.
+/* The Standard C Library may not declare strcasecmp() if the including source
+   file doesn't request BSD functions, with _BSD_SOURCE or SUSv2 function,
+   with _XOPEN_SOURCE >= 500.  So we don't define functions that use
+   strcasecmp() in that case.
+
+   (Actually, _XOPEN_SOURCE 500 is stronger than you need for strcasecmp -
+   _XOPEN_SOURCE_EXTENDED, which asks for XPG 4, would do, whereas
+   _XOPEN_SOURCE 500 asks for XPG 5, but for simplicity, we don't use
+   _XOPEN_SOURCE_EXTENDED in Netpbm.
 */
-#ifdef _BSD_SOURCE
+#if defined(_BSD_SOURCE) || (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE - 0) >= 500)
 static __inline__ int
 strcaseeq(const char * const comparand,
           const char * const comparator) {
@@ -86,7 +92,7 @@ strncaseeq(const char * const comparand,
 #endif
 
 
-/* The standard C library routines isdigit(), for some weird 
+/* The standard C library routines isdigit(), for some weird
    historical reason, does not take a character (type 'char') as its
    argument.  Instead it takes an integer.  When the integer is a whole
    number, it represents a character in the obvious way using the local
@@ -126,7 +132,7 @@ strncaseeq(const char * const comparand,
    Netpbm must include them in its own libraries, and because some
    standard C libraries have some of them, Netpbm must use different
    names for them.
-   
+
    The GNU C library has all of them.  All but the oldest standard C libraries
    have snprintf().
 
@@ -183,7 +189,7 @@ pm_vasprintf(const char ** const resultP,
 bool
 pm_vasprintf_knows_float(void);
 
-void 
+void
 pm_strfree(const char * const string);
 
 const char *
@@ -203,11 +209,6 @@ bool
 pm_strishex(const char * const subject);
 
 void
-pm_interpret_uint(const char *   const string,
-               unsigned int * const valueP,
-               const char **  const errorP);
-
-void
 pm_string_to_uint(const char *   const string,
                   unsigned int * const uintP,
                   const char **  const errorP);
diff --git a/other/pampick.c b/other/pampick.c
index 61941f06..67d42fc5 100644
--- a/other/pampick.c
+++ b/other/pampick.c
@@ -58,7 +58,7 @@ isMemberOfUintSet(const struct uintSet * const uintSetP,
     unsigned int i;
 
     retval = FALSE;  /* initial assumption */
-    
+
     for (i = 0; i < uintSetP->count; ++i) {
         if (uintSetP->list[i] == searchValue)
             retval = TRUE;
@@ -137,7 +137,7 @@ parseCommandLine(int argc, const char ** argv,
                 if (*endPtr != '\0')
                     pm_error("Garbage in sequence number argument '%s': '%s'",
                              argv[i+1], endPtr);
-                
+
                 if (strtolResult < 0)
                     pm_error("Image sequence number cannot be negative.  "
                              "You specified %d", strtolResult);
@@ -171,7 +171,7 @@ extractOneImage(FILE * const infileP,
     struct pam inpam;
     struct pam outpam;
     enum pm_check_code checkRetval;
-    
+
     unsigned int row;
     tuple * tuplerow;
 
@@ -222,13 +222,13 @@ main(int argc, const char *argv[]) {
     struct cmdlineInfo cmdline;
 
     int eof;  /* No more images in input */
-    unsigned int imageSeq;  
+    unsigned int imageSeq;
         /* Sequence of current image in input file.  First = 0 */
 
     pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
-    
+
     eof = FALSE;
     for (imageSeq = 0; !eof; ++imageSeq) {
         if (isMemberOfUintSet(&cmdline.imageSeqList, imageSeq)) {
@@ -247,6 +247,6 @@ main(int argc, const char *argv[]) {
 
     pm_close(stdin);
     pm_close(stdout);
-    
+
     return 0;
 }
diff --git a/test/Execute-Tests b/test/Execute-Tests
index e69c84e7..7a65d51f 100755
--- a/test/Execute-Tests
+++ b/test/Execute-Tests
@@ -180,7 +180,7 @@ elif [ $VALGRIND_TESTS = "on" ]
   vg_command_base="valgrind --trace-children=yes";
 
   for i in awk cat cksum cmp cp cut date dirname egrep fgrep file grep gs \
-    head mkdir mktemp perl rm sed seq sh tee testrandom tr uniq \
+    head iconv mkdir mktemp perl rm sed seq sh tee testrandom tr uniq \
     Available-Testprog
 
     # Tell valgrind not to probe execution of the above programs.
diff --git a/test/Test-Order b/test/Test-Order
index 9b280d12..6abc2287 100644
--- a/test/Test-Order
+++ b/test/Test-Order
@@ -12,6 +12,9 @@ pamseq.test
 
 pbmpage.test
 pbmtext.test
+pbmtext-bdf.test
+pbmtext-iso88591.test
+pbmtext-utf8.test
 pbmupc.test
 pgmramp.test
 pamgauss.test
diff --git a/test/pbmtext-bdf.ok b/test/pbmtext-bdf.ok
new file mode 100644
index 00000000..5ab8b4af
--- /dev/null
+++ b/test/pbmtext-bdf.ok
@@ -0,0 +1,8 @@
+386826492 35
+1
+1
+1
+1
+1
+1
+1
diff --git a/test/pbmtext-bdf.test b/test/pbmtext-bdf.test
new file mode 100755
index 00000000..1bd7c52c
--- /dev/null
+++ b/test/pbmtext-bdf.test
@@ -0,0 +1,99 @@
+#! /bin/bash
+# This script tests: pbmtext
+# Also requires:
+
+tmpdir=${tmpdir:-/tmp}
+
+font_bdf=${tmpdir}/font.bdf
+font_corrupt_bdf=${tmpdir}/fontcorrupt.bdf
+
+# Though this BDF font file defines only three letters, it is valid.
+
+cat > ${font_bdf} << EOF
+STARTFONT 2.1
+COMMENT simple font for pbmtext test
+COMMENT derived from: $XFree86: xc/fonts/bdf/misc/micro.bdf,v 1.1 1999/09/25 14:36:34 dawes Exp $
+FONT test
+SIZE 4 75 75
+FONTBOUNDINGBOX 4 5 0 0
+STARTPROPERTIES 5
+FONT_DESCENT 0
+FONT_ASCENT 5
+CHARSET_REGISTRY "ISO88591"
+CHARSET_ENCODING "1"
+COPYRIGHT "Public domain font.  Share and enjoy."
+ENDPROPERTIES
+CHARS 3
+STARTCHAR A
+ENCODING 65
+SWIDTH 1000 0
+DWIDTH 4 0
+BBX 4 5 0 0
+BITMAP
+e0
+a0
+e0
+a0
+a0
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 1000 0
+DWIDTH 4 0
+BBX 4 5 0 0
+BITMAP
+e0
+a0
+c0
+a0
+e0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 1000 0
+DWIDTH 4 0
+BBX 4 5 0 0
+BITMAP
+e0
+80
+80
+80
+e0
+ENDCHAR
+ENDFONT
+EOF
+
+# Test 1
+# This should succeed and produce 386826492 35
+pbmtext -font ${font_bdf} ABC | cksum
+
+
+# Test 2
+# The rest should all fail.  Writes 1 seven times.
+
+echo "Test whether corrupted BDF font files are properly handled." 1>&2
+echo "Error messages will appear." 1>&2
+echo 1>&2
+
+pbmtext -font ${font_bdf} BCD
+echo $?
+
+sed 's/FONTBOUNDINGBOX 4 5 0 0/FONTBOUNDINGBOX 4 4 0 0/' \
+  ${font_bdf} >  ${font_corrupt_bdf}
+pbmtext -font ${font_corrupt_bdf} ABC > /dev/null
+echo $?
+rm ${font_corrupt_bdf}
+
+sed 's/BBX 4 5 0 0/BBX 4 6 0 0/' \
+  ${font_bdf} >  ${font_corrupt_bdf}
+pbmtext -font ${font_corrupt_bdf} ABC > /dev/null
+echo $?
+rm ${font_corrupt_bdf}
+
+for delete_line in 14 16 18 20
+  do
+  sed "${delete_line}"d ${font_bdf} >  ${font_corrupt_bdf}
+  pbmtext -font ${font_corrupt_bdf} ABC > /dev/null
+  echo $?
+  rm ${font_corrupt_bdf}
+  done
diff --git a/test/pbmtext-iso88591.ok b/test/pbmtext-iso88591.ok
new file mode 100644
index 00000000..d1516357
--- /dev/null
+++ b/test/pbmtext-iso88591.ok
@@ -0,0 +1,4 @@
+3491766365 5110
+3491766365 5110
+259944121 191
+259944121 191
diff --git a/test/pbmtext-iso88591.test b/test/pbmtext-iso88591.test
new file mode 100755
index 00000000..34346f5c
--- /dev/null
+++ b/test/pbmtext-iso88591.test
@@ -0,0 +1,46 @@
+#! /bin/bash
+# This script tests: pbmtext
+# Also requires:
+
+# This test requires the following locale:
+#   LC_ALL en_US.iso88591
+# Skip this test if it is not available
+
+iconv /dev/null
+if [ $? -ne 0  ]
+  then echo "iconv command not available." 1>&2
+       echo "Skipping." 1>&2
+  exit 80;
+fi
+
+echo "A" | LC_ALL=en_US.iso88591 pbmtext -wchar > /dev/null
+if [ $? -ne 0  ]
+  then echo "LC_ALL could not be set to en_US.iso88591" 1>&2
+       echo "Skipping." 1>&2
+  exit 80;
+fi
+
+# Two rows
+# Should print 3491766365 5110 twice
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i); print ""; \
+             for (i=160;i<=255;++i) printf("%c",i); }' | \
+    pbmtext -builtin bdf | cksum
+
+
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i);  print ""; \
+             for (i=160;i<=255;++i) printf("%c",i); }' | \
+    LC_ALL=en_US.iso88591 pbmtext -builtin bdf -wchar | cksum
+
+
+# Two rows
+# Should print 259944121 191 twice
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i); print ""; \
+             for (i=161;i<=255;++i) printf("%c",i); print "" }' | cksum
+
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i); print ""; \
+             for (i=161;i<=255;++i) printf("%c",i); print ""}' | \
+    LC_ALL=en_US.iso88591 pbmtext -builtin bdf -wchar -text-dump | cksum
\ No newline at end of file
diff --git a/test/pbmtext-utf8.ok b/test/pbmtext-utf8.ok
new file mode 100644
index 00000000..864c530a
--- /dev/null
+++ b/test/pbmtext-utf8.ok
@@ -0,0 +1,8 @@
+1240895458 5110
+1240895458 5110
+898975479 2272
+898975479 2272
+0
+ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
+ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
+1
diff --git a/test/pbmtext-utf8.test b/test/pbmtext-utf8.test
new file mode 100755
index 00000000..ca1f45a2
--- /dev/null
+++ b/test/pbmtext-utf8.test
@@ -0,0 +1,91 @@
+#! /bin/bash
+# This script tests: pbmtext
+# Also requires:
+
+# This test requires the en_US.utf8 locale
+# Skip this test if it is not available
+
+iconv /dev/null
+if [ $? -ne 0  ]
+  then echo "iconv command not available." 1>&2
+       echo "Skipping." 1>&2
+  exit 80;
+fi
+
+echo "A" | LC_ALL=en_US.utf8 pbmtext -wchar > /dev/null
+if [ $? -ne 0  ]
+  then echo "LC_ALL could not be set to en_US.utf8." 1>&2
+       echo "Skipping." 1>&2
+  exit 80;
+fi
+
+# Test 1.
+# Two rows
+# Should print 1240895458 5110 twice
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i); print ""; \
+             for (i=161;i<=255;++i) printf("%c",i); }' | \
+    pbmtext -builtin bdf | cksum
+
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i); print ""; \
+             for (i=161;i<=255;++i) printf("%c",i);  }' | \
+    iconv -f iso8859-1 -t utf-8 | \
+    LC_ALL=en_US.utf8 pbmtext -builtin bdf -wchar | cksum
+
+
+# Test 2.
+# One row
+# Should print 898975479 2272 twice
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i); print "" }' | \
+    pbmtext -builtin bdf | cksum
+
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i);  print ""}' | \
+    LC_ALL=en_US.utf8 pbmtext -builtin bdf -wchar | cksum
+
+
+tmpdir=${tmpdir:-/tmp}
+output=${tmpdir}/output
+
+
+# Test 3.
+# Two rows
+# Output may be affected by locale.  Compare with cmp.
+# Should print 0
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i); print ""; \
+             for (i=161;i<=255;++i) printf("%c",i); print "" }' | \
+    iconv -f iso88591 -t utf8 > ${output}
+
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i); print ""; \
+             for (i=161;i<=255;++i) printf("%c",i); print "" }' | \
+    iconv -f iso8859-1 -t utf-8 | \
+    LC_ALL=en_US.utf8 pbmtext -builtin bdf -wchar -text-dump | \
+    cmp --quiet - ${output}
+
+echo $?
+rm ${output}
+
+
+# Test 4.
+# One row
+# Should print the following twice:
+# !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i); print "" } '
+
+LC_ALL=C \
+awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i);  print ""}' | \
+        LC_ALL=en_US.utf8 pbmtext -builtin bdf -wchar -text-dump
+
+
+# Test 5.
+# Invalid utf-8 sequence
+# Should print 1
+LC_ALL=C \
+awk 'BEGIN { for (i=128; i<=129;++i) printf("%c",i);  print ""}' | \
+        LC_ALL=en_US.utf8 pbmtext -builtin bdf -wchar -text-dump
+echo $?
diff --git a/test/pbmtext.ok b/test/pbmtext.ok
index bd12fb94..000c0897 100644
--- a/test/pbmtext.ok
+++ b/test/pbmtext.ok
@@ -14,11 +14,3 @@
 1647614653 2027
 3233136020 4535
 1216262214 5711
-386826492 35
-1
-1
-1
-1
-1
-1
-1
diff --git a/test/pbmtext.test b/test/pbmtext.test
index eeb8bf50..c92ed599 100755
--- a/test/pbmtext.test
+++ b/test/pbmtext.test
@@ -81,103 +81,14 @@ rm ${fontRectangle_txt} ${font_pbm}
 
 # One long row
 # Should print 3233136020 4535
-LC_CTYPE=C \
+LC_ALL=C \
 awk 'BEGIN { for (i=32; i<=125;++i) printf("%c",i);
              for (i=160;i<=255;++i) printf("%c",i); }' | \
     pbmtext -builtin bdf | cksum
 
 # One tall column
 # Should print 1216262214 5711
-LC_CTYPE=C \
+LC_ALL=C \
 awk 'BEGIN { for (i=32; i<=125;++i) printf("%c\n",i);
              for (i=160;i<=255;++i) printf("%c\n",i); }' | \
     pbmtext -nomargins -builtin bdf | cksum
-
-
-# Test 6:
-# Test corruptions in BDF font file.
-
-font_bdf=${tmpdir}/font.bdf
-font_corrupt_bdf=${tmpdir}/fontcorrupt.bdf
-
-# Though this BDF font file defines only three letters, it is valid.
-
-cat > ${font_bdf} << EOF
-STARTFONT 2.1
-COMMENT $XFree86: xc/fonts/bdf/misc/micro.bdf,v 1.1 1999/09/25 14:36:34 dawes Exp $  - Modified for test
-FONT micro
-SIZE 4 75 75
-FONTBOUNDINGBOX 4 5 0 0
-STARTPROPERTIES 3
-FONT_DESCENT 0
-FONT_ASCENT 5
-CHARSET_REGISTRY "ISO88591"
-CHARSET_ENCODING "1"
-COPYRIGHT "Public domain font.  Share and enjoy."
-ENDPROPERTIES
-CHARS 3
-STARTCHAR A
-ENCODING 65
-SWIDTH 1000 0
-DWIDTH 4 0
-BBX 4 5 0 0
-BITMAP
-e0
-a0
-e0
-a0
-a0
-ENDCHAR
-STARTCHAR B
-ENCODING 66
-SWIDTH 1000 0
-DWIDTH 4 0
-BBX 4 5 0 0
-BITMAP
-e0
-a0
-c0
-a0
-e0
-ENDCHAR
-STARTCHAR C
-ENCODING 67
-SWIDTH 1000 0
-DWIDTH 4 0
-BBX 4 5 0 0
-BITMAP
-e0
-80
-80
-80
-e0
-ENDCHAR
-ENDFONT
-EOF
-
-# This should succeed and produce 386826492 35
-pbmtext -font ${font_bdf} ABC | cksum
-
-# The rest should all fail.  Writes 1 seven times.
-pbmtext -font ${font_bdf} BCD
-echo $?
-
-sed 's/FONTBOUNDINGBOX 4 5 0 0/FONTBOUNDINGBOX 4 4 0 0/' \
-  ${font_bdf} >  ${font_corrupt_bdf}
-pbmtext -font ${font_corrupt_bdf} ABC > /dev/null
-echo $?
-rm ${font_corrupt_bdf}
-
-sed 's/BBX 4 5 0 0/BBX 4 6 0 0/' \
-  ${font_bdf} >  ${font_corrupt_bdf}
-pbmtext -font ${font_corrupt_bdf} ABC > /dev/null
-echo $?
-rm ${font_corrupt_bdf}
-
-for delete_line in 14 16 18 20
-  do
-  sed "${delete_line}"d ${font_bdf} >  ${font_corrupt_bdf}
-  pbmtext -font ${font_corrupt_bdf} ABC > /dev/null
-  echo $?
-  rm ${font_corrupt_bdf}
-  done
diff --git a/version.mk b/version.mk
index 79c2b14a..38f009f0 100644
--- a/version.mk
+++ b/version.mk
@@ -1,3 +1,3 @@
 NETPBM_MAJOR_RELEASE = 10
-NETPBM_MINOR_RELEASE = 82
-NETPBM_POINT_RELEASE = 3
+NETPBM_MINOR_RELEASE = 83
+NETPBM_POINT_RELEASE = 0