about summary refs log tree commit diff
path: root/converter/other
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2019-03-30 15:18:58 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2019-03-30 15:18:58 +0000
commitaad47e743f21763ac13b73eb927ad7d001254572 (patch)
tree2be395fe14e199ac00f002dc8b0ded2f0304c557 /converter/other
parentb10a418cefe3413a727b89300848dc84e8a6195d (diff)
downloadnetpbm-mirror-aad47e743f21763ac13b73eb927ad7d001254572.tar.gz
netpbm-mirror-aad47e743f21763ac13b73eb927ad7d001254572.tar.xz
netpbm-mirror-aad47e743f21763ac13b73eb927ad7d001254572.zip
Promote Development to Advanced
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@3587 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/other')
-rw-r--r--converter/other/pamtopng.c395
-rw-r--r--converter/other/pngx.c64
-rw-r--r--converter/other/pngx.h13
-rw-r--r--converter/other/pnmtopng.c383
4 files changed, 539 insertions, 316 deletions
diff --git a/converter/other/pamtopng.c b/converter/other/pamtopng.c
index a3c60f24..a323844f 100644
--- a/converter/other/pamtopng.c
+++ b/converter/other/pamtopng.c
@@ -1,21 +1,8 @@
-/*
-** read a PNM/PAM image and produce a Portable Network Graphics (PNG) file
-**
-** derived from pnmtorast.c by Jef Poskanzer and pamrgbatopng.c by Bryan
-** Henderson <bryanh@giraffe-data.com> and probably some other sources
-**
-** Copyright (C) 1995-1998 by Alexander Lehmann <alex@hal.rhein-main.de>
-**                        and Willem van Schaik <willem@schaik.com>
-** Copyright (C) 1999,2001 by Greg Roelofs <newt@pobox.com>
-** Copyright (C) 2015 by Willem van Schaik <willem@schaik.com>
-**
-** 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.
-*/
+/*=============================================================================
+                                  pamtopng
+===============================================================================
+  Read a Netpbm image and produce a PNG (Portable Network Graphics) image.
+=============================================================================*/
 
 /*
   This Netpbm program pamtopng was derived in 2015 from the Netpbm program
@@ -29,16 +16,16 @@
     had become rather complex.  This program is roughly 1/3 the size of
     pnmtopng.c that it replaces.
 
-  - In 1995 bandwith was limited and therefore filesize had to be kept
+  - In 1995, bandwith was limited and therefore filesize had to be kept
     small. The original program tried to optimize for that by applying
-    many "clever tricks". Today that isn't an issue anymore, so gone 
+    many "clever tricks". Today that isn't an issue anymore, so gone
     are filters, palettes, etc. Also, image conversions were removed,
     because those should be done with other NetPBM tools.
 
   - Add ability to create iTXt (international language) chunks.
 */
 
-
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
@@ -62,6 +49,7 @@ static bool verbose;
 struct CmdlineInfo {
     const char * inputFileName;
     unsigned int verbose;
+    unsigned int interlace;
     unsigned int transparencySpec;
     const char * transparency;
     unsigned int chromaSpec;
@@ -89,7 +77,7 @@ parseChromaOpt(const char *         const chromaOpt,
                struct pngx_chroma * const chromaP) {
 
     int count;
-    
+
     count = sscanf(chromaOpt, "%f %f %f %f %f %f %f %f",
                    &chromaP->wx, &chromaP->wy,
                    &chromaP->rx, &chromaP->ry,
@@ -108,7 +96,7 @@ parseChromaOpt(const char *         const chromaOpt,
 static void
 parseSrgbintentOpt(const char *      const srgbintentOpt,
                    pngx_srgbIntent * const srgbintentP) {
-    
+
     if (streq(srgbintentOpt, "perceptual"))
         *srgbintentP = PNGX_PERCEPTUAL;
     else if (streq(srgbintentOpt, "relativecolorimetric"))
@@ -146,7 +134,7 @@ parseTimeOpt(const char * const timeOpt,
     if (count != 6)
         pm_error("Invalid value for -time '%s'.   It should have "
                  "the form [yy]yy-mm-dd hh:mm:ss.", timeOpt);
-    
+
     if (year < 0)
         pm_error("Year is negative in -time value '%s'", timeOpt);
     if (year > 9999)
@@ -193,7 +181,7 @@ static void
 parseCommandLine (int                  argc,
                   const char **        argv,
                   struct CmdlineInfo * const cmdlineP) {
-    
+
     optEntry * option_def;
     optStruct3 opt;
     unsigned int option_def_index = 0;  /* incremented by OPTENT3 */
@@ -206,6 +194,8 @@ parseCommandLine (int                  argc,
 
     OPTENT3(0,  "verbose",      OPT_FLAG,       NULL,
             &cmdlineP->verbose,        0);
+    OPTENT3(0,  "interlace",    OPT_FLAG,       NULL,
+            &cmdlineP->interlace,      0);
     OPTENT3(0,  "transparency", OPT_STRING,     &cmdlineP->transparency,
             &cmdlineP->transparencySpec, 0);
     OPTENT3(0,  "chroma",       OPT_STRING,     &chroma,
@@ -240,7 +230,7 @@ parseCommandLine (int                  argc,
 
     if (cmdlineP->timeSpec)
         parseTimeOpt(time, &cmdlineP->time);
-    
+
     /* get the input-file or stdin pipe */
     if (argc-1 < 1)
         cmdlineP->inputFileName = "-";
@@ -257,7 +247,7 @@ parseCommandLine (int                  argc,
 static png_byte
 colorTypeFromInputType(const struct pam * const pamP) {
 /*----------------------------------------------------------------------------
-  Analyse the Netpbm image for color-type and bit-depth
+  Analyze the Netpbm image for color-type and bit-depth
 -----------------------------------------------------------------------------*/
     png_byte retval;
 
@@ -287,7 +277,7 @@ colorTypeFromInputType(const struct pam * const pamP) {
         if (pamP->depth == 2)
             retval = PNG_COLOR_TYPE_GRAY_ALPHA;
         else
-            pm_error("Input tupel type is GRAYSCALE_ALPHA, "
+            pm_error("Input tuple type is GRAYSCALE_ALPHA, "
                      "but number of planes is %u instread of 2",
                      pamP->depth);
     } else if (strneq(pamP->tuple_type, "GRAYSCALE", 9)) {
@@ -386,6 +376,8 @@ sigBitsFmImgType(unsigned int const pnmBitDepth,
             retval.gray  = pnmBitDepth;
             retval.alpha = pnmBitDepth;
             break;
+        default:
+            assert(false);
         }
     } else {
         /* PNG can (so presumably will) use original bit depth */
@@ -405,7 +397,7 @@ doTrnsChunk(const struct pam * const pamP,
             struct pngx *      const pngxP,
             const char *       const trans) {
 
-    if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY_ALPHA || 
+    if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY_ALPHA ||
         pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB_ALPHA)
         pm_error("Both alpha channel and transparency chunk not allowed.");
     else {
@@ -435,13 +427,13 @@ doTrnsChunk(const struct pam * const pamP,
 static void
 doChrmChunk(struct pngx *      const pngxP,
             struct pngx_chroma const chroma) {
-    
+
     pngx_setChrm(pngxP, chroma);
 
     if (verbose) {
         pm_message("writing cHRM chunk { wx, wy, rx, ry, gx, gy, bx, by } = "
                    "{ %4.2f, %4.2f, %4.2f, %4.2f, "
-                   "%4.2f, %4.2f, %4.2f, %4.2f }", 
+                   "%4.2f, %4.2f, %4.2f, %4.2f }",
                    chroma.wx, chroma.wy,
                    chroma.rx, chroma.ry,
                    chroma.gx, chroma.gy,
@@ -451,7 +443,7 @@ doChrmChunk(struct pngx *      const pngxP,
 
 
 
-static void 
+static void
 doGamaChunk(struct pngx *  const pngxP,
             float          const gamma) {
 
@@ -501,9 +493,9 @@ doTextChunkSet(struct pngx * const pngxP,
     FILE * tfP;
 
     tfP = pm_openr(textFileName);
-    
+
     pngtxt_addChunk(pngxP, tfP, ztxt, itxt, verbose);
-    
+
     pm_close(tfP);
 }
 
@@ -519,9 +511,9 @@ doZtxtChunkSet(struct pngx * const pngxP,
     FILE * tfP;
 
     tfP = pm_openr(textFileName);
-    
+
     pngtxt_addChunk(pngxP, tfP, ztxt, itxt, verbose);
-    
+
     pm_close(tfP);
 }
 
@@ -557,11 +549,11 @@ doBkgdChunk (const struct pam * const pamP,
     pngx_setBkgdRgb(pngxP, pngColor);
 
     if (verbose) {
-        if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY || 
+        if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY ||
             pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY_ALPHA) {
             pm_message("writing bKGD chunk with gray level = %u",
                        pngColor.gray);
-        } else if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB || 
+        } else if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB ||
                    pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB_ALPHA) {
             pm_message("writing bKGD chunk with color {red, green, blue} = "
                        "{%u, %u, %u}",
@@ -592,24 +584,10 @@ doTimeChunk(struct pngx * const pngxP,
 
 
 static void
-setShift(struct pngx * const pngxP,
-         png_color_8   const sigBits) {
-
-    if (sigBits.red + sigBits.green + sigBits.blue +
-        sigBits.gray + sigBits.alpha > 0) {
-
-        /* Move the 1, 2, 4 bits to most significant bits */
-        pngx_setShift(pngxP, sigBits);
-    }
-}
-
-
-
-static void
-convertRaster(const struct pam * const pamP,
-              const tuple *      const tuplerow,
-              png_byte *         const pngRow,
-              unsigned int       const bitDepth) {
+convertRow(const struct pam * const pamP,
+           const tuple *      const tuplerow,
+           png_byte *         const pngRow,
+           unsigned int       const bitDepth) {
 
     unsigned int col;
 
@@ -638,9 +616,12 @@ convertRaster(const struct pam * const pamP,
 
 
 static void
-writeRaster(const struct pam * const pamP,
-            struct pngx *      const pngxP,
-            int                const bitDepth) {
+writeRasterRowByRow(const struct pam * const pamP,
+                    struct pngx *      const pngxP,
+                    int                const bitDepth) {
+
+    unsigned int const rowSz =
+        pamP->width * pamP->depth * (MAX(1, bitDepth/8));
 
     tuple * tupleRow;
     png_byte * pngRow;
@@ -650,8 +631,7 @@ writeRaster(const struct pam * const pamP,
 
     tupleRow = pnm_allocpamrow(pamP);
 
-    MALLOCARRAY(pngRow, pamP->width * 8);
-        /* sufficient to store a 16-bit RGB+A row */
+    MALLOCARRAY(pngRow, rowSz);
 
     if (pngRow == NULL)
         pm_error("Unable to allocate space for PNG pixel row for "
@@ -660,9 +640,9 @@ writeRaster(const struct pam * const pamP,
         for (row = 0; row < pamP->height; ++row) {
             pnm_readpamrow(pamP, tupleRow);
 
-            convertRaster(pamP, tupleRow, pngRow, bitDepth);
+            convertRow(pamP, tupleRow, pngRow, bitDepth);
 
-            png_write_row(pngxP->png_ptr, pngRow);
+            pngx_writeRow(pngxP, pngRow);
         }
         free(pngRow);
     }
@@ -671,40 +651,160 @@ writeRaster(const struct pam * const pamP,
 
 
 
+static png_bytep
+mallocPngImage(unsigned int const rowSize,
+               unsigned int const height) {
+
+    png_bytep pngImage;
+
+    if (UINT_MAX / rowSize < height)
+        pm_error("Image is uncomputably large at %u rows of %u bytes",
+                 height, rowSize);
+
+    MALLOCARRAY(pngImage, height * rowSize);
+
+    if (!pngImage)
+        pm_error("could not allocate %u bytes for a PNG image buffer",
+                 height * rowSize);
+
+    return pngImage;
+}
+
+
+
+static unsigned int
+pngLineSize(struct pngx * const pngxP) {
+
+    unsigned int const bytesPerSample = pngx_bitDepth(pngxP) == 16 ? 2 : 1;
+
+    unsigned int samplesPerPixel;
+
+    switch (pngx_colorType(pngxP)) {
+        case PNG_COLOR_TYPE_GRAY:
+            samplesPerPixel = 1;
+            break;
+        case PNG_COLOR_TYPE_GRAY_ALPHA:
+            samplesPerPixel = 2;
+            break;
+        case PNG_COLOR_TYPE_RGB:
+            samplesPerPixel = 3;
+            break;
+        case PNG_COLOR_TYPE_RGB_ALPHA:
+            samplesPerPixel = 4;
+            break;
+        default:
+            assert(false);
+    }
+
+    if (UINT_MAX / bytesPerSample / samplesPerPixel < pngx_imageWidth(pngxP)) {
+        pm_error("pngcopy: width %u of PNG is uncomputably large\n",
+                  pngx_imageWidth(pngxP));
+    }
+
+    return pngx_imageWidth(pngxP) * bytesPerSample * samplesPerPixel;
+}
+
+
+
 static void
-writePng(const struct pam * const pamP,
-         FILE *             const ofP,
-         struct CmdlineInfo const cmdline) {
+writeRasterWholeImg(struct pam *  const pamP,
+                    struct pngx * const pngxP,
+                    unsigned int  const bitDepth) {
 
-    unsigned int const pnmBitDepth = pm_maxvaltobits(pamP->maxval);
-    int const pngColorType = colorTypeFromInputType(pamP);
+    unsigned int const pngRowSize = pngLineSize(pngxP);
 
-    struct pngx * pngxP;
-    unsigned int pngBitDepth;
-    png_color_8 sBit;
+    tuple * tupleRow;
+    png_bytep pngImage;
+        /* A one-dimensional malloc'ed array of all pixels in image */
+    png_bytep * pngRowP;
+        /* A malloc'ed array of row pointers into pngImage[] */
+    unsigned int row;
 
-    pngx_create(&pngxP, PNGX_WRITE, NULL);
+    tupleRow = pnm_allocpamrow(pamP);
+
+    pngImage = mallocPngImage(pngRowSize, pamP->height);
+
+    MALLOCARRAY(pngRowP, pamP->height);
+
+    if (!pngRowP)
+        pm_error("Failed to allocate an array for %u PNG row pointers",
+                 pamP->height);
 
+    for (row = 0; row < pamP->height; ++row) {
+        png_bytep const thisPngRowP = &pngImage[row * pngRowSize];
 
+        pnm_readpamrow(pamP, tupleRow);
+
+        convertRow(pamP, tupleRow, thisPngRowP, bitDepth);
+
+        pngRowP[row] = thisPngRowP;
+    }
+
+    pngx_writeImage(pngxP, pngRowP);
+
+    free(pngRowP);
+    free(pngImage);
+    pnm_freepamrow(tupleRow);
+}
+
+
+
+static void
+reportInputFormat(const struct pam * const pamP) {
+
+    const char * formatDesc;
+
+    if (pamP->format == PBM_FORMAT || pamP->format == RPBM_FORMAT)
+        formatDesc = "PBM";
+    else if (pamP->format == PGM_FORMAT || pamP->format == RPGM_FORMAT)
+        formatDesc = "PGM";
+    else if (pamP->format == PPM_FORMAT || pamP->format == RPPM_FORMAT)
+        formatDesc = "PPM";
+    else if (pamP->format == PAM_FORMAT)
+        formatDesc = "PAM";
+    else
+        formatDesc = NULL;
+
+    if (formatDesc)
+        pm_message("Input format = %s", formatDesc);
+    else
+        pm_message("Unrecognized input format, format code = 0x%x",
+                   pamP->format);
+
+    pm_message("Input tuple type = '%s'", pamP->tuple_type);
+    pm_message("Input depth = %u", pamP->depth);
+    pm_message("Input maxval = %u", (unsigned int) pamP->maxval);
+}
+
+
+
+static unsigned int
+pngBitDepth(unsigned int const pnmBitDepth,
+            int          const pngColorType) {
+
+    unsigned int retval;
 
     if ((pngColorType == PNG_COLOR_TYPE_RGB ||
          pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) &&
         pnmBitDepth < 8) {
 
-        pngBitDepth = 8;
+        retval = 8;
     } else
-        pngBitDepth = pnmBitDepth;
+        retval = pnmBitDepth;
 
-    png_init_io(pngxP->png_ptr, ofP);
+    return retval;
+}
 
-    pngx_setIhdr(pngxP, pamP->width, pamP->height,
-                 pngBitDepth, pngColorType,
-                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
-                 PNG_FILTER_TYPE_BASE);
 
-    sBit = sigBitsFmImgType(pnmBitDepth, pngColorType);
 
-    /* Where requested, add ancillary chunks */
+static void
+addAncillaryChunks(struct pam *       const pamP,
+                   struct pngx *      const pngxP,
+                   struct CmdlineInfo const cmdline,
+                   png_color_8        const sigBits) {
+/*----------------------------------------------------------------------------
+  Where requested, add ancillary chunks.
+-----------------------------------------------------------------------------*/
     if (cmdline.transparencySpec)
         doTrnsChunk(pamP, pngxP,cmdline.transparency);
 
@@ -716,7 +816,7 @@ writePng(const struct pam * const pamP,
 
     /* no iccp */
 
-    doSbitChunk(pamP, pngxP, sBit);
+    doSbitChunk(pamP, pngxP, sigBits);
 
     if (cmdline.srgbintentSpec)
         doSrgbChunk(pngxP, cmdline.srgbintent);
@@ -742,54 +842,96 @@ writePng(const struct pam * const pamP,
     if (cmdline.timeSpec)
         doTimeChunk(pngxP, cmdline.time);
 
-    setShift(pngxP, sBit);
-
-    /* Write the ancillary chunks to PNG file */
+    /* Write the ancillary chunks to PNG image */
     pngx_writeInfo(pngxP);
+}
+
+
+
+static void
+setShift(struct pngx * const pngxP,
+         png_color_8   const sigBits) {
+
+    if (sigBits.red + sigBits.green + sigBits.blue +
+        sigBits.gray + sigBits.alpha > 0) {
 
-    if (pngColorType != PNG_COLOR_TYPE_GRAY && pnmBitDepth < 8) {
         /* Move the 1, 2, 4 bits to most significant bits */
-        pngx_setShift(pngxP, sBit);
-    }
-    if ((pngColorType == PNG_COLOR_TYPE_GRAY) && (pnmBitDepth < 8)) {
-        /* Pack multiple pixels in a byte */
-        pngx_setPacking(pngxP);
+        pngx_setShift(pngxP, sigBits);
     }
+}
 
-    writeRaster(pamP, pngxP, pnmBitDepth);
 
-    pngx_writeEnd(pngxP);
-    pngx_destroy(pngxP);
-}
 
+static void
+doIhdrChunk(struct pngx * const pngxP,
+            unsigned int  const width,
+            unsigned int  const height,
+            unsigned int  const pnmBitDepth,
+            int           const pngColorType,
+            bool          const interlace) {
+
+    int const interlaceMethod =
+        interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE;
+
+    pngx_setIhdr(pngxP, width, height,
+                 pngBitDepth(pnmBitDepth, pngColorType), pngColorType,
+                 interlaceMethod, PNG_COMPRESSION_TYPE_BASE,
+                 PNG_FILTER_TYPE_BASE);
+}
 
 
 
 static void
-reportInputFormat(const struct pam * const pamP) {
+pamtopng(FILE *             const ifP,
+         FILE *             const ofP,
+         struct CmdlineInfo const cmdline) {
 
-    const char * formatDesc;
+    unsigned int  pnmBitDepth;
+    int           pngColorType;
+    struct pngx * pngxP;
+    png_color_8   sigBits;
+    struct pam    pam;
 
-    if (pamP->format == PBM_FORMAT || pamP->format == RPBM_FORMAT)
-        formatDesc = "PBM";
-    else if (pamP->format == PGM_FORMAT || pamP->format == RPGM_FORMAT)
-        formatDesc = "PGM";
-    else if (pamP->format == PPM_FORMAT || pamP->format == RPPM_FORMAT)
-        formatDesc = "PPM";
-    else if (pamP->format == PAM_FORMAT)
-        formatDesc = "PAM";
-    else
-        formatDesc = NULL;
+    pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type));
 
-    if (formatDesc)
-        pm_message("Input format = %s", formatDesc);
-    else
-        pm_message("Unrecognized input format, format code = 0x%x",
-                   pamP->format);
+    if (verbose)
+        reportInputFormat(&pam);
 
-    pm_message("Input tuple type = '%s'", pamP->tuple_type);
-    pm_message("Input depth = %u", pamP->depth);
-    pm_message("Input maxval = %u", (unsigned int) pamP->maxval);
+    pnmBitDepth = pm_maxvaltobits(pam.maxval);
+
+    pngColorType = colorTypeFromInputType(&pam);
+
+    pngx_create(&pngxP, PNGX_WRITE, NULL);
+
+    png_init_io(pngxP->png_ptr, ofP);
+
+    doIhdrChunk(pngxP, pam.width, pam.height,
+                pnmBitDepth, pngColorType, cmdline.interlace > 0);
+
+    sigBits = sigBitsFmImgType(pnmBitDepth, pngColorType);
+
+    addAncillaryChunks(&pam, pngxP, cmdline, sigBits);
+
+    setShift(pngxP, sigBits);
+
+    if ((pngColorType == PNG_COLOR_TYPE_GRAY) && (pnmBitDepth < 8)) {
+        /* Pack multiple pixels in a byte */
+        pngx_setPacking(pngxP);
+    }
+
+    if (cmdline.interlace) {
+        /* Libpng will expect us to provide pixels in interlaced sequence
+           if we write row-by-row, and that is much to difficult, so we
+           do whole-image-at-once and let Libpng do the work.
+        */
+        writeRasterWholeImg(&pam, pngxP, pnmBitDepth);
+    } else {
+        /* We save memory by going row-by-row */
+        writeRasterRowByRow(&pam, pngxP, pnmBitDepth);
+    }
+
+    pngx_writeEnd(pngxP);
+    pngx_destroy(pngxP);
 }
 
 
@@ -800,7 +942,6 @@ main(int           argc,
 
     FILE * ifP;
     struct CmdlineInfo cmdline;
-    struct pam pam;
 
     pm_proginit(&argc, argv);
 
@@ -810,12 +951,7 @@ main(int           argc,
 
     ifP = pm_openr(cmdline.inputFileName);
 
-    pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type));
-
-    if (verbose)
-        reportInputFormat(&pam);
-
-    writePng(&pam, stdout, cmdline);
+    pamtopng(ifP, stdout, cmdline);
 
     pm_close(ifP);
 
@@ -824,3 +960,18 @@ main(int           argc,
 
 
 
+/* Derived from pnmtorast.c by Jef Poskanzer and pamrgbatopng.c by Bryan
+** Henderson <bryanh@giraffe-data.com> and probably some other sources
+**
+** Copyright (C) 1995-1998 by Alexander Lehmann <alex@hal.rhein-main.de>
+**                        and Willem van Schaik <willem@schaik.com>
+** Copyright (C) 1999,2001 by Greg Roelofs <newt@pobox.com>
+** Copyright (C) 2015 by Willem van Schaik <willem@schaik.com>
+**
+** 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.
+*/
diff --git a/converter/other/pngx.c b/converter/other/pngx.c
index dfc74485..4bb09421 100644
--- a/converter/other/pngx.c
+++ b/converter/other/pngx.c
@@ -1,3 +1,4 @@
+#include <stdbool.h>
 #include <assert.h>
 #include <png.h>
 #include "pm_c_util.h"
@@ -59,6 +60,7 @@ pngx_create(struct pngx ** const pngxPP,
     if (!pngxP)
         pm_error("Failed to allocate memory for PNG object");
     else {
+        pngxP->infoPrepared = false;
         pngxP->numPassesRequired = 1;
 
         switch(rw) {
@@ -466,6 +468,37 @@ pngx_setIhdr(struct pngx * const pngxP,
 
 void
 pngx_setInterlaceHandling(struct pngx * const pngxP) {
+    /* The documentation is vague and contradictory on what this does, but
+       what it appears from reasoning and experimentation to do is the
+       following.
+
+       It applies to reading and writing by rows (png_write_row, png_read_row)
+       as opposed to whole image (png_write_image, png_read_image).  It has
+       no effect on whole image read and write.
+
+       This is not what makes an image interlaced or tells the decompressor
+       that it is interlaced.  All it does is control how you you read and
+       write the raster when the image is interlaced.  It has no effect if the
+       image is not interlaced.  (You make an image interlaced by setting the
+       IHDR; the decompressor finds out from the IHDR that it is interlaced).
+
+       In the write case, it controls whether you construct the subimages
+       yourself and feed them to libpng in sequence or you feed libpng the
+       entire image multiple times and libpng picks out the pixels appropriate
+       for each subimage in each pass.
+
+       In the read case, it controls whether you get the raw subimages and you
+       assemble them into the full image or you read the whole image multiple
+       times into the same buffer, with the pixels that belong to each
+       subimage being filled in on each pass.
+
+       Note that the only kind of interlacing that exists today is ADAM7 and
+       consequently, the number of passes is always 1 (for no interlacing) or
+       7 (for interlacing).
+    */
+    if (!pngxP->infoPrepared)
+        pm_error("pngx_setInterlaceHandling must not be called before "
+                 "pngx_writeInfo or pngx_readInfo");
 
     pngxP->numPassesRequired = png_set_interlace_handling(pngxP->png_ptr);
 }
@@ -475,6 +508,10 @@ pngx_setInterlaceHandling(struct pngx * const pngxP) {
 void
 pngx_setPacking(struct pngx * const pngxP) {
 
+    if (!pngxP->infoPrepared)
+        pm_error("pngx_setPacking must not be called before "
+                 "pngx_writeInfo or pngx_readInfo");
+
     png_set_packing(pngxP->png_ptr);
 }
 
@@ -516,7 +553,19 @@ pngx_setSbit(struct pngx * const pngxP,
 void
 pngx_setShift(struct pngx * const pngxP,
               png_color_8   const sigBitArg) {
-
+/*----------------------------------------------------------------------------
+   Tell the number of significant bits in the row buffers that will be given
+   to the compressor.  Those bits are the least significant of the 8 bits of
+   space in the row buffer for each sample.  For example, if red sample values
+   are in the range 0-7, only the lower 3 bits of the 8-bit byte for each
+   red sample will be used, so one would call this with sigBitArg.red == 3.
+
+   The name alludes to the fact that to normalize the sample to 8 bits, one
+   shifts it left, and this function tells how much shift has to happen.  In
+   the example above, each red sample has to be shifted left 5 bits (so that
+   the upper 3 bits are significant and the lower 5 bits are always zero) to
+   create an 8 bit sample out of the 3 bit samples.
+-----------------------------------------------------------------------------*/
     png_color_8 sigBit;
 
     sigBit = sigBitArg;
@@ -651,6 +700,8 @@ void
 pngx_readInfo(struct pngx * const pngxP) {
 
     png_read_info(pngxP->png_ptr, pngxP->info_ptr);
+
+    pngxP->infoPrepared = true;
 }
 
 
@@ -659,6 +710,8 @@ void
 pngx_writeInfo(struct pngx * const pngxP) {
 
     png_write_info(pngxP->png_ptr, pngxP->info_ptr);
+
+    pngxP->infoPrepared = true;
 }
 
 
@@ -733,6 +786,15 @@ pngx_writeRow(struct pngx *    const pngxP,
 
 
 void
+pngx_writeImage(struct pngx * const pngxP,
+                png_byte **   const raster) {
+
+    png_write_image(pngxP->png_ptr, (png_byte **)raster);
+}
+
+
+
+void
 pngx_readEnd(struct pngx * const pngxP) {
 
     /* Note that some of info_ptr is not defined until png_read_end()
diff --git a/converter/other/pngx.h b/converter/other/pngx.h
index be9b9558..f4701bb2 100644
--- a/converter/other/pngx.h
+++ b/converter/other/pngx.h
@@ -1,6 +1,7 @@
 #ifndef PNGX_H_INCLUDED
 #define PNGX_H_INCLUDED
 
+#include <stdbool.h>
 #include <png.h>
     /* This includes the Zlib interface header file zlib.h because libpng uses
        libz and some of the Zlib interface, e.g. the Z_DEFLATED constant,
@@ -53,10 +54,16 @@ struct pngx {
     pngx_rw      rw;
     png_uint_16  maxval;
     unsigned int numPassesRequired;
-        /* The number of times we have write the complete image to the
+        /* The number of times we have to write the complete image to the
            compressor.  This is more than one when the compressor is set
            up to do an interlaced format.
         */
+    bool         infoPrepared;
+        /* png_write_info or png_read_info has been called, so libpng is in a
+           state in which things such as png_set_interlace_handling will work.
+           These functions use information in *png_ptr that is set by
+           png_XXX_info.
+        */
 };
 
 void
@@ -270,6 +277,10 @@ pngx_writeRow(struct pngx *    const pngxP,
               const png_byte * const line);
 
 void
+pngx_writeImage(struct pngx * const pngxP,
+                png_byte **   const raster);
+
+void
 pngx_readEnd(struct pngx * const pngxP);
 
 void
diff --git a/converter/other/pnmtopng.c b/converter/other/pnmtopng.c
index 08263f29..80f74adb 100644
--- a/converter/other/pnmtopng.c
+++ b/converter/other/pnmtopng.c
@@ -26,7 +26,7 @@
    it's easy to see that an ordinary fax could deplete your virtual
    memory and even if it didn't, it might deplete your real memory and
    iterating through the array would cause thrashing.  This program
-   iterates through the image multiple times.  
+   iterates through the image multiple times.
 
    So instead, we read the image into memory one row at a time, into a
    single row buffer.  We use Netpbm's pm_openr_seekable() facility to
@@ -38,19 +38,19 @@
    in the system's I/O cache (remember that the file is a lot smaller than
    the xel array you'd get by doing a pnm_readpnm() of it).
 
-   However, it does introduce some delay because of all the system calls 
+   However, it does introduce some delay because of all the system calls
    required to read the file.  A future enhancement might read the entire
-   file into an xel array in some cases, and read one row at a time in 
+   file into an xel array in some cases, and read one row at a time in
    others, depending on the needs of the particular use.
 
    We do still read the entire alpha mask (if there is one) into a
-   'gray' array, rather than access it one row at a time.  
+   'gray' array, rather than access it one row at a time.
 
    Before May 2001, we did in fact read the whole image into an xel array,
    and we got complaints.  Before April 2000, it wasn't as big a problem
    because xels were only 24 bits.  Now they're 96.
 */
-   
+
 #ifndef PNMTOPNG_WARNING_LEVEL
 #  define PNMTOPNG_WARNING_LEVEL 0   /* use 0 for backward compatibility, */
 #endif                               /*  2 for warnings (1 == error) */
@@ -62,7 +62,7 @@
 /* Because of a design error in png.h, you must not #include <setjmp.h> before
    <png.h>.  If you do, png.h won't compile.
 */
-#include <setjmp.h> 
+#include <setjmp.h>
 #include <zlib.h>
 
 #include "pm_c_util.h"
@@ -169,7 +169,7 @@ parseSizeOpt(const char *       const sizeOpt,
              struct pngx_phys * const sizeP) {
 
     int count;
-    
+
     count = sscanf(sizeOpt, "%d %d %d", &sizeP->x, &sizeP->y, &sizeP->unit);
 
     if (count != 3)
@@ -184,7 +184,7 @@ parseRgbOpt(const char *         const rgbOpt,
             struct pngx_chroma * const rgbP) {
 
     int count;
-    
+
     count = sscanf(rgbOpt, "%f %f %f %f %f %f %f %f",
                    &rgbP->wx, &rgbP->wy,
                    &rgbP->rx, &rgbP->ry,
@@ -203,7 +203,7 @@ parseRgbOpt(const char *         const rgbOpt,
 static void
 parseSrgbintentOpt(const char *      const srgbintentOpt,
                    pngx_srgbIntent * const srgbintentP) {
-    
+
     if (streq(srgbintentOpt, "perceptual"))
         *srgbintentP = PNGX_PERCEPTUAL;
     else if (streq(srgbintentOpt, "relativecolorimetric"))
@@ -241,7 +241,7 @@ parseModtimeOpt(const char * const modtimeOpt,
     if (count != 6)
         pm_error("Invalid value for -modtime '%s'.   It should have "
                  "the form [yy]yy-mm-dd hh:mm:ss.", modtimeOpt);
-    
+
     if (year < 0)
         pm_error("Year is negative in -modtime value '%s'", modtimeOpt);
     if (year > 9999)
@@ -289,7 +289,7 @@ 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.
@@ -421,11 +421,11 @@ parseCommandLine(int argc, const char ** argv,
         cmdlineP->ztxt = NULL;
     if (!paletteSpec)
         cmdlineP->palette = NULL;
-    
+
     if (filterSpec + nofilter + sub + up + avg + paeth > 1)
         pm_error("You may specify at most one of "
                  "-nofilter, -sub, -up, -avg, -paeth, and -filter");
-    
+
     if (filterSpec) {
         if (filter < 0 || filter > 4)
             pm_error("-filter is obsolete.  Use -nofilter, -sub, -up, -avg, "
@@ -452,13 +452,13 @@ parseCommandLine(int argc, const char ** argv,
         else
             cmdlineP->filterSet = PNG_FILTER_NONE;
     }
-    
+
     if (cmdlineP->sizeSpec)
         parseSizeOpt(size, &cmdlineP->size);
 
     if (cmdlineP->rgbSpec)
         parseRgbOpt(rgb, &cmdlineP->rgb);
-    
+
     if (cmdlineP->srgbintentSpec)
         parseSrgbintentOpt(srgbintent, &cmdlineP->srgbintent);
 
@@ -530,14 +530,14 @@ reportInputType(int    const format,
 
 
 static png_color_16
-xelToPngColor_16(xel    const input, 
-                 xelval const maxval, 
+xelToPngColor_16(xel    const input,
+                 xelval const maxval,
                  xelval const pngMaxval) {
 
     png_color_16 retval;
 
     xel scaled;
-    
+
     PPM_DEPTH(scaled, input, maxval, pngMaxval);
 
     retval.red   = PPM_GETR(scaled);
@@ -551,12 +551,12 @@ xelToPngColor_16(xel    const input,
 
 
 static void
-closestColorInPalette(pixel          const targetColor, 
+closestColorInPalette(pixel          const targetColor,
                       pixel                palette_pnm[],
                       unsigned int   const paletteSize,
                       unsigned int * const bestIndexP,
                       unsigned int * const bestMatchP) {
-    
+
     unsigned int paletteIndex;
     unsigned int bestIndex;
     unsigned int bestMatch;
@@ -565,7 +565,7 @@ closestColorInPalette(pixel          const targetColor,
 
     bestMatch = UINT_MAX;
     for (paletteIndex = 0; paletteIndex < paletteSize; ++paletteIndex) {
-        unsigned int const dist = 
+        unsigned int const dist =
             PPM_DISTANCE(palette_pnm[paletteIndex], targetColor);
 
         if (dist < bestMatch) {
@@ -670,13 +670,13 @@ static colorhist_vector getChv_chv;
 
 
 static void
-getChv(FILE *             const ifP, 
+getChv(FILE *             const ifP,
        pm_filepos         const rasterPos,
-       int                const cols, 
-       int                const rows, 
+       int                const cols,
+       int                const rows,
        xelval             const maxval,
-       int                const format, 
-       int                const maxColors, 
+       int                const format,
+       int                const maxColors,
        colorhist_vector * const chvP,
        unsigned int *     const colorsP) {
 /*----------------------------------------------------------------------------
@@ -685,7 +685,7 @@ getChv(FILE *             const ifP,
    raster starts at position 'rasterPos' of the file.  The image's properties
    are 'cols', 'rows', 'maxval', and 'format'.
 
-   Return the number of colors as *colorsP.  Return the details of the 
+   Return the number of colors as *colorsP.  Return the details of the
    colors in newly malloc'ed storage, and its address as *chvP.  If
    there are more than 'maxColors' colors, though, just return NULL as
    *chvP and leave *colorsP undefined.
@@ -700,13 +700,13 @@ getChv(FILE *             const ifP,
 
     if (!getChv_computed) {
         int colorCount;
-        if (verbose) 
+        if (verbose)
             pm_message ("Finding colors in input image...");
 
         pm_seek2(ifP, &rasterPos, sizeof(rasterPos));
-        getChv_chv = ppm_computecolorhist2(ifP, cols, rows, maxval, format, 
+        getChv_chv = ppm_computecolorhist2(ifP, cols, rows, maxval, format,
                                            maxColors, &colorCount);
-        
+
         getChv_colors = colorCount;
 
         if (verbose) {
@@ -737,7 +737,7 @@ static void freeChv(void) {
 static bool
 pgmBitsAreRepeated(unsigned int const repeatedSize,
                    FILE *       const ifP,
-                   pm_filepos   const rasterPos, 
+                   pm_filepos   const rasterPos,
                    int          const cols,
                    int          const rows,
                    xelval       const maxval,
@@ -764,7 +764,7 @@ pgmBitsAreRepeated(unsigned int const repeatedSize,
     xel * xelrow;
 
     xelrow = pnm_allocrow(cols);
-    
+
     pm_seek2(ifP, &rasterPos, sizeof(rasterPos));
 
     mayscale = TRUE;  /* initial assumption */
@@ -789,8 +789,8 @@ pgmBitsAreRepeated(unsigned int const repeatedSize,
 
 
 static void
-meaningful_bits_pgm(FILE *         const ifP, 
-                    pm_filepos     const rasterPos, 
+meaningful_bits_pgm(FILE *         const ifP,
+                    pm_filepos     const rasterPos,
                     int            const cols,
                     int            const rows,
                     xelval         const maxval,
@@ -841,8 +841,8 @@ meaningful_bits_pgm(FILE *         const ifP,
 
 
 static void
-meaningful_bits_ppm(FILE *         const ifp, 
-                    pm_filepos     const rasterPos, 
+meaningful_bits_ppm(FILE *         const ifp,
+                    pm_filepos     const rasterPos,
                     int            const cols,
                     int            const rows,
                     xelval         const maxval,
@@ -895,12 +895,12 @@ meaningful_bits_ppm(FILE *         const ifp,
 
 
 static void
-tryTransparentColor(FILE *     const ifp, 
-                    pm_filepos const rasterPos, 
-                    int        const cols, 
-                    int        const rows, 
+tryTransparentColor(FILE *     const ifp,
+                    pm_filepos const rasterPos,
+                    int        const cols,
+                    int        const rows,
                     xelval     const maxval,
-                    int        const format, 
+                    int        const format,
                     gray **    const alphaMask,
                     gray       const alphaMaxval,
                     pixel      const transcolor,
@@ -918,7 +918,7 @@ tryTransparentColor(FILE *     const ifp,
     pm_seek2(ifp, &rasterPos, sizeof(rasterPos));
 
     singleColorIsTrans = TRUE;  /* initial assumption */
-        
+
     for (row = 0; row < rows && singleColorIsTrans; ++row) {
         int col;
         pnm_readpnmrow(ifp, xelrow, cols, maxval, format);
@@ -953,7 +953,7 @@ tryTransparentColor(FILE *     const ifp,
                 }
             }
         }
-    }  
+    }
     pnm_freerow(xelrow);
 }
 
@@ -961,15 +961,15 @@ tryTransparentColor(FILE *     const ifp,
 
 static void
 analyzeAlpha(FILE *       const ifP,
-             pm_filepos   const rasterPos, 
-             unsigned int const cols, 
-             unsigned int const rows, 
+             pm_filepos   const rasterPos,
+             unsigned int const cols,
+             unsigned int const rows,
              xelval       const maxval,
-             int          const format, 
+             int          const format,
              gray **      const alphaMask,
              gray         const alphaMaxval,
              bool *       const allOpaqueP,
-             bool *       const singleColorIsTransP, 
+             bool *       const singleColorIsTransP,
              pixel *      const alphaTranscolorP) {
 /*----------------------------------------------------------------------------
   Get information about the alpha mask, in combination with the masked
@@ -995,7 +995,7 @@ analyzeAlpha(FILE *       const ifP,
         /* We found a pixel in the image where the alpha mask says it is
            not fully opaque.
         */
-    
+
     xelrow = pnm_allocrow(cols);
 
     {
@@ -1075,7 +1075,7 @@ determineTransparency(struct cmdlineInfo const cmdline,
    or identify a transparent color.
 
    We return as *transparentP:
-   
+
      -1 PNG is not to have single-color transparency
       1 PNG is to have single-color transparency as directed by user
       2 PNG is to have single-color transparency that effects an alpha
@@ -1099,7 +1099,7 @@ determineTransparency(struct cmdlineInfo const cmdline,
         if (alphaCols != cols || alphaRows != rows) {
             pm_error("dimensions for image and alpha mask do not agree");
         }
-        analyzeAlpha(ifP, rasterPos, cols, rows, maxval, format, 
+        analyzeAlpha(ifP, rasterPos, cols, rows, maxval, format,
                      alphaMask, alphaMaxval, &allOpaque,
                      &alphaCanBeTransparencyIndex, &alphaTranscolor);
 
@@ -1129,7 +1129,7 @@ determineTransparency(struct cmdlineInfo const cmdline,
         *alphaMaxvalP = 255;
 
         if (cmdline.transparent) {
-            const char * transstring2;  
+            const char * transstring2;
             /* The -transparent value, but with possible leading '=' removed */
             if (cmdline.transparent[0] == '=') {
                 *transExactP = TRUE;
@@ -1137,12 +1137,12 @@ determineTransparency(struct cmdlineInfo const cmdline,
             } else {
                 *transExactP = FALSE;
                 transstring2 = cmdline.transparent;
-            }  
+            }
             /* We do this funny PPM_DEPTH thing instead of just passing 'maxval'
                to ppm_parsecolor() because ppm_parsecolor() does a cheap maxval
                scaling, and this is more precise.
             */
-            PPM_DEPTH(*transColorP, 
+            PPM_DEPTH(*transColorP,
                       ppm_parsecolor(transstring2, PNM_OVERALLMAXVAL),
                       PNM_OVERALLMAXVAL, maxval);
 
@@ -1159,9 +1159,9 @@ determineBackground(struct cmdlineInfo const cmdline,
                     xelval             const maxval,
                     xel *              const backColorP) {
 
-  if (cmdline.background) 
+  if (cmdline.background)
       PPM_DEPTH(*backColorP,
-                ppm_parsecolor(cmdline.background, PNM_OVERALLMAXVAL), 
+                ppm_parsecolor(cmdline.background, PNM_OVERALLMAXVAL),
                 PNM_OVERALLMAXVAL, maxval);;
 }
 
@@ -1213,8 +1213,8 @@ hasColor(FILE *       const ifP,
 
 
 static void
-findRedundantBits(FILE *         const ifp, 
-                  int            const rasterPos, 
+findRedundantBits(FILE *         const ifp,
+                  int            const rasterPos,
                   int            const cols,
                   int            const rows,
                   xelval         const maxval,
@@ -1231,13 +1231,13 @@ findRedundantBits(FILE *         const ifp,
    of bits, starting from the least significant end, that contain
    original information.
 -----------------------------------------------------------------------------*/
-  if (!alpha && PNM_FORMAT_TYPE(format) == PGM_TYPE && !force) 
+  if (!alpha && PNM_FORMAT_TYPE(format) == PGM_TYPE && !force)
       meaningful_bits_pgm(ifp, rasterPos, cols, rows, maxval, format,
                           meaningfulBitsP);
   else if (PNM_FORMAT_TYPE(format) == PPM_TYPE && !force)
       meaningful_bits_ppm(ifp, rasterPos, cols, rows, maxval, format,
                           meaningfulBitsP);
-  else 
+  else
       *meaningfulBitsP = pm_maxvaltobits(maxval);
 
   if (verbose && *meaningfulBitsP != pm_maxvaltobits(maxval))
@@ -1249,24 +1249,24 @@ findRedundantBits(FILE *         const ifp,
 
 static void
 readOrderedPalette(FILE *         const pfp,
-                   xel                  ordered_palette[], 
+                   xel                  ordered_palette[],
                    unsigned int * const ordered_palette_size_p) {
 
     xel ** xels;
     int cols, rows;
     xelval maxval;
     int format;
-    
+
     if (verbose)
         pm_message("reading ordered palette (colormap)...");
 
     xels = pnm_readpnm(pfp, &cols, &rows, &maxval, &format);
-    
-    if (PNM_FORMAT_TYPE(format) != PPM_TYPE) 
+
+    if (PNM_FORMAT_TYPE(format) != PPM_TYPE)
         pm_error("ordered palette must be a PPM file, not type %d", format);
 
     *ordered_palette_size_p = rows * cols;
-    if (*ordered_palette_size_p > MAXCOLORS) 
+    if (*ordered_palette_size_p > MAXCOLORS)
         pm_error("ordered-palette image contains %d pixels.  Maximum is %d",
                  *ordered_palette_size_p, MAXCOLORS);
     if (verbose)
@@ -1278,12 +1278,12 @@ readOrderedPalette(FILE *         const pfp,
         j = 0;  /* initial value */
         for (row = 0; row < rows; ++row) {
             int col;
-            for (col = 0; col < cols; ++col) 
+            for (col = 0; col < cols; ++col)
                 ordered_palette[j++] = xels[row][col];
         }
     }
     pnm_freearray(xels, rows);
-}        
+}
 
 
 
@@ -1307,31 +1307,31 @@ compute_nonalpha_palette(colorhist_vector const chv,
    wants the colors in a particular order in the palette.
 -----------------------------------------------------------------------------*/
     unsigned int colorIndex;
-    
+
     xel ordered_palette[MAXCOLORS];
     unsigned int ordered_palette_size;
 
     if (pfp) {
         readOrderedPalette(pfp, ordered_palette, &ordered_palette_size);
 
-        if (colors != ordered_palette_size) 
+        if (colors != ordered_palette_size)
             pm_error("sizes of ordered palette (%d) "
                      "and existing palette (%d) differ",
                      ordered_palette_size, colors);
-        
+
         /* Make sure the ordered palette contains all the colors in
-           the image 
+           the image
         */
         for (colorIndex = 0; colorIndex < colors; colorIndex++) {
             int j;
             bool found;
-            
+
             found = FALSE;
             for (j = 0; j < ordered_palette_size && !found; ++j) {
-                if (PNM_EQUAL(ordered_palette[j], chv[colorIndex].color)) 
+                if (PNM_EQUAL(ordered_palette[j], chv[colorIndex].color))
                     found = TRUE;
             }
-            if (!found) 
+            if (!found)
                 pm_error("failed to find color (%d, %d, %d), which is in the "
                          "input image, in the ordered palette",
                          PPM_GETR(chv[colorIndex].color),
@@ -1344,7 +1344,7 @@ compute_nonalpha_palette(colorhist_vector const chv,
         for (colorIndex = 0; colorIndex < colors; ++colorIndex)
             palette_pnm[colorIndex] = ordered_palette[colorIndex];
     } else {
-        for (colorIndex = 0; colorIndex < colors; ++colorIndex) 
+        for (colorIndex = 0; colorIndex < colors; ++colorIndex)
             palette_pnm[colorIndex] = chv[colorIndex].color;
     }
     *paletteSizeP = colors;
@@ -1434,7 +1434,7 @@ computeUnsortedAlphaPalette(FILE *           const ifP,
    described by 'cols', 'rows', 'maxval', and 'format'.
 
    Using the alpha mask 'alpha_mask' and color map 'chv' (of size 'colors')
-   for the image, construct a palette of (color index, alpha) ordered pairs 
+   for the image, construct a palette of (color index, alpha) ordered pairs
    for the image, as follows.
 
    The alpha/color palette is the set of all ordered pairs of
@@ -1468,7 +1468,7 @@ computeUnsortedAlphaPalette(FILE *           const ifP,
         alphasOfColor[colorIndex] = NULL;
         alphasOfColorCnt[colorIndex] = 0;
     }
- 
+
     pm_seek2(ifP, &rasterPos, sizeof(rasterPos));
 
     xelrow = pnm_allocrow(cols);
@@ -1554,22 +1554,22 @@ sortAlphaPalette(gray *         const alphasOfColor[],
         unsigned int bot_idx;
         unsigned int top_idx;
         unsigned int colorIndex;
-    
+
         /* We start one index at the bottom of the palette index range
            and another at the top.  We run through the unsorted palette,
            and when we see an opaque entry, we map it to the current top
-           cursor and bump it down.  When we see a non-opaque entry, we map 
+           cursor and bump it down.  When we see a non-opaque entry, we map
            it to the current bottom cursor and bump it up.  Because the input
            and output palettes are the same size, the two cursors should meet
            right when we process the last entry of the unsorted palette.
-        */    
+        */
         bot_idx = 0;
         top_idx = alphasFirstIndex[colors-1] + alphasOfColorCnt[colors-1] - 1;
-    
+
         for (colorIndex = 0;  colorIndex < colors;  ++colorIndex) {
             unsigned int j;
             for (j = 0; j < alphasOfColorCnt[colorIndex]; ++j) {
-                unsigned int const paletteIndex = 
+                unsigned int const paletteIndex =
                     alphasFirstIndex[colorIndex] + j;
                 if (alphasOfColor[colorIndex][j] == alphaMaxval)
                     mapping[paletteIndex] = top_idx--;
@@ -1590,7 +1590,7 @@ sortAlphaPalette(gray *         const alphasOfColor[],
 
 
 static void
-compute_alpha_palette(FILE *         const ifP, 
+compute_alpha_palette(FILE *         const ifP,
                       int            const cols,
                       int            const rows,
                       xelval         const maxval,
@@ -1618,10 +1618,10 @@ compute_alpha_palette(FILE *         const ifP,
    The palette is sorted so that the opaque entries are last, and we return
    *transSizeP as the number of non-opaque entries.
 
-   palette[] and trans[] are allocated by the caller to at least 
+   palette[] and trans[] are allocated by the caller to at least
    MAXPALETTEENTRIES elements.
 
-   If there are more than MAXPALETTEENTRIES color/alpha pairs in the image, 
+   If there are more than MAXPALETTEENTRIES color/alpha pairs in the image,
    don't return any palette information -- just return *tooBigP == TRUE.
 -----------------------------------------------------------------------------*/
     colorhist_vector chv;
@@ -1630,8 +1630,8 @@ compute_alpha_palette(FILE *         const ifP,
     gray * alphas_of_color[MAXPALETTEENTRIES];
     unsigned int alphas_first_index[MAXPALETTEENTRIES];
     unsigned int alphas_of_color_cnt[MAXPALETTEENTRIES];
- 
-    getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS, 
+
+    getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS,
            &chv, &colors);
 
     assert(colors <= ARRAY_SIZE(alphas_of_color));
@@ -1650,7 +1650,7 @@ compute_alpha_palette(FILE *         const ifP,
                index into the sorted PNG palette of the alpha/color
                pair whose index is x in the unsorted PNG palette.
                This mapping sorts the palette so that opaque entries
-               are last.  
+               are last.
             */
 
         *paletteSizeP = colors == 0 ?
@@ -1669,22 +1669,22 @@ compute_alpha_palette(FILE *         const ifP,
             for (colorIndex = 0; colorIndex < colors; ++colorIndex) {
                 unsigned int j;
                 for (j = 0; j < alphas_of_color_cnt[colorIndex]; ++j) {
-                    unsigned int const paletteIndex = 
+                    unsigned int const paletteIndex =
                         alphas_first_index[colorIndex] + j;
                     palette_pnm[mapping[paletteIndex]] = chv[colorIndex].color;
-                    trans_pnm[mapping[paletteIndex]] = 
+                    trans_pnm[mapping[paletteIndex]] =
                     alphas_of_color[colorIndex][j];
                 }
             }
         }
         freeAlphasOfColor(alphas_of_color, colors);
     }
-} 
+}
 
 
 
 static void
-makeOneColorTransparentInPalette(xel            const transColor, 
+makeOneColorTransparentInPalette(xel            const transColor,
                                  bool           const exact,
                                  pixel                palette_pnm[],
                                  unsigned int   const paletteSize,
@@ -1692,12 +1692,12 @@ makeOneColorTransparentInPalette(xel            const transColor,
                                  unsigned int * const transSizeP) {
 /*----------------------------------------------------------------------------
    Find the color 'transColor' in the color/alpha palette defined by
-   palette_pnm[], paletteSize, trans_pnm[] and *transSizeP.  
+   palette_pnm[], paletteSize, trans_pnm[] and *transSizeP.
 
    Make that entry fully transparent.
 
    Rearrange the palette so that that entry is first.  (The PNG compressor
-   can do a better job when the opaque entries are all last in the 
+   can do a better job when the opaque entries are all last in the
    color/alpha palette).
 
    If the specified color is not there and exact == TRUE, return
@@ -1712,26 +1712,26 @@ makeOneColorTransparentInPalette(xel            const transColor,
     unsigned int distance;
 
     assert(paletteSize > 0);
-    
+
     if (*transSizeP != 0)
         pm_error("Internal error: trying to make a color in the palette "
                  "transparent where there already is one.");
 
-    closestColorInPalette(transColor, palette_pnm, paletteSize, 
+    closestColorInPalette(transColor, palette_pnm, paletteSize,
                           &transparentIndex, &distance);
 
     if (distance != 0 && exact) {
         pm_message("specified transparent color not present in palette; "
                    "ignoring -transparent");
         errorlevel = PNMTOPNG_WARNING_LEVEL;
-    } else {        
+    } else {
         /* Swap this with the first entry in the palette */
         pixel tmp;
-    
+
         tmp = palette_pnm[transparentIndex];
         palette_pnm[transparentIndex] = palette_pnm[0];
         palette_pnm[0] = tmp;
-        
+
         /* Make it transparent */
         trans_pnm[0] = PGM_TRANSPARENT;
         *transSizeP = 1;
@@ -1747,8 +1747,8 @@ makeOneColorTransparentInPalette(xel            const transColor,
 
 
 static void
-findOrAddBackgroundInPalette(pixel          const backColor, 
-                             pixel                palette_pnm[], 
+findOrAddBackgroundInPalette(pixel          const backColor,
+                             pixel                palette_pnm[],
                              unsigned int * const paletteSizeP,
                              unsigned int * const backgroundIndexP) {
 /*----------------------------------------------------------------------------
@@ -1757,11 +1757,11 @@ findOrAddBackgroundInPalette(pixel          const backColor,
   add it, choose a background color that's already in the palette,
   as close to 'backColor' as possible.
 
-  If we add an entry to the palette, make it opaque.  But in searching the 
+  If we add an entry to the palette, make it opaque.  But in searching the
   existing palette, ignore transparency.
 
   Note that PNG specs say that transparency of the background is meaningless;
-  i.e. a viewer must ignore the transparency of the palette entry when 
+  i.e. a viewer must ignore the transparency of the palette entry when
   using the background color.
 
   Return the palette index of the background color as *backgroundIndexP.
@@ -1770,9 +1770,9 @@ findOrAddBackgroundInPalette(pixel          const backColor,
     unsigned int paletteIndex;
 
     backgroundIndex = -1;
-    for (paletteIndex = 0; 
-         paletteIndex < *paletteSizeP; 
-         ++paletteIndex) 
+    for (paletteIndex = 0;
+         paletteIndex < *paletteSizeP;
+         ++paletteIndex)
         if (PPM_EQUAL(palette_pnm[paletteIndex], backColor))
             backgroundIndex = paletteIndex;
 
@@ -1815,8 +1815,8 @@ findOrAddBackgroundInPalette(pixel          const backColor,
 
 
 
-static void 
-buildColorLookup(pixel                   palette_pnm[], 
+static void
+buildColorLookup(pixel                   palette_pnm[],
                  unsigned int      const paletteSize,
                  colorhash_table * const chtP) {
 /*----------------------------------------------------------------------------
@@ -1841,14 +1841,14 @@ buildColorLookup(pixel                   palette_pnm[],
 
 
 
-static void 
-buildColorAlphaLookup(pixel              palettePnm[], 
+static void
+buildColorAlphaLookup(pixel              palettePnm[],
                       unsigned int const paletteSize,
-                      gray               transPnm[], 
+                      gray               transPnm[],
                       unsigned int const transSize,
                       gray         const alphaMaxval,
                       coloralphahash_table * const cahtP) {
-    
+
     coloralphahash_table const caht = alloccoloralphahash();
 
     unsigned int paletteIndex;
@@ -1897,18 +1897,18 @@ tryAlphaPalette(FILE *         const ifP,
                  "a PNG with transparency when you specify "
                  "the palette with -palette.");
 
-    compute_alpha_palette(ifP, cols, rows, maxval, format, 
+    compute_alpha_palette(ifP, cols, rows, maxval, format,
                           rasterPos,  alpha_mask, alphaMaxval,
-                          palette_pnm, trans_pnm, 
+                          palette_pnm, trans_pnm,
                           paletteSizeP, transSizeP, &tooBig);
     if (tooBig) {
         pm_asprintf(impossibleReasonP,
                     "too many color/transparency pairs "
-                    "(more than the PNG maximum of %u", 
+                    "(more than the PNG maximum of %u",
                     MAXPALETTEENTRIES);
     } else
         *impossibleReasonP = NULL;
-} 
+}
 
 
 
@@ -1922,15 +1922,15 @@ computePixelWidth(bool           const colorPng,
     unsigned int bitsPerSample, bitsPerPixel;
 
     if (colorPng || alpha) {
-        /* PNG allows only depths of 8 and 16 for a truecolor image 
+        /* PNG allows only depths of 8 and 16 for a truecolor image
            and for a grayscale image with an alpha channel.
           */
         if (pnmMeaningfulBitCt > 8)
             bitsPerSample = 16;
-        else 
+        else
             bitsPerSample = 8;
     } else {
-        /* A grayscale, non-colormapped, no-alpha PNG may have any 
+        /* A grayscale, non-colormapped, no-alpha PNG may have any
              bit depth from 1 to 16
           */
         if (pnmMeaningfulBitCt > 8)
@@ -1969,7 +1969,7 @@ paletteIndexBits(unsigned int const nColors) {
   Return the number of bits that a palette index in the PNG will
   occupy given that the palette has 'nColors' colors in it.  It is 1,
   2, 4, or 8 bits.
-  
+
   If 'nColors' is not a valid PNG palette size, return 0.
 -----------------------------------------------------------------------------*/
     unsigned int retval;
@@ -2048,7 +2048,7 @@ computeColorMap(FILE *         const ifP,
         pm_asprintf(noColormapReasonP, "You requested no color map");
     else if (maxval > PALETTEMAXVAL)
         pm_asprintf(noColormapReasonP, "The maxval of the input image (%u) "
-                    "exceeds the PNG palette maxval (%u)", 
+                    "exceeds the PNG palette maxval (%u)",
                     maxval, PALETTEMAXVAL);
     else {
         unsigned int bitsPerPixel;
@@ -2068,20 +2068,20 @@ computeColorMap(FILE *         const ifP,
             */
             colorhist_vector chv;
             unsigned int colors;
-            
-            getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS, 
+
+            getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS,
                    &chv, &colors);
 
             if (chv == NULL) {
-                pm_asprintf(noColormapReasonP, 
+                pm_asprintf(noColormapReasonP,
                             "More than %u colors found -- too many for a "
                             "colormapped PNG", MAXCOLORS);
             } else {
                 /* There are few enough colors that a palette is possible */
                 if (bitsPerPixel <= paletteIndexBits(colors) && !pfP)
-                    pm_asprintf(noColormapReasonP, 
+                    pm_asprintf(noColormapReasonP,
                                 "palette index for %u colors would be "
-                                "no smaller than the indexed value (%u bits)", 
+                                "no smaller than the indexed value (%u bits)",
                                 colors, bitsPerPixel);
                 else {
                     unsigned int paletteSize;
@@ -2090,7 +2090,7 @@ computeColorMap(FILE *         const ifP,
                         tryAlphaPalette(ifP, cols, rows, maxval, format,
                                         rasterPos, alpha_mask, alphaMaxval,
                                         pfP,
-                                        palette_pnm, &paletteSize, 
+                                        palette_pnm, &paletteSize,
                                         trans_pnm, &transSize,
                                         noColormapReasonP);
 
@@ -2098,13 +2098,13 @@ computeColorMap(FILE *         const ifP,
                         *noColormapReasonP = NULL;
 
                         compute_nonalpha_palette(chv, colors, maxval, pfP,
-                                                 palette_pnm, &paletteSize, 
+                                                 palette_pnm, &paletteSize,
                                                  trans_pnm, &transSize);
-    
+
                         if (transparent)
                             makeOneColorTransparentInPalette(
-                                transcolor, transexact, 
-                                palette_pnm, paletteSize, trans_pnm, 
+                                transcolor, transexact,
+                                palette_pnm, paletteSize, trans_pnm,
                                 &transSize);
                     }
                     if (!*noColormapReasonP) {
@@ -2137,7 +2137,7 @@ static void computeColorMapLookupTable(
 /*----------------------------------------------------------------------------
    Compute applicable lookup tables for the palette index.  If there's no
    alpha mask, this is just a standard Netpbm colorhash_table.  If there's
-   an alpha mask, it is the slower Pnmtopng-specific 
+   an alpha mask, it is the slower Pnmtopng-specific
    coloralphahash_table.
 
    If a lookup table is not applicable to the image, return NULL as
@@ -2145,10 +2145,10 @@ static void computeColorMapLookupTable(
 -----------------------------------------------------------------------------*/
     if (colorMapped) {
         if (alpha) {
-            buildColorAlphaLookup(palette_pnm, palette_size, 
+            buildColorAlphaLookup(palette_pnm, palette_size,
                                   trans_pnm, trans_size, alpha_maxval, cahtP);
             *chtP = NULL;
-        } else { 
+        } else {
             buildColorLookup(palette_pnm, palette_size, chtP);
             *cahtP = NULL;
         }
@@ -2195,15 +2195,15 @@ computeRasterWidth(bool           const colorMapped,
                           bitsPerSampleP, bitsPerPixelP);
 
         if (verbose)
-            pm_message("Writing %u bits per component per pixel", 
+            pm_message("Writing %u bits per component per pixel",
                        *bitsPerSampleP);
     }
 }
 
 
 static void
-createPngPalette(pixel              palette_pnm[], 
-                 unsigned int const paletteSize, 
+createPngPalette(pixel              palette_pnm[],
+                 unsigned int const paletteSize,
                  pixval       const maxval,
                  gray               trans_pnm[],
                  unsigned int const transSize,
@@ -2261,7 +2261,7 @@ setZlibCompression(struct pngx *          const pngxP,
         pngx_setCompressionSize(pngxP, zlibCompression.buffer_size);
     }
 }
-                  
+
 
 
 static void
@@ -2276,7 +2276,7 @@ makePngLine(png_byte *           const line,
             struct pngx *        const pngxP,
             xelval               const png_maxval,
             unsigned int         const depth) {
-            
+
     unsigned int col;
     png_byte *pp;
 
@@ -2310,7 +2310,7 @@ makePngLine(png_byte *           const line,
             *pp++ = PPM_GETB(p_png) & 0xff;
         } else
             pm_error("INTERNAL ERROR: undefined color_type");
-                
+
         if (pngx_colorType(pngxP) & PNG_COLOR_MASK_ALPHA) {
             int const png_alphaval = (int)
                 alpha_mask[col] * (float) png_maxval / maxval + 0.5;
@@ -2364,7 +2364,7 @@ writeRaster(struct pngx *        const pngxP,
             pnm_readpnmrow(ifP, xelrow, cols, maxval, format);
             pnm_promoteformatrow(xelrow, cols, maxval, format, maxval,
                                  PPM_TYPE);
-            
+
             makePngLine(line, xelrow, cols, maxval,
                         alpha, alpha ? alpha_mask[row] : NULL,
                         cht, caht, pngxP, png_maxval, depth);
@@ -2393,15 +2393,15 @@ doHistChunk(struct pngx * const pngxP,
         colorhist_vector chv;
         unsigned int colorCt;
         colorhash_table cht;
-        
-        getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS, 
+
+        getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS,
                &chv, &colorCt);
 
         cht = ppm_colorhisttocolorhash(chv, colorCt);
-                
-        { 
+
+        {
             png_uint_16 * histogram;  /* malloc'ed */
-        
+
             MALLOCARRAY(histogram, MAXCOLORS);
 
             if (!histogram)
@@ -2416,7 +2416,7 @@ doHistChunk(struct pngx * const pngxP,
                     else
                         histogram[i] = chv[chvIndex].value;
                 }
-            
+
                 pngx_setHist(pngxP, histogram);
 
                 if (verbose)
@@ -2463,7 +2463,7 @@ doIhdrChunk(struct pngx * const pngxP,
 static void
 doGamaChunk(struct cmdlineInfo const cmdline,
             struct pngx *      const pngxP) {
-            
+
     if (cmdline.gammaSpec)
         pngx_setGama(pngxP, cmdline.gamma);
 }
@@ -2507,7 +2507,7 @@ reportTrans(struct pngx * const pngxP) {
         struct pngx_trns const transInfo = pngx_trns(pngxP);
 
         pm_message("%u transparency values", transInfo.numTrans);
-        
+
         pm_message("Transparent color {gray, red, green, blue} = "
                    "{%d, %d, %d, %d}",
                    transInfo.transColor.gray,
@@ -2560,21 +2560,21 @@ doBkgdChunk(struct pngx * const pngxP,
             xelval        const maxval,
             xelval        const pngMaxval,
             bool          const verbose) {
-    
+
     if (bkgdRequested) {
         if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_PALETTE)
             pngx_setBkgdPalette(pngxP, backgroundIndex);
         else {
-            png_color_16 const pngBackground = 
+            png_color_16 const pngBackground =
                 xelToPngColor_16(backColor, maxval, pngMaxval);
             pngx_setBkgdRgb(pngxP, pngBackground);
             if (verbose)
                 pm_message("Writing bKGD chunk with background color "
                            " {gray, red, green, blue} = {%d, %d, %d, %d}",
-                           pngBackground.gray, 
-                           pngBackground.red, 
-                           pngBackground.green, 
-                           pngBackground.blue ); 
+                           pngBackground.gray,
+                           pngBackground.red,
+                           pngBackground.green,
+                           pngBackground.blue );
         }
     }
 }
@@ -2591,20 +2591,19 @@ doSbitChunk(struct pngx * const pngxP,
     if (pngx_colorType(pngxP) != PNG_COLOR_TYPE_PALETTE &&
         (pngMaxval > maxval || (alpha && pngMaxval > alphaMaxval))) {
 
-        /* We're writing in a bit depth that doesn't match the maxval
-           of the input image and the alpha mask.  So we write an sBIT
-           chunk to tell what the original image's maxval was.  The
-           sBit chunk doesn't let us specify any maxval -- only powers
-           of two minus one.  So we pick the power of two minus one
-           which is greater than or equal to the actual input maxval.
-           
-           PNG also doesn't let an sBIT chunk indicate a maxval
-           _greater_ than the the PNG maxval.  The designers probably
-           did not conceive of the case where that would happen.  The
-           case is this: We detected redundancy in the bits so were
-           able to store fewer bits than the user provided.  But since
-           PNG doesn't allow it, we don't attempt to create such an
-           sBIT chunk.
+        /* We're writing in a bit depth that doesn't match the maxval of the
+           input image and the alpha mask.  So we write an sBIT chunk to tell
+           what the original image's maxval was.  The sBit chunk doesn't let
+           us specify any maxval -- only powers of two minus one.  So we pick
+           the power of two minus one which is greater than or equal to the
+           actual input maxval.
+
+           PNG also doesn't let an sBIT chunk indicate a maxval _greater_ than
+           the PNG maxval.  The designers probably did not conceive of the
+           case where that would happen.  The case is this: We detected
+           redundancy in the bits so were able to store fewer bits than the
+           user provided.  But since PNG doesn't allow it, we don't attempt to
+           create such an sBIT chunk.
         */
 
         {
@@ -2618,7 +2617,7 @@ doSbitChunk(struct pngx * const pngxP,
                 sbit.blue  = sbitval;
             } else
                 sbit.gray  = sbitval;
-            
+
             if (verbose)
                 pm_message("Writing sBIT chunk with bits = %d", sbitval);
 
@@ -2649,7 +2648,7 @@ addSrgbChunk(struct pngx *   const pngxP,
 
 
 
-static void 
+static void
 convertpnm(struct cmdlineInfo const cmdline,
            FILE *             const ifP,
            FILE *             const ofP,
@@ -2668,14 +2667,14 @@ convertpnm(struct cmdlineInfo const cmdline,
     xelval maxval;
     /* The maxval of the input image */
     xelval pngMaxval;
-        /* The maxval of the samples in the PNG output 
+        /* The maxval of the samples in the PNG output
            (must be 1, 3, 7, 15, 255, or 65535)
         */
     pixel transcolor;
         /* The color that is to be transparent, with maxval equal to that
            of the input image.
         */
-    bool transExact;  
+    bool transExact;
         /* boolean: the user wants only the exact color he specified to be
            transparent; not just something close to it.
         */
@@ -2694,14 +2693,14 @@ convertpnm(struct cmdlineInfo const cmdline,
     pixel palettePnm[MAXCOLORS];
     png_color palette[MAXCOLORS];
         /* The color part of the color/alpha palette passed to the PNG
-           compressor 
+           compressor
         */
     unsigned int paletteSize;
 
     gray transPnm[MAXCOLORS];
     png_byte  trans[MAXCOLORS];
         /* The alpha part of the color/alpha palette passed to the PNG
-           compressor 
+           compressor
         */
     unsigned int transSize;
 
@@ -2717,7 +2716,7 @@ convertpnm(struct cmdlineInfo const cmdline,
            we should.  malloc'ed null-terminated string.
         */
     unsigned int depth;
-        /* The number of bits per sample in the (uncompressed) png 
+        /* The number of bits per sample in the (uncompressed) png
            raster -- if the raster contains palette indices, this is the
            number of bits in the index.
         */
@@ -2725,7 +2724,7 @@ convertpnm(struct cmdlineInfo const cmdline,
         /* The total number of bits per pixel in the (uncompressed) png
            raster, including all channels.
         */
-    pm_filepos rasterPos;  
+    pm_filepos rasterPos;
         /* file position in input image file of start of image (i.e. after
            the header)
         */
@@ -2766,7 +2765,7 @@ convertpnm(struct cmdlineInfo const cmdline,
         colorPng = (PNM_FORMAT_TYPE(format) == PPM_TYPE);
     else {
         if (PNM_FORMAT_TYPE(format) == PPM_TYPE) {
-            colorPng = hasColor(ifP, cols, rows, maxval, format, rasterPos); 
+            colorPng = hasColor(ifP, cols, rows, maxval, format, rasterPos);
         } else
             colorPng = false;
     }
@@ -2781,10 +2780,10 @@ convertpnm(struct cmdlineInfo const cmdline,
 
     findRedundantBits(ifP, rasterPos, cols, rows, maxval, format, alpha,
                       cmdline.force, &pnmMeaningfulBitCt);
-  
+
     computeColorMap(ifP, rasterPos, cols, rows, maxval, colorPng, format,
                     cmdline.force, pfP,
-                    alpha, transparent >= 0, transcolor, transExact, 
+                    alpha, transparent >= 0, transcolor, transExact,
                     !!cmdline.background, backColor,
                     alpha_mask, alphaMaxval, pnmMeaningfulBitCt,
                     palettePnm, &paletteSize, transPnm, &transSize,
@@ -2801,7 +2800,7 @@ convertpnm(struct cmdlineInfo const cmdline,
         colorMapped = FALSE;
     } else
         colorMapped = TRUE;
-  
+
     computeColorMapLookupTable(colorMapped, palettePnm, paletteSize,
                                transPnm, transSize, alpha, alphaMaxval,
                                &cht, &caht);
@@ -2812,7 +2811,7 @@ convertpnm(struct cmdlineInfo const cmdline,
     if (verbose)
         pm_message ("writing a%s %d-bit %s%s file%s",
                     fulldepth == 8 ? "n" : "", fulldepth,
-                    colorMapped ? "palette": 
+                    colorMapped ? "palette":
                     colorPng ? "RGB" : "gray",
                     alpha ? (colorMapped ? "+transparency" : "+alpha") : "",
                     cmdline.interlace ? " (interlaced)" : "");
@@ -2839,7 +2838,7 @@ convertpnm(struct cmdlineInfo const cmdline,
         /* creating PNG palette (Not counting the transparency palette) */
 
         createPngPalette(palettePnm, paletteSize, maxval,
-                         transPnm, transSize, alphaMaxval, 
+                         transPnm, transSize, alphaMaxval,
                          palette, trans);
         pngx_setPlte(pngxP, palette, paletteSize);
 
@@ -2940,7 +2939,7 @@ displayVersion() {
 
 
 
-int 
+int
 main(int argc, const char * argv[]) {
 
     struct cmdlineInfo cmdline;
@@ -2950,29 +2949,29 @@ main(int argc, const char * argv[]) {
     FILE * tfP;
 
     int errorlevel;
-    
+
     pm_proginit(&argc, argv);
-    
+
     parseCommandLine(argc, argv, &cmdline);
-    
+
     if (cmdline.libversion) {
         displayVersion();
         return 0;
     }
     verbose = cmdline.verbose;
-    
+
     ifP = pm_openr_seekable(cmdline.inputFileName);
-    
+
     if (cmdline.alpha)
         afP = pm_openr(cmdline.alpha);
     else
         afP = NULL;
-    
+
     if (cmdline.palette)
         pfP = pm_openr(cmdline.palette);
     else
         pfP = NULL;
-    
+
     if (cmdline.text)
         tfP = pm_openr(cmdline.text);
     else if (cmdline.ztxt)
@@ -2981,7 +2980,7 @@ main(int argc, const char * argv[]) {
         tfP = NULL;
 
     convertpnm(cmdline, ifP, stdout, afP, pfP, tfP, &errorlevel);
-    
+
     if (afP)
         pm_close(afP);
     if (pfP)