about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--converter/other/pnmtops.c2294
1 files changed, 1188 insertions, 1106 deletions
diff --git a/converter/other/pnmtops.c b/converter/other/pnmtops.c
index e9f17215..c238e765 100644
--- a/converter/other/pnmtops.c
+++ b/converter/other/pnmtops.c
@@ -57,7 +57,7 @@ struct cmdlineInfo {
        in a form easy for the program to use.
     */
     const char * inputFileName;  /* Filespecs of input file */
-    float scale;
+    float        scale;
     unsigned int dpiX;     /* horiz component of DPI option */
     unsigned int dpiY;     /* vert component of DPI option */
     unsigned int width;              /* in 1/72 inch */
@@ -85,42 +85,44 @@ struct cmdlineInfo {
 
 static bool verbose;
 
+
+
 static void
 parseDpi(const char *   const dpiOpt, 
-     unsigned int * const dpiXP, 
-     unsigned int * const dpiYP) {
+         unsigned int * const dpiXP, 
+         unsigned int * const dpiYP) {
 
     char *dpistr2;
     unsigned long int dpiX, dpiY;
 
     dpiX = strtol(dpiOpt, &dpistr2, 10);
     if (dpistr2 == dpiOpt)
-    pm_error("Invalid value for -dpi: '%s'.  Must be either number "
-         "or NxN ", dpiOpt);
+        pm_error("Invalid value for -dpi: '%s'.  Must be either number "
+                 "or NxN ", dpiOpt);
     else if (dpiX > INT_MAX)
-    pm_error("Invalid value for -dpi: '%s'.  "
-         "Value too large for computation", dpiOpt);
-    else {
-    if (*dpistr2 == '\0') {
-        *dpiXP = dpiX;
-        *dpiYP = dpiX;
-    } else if (*dpistr2 == 'x') {
-        char * dpistr3;
-
-        dpistr2++;  /* Move past 'x' */
-        dpiY = strtol(dpistr2, &dpistr3, 10);
-        if (dpiY > INT_MAX)
         pm_error("Invalid value for -dpi: '%s'.  "
-             "Value too large for computation", dpiOpt);
-        else if (dpistr3 != dpistr2 && *dpistr3 == '\0') {
-        *dpiXP = dpiX;
-        *dpiYP = dpiY;
-        } else {
-        pm_error("Invalid value for -dpi: '%s'.  Must be either "
-             "number or NxN", dpiOpt);
+                 "Value too large for computation", dpiOpt);
+    else {
+        if (*dpistr2 == '\0') {
+            *dpiXP = dpiX;
+            *dpiYP = dpiX;
+        } else if (*dpistr2 == 'x') {
+            char * dpistr3;
+
+            dpistr2++;  /* Move past 'x' */
+            dpiY = strtol(dpistr2, &dpistr3, 10);
+            if (dpiY > INT_MAX)
+                pm_error("Invalid value for -dpi: '%s'.  "
+                         "Value too large for computation", dpiOpt);
+            else if (dpistr3 != dpistr2 && *dpistr3 == '\0') {
+                *dpiXP = dpiX;
+                *dpiYP = dpiY;
+            } else {
+                pm_error("Invalid value for -dpi: '%s'.  Must be either "
+                         "number or NxN", dpiOpt);
+            }
         }
     }
-    }
 }
 
 
@@ -134,34 +136,35 @@ validateBps_1_2_4_8_12(unsigned int const bitsPerSample) {
     case 4:
     case 8:
     case 12:
-    break;
+        break;
     default:
-    pm_error("Invalid -bitspersample value: %u.  Must be "
-         "1, 2, 4, 8, or 12", bitsPerSample);
+        pm_error("Invalid -bitspersample value: %u.  Must be "
+                 "1, 2, 4, 8, or 12", bitsPerSample);
     }
 }
 
 
+
 static void
 validateCompDimension(unsigned int const value,
-              unsigned int const scaleFactor,
-              const char * const vname) {
+                      unsigned int const scaleFactor,
+                      const char * const vname) {
 /*----------------------------------------------------------------------------
-   Validate that the image dimension (width or height) 'value' isn't so big
-   that in this program's calculations, involving scale factor 'scaleFactor',
-   it would cause a register overflow.  If it is, abort the program and refer
-   to the offending dimension as 'vname' in the error message.
-
-   Note that this early validation approach (calling this function) means
-   the actual computations don't have to be complicated with arithmetic
-   overflow checks, so they're easier to read.
+  Validate that the image dimension (width or height) 'value' isn't so big
+  that in this program's calculations, involving scale factor 'scaleFactor',
+  it would cause a register overflow.  If it is, abort the program and refer
+  to the offending dimension as 'vname' in the error message.
+
+  Note that this early validation approach (calling this function) means
+  the actual computations don't have to be complicated with arithmetic
+  overflow checks, so they're easier to read.
 -----------------------------------------------------------------------------*/
     if (value > 0) {
-    unsigned int const maxWidthHeight = INT_MAX - 2;
-    unsigned int const maxScaleFactor = maxWidthHeight / value;
+        unsigned int const maxWidthHeight = INT_MAX - 2;
+        unsigned int const maxScaleFactor = maxWidthHeight / value;
 
-    if (scaleFactor > maxScaleFactor)
-        pm_error("%s is too large for compuations: %u", vname, value);
+        if (scaleFactor > maxScaleFactor)
+            pm_error("%s is too large for compuations: %u", vname, value);
     }
 }
 
@@ -169,7 +172,7 @@ validateCompDimension(unsigned int const value,
 
 static void
 parseCommandLine(int argc, const char ** argv,
-         struct cmdlineInfo * const cmdlineP) {
+                 struct cmdlineInfo * const cmdlineP) {
 
     unsigned int imagewidthSpec, imageheightSpec;
     float imagewidth, imageheight;
@@ -203,7 +206,7 @@ parseCommandLine(int argc, const char ** argv,
     OPTENT3(0, "imagewidth",  OPT_FLOAT, &imagewidth,  &imagewidthSpec,  0);
     OPTENT3(0, "imageheight", OPT_FLOAT, &imageheight, &imageheightSpec, 0);
     OPTENT3(0, "bitspersample", OPT_UINT, &cmdlineP->bitspersample,
-        &cmdlineP->bitspersampleSpec, 0);
+            &cmdlineP->bitspersampleSpec, 0);
     OPTENT3(0, "nosetpage",   OPT_FLAG,  NULL, &nosetpage,               0);
     OPTENT3(0, "setpage",     OPT_FLAG,  NULL, &cmdlineP->setpage,       0);
     OPTENT3(0, "noshowpage",  OPT_FLAG,  NULL, &noshowpage,              0);
@@ -213,7 +216,7 @@ parseCommandLine(int argc, const char ** argv,
     OPTENT3(0, "showpage",    OPT_FLAG,  NULL, &showpage,                0);
     OPTENT3(0, "verbose",     OPT_FLAG,  NULL, &cmdlineP->verbose,       0);
     OPTENT3(0, "level",       OPT_UINT, &cmdlineP->level, 
-        &cmdlineP->levelSpec,              0);
+            &cmdlineP->levelSpec,              0);
     
     opt.opt_table = option_def;
     opt.short_allowed = FALSE;
@@ -222,28 +225,28 @@ parseCommandLine(int argc, const char ** argv,
     pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
 
     if (cmdlineP->mustturn && noturn)
-    pm_error("You cannot specify both -turn and -noturn");
+        pm_error("You cannot specify both -turn and -noturn");
     if (center && nocenter)
-    pm_error("You cannot specify both -center and -nocenter");
+        pm_error("You cannot specify both -center and -nocenter");
     if (showpage && noshowpage)
-    pm_error("You cannot specify both -showpage and -noshowpage");
+        pm_error("You cannot specify both -showpage and -noshowpage");
     if (cmdlineP->setpage && nosetpage)
-    pm_error("You cannot specify both -setpage and -nosetpage");
+        pm_error("You cannot specify both -setpage and -nosetpage");
 
     if (!scaleSpec)
-    cmdlineP->scale = 1.0;
+        cmdlineP->scale = 1.0;
 
     if (!widthSpec)
-    width = 8.5;
+        width = 8.5;
 
     if (!heightSpec)
-    height = 11.0;
+        height = 11.0;
 
     if (dpiSpec)
-    parseDpi(dpiOpt, &cmdlineP->dpiX, &cmdlineP->dpiY);
+        parseDpi(dpiOpt, &cmdlineP->dpiX, &cmdlineP->dpiY);
     else {
-    cmdlineP->dpiX = 300;
-    cmdlineP->dpiY = 300;
+        cmdlineP->dpiX = 300;
+        cmdlineP->dpiY = 300;
     }
 
     cmdlineP->center  =  !nocenter;
@@ -257,714 +260,785 @@ parseCommandLine(int argc, const char ** argv,
     cmdlineP->height = height * 72;
 
     if (imagewidthSpec) {
-    validateCompDimension(imagewidth, 72, "-imagewidth value");
-    cmdlineP->imagewidth = imagewidth * 72;
+        validateCompDimension(imagewidth, 72, "-imagewidth value");
+        cmdlineP->imagewidth = imagewidth * 72;
     }
     else
-    cmdlineP->imagewidth = 0;
+        cmdlineP->imagewidth = 0;
     if (imageheightSpec) {
-    validateCompDimension(imagewidth, 72, "-imageheight value");
-    cmdlineP->imageheight = imageheight * 72;
+        validateCompDimension(imagewidth, 72, "-imageheight value");
+        cmdlineP->imageheight = imageheight * 72;
     }
     else
-    cmdlineP->imageheight = 0;
-
-#ifdef NOFLATE
-    if (cmdlineP->flate)
-        pm_error("This program cannot handle flate compression. "
-                 "Flate support suppressed at compile time.");
-#endif
+        cmdlineP->imageheight = 0;
 
     if (!cmdlineP->psfilter &&
-    (cmdlineP->flate || cmdlineP->ascii85))
-    pm_error("You must specify -psfilter in order to specify "
-         "-flate or -ascii85");
+        (cmdlineP->flate || cmdlineP->ascii85))
+        pm_error("You must specify -psfilter in order to specify "
+                 "-flate or -ascii85");
 
     if (cmdlineP->bitspersampleSpec)
-    validateBps_1_2_4_8_12(cmdlineP->bitspersample);
+        validateBps_1_2_4_8_12(cmdlineP->bitspersample);
 
     if (argc-1 == 0) 
-    cmdlineP->inputFileName = "-";
+        cmdlineP->inputFileName = "-";
     else if (argc-1 != 1)
-    pm_error("Program takes zero or one argument (filename).  You "
-         "specified %d", argc-1);
+        pm_error("Program takes zero or one argument (filename).  You "
+                 "specified %d", argc-1);
     else
-    cmdlineP->inputFileName = argv[1];
+        cmdlineP->inputFileName = argv[1];
 
     free(option_def); 
 }
 
 
+
+static bool
+progIsFlateCapable(void) {
+
+    return
+#ifdef NOFLATE
+        false
+#else
+        true
+#endif
+        ;
+}
+
+
+
+static const char *
+basebasename(const char * const filespec) {
+/*----------------------------------------------------------------------------
+  Return filename up to first period
+-----------------------------------------------------------------------------*/
+    char const dirsep = '/';
+    const char * const lastSlashPos = strrchr(filespec, dirsep);
+
+    char * name;
+    const char * filename;
+
+    if (lastSlashPos)
+        filename = lastSlashPos + 1;
+    else
+        filename = filespec;
+
+    name = strdup(filename);
+    if (name != NULL) {
+        char * const dotPosition = strchr(name, '.');
+
+        if (dotPosition)
+            *dotPosition = '\0';
+    }
+    return name;
+}
+
+
+
+#define MAX_FILTER_CT 10
+    /* The maximum number of filters this code is capable of applying */
+
+
+
+static void
+initPidList(pid_t * const pidList) {
+
+    pidList[0] = (pid_t)0;  /* end of list marker */
+}
+
+
+
+static void
+addToPidList(pid_t * const pidList,
+             pid_t   const newPid) {
+
+    unsigned int i;
+
+    for (i = 0; i < MAX_FILTER_CT && pidList[i]; ++i);
+
+    assert(i < MAX_FILTER_CT);
+
+    pidList[i] = newPid;
+    pidList[i+1] = (pid_t)0;  /* end of list marker */
+}
+
+
+
 /*===========================================================================
   The output encoder
-===========================================================================*/
+  ===========================================================================*/
     
-enum output {AsciiHex, Ascii85};
-enum compress {none, Runlength, Flate, RunlengthFlate};
+enum OutputType {AsciiHex, Ascii85};
 
 typedef struct {
-  enum output        output;
-  enum compress      compress;
-  unsigned int       runlengthRefresh;
-  int                pid[3]; /* child process ID, transmitted to parent */
+    enum OutputType    outputType;
+    bool               compressRle;
+    bool               compressFlate;
+    unsigned int       runlengthRefresh;
 } OutputEncoder;
 
 
+
 static void
 initOutputEncoder(OutputEncoder  * const oeP,
-          unsigned int     const icols,
-          unsigned int     const bitsPerSample,
-          bool             const rle,
-          bool             const flate,
-          bool             const ascii85,
-          bool             const psFilter) {
+                  unsigned int     const icols,
+                  unsigned int     const bitsPerSample,
+                  bool             const rle,
+                  bool             const flate,
+                  bool             const ascii85,
+                  bool             const psFilter) {
 
     unsigned int const bytesPerRow = icols / (8/bitsPerSample) +
-    (icols % (8/bitsPerSample) > 0 ? 1 : 0);
-    /* Size of row buffer, padded up to byte boundary.
+        (icols % (8/bitsPerSample) > 0 ? 1 : 0);
+        /* Size of row buffer, padded up to byte boundary.
+
+           A more straightforward calculation would be
+           (icols * bitsPerSample + 7) / 8 ,
+           but this overflows when icols is large.
+        */
+
+    oeP->outputType = ascii85 ? Ascii85 : AsciiHex;
 
-       A more straightforward calculation would be
-         (icols * bitsPerSample + 7) / 8 ,
-       but this overflows when icols is large.
+    if (rle) {
+        oeP->compressRle = true;
+        oeP->runlengthRefresh = psFilter ? INT_MAX : bytesPerRow;
+    } else
+        oeP->compressRle = false;
+
+    if (flate) {
+        assert(psFilter);
+        oeP->compressFlate = true;
+    } else
+        oeP->compressFlate = false;
+
+    if (ascii85) {
+        assert(psFilter);
+        oeP->outputType = Ascii85;
+    } else
+        oeP->outputType = AsciiHex;
+}
+
+
+
+typedef void FilterFn(FILE *          const ifP,
+                      FILE *          const ofP,
+                      OutputEncoder * const oeP);
+    /* This is a function that can be run in a separate process to do
+       arbitrary modifications of the raster data stream.
     */
+       
 
-    oeP->output = ascii85 ? Ascii85 : AsciiHex;
 
-    if (rle && flate) {
-      assert(psFilter);
-      oeP->compress = RunlengthFlate;
-      oeP->runlengthRefresh = INT_MAX;
-    }
-    else if (rle) {
-      oeP->compress = Runlength;
-      oeP->runlengthRefresh = psFilter ? INT_MAX : bytesPerRow;
-    }
-    else if (flate) {
-      assert(psFilter);
-      oeP->compress = Flate;
-    }
-    else   /* neither rle nor flate */
-      oeP->compress = none;
+#ifndef NOFLATE
+static void
+initZlib(z_stream * const strmP) {
 
-    if(ascii85) {
-      assert(psFilter);
-      oeP->output = Ascii85;
-    }
-    else
-      oeP->output = AsciiHex;
+    int const level = 9; /* maximum compression.  see zlib.h */
+
+    int ret;
 
+    /* allocate deflate state */
+    strmP->zalloc = Z_NULL;
+    strmP->zfree  = Z_NULL;
+    strmP->opaque = Z_NULL;
+
+    ret = deflateInit(strmP, level);
+    if (ret != Z_OK)
+        pm_error("Failed to initialize zlib.");
 }
+#endif
 
-/*
-The following function flateFilter() is based on def() in zpipe.c.
-zpipe is an example program which comes with the zlib source package.
-zpipe.c is public domain and is available from the Zlib website:
-http://www.zlib.net/
 
-See zlib.h for details on zlib parameters Z_NULL, Z_OK, etc.
-*/
+
+static FilterFn flateFilter;
 
 static void 
-flateFilter(int const fdsource, int const fddest, OutputEncoder * const oeP)
+flateFilter(FILE *          const ifP,
+            FILE *          const ofP,
+            OutputEncoder * const oeP) {
+
 #ifndef NOFLATE
-{
 
-#define CHUNK 128*1024 /* recommended in zpipe.c */
-               /* 4096 is not efficient but works */
+    /* This code is based on def() in zpipe.c.  zpipe is an example program
+       which comes with the zlib source package.  zpipe.c is public domain and
+       is available from the Zlib website: http://www.zlib.net/
 
-    int ret, flush;
-    unsigned have;
+       See zlib.h for details on zlib parameters Z_NULL, Z_OK, etc.
+    */
+    unsigned int const chunkSz = 128*1024;
+        /* 128K recommended in zpipe.c.  4096 is not efficient but works. */
+
+    int flush;
     z_stream strm;
-    unsigned char * const  in = pm_allocrow(CHUNK, 1);
-    unsigned char * const out = pm_allocrow(CHUNK, 1);
-    const int level = 9; /* maximum compression.  see zlib.h */
+    unsigned char * in;
+    unsigned char * out;
 
-    FILE * source;
-    FILE * dest;
- 
-    /* allocate deflate state */
-    strm.zalloc = Z_NULL;
-    strm.zfree = Z_NULL;
-    strm.opaque = Z_NULL;
-    ret = deflateInit(&strm, level);
-    if (ret != Z_OK)
-      pm_error("Failed to initialize zlib.");
+    in  = pm_allocrow(chunkSz, 1);
+    out = pm_allocrow(chunkSz, 1);
 
-    /* open files */
-    source = fdopen(fdsource, "r");
-    dest = fdopen(fddest, "w");
-    if (source ==NULL || dest==NULL)
-      pm_error("Failed to open internal pipe(s) for flate compression.");
+    initZlib(&strm);
 
     /* compress until end of file */
     do {
-    strm.avail_in = fread(in, 1, CHUNK, source);
-    if (ferror(source)) {
-      (void)deflateEnd(&strm);
-      pm_error("Error reading from internal pipe during "
-           "flate compression.");
-    }
-    flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
-    strm.next_in = in;
-
-    /* run deflate() on input until output buffer not full, finish
-       compression if all of source has been read in */
-    do {
-        strm.avail_out = CHUNK;
-        strm.next_out = out;
-        ret = deflate(&strm, flush);    /* no bad return value */
-        assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
-        have = CHUNK - strm.avail_out;
-        if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
-        (void)deflateEnd(&strm);
-        pm_error("Error writing to internal pipe during "
-             "flate compression.");
+        strm.avail_in = fread(in, 1, chunkSz, ifP);
+        if (ferror(ifP)) {
+            deflateEnd(&strm);
+            pm_error("Error reading from internal pipe during "
+                     "flate compression.");
         }
-    } while (strm.avail_out == 0);
-    assert(strm.avail_in == 0);     /* all input will be used */
+        flush = feof(ifP) ? Z_FINISH : Z_NO_FLUSH;
+        strm.next_in = in;
 
-    /* done when last data in file processed */
+        /* run deflate() on input until output buffer not full, finish
+           compression if we have reached end of input.
+        */
+        do {
+            unsigned int have;
+            size_t bytesWritten;
+
+            strm.avail_out = chunkSz;
+            strm.next_out = out;
+            deflate(&strm, flush);
+            have = chunkSz - strm.avail_out;
+            bytesWritten = fwrite(out, 1, have, ofP);
+            if (ferror(ofP) || bytesWritten != have) {
+                deflateEnd(&strm);
+                pm_error("Error writing to internal pipe during "
+                         "flate compression.");
+            }
+        } while (strm.avail_out == 0);
+        assert(strm.avail_in == 0);     /* all input is used */
+
+        /* done when last data in file processed */
     } while (flush != Z_FINISH);
-    assert(ret == Z_STREAM_END);        /* stream will be complete */
 
-    /* clean up and return */
     free(in);
     free(out); 
-    (void)deflateEnd(&strm);
-    fclose(source);
-    fclose(dest);
-}
+    deflateEnd(&strm);
+    fclose(ifP);
+    fclose(ofP);
 #else
-{
-  assert(0==1);    /* should never be executed */ 
-}
+    assert(false);    /* filter is never used */ 
 #endif
+}
+
 
 
 /* Run length encoding
 
-In this simple run-length encoding scheme, compressed and uncompressed
-strings follow a single index byte N.  N 0-127 means the next N+1
-bytes are uncompressed; 129-255 means the next byte is to be repeated
-257-N times.
+   In this simple run-length encoding scheme, compressed and uncompressed
+   strings follow a single index byte N.  N 0-127 means the next N+1
+   bytes are uncompressed; 129-255 means the next byte is to be repeated
+   257-N times.
 
-In native (non-psfilter) mode, the run length filter must flush at
-the end of every row.  But the entire raster is sent to the run length
-filter as one continuous stream.  The run length filter learns the
-refresh interval from oeP->runlengthRefresh.
+   In native (non-psfilter) mode, the run length filter must flush at
+   the end of every row.  But the entire raster is sent to the run length
+   filter as one continuous stream.  The run length filter learns the
+   refresh interval from oeP->runlengthRefresh.
 */
 
 
 static void
-rlePutBuffer (unsigned int const repeat,
-          unsigned int const count,
-          unsigned int const repeatitem,
-          unsigned char * const itembuf,
-          FILE * const fp) {
-
-  if (repeat) {
-    fputc ( 257-count,  fp);
-    fputc ( repeatitem, fp);
-  }
-  else {
-    fputc ( count-1, fp);
-    fwrite( itembuf, 1, count, fp);
-  }
+rlePutBuffer (unsigned int    const repeat,
+              unsigned int    const count,
+              unsigned int    const repeatitem,
+              unsigned char * const itembuf,
+              FILE *          const fP) {
+
+    if (repeat) {
+        fputc(257 - count,  fP);
+        fputc(repeatitem, fP);
+    } else {
+        fputc(count - 1, fP);
+        fwrite(itembuf, 1, count, fP);
+    }
 }
 
 
 
+static FilterFn rleFilter;
+
 static void
-rleFilter (int const in, int const out, OutputEncoder * const  oeP)
-{
+rleFilter (FILE *          const ifP,
+           FILE *          const ofP,
+           OutputEncoder * const oeP) {
 
-  unsigned int repeat = 1, count = 0, incount=0, repeatcount;
-  unsigned int const refresh = oeP->runlengthRefresh;
-  unsigned char repeatitem;
-  int     rleitem;
-  unsigned char itembuf[128];
-  int     i;
-  FILE   *fin;
-  FILE   *fout;
+    unsigned int const refresh = oeP->runlengthRefresh;
 
+    bool eof;
+    bool repeat;
+    unsigned int count;
+    unsigned int incount;
+    unsigned int repeatcount;
+    unsigned char repeatitem;
+    unsigned char itembuf[128];
 
-  fin = fdopen (in, "r");
-  fout = fdopen (out, "w");
-  if (fin == NULL || fout == NULL)
-    pm_error("Failed to open internal pipe(s) for run-length compression.");
+    repeat = true; /* initial value */
+    count = 0; /* initial value */
 
-  while ((rleitem = fgetc (fin)) != EOF) {
-    incount++;
+    for (eof = false, incount = 0; !eof; ) {
+        int rleitem;
 
-    if (repeat && count == 0) { /* Still initializing a repeat buf. */
-      itembuf[count++] = repeatitem = rleitem;
-    }
-    else if (repeat) {          /* Repeating - watch for end of run. */
-      if (rleitem == repeatitem) {      /* Run continues. */
-    itembuf[count++] = rleitem;
-      }
-      else {                    /* Run ended - is it long enough to dump? */
-    if (count > 2) {
-    /* Yes, dump a repeat-mode buffer and start a new one. */
-      rlePutBuffer (repeat, count, repeatitem, itembuf, fout);
-      repeat = 1;
-      count = 0;
-      itembuf[count++] = repeatitem = rleitem;
-    }
-    else {
-    /* Not long enough - convert to non-repeat mode. */
-      repeat = 0;
-      itembuf[count++] = repeatitem = rleitem;
-      repeatcount = 1;
-    }
-      }
-    }
-    else {
-    /* Not repeating - watch for a run worth repeating. */
-      if (rleitem == repeatitem) {      /* Possible run continues. */
-    ++repeatcount;
-    if (repeatcount > 3) {
-    /* Long enough - dump non-repeat part and start repeat. */
-      count = count - (repeatcount - 1);
-      rlePutBuffer (repeat, count, repeatitem, itembuf, fout);
-      repeat = 1;
-      count = repeatcount;
-      for (i = 0; i < count; ++i)
-        itembuf[i] = rleitem;
-    }
-    else {
-    /* Not long enough yet - continue as non-repeat buf. */
-      itembuf[count++] = rleitem;
+        rleitem = fgetc(ifP);
+        if (rleitem == EOF)
+            eof = true;
+        else {
+            ++incount;
+
+            if (repeat && count == 0) {
+                /* Still initializing a repeat buf. */
+                itembuf[count++] = repeatitem = rleitem;
+            }
+            else if (repeat) {
+                /* Repeating - watch for end of run. */
+                if (rleitem == repeatitem) {
+                    /* Run continues. */
+                    itembuf[count++] = rleitem;
+                } else {
+                    /* Run ended */
+                    if (count > 2) {
+                        /* Long enough to dump, so dump a repeat-mode buffer
+                           and start a new one.
+                        */
+                        rlePutBuffer(repeat, count, repeatitem, itembuf, ofP);
+                        repeat = true;
+                        count = 0;
+                        itembuf[count++] = repeatitem = rleitem;
+                    } else {
+                        /* Not long enough - convert to non-repeat mode. */
+                        repeat = false;
+                        itembuf[count++] = repeatitem = rleitem;
+                        repeatcount = 1;
+                    }
+                }
+            } else {
+                /* Not repeating - watch for a run worth repeating. */
+                if (rleitem == repeatitem) {
+                    /* Possible run continues. */
+                    ++repeatcount;
+                    if (repeatcount > 3) {
+                        /* Long enough - dump non-repeat part and start
+                           repeat.
+                        */
+                        unsigned int i;
+                        count = count - (repeatcount - 1);
+                        rlePutBuffer(repeat, count, repeatitem, itembuf, ofP);
+                        repeat = true;
+                        count = repeatcount;
+                        for (i = 0; i < count; ++i)
+                            itembuf[i] = rleitem;
+                    } else {
+                        /* Not long enough yet - continue as non-repeat buf. */
+                        itembuf[count++] = rleitem;
+                    }
+                } else {                    /* Broken run. */
+                    itembuf[count++] = repeatitem = rleitem;
+                    repeatcount = 1;
+                }
+            }
+
+            if (incount == refresh) {
+                rlePutBuffer(repeat, count, repeatitem, itembuf, ofP);
+                repeat = true;
+                count = incount = 0;
+            }
+
+            if (count == 128) {
+                rlePutBuffer(repeat, count, repeatitem, itembuf, ofP);
+                repeat = true;
+                count = 0;
+            }
+        }
     }
-      }
-      else {                    /* Broken run. */
-    itembuf[count++] = repeatitem = rleitem;
-    repeatcount = 1;
 
-      }
-    }
+    if (count > 0)
+        rlePutBuffer(repeat, count, repeatitem, itembuf, ofP);
+
+    fclose(ifP);
+    fclose(ofP);
+}
+
+
+
+static FilterFn asciiHexFilter;
+
+static void
+asciiHexFilter(FILE *          const ifP,
+               FILE *          const ofP,
+               OutputEncoder * const oeP) {
+
+    char const hexits[16] = "0123456789abcdef";
+
+    bool eof;
+    unsigned char inbuff[40], outbuff[81];
 
-    if (incount == refresh) {
-      rlePutBuffer (repeat, count, repeatitem, itembuf, fout);
-      repeat = 1;
-      count = incount = 0;
+    for (eof = false; !eof; ) {
+        size_t bytesRead;
+
+        bytesRead = fread(inbuff, 1, 40, ifP);
+
+        if (bytesRead == 0)
+            eof = true;
+        else {
+            unsigned int i;
+
+            for (i = 0; i < bytesRead; ++i) {
+                int const item = inbuff[i]; 
+                outbuff[i*2]   = hexits[item >> 4];
+                outbuff[i*2+1] = hexits[item & 15];
+            }
+        }
+        outbuff[bytesRead * 2] = '\n';
+        fwrite(outbuff, 1, bytesRead*2 + 1, ofP);
     }
 
-    if (count == 128) {
-      rlePutBuffer (repeat, count, repeatitem, itembuf, fout);
-      repeat = 1;
-      count = 0;
+    fclose(ifP);
+    fclose(ofP);
+}
+
+
+
+static FilterFn ascii85Filter;
+
+static void
+ascii85Filter(FILE *          const ifP,
+              FILE *          const ofP,
+              OutputEncoder * const oeP) {
+
+    bool eof;
+    char outbuff[5];
+    unsigned long int value; /* requires 32 bits */
+    int count;
+    int outcount;
+
+    value = 0;  /* initial value */
+    count = 0;  /* initial value */
+    outcount = 0; /* initial value */
+
+    for (eof = false; !eof; ) {
+        int c;
+
+        c = fgetc(ifP);
+
+        if (c == EOF)
+            eof = true;
+        else {
+            value = value*256 + c;
+            ++count;
+
+            if (value == 0 && count == 4) {
+                putchar('z');  /* Ascii85 encoding z exception */
+                ++outcount;
+                count = 0;
+            } else if (count == 4) {
+                outbuff[4] = value % 85 + 33;  value/=85; 
+                outbuff[3] = value % 85 + 33;  value/=85;
+                outbuff[2] = value % 85 + 33;  value/=85;
+                outbuff[1] = value % 85 + 33;
+                outbuff[0] = value / 85 + 33;
+
+                fwrite(outbuff, 1, count + 1, ofP);
+                count = value = 0;
+                outcount += 5; 
+            }
+
+            if (outcount > 75) {
+                putchar('\n');
+                outcount = 0;
+            }
+        }
     }
 
-  }
+    if (count > 0) { /* EOF, flush */
+        assert (count < 4);
 
-  if (count > 0)
-    rlePutBuffer (repeat, count, repeatitem, itembuf, fout);
+        value <<= (4 - count) * 8;   value/=85;
+        outbuff[3] = value % 85 + 33;  value/=85;
+        outbuff[2] = value % 85 + 33;  value/=85;
+        outbuff[1] = value % 85 + 33;
+        outbuff[0] = value / 85 + 33;
+        outbuff[count + 1] = '\n';
 
-  fclose (fin);
-  fclose (fout);
+        fwrite(outbuff, 1, count + 2, ofP);
+    }
+
+    fclose(ifP);
+    fclose(ofP);
 }
 
 
 
 static void
-asciiHexFilter (int const fd)
-{
-  FILE   *fp;
-  int     c;
-  unsigned char inbuff[40], outbuff[81];
-  const char hexits[16] = "0123456789abcdef";
-
-  fp = fdopen (fd, "r");
-  if (fp == NULL)
-    pm_error ("Ascii Hex filter input pipe open failed");
-
-  while ((c = fread (inbuff, 1, 40, fp)) > 0) {
-    int     i;
-    for (i = 0; i < c; ++i) {
-      int const item = inbuff[i]; 
-      outbuff[i*2]   =hexits[item >> 4];
-      outbuff[i*2+1] =hexits[item & 15];
-      }
-
-    outbuff[c*2] = '\n';
-    fwrite(outbuff, 1, c*2+1, stdout);    
-  }
-
-  fclose (fp);
-  fclose (stdout);
+makePipe(int * const pipeFdArray) {
+
+    int rc;
+    rc = pipe(pipeFdArray);
+    if (rc == -1)
+        pm_error("pipe() failed, errno = %d (%s)", errno, strerror(errno));
 }
 
 
 
 static void
-ascii85Filter (int const fd) {
-  FILE   *fp;
-  int     c;
-  char outbuff[5];
-  unsigned long int value=0; /* requires 32 bits */
-  int count=0;
-  int outcount=0;
-
-  fp = fdopen (fd, "r");
-  if (fp == NULL)
-    pm_error ("Ascii 85 filter input pipe open failed");
-
-  while ((c = fgetc (fp)) !=EOF) {
-    value = value*256 + c;
-    count++;
-
-    if (value == 0 && count == 4) {
-      putchar('z');  /* Ascii85 encoding z exception */
-      outcount++;
-      count=0;
-    }
-    else if (count == 4) {
+closeAllBut(int const saveFd0,
+            int const saveFd1,
+            int const saveFd2) {
+/*----------------------------------------------------------------------------
+   Close every file descriptor in this process except 'saveFd0',
+   'saveFd1', and 'saveFd2'.
 
-      outbuff[4] = value % 85 + 33;  value/=85; 
-      outbuff[3] = value % 85 + 33;  value/=85;
-      outbuff[2] = value % 85 + 33;  value/=85;
-      outbuff[1] = value % 85 + 33;
-      outbuff[0] = value / 85 + 33;
+   This is helpful because even if this process doesn't touch other file
+   desriptors, its very existence will keep the files open.
+-----------------------------------------------------------------------------*/
+    
+    /* Unix provides no good way to do this; we just assume file descriptors
+       above 9 are not used in this program; Caller must ensure that is true.
+    */
+    int fd;
 
-      fwrite(outbuff, 1, count+1, stdout);
-      count = value = 0;
-      outcount+=5; 
+    for (fd = 0; fd < 10; ++fd) {
+        if (fd != saveFd0 && fd != saveFd1 && fd != saveFd2)
+            close(fd);
     }
+}
 
-    if (outcount > 75) {
-      putchar('\n');
-      outcount=0;
-    }
-  }
 
-  if (count >0) { /* EOF, flush */
-    assert (count < 4 );
 
-    value <<= ( 4 - count ) * 8;   value/=85;
-    outbuff[3] = value % 85 + 33;  value/=85;
-    outbuff[2] = value % 85 + 33;  value/=85;
-    outbuff[1] = value % 85 + 33;
-    outbuff[0] = value / 85 + 33;
-    outbuff[count+1] = '\n';
+static void
+spawnFilter(FILE *          const ofP,
+            FilterFn *      const filterFn,
+            OutputEncoder * const oeP,
+            FILE **         const feedFilePP,
+            pid_t *         const pidP) {
+/*----------------------------------------------------------------------------
+   Fork a child process to run filter function 'filterFn' and send its
+   output to *ofP.
 
-    fwrite(outbuff, 1, count+2, stdout);
-  }
+   Create a pipe for feeding the filter and return as *feedFilePP the
+   stream to which Caller can write to push stuff into the filter.
 
-  fclose (fp);
-  fclose (stdout);
-}
+   *oeP is the parameter to 'filterFn'.
+-----------------------------------------------------------------------------*/
+    int pipeFd[2];
+    pid_t rc;
 
+    makePipe(pipeFd);
+    
+    rc = fork();
 
-/*
-Open pipes and spawn child processes
+    if (rc == (pid_t)-1)
+        pm_error("fork() of filter process failed.  errno=%d (%s)", 
+                 errno, strerror(errno));
+    else if (rc == 0) {
+        /* This is the child process */
+ 
+        FILE * ifP;
 
-Each filter is a separate child process.  The parent process feeds
-raster data into the pipeline.
+        ifP = fdopen(pipeFd[0], "r");
 
-  convertRow | asciiHexFilter
-  convertRow | ascii85Filter
-  convertRow | rleFilter   | asciiHexFilter
-  convertRow | flateFilter | asciiHexFilter
-  convertRow | flateFilter | rleFilter | asciiHexFilter
+        if (!ifP)
+            pm_error("filter process failed to make "
+                     "file stream (\"FILE\") "
+                     "out of the file descriptor which is input to the "
+                     "filter.  errno=%d (%s)",
+                     errno, strerror(errno));
 
-When adding functionality, it should be done by writing new filters,
-amending existing filters and/or the convertRow functions.  The
-following activate*Filter functions and the bit accumulator functions
-should be kept as simple as possible.
+        closeAllBut(fileno(ifP), fileno(ofP), STDERR_FILENO);
 
-*/
+        filterFn(ifP, ofP, oeP);
 
+        exit(EXIT_SUCCESS);
+    } else {
+        /* This is the parent process */
 
-static void
-activateOneFilter (int * const feedP, OutputEncoder * const oeP)
-{
-  int     p1[2];
-  /* open pipe */
-
-  if (pipe (p1) == -1) {
-    pm_error ("pipe() failed");
-    exit (1);
-  }
-
-  switch (oeP->pid[0] = fork ()) {
-  case -1:          /* error */
-    pm_error("fork() of filter process failed.  errno=%d (%s)", 
-          errno, strerror(errno));
-    exit (EXIT_FAILURE);
-    break;
-
-  case 0:           /* child */
-    close (p1[1]);
-    if(oeP->output==Ascii85)
-      ascii85Filter (p1[0]);
-    else
-      asciiHexFilter (p1[0]);
+        pid_t const childPid = rc;
+
+        close(pipeFd[0]);
 
-    exit (EXIT_SUCCESS);
-    break;
-  }
+        *feedFilePP = fdopen(pipeFd[1], "w");
 
-  /* parent (Neither child comes here) */
-  close (p1[0]);
-  *feedP = p1[1];
-  oeP->pid[1] = oeP->pid[2] = 0;
+        *pidP = childPid;
+    }
 }
 
 
 
 static void
-activateTwoFilters (int * const feedP, OutputEncoder * const oeP)
-{
-  int     p1[2], p2[2];
-  /* open pipes */
-
-  if (pipe (p1) == -1) {
-    pm_error ("pipe() failed");
-    exit (1);
-  }
-
-  if (pipe (p2) == -1) {
-    pm_error ("pipe() failed");
-    exit (1);
-  }
-
-  switch (oeP->pid[0] = fork ()) {
-  case -1:          /* error */
-    pm_error("fork() of filter process failed.  errno=%d (%s)", 
-          errno, strerror(errno));
-    exit (EXIT_FAILURE);
-    break;
-
-  case 0:           /* child */
-    close (p1[1]);
-    close (p2[0]);
-
-    switch(oeP->compress) {
-    case(Runlength):
-      rleFilter (p1[0], p2[1], oeP);
-      break;
-    case(Flate):
-      flateFilter (p1[0], p2[1], oeP);
-      break;
-    default:
-      /* error */
-      break;
-    }
+addFilter(const char *    const description,
+          FilterFn *      const filter,
+          OutputEncoder * const oeP,
+          FILE **         const feedFilePP,
+          pid_t *         const pidList) {
 
-    exit (EXIT_SUCCESS);
-    break;
-  }
+    pid_t pid;
 
-  switch (oeP->pid[1] = fork ()) {
-  case -1:          /* error */
-    pm_error("fork() of filter process failed.  errno=%d (%s)", 
-          errno, strerror(errno));
-    exit (EXIT_FAILURE);
-    break;
+    FILE * const oldFeedFileP = *feedFilePP;
 
-  case 0:           /* child */
-    close (p1[0]);     close (p1[1]);     close (p2[1]);
+    FILE * newFeedFileP;
+        
+    spawnFilter(oldFeedFileP, filter, oeP, &newFeedFileP, &pid);
+            
+    if (verbose)
+        pm_message("%s filter spawned: pid %u",
+                   description, (unsigned)pid);
+    
+    fclose(oldFeedFileP);  /* Child keeps this open now */
+    
+    addToPidList(pidList, pid);
 
-    if(oeP->output==Ascii85)
-      ascii85Filter (p2[0]);
-    else
-      asciiHexFilter (p2[0]);
-
-    exit (EXIT_SUCCESS);
-    break;
-  }
-  /* parent (Neither child comes here) */
-  close (p1[0]);  close (p2[0]);  close (p2[1]);
-  *feedP = p1[1];
-  oeP->pid[2] = 0;
+    *feedFilePP = newFeedFileP;
 }
 
 
 
 static void
-activateThreeFilters (int * const feedP, OutputEncoder * const oeP)
-{
-  int     p1[2], p2[2], p3[2];
-  /* open pipes */
-
-  if (pipe (p1) == -1) {
-    pm_error ("pipe() failed");
-    exit (1);
-  }
-
-  if (pipe (p2) == -1) {
-    pm_error ("pipe() failed");
-    exit (1);
-  }
-
-  if (pipe (p3) == -1) {
-    pm_error ("pipe() failed");
-    exit (1);
-  }
-
-  switch (oeP->pid[0] = fork ()) {
-  case -1:          /* error */
-    pm_error("fork() of filter process failed.  errno=%d (%s)", 
-          errno, strerror(errno));
-    exit (EXIT_FAILURE);
-    break;
-
-  case 0:           /* child */
-    close (p1[1]);    close (p2[0]);    close (p3[0]);    close (p3[1]);
-    rleFilter (p1[0], p2[1], oeP);
-    exit (EXIT_SUCCESS);
-    break;
-  }
-
-  switch (oeP->pid[1] = fork ()) {
-  case -1:          /* error */
-    pm_error("fork() of filter process failed.  errno=%d (%s)", 
-          errno, strerror(errno));
-    exit (EXIT_FAILURE);
-    break;
-
-  case 0:           /* child */
-    close (p1[0]);    close (p1[1]);    close (p2[1]);    close (p3[0]);
-    flateFilter(p2[0], p3[1], oeP);
-    exit (EXIT_SUCCESS);
-    break;
-  }
-
-  switch (oeP->pid[2] = fork ()) {
-  case -1:          /* error */
-    pm_error("fork() of filter process failed.  errno=%d (%s)", 
-          errno, strerror(errno));
-    exit (EXIT_FAILURE);
-    break;
-
-  case 0:           /* child */
-    close (p1[0]);    close (p1[1]);    close (p2[0]);    close (p2[1]);
-    close (p3[1]);
-
-    if(oeP->output==Ascii85)
-      ascii85Filter (p3[0]);
-    else
-      asciiHexFilter (p3[0]);
+spawnFilters(FILE *          const ofP,
+             OutputEncoder * const oeP,
+             FILE **         const feedFilePP,
+             pid_t *         const pidList) {
+/*----------------------------------------------------------------------------
+   Get all the child processes for the filters running and connected.
+   Return at *feedFileP the file stream to which to write the raw data,
+   with the filtered data going to *ofP.
 
-    exit (EXIT_SUCCESS);
-    break;
-  }
+   Filter according to *oeP.
+-----------------------------------------------------------------------------*/
 
-  /* parent (Neither child comes here) */
-  close (p1[0]);  close (p2[0]);  close (p2[1]);
-  close (p3[0]);  close (p3[1]);
-  *feedP = p1[1];
-}
+    /* Build up the pipeline from the final to the initial stage.  The
+       result is one of:
 
+          FEED | convertRow | asciiHexFilter | *ofP
+          FEED | convertRow | ascii85Filter | *ofP
+          FEED | convertRow | rleFilter   | asciiHexFilter | *ofP
+          FEED | convertRow | flateFilter | asciiHexFilter | *ofP
+          FEED | convertRow | flateFilter | rleFilter | asciiHexFilter | *ofP
+    */
 
-static void
-activateFilters (int * const feedP, OutputEncoder * const oeP){
-
-  switch(oeP->compress) {
-  case none:
-    activateOneFilter(feedP, oeP);
-    break;
-  case RunlengthFlate:
-    activateThreeFilters(feedP, oeP);
-    break;
-  default:
-    activateTwoFilters(feedP, oeP);
-  }
+    FILE * feedFileP;
+        /* The current head of the filter chain; changes as we add filters */
+
+    initPidList(pidList);
+
+    feedFileP = ofP;  /* Initial state: no filter at all */
+
+    addFilter(
+        "output",
+        oeP->outputType == Ascii85 ? &ascii85Filter : asciiHexFilter,
+        oeP,
+        &feedFileP,
+        pidList);
+
+    if (oeP->compressFlate)
+        addFilter("flate", flateFilter, oeP, &feedFileP, pidList);
+
+    if (oeP->compressRle)
+        addFilter("rle", rleFilter, oeP, &feedFileP, pidList);
+
+    *feedFilePP = feedFileP;
 }
 
+
+
 static void
-waitForChildren(int * const pid) {
-
-  int i;
-  int status;
-
-  for (i = 0; i < 3; ++i) {
-    if (pid[i] != 0) {
-      if (waitpid (pid[i], &status, 0) == -1) {
-    pm_error ("waitpid() failed");
-    exit (EXIT_FAILURE);
-      }
-      else if (status != EXIT_SUCCESS) {
-    pm_error ("Child process terminated abnoramally");
-    exit (EXIT_FAILURE);
-      }
+waitForChildren(const pid_t * const pidList) {
+/*----------------------------------------------------------------------------
+   Wait for all child processes with PIDs in pidList[] to exit.
+   In pidList[], end-of-list is marked with a special zero value.
+-----------------------------------------------------------------------------*/
+    unsigned int i;
+
+    for (i = 0; pidList[i]; ++i) {
+        pid_t rc;
+        int status;
+
+        if (verbose)
+            pm_message("Waiting for PID %u to exit", (unsigned)pidList[i]);
+
+        rc = waitpid(pidList[i], &status, 0);
+        if (rc == -1)
+            pm_error ("waitpid() for child %u failed", i);
+        else if (status != EXIT_SUCCESS)
+            pm_error ("Child process %u terminated abnormally", i);
     }
-  }
+    if (verbose)
+        pm_message("All children have exited");
 }
+
+
+
 /*============================================================================
-   END OF OUTPUT ENCODERS
+  END OF OUTPUT ENCODERS
 ============================================================================*/
 
 
 
 static void
 validateComputableBoundingBox(float const scols, 
-                  float const srows,
-                  float const llx, 
-                  float const lly) {
-
-  float const bbWidth  = llx + scols + 0.5;
-  float const bbHeight = lly + srows + 0.5;
-
-  if (bbHeight < INT_MIN || bbHeight > INT_MAX ||
-      bbWidth  < INT_MIN || bbWidth  > INT_MAX)
-      pm_error("Bounding box dimensions %.1f x %.1f are too large "
-           "for computations.  "
-           "This probably means input image width, height, "
-           "or scale factor is too large", bbWidth, bbHeight);
+                              float const srows,
+                              float const llx, 
+                              float const lly) {
+
+    float const bbWidth  = llx + scols + 0.5;
+    float const bbHeight = lly + srows + 0.5;
+
+    if (bbHeight < INT_MIN || bbHeight > INT_MAX ||
+        bbWidth  < INT_MIN || bbWidth  > INT_MAX)
+        pm_error("Bounding box dimensions %.1f x %.1f are too large "
+                 "for computations.  "
+                 "This probably means input image width, height, "
+                 "or scale factor is too large", bbWidth, bbHeight);
 }
 
 
 
 static void
 computeImagePosition(int     const dpiX, 
-             int     const dpiY, 
-             int     const icols, 
-             int     const irows,
-             bool    const mustturn,
-             bool    const canturn,
-             bool    const center,
-             int     const pagewid, 
-             int     const pagehgt, 
-             float   const requestedScale,
-             float   const imagewidth,
-             float   const imageheight,
-             bool    const equalpixels,
-             float * const scolsP,
-             float * const srowsP,
-             float * const llxP, 
-             float * const llyP,
-             bool *  const turnedP ) {
+                     int     const dpiY, 
+                     int     const icols, 
+                     int     const irows,
+                     bool    const mustturn,
+                     bool    const canturn,
+                     bool    const center,
+                     int     const pagewid, 
+                     int     const pagehgt, 
+                     float   const requestedScale,
+                     float   const imagewidth,
+                     float   const imageheight,
+                     bool    const equalpixels,
+                     float * const scolsP,
+                     float * const srowsP,
+                     float * const llxP, 
+                     float * const llyP,
+                     bool *  const turnedP ) {
 /*----------------------------------------------------------------------------
-   Determine where on the page the image is to go.  This means position,
-   dimensions, and orientation.
+  Determine where on the page the image is to go.  This means position,
+  dimensions, and orientation.
 
-   icols/irows are the dimensions of the PNM input in xels.
+  icols/irows are the dimensions of the PNM input in xels.
 
-   'mustturn' means we are required to rotate the image.
+  'mustturn' means we are required to rotate the image.
 
-   'canturn' means we may rotate the image if it fits better, but don't
-   have to.
+  'canturn' means we may rotate the image if it fits better, but don't
+  have to.
 
-   *scolsP, *srowsP are the dimensions of the image in 1/72 inch.
+  *scolsP, *srowsP are the dimensions of the image in 1/72 inch.
 
-   *llxP, *llyP are the coordinates, in 1/72 inch, of the lower left
-   corner of the image on the page.
+  *llxP, *llyP are the coordinates, in 1/72 inch, of the lower left
+  corner of the image on the page.
 
-   *turnedP is true iff the image is to be rotated 90 degrees on the page.
+  *turnedP is true iff the image is to be rotated 90 degrees on the page.
 
-   imagewidth/imageheight are the requested dimensions of the image on
-   the page, in 1/72 inch.  Image will be as large as possible within
-   those dimensions.  Zero means unspecified, so 'scale', 'pagewid',
-   'pagehgt', 'irows', and 'icols' determine image size.
+  imagewidth/imageheight are the requested dimensions of the image on
+  the page, in 1/72 inch.  Image will be as large as possible within
+  those dimensions.  Zero means unspecified, so 'scale', 'pagewid',
+  'pagehgt', 'irows', and 'icols' determine image size.
 
-   'equalpixels' means the user wants one printed pixel per input pixel.
-   It is inconsistent with imagewidth or imageheight != 0
+  'equalpixels' means the user wants one printed pixel per input pixel.
+  It is inconsistent with imagewidth or imageheight != 0
 
-   'requestedScale' is meaningful only when imageheight/imagewidth == 0
-   and equalpixels == FALSE.  It tells how many inches the user wants
-   72 pixels of input to occupy, if it fits on the page.
+  'requestedScale' is meaningful only when imageheight/imagewidth == 0
+  and equalpixels == FALSE.  It tells how many inches the user wants
+  72 pixels of input to occupy, if it fits on the page.
 -----------------------------------------------------------------------------*/
     int cols, rows;
     /* Number of columns, rows of input xels in the output, as
@@ -973,65 +1047,65 @@ computeImagePosition(int     const dpiX,
     bool shouldturn;  /* The image fits the page better if we turn it */
     
     if (icols > irows && pagehgt > pagewid)
-    shouldturn = TRUE;
+        shouldturn = TRUE;
     else if (irows > icols && pagewid > pagehgt)
-    shouldturn = TRUE;
+        shouldturn = TRUE;
     else
-    shouldturn = FALSE;
+        shouldturn = FALSE;
 
     if (mustturn || (canturn && shouldturn)) {
-    *turnedP = TRUE;
-    cols = irows;
-    rows = icols;
+        *turnedP = TRUE;
+        cols = irows;
+        rows = icols;
     } else {
-    *turnedP = FALSE;
-    cols = icols;
-    rows = irows;
+        *turnedP = FALSE;
+        cols = icols;
+        rows = irows;
     }
     if (equalpixels) {
-    *scolsP = (72.0/dpiX)*cols;
-    *srowsP = (72.0/dpiY)*rows;
+        *scolsP = (72.0/dpiX)*cols;
+        *srowsP = (72.0/dpiY)*rows;
     } else if (imagewidth > 0 || imageheight > 0) {
-    float scale;
+        float scale;
 
-    if (imagewidth == 0)
-        scale = (float) imageheight/rows;
-    else if (imageheight == 0)
-        scale = (float) imagewidth/cols;
-    else
-        scale = MIN((float)imagewidth/cols, (float)imageheight/rows);
+        if (imagewidth == 0)
+            scale = (float) imageheight/rows;
+        else if (imageheight == 0)
+            scale = (float) imagewidth/cols;
+        else
+            scale = MIN((float)imagewidth/cols, (float)imageheight/rows);
     
-    *scolsP = cols*scale;
-    *srowsP = rows*scale;
+        *scolsP = cols*scale;
+        *srowsP = rows*scale;
     } else {
-    /* He didn't give us a bounding box for the image so figure
-       out output image size from other inputs.
-    */
-    const int devpixX = dpiX / 72.0 + 0.5;        
-    const int devpixY = dpiY / 72.0 + 0.5;        
+        /* He didn't give us a bounding box for the image so figure
+           out output image size from other inputs.
+        */
+        const int devpixX = dpiX / 72.0 + 0.5;        
+        const int devpixY = dpiY / 72.0 + 0.5;        
         /* How many device pixels make up 1/72 inch, rounded to
            nearest integer */
-    const float pixfacX = 72.0 / dpiX * devpixX;  /* 1, approx. */
-    const float pixfacY = 72.0 / dpiY * devpixY;  /* 1, approx. */
-    float scale;
+        const float pixfacX = 72.0 / dpiX * devpixX;  /* 1, approx. */
+        const float pixfacY = 72.0 / dpiY * devpixY;  /* 1, approx. */
+        float scale;
 
-    scale = MIN(requestedScale, 
-            MIN((float)pagewid/cols, (float)pagehgt/rows));
+        scale = MIN(requestedScale, 
+                    MIN((float)pagewid/cols, (float)pagehgt/rows));
 
-    *scolsP = scale * cols * pixfacX;
-    *srowsP = scale * rows * pixfacY;
+        *scolsP = scale * cols * pixfacX;
+        *srowsP = scale * rows * pixfacY;
     
-    if (scale != requestedScale)
-        pm_message("warning, image too large for page, rescaling to %g", 
-               scale );
-
-    /* Before May 2001, Pnmtops enforced a 5% margin around the page.
-       If the image would be too big to leave a 5% margin, Pnmtops would
-       scale it down.  But people have images that are exactly the size
-       of a page, e.g. because they created them with Sane's 'scanimage'
-       program from a full page of input.  So we removed the gratuitous
-       5% margin.  -Bryan.
-    */
+        if (scale != requestedScale)
+            pm_message("warning, image too large for page, rescaling to %g", 
+                       scale );
+
+        /* Before May 2001, Pnmtops enforced a 5% margin around the page.
+           If the image would be too big to leave a 5% margin, Pnmtops would
+           scale it down.  But people have images that are exactly the size
+           of a page, e.g. because they created them with Sane's 'scanimage'
+           program from a full page of input.  So we removed the gratuitous
+           5% margin.  -Bryan.
+        */
     }
     *llxP = (center) ? ( pagewid - *scolsP ) / 2 : 0;
     *llyP = (center) ? ( pagehgt - *srowsP ) / 2 : 0;
@@ -1039,30 +1113,30 @@ computeImagePosition(int     const dpiX,
     validateComputableBoundingBox( *scolsP, *srowsP, *llxP, *llyP);
 
     if (verbose)
-    pm_message("Image will be %3.2f points wide by %3.2f points high, "
-           "left edge %3.2f points from left edge of page, "
-           "bottom edge %3.2f points from top of page; "
-           "%sturned to landscape orientation",
-           *scolsP, *srowsP, *llxP, *llyP, *turnedP ? "" : "NOT ");
+        pm_message("Image will be %3.2f points wide by %3.2f points high, "
+                   "left edge %3.2f points from left edge of page, "
+                   "bottom edge %3.2f points from top of page; "
+                   "%sturned to landscape orientation",
+                   *scolsP, *srowsP, *llxP, *llyP, *turnedP ? "" : "NOT ");
 }
 
 
 
 static void
 determineDictionaryRequirement(bool           const userWantsDict,
-                   bool           const psFilter,
-                   unsigned int * const dictSizeP) {
+                               bool           const psFilter,
+                               unsigned int * const dictSizeP) {
 
     if (userWantsDict) {
-    if (psFilter) {
-        /* The Postscript this program generates to use built-in
-           Postscript filters does not define any variables.
-        */
-        *dictSizeP = 0;
-    } else
-        *dictSizeP = 8;
+        if (psFilter) {
+            /* The Postscript this program generates to use built-in
+               Postscript filters does not define any variables.
+            */
+            *dictSizeP = 0;
+        } else
+            *dictSizeP = 8;
     } else
-    *dictSizeP = 0;
+        *dictSizeP = 0;
 }
 
 
@@ -1070,45 +1144,45 @@ determineDictionaryRequirement(bool           const userWantsDict,
 static void
 defineReadstring(bool const rle) {
 /*----------------------------------------------------------------------------
-   Write to Standard Output Postscript statements to define /readstring.
+  Write to Standard Output Postscript statements to define /readstring.
 -----------------------------------------------------------------------------*/
     if (rle) {
-    printf("/rlestr1 1 string def\n");
-    printf("/readrlestring {\n");             /* s -- nr */
-    printf("  /rlestr exch def\n");           /* - */
-    printf("  currentfile rlestr1 readhexstring pop\n");  /* s1 */
-    printf("  0 get\n");                  /* c */
-    printf("  dup 127 le {\n");               /* c */
-    printf("    currentfile rlestr 0\n");         /* c f s 0 */
-    printf("    4 3 roll\n");             /* f s 0 c */
-    printf("    1 add  getinterval\n");           /* f s */
-    printf("    readhexstring pop\n");            /* s */
-    printf("    length\n");               /* nr */
-    printf("  } {\n");                    /* c */
-    printf("    257 exch sub dup\n");         /* n n */
-    printf("    currentfile rlestr1 readhexstring pop\n");/* n n s1 */
-    printf("    0 get\n");                /* n n c */
-    printf("    exch 0 exch 1 exch 1 sub {\n");       /* n c 0 1 n-1*/
-    printf("      rlestr exch 2 index put\n");
-    printf("    } for\n");                /* n c */
-    printf("    pop\n");                  /* nr */
-    printf("  } ifelse\n");               /* nr */
-    printf("} bind def\n");
-    printf("/readstring {\n");                /* s -- s */
-    printf("  dup length 0 {\n");             /* s l 0 */
-    printf("    3 copy exch\n");              /* s l n s n l*/
-    printf("    1 index sub\n");              /* s l n s n r*/
-    printf("    getinterval\n");              /* s l n ss */
-    printf("    readrlestring\n");            /* s l n nr */
-    printf("    add\n");                  /* s l n */
-    printf("    2 copy le { exit } if\n");        /* s l n */
-    printf("  } loop\n");                 /* s l l */
-    printf("  pop pop\n");                /* s */
-    printf("} bind def\n");
+        printf("/rlestr1 1 string def\n");
+        printf("/readrlestring {\n");             /* s -- nr */
+        printf("  /rlestr exch def\n");           /* - */
+        printf("  currentfile rlestr1 readhexstring pop\n");  /* s1 */
+        printf("  0 get\n");                  /* c */
+        printf("  dup 127 le {\n");               /* c */
+        printf("    currentfile rlestr 0\n");         /* c f s 0 */
+        printf("    4 3 roll\n");             /* f s 0 c */
+        printf("    1 add  getinterval\n");           /* f s */
+        printf("    readhexstring pop\n");            /* s */
+        printf("    length\n");               /* nr */
+        printf("  } {\n");                    /* c */
+        printf("    257 exch sub dup\n");         /* n n */
+        printf("    currentfile rlestr1 readhexstring pop\n");/* n n s1 */
+        printf("    0 get\n");                /* n n c */
+        printf("    exch 0 exch 1 exch 1 sub {\n");       /* n c 0 1 n-1*/
+        printf("      rlestr exch 2 index put\n");
+        printf("    } for\n");                /* n c */
+        printf("    pop\n");                  /* nr */
+        printf("  } ifelse\n");               /* nr */
+        printf("} bind def\n");
+        printf("/readstring {\n");                /* s -- s */
+        printf("  dup length 0 {\n");             /* s l 0 */
+        printf("    3 copy exch\n");              /* s l n s n l*/
+        printf("    1 index sub\n");              /* s l n s n r*/
+        printf("    getinterval\n");              /* s l n ss */
+        printf("    readrlestring\n");            /* s l n nr */
+        printf("    add\n");                  /* s l n */
+        printf("    2 copy le { exit } if\n");        /* s l n */
+        printf("  } loop\n");                 /* s l l */
+        printf("  pop pop\n");                /* s */
+        printf("} bind def\n");
     } else {
-    printf("/readstring {\n");                /* s -- s */
-    printf("  currentfile exch readhexstring pop\n");
-    printf("} bind def\n");
+        printf("/readstring {\n");                /* s -- s */
+        printf("  currentfile exch readhexstring pop\n");
+        printf("} bind def\n");
     }
 }
 
@@ -1116,47 +1190,50 @@ defineReadstring(bool const rle) {
 
 static void
 setupReadstringNative(bool         const rle,
-              bool         const color,
-              unsigned int const icols, 
-              unsigned int const bitsPerSample) {
+                      bool         const color,
+                      unsigned int const icols, 
+                      unsigned int const bitsPerSample) {
 /*----------------------------------------------------------------------------
-   Write to Standard Output statements to define /readstring and also
-   arguments for it (/picstr or /rpicstr, /gpicstr, and /bpicstr).
+  Write to Standard Output statements to define /readstring and also
+  arguments for it (/picstr or /rpicstr, /gpicstr, and /bpicstr).
 -----------------------------------------------------------------------------*/
     unsigned int const bytesPerRow = icols / (8/bitsPerSample) +
-    (icols % (8/bitsPerSample) > 0 ? 1 : 0);
-    /* Size of row buffer, padded up to byte boundary. */
+        (icols % (8/bitsPerSample) > 0 ? 1 : 0);
+        /* Size of row buffer, padded up to byte boundary. */
 
     defineReadstring(rle);
     
     if (color) {
-    printf("/rpicstr %d string def\n", bytesPerRow);
-    printf("/gpicstr %d string def\n", bytesPerRow);
-    printf("/bpicstr %d string def\n", bytesPerRow);
+        printf("/rpicstr %d string def\n", bytesPerRow);
+        printf("/gpicstr %d string def\n", bytesPerRow);
+        printf("/bpicstr %d string def\n", bytesPerRow);
     } else
-    printf("/picstr %d string def\n", bytesPerRow);
+        printf("/picstr %d string def\n", bytesPerRow);
 }
 
 
 
 static void
 putFilters(unsigned int const postscriptLevel,
-       bool         const rle,
-       bool         const flate,
-       bool         const ascii85,
-       bool         const color) {
+           bool         const rle,
+           bool         const flate,
+           bool         const ascii85,
+           bool         const color) {
 
     assert(postscriptLevel > 1);
     
+    /* We say to decode flate, then rle, so Caller must ensure it encodes
+       rel, then flate.
+    */
+
     if (ascii85)
-    printf("/ASCII85Decode filter ");
+        printf("/ASCII85Decode filter ");
     else 
-    printf("/ASCIIHexDecode filter ");
+        printf("/ASCIIHexDecode filter ");
     if (flate)
-    printf("/FlateDecode filter ");
-    if (rle) /* activateThreeFilters() encodes rle before flate,
-        so decode must be flate then rle */
-    printf("/RunLengthDecode filter ");
+        printf("/FlateDecode filter ");
+    if (rle) 
+        printf("/RunLengthDecode filter ");
 }
 
 
@@ -1165,33 +1242,33 @@ static void
 putReadstringNative(bool const color) {
 
     if (color) {
-    printf("{ rpicstr readstring }\n");
-    printf("{ gpicstr readstring }\n");
-    printf("{ bpicstr readstring }\n");
+        printf("{ rpicstr readstring }\n");
+        printf("{ gpicstr readstring }\n");
+        printf("{ bpicstr readstring }\n");
     } else
-    printf("{ picstr readstring }\n");
+        printf("{ picstr readstring }\n");
 }
 
 
 
 static void
 putSetup(unsigned int const dictSize,
-     bool         const psFilter,
-     bool         const rle,
-     bool         const color,
-     unsigned int const icols,
-     unsigned int const bitsPerSample) {
+         bool         const psFilter,
+         bool         const rle,
+         bool         const color,
+         unsigned int const icols,
+         unsigned int const bitsPerSample) {
 /*----------------------------------------------------------------------------
-   Put the setup section in the Postscript program on Standard Output.
+  Put the setup section in the Postscript program on Standard Output.
 -----------------------------------------------------------------------------*/
     printf("%%%%BeginSetup\n");
 
     if (dictSize > 0)
-    /* inputf {r,g,b,}pictsr readstring readrlestring rlestring */
-    printf("%u dict begin\n", dictSize);
+        /* inputf {r,g,b,}pictsr readstring readrlestring rlestring */
+        printf("%u dict begin\n", dictSize);
     
     if (!psFilter)
-    setupReadstringNative(rle, color, icols, bitsPerSample);
+        setupReadstringNative(rle, color, icols, bitsPerSample);
 
     printf("%%%%EndSetup\n");
 }
@@ -1200,29 +1277,29 @@ putSetup(unsigned int const dictSize,
 
 static void
 putImage(bool const psFilter,
-     bool const color) {
+         bool const color) {
 /*----------------------------------------------------------------------------
-   Put the image/colorimage statement in the Postscript program on
-   Standard Output.
+  Put the image/colorimage statement in the Postscript program on
+  Standard Output.
 -----------------------------------------------------------------------------*/
     if (color) {
-    if (psFilter)
-        printf("false 3\n");
-    else
-        printf("true 3\n");
-    printf("colorimage");
+        if (psFilter)
+            printf("false 3\n");
+        else
+            printf("true 3\n");
+        printf("colorimage");
     } else
-    printf("image");
+        printf("image");
 }
 
 
 
 static void
 putInitPsFilter(unsigned int const postscriptLevel,
-        bool         const rle,
-        bool         const flate,
-        bool         const ascii85,
-        bool         const color) {
+                bool         const rle,
+                bool         const flate,
+                bool         const ascii85,
+                bool         const color) {
 
     bool const filterTrue = TRUE;
 
@@ -1251,27 +1328,27 @@ putInitReadstringNative(bool const color) {
 
 static void
 putInit(unsigned int const postscriptLevel,
-    char         const name[], 
-    int          const icols, 
-    int          const irows, 
-    float        const scols, 
-    float        const srows,
-    float        const llx, 
-    float        const lly,
-    int          const bitsPerSample,
-    int          const pagewid, 
-    int          const pagehgt,
-    bool         const color, 
-    bool         const turned, 
-    bool         const rle,
-    bool         const flate,
-    bool         const ascii85,
-    bool         const setpage,
-    bool         const psFilter,
-    unsigned int const dictSize) {
+        char         const name[], 
+        int          const icols, 
+        int          const irows, 
+        float        const scols, 
+        float        const srows,
+        float        const llx, 
+        float        const lly,
+        int          const bitsPerSample,
+        int          const pagewid, 
+        int          const pagehgt,
+        bool         const color, 
+        bool         const turned, 
+        bool         const rle,
+        bool         const flate,
+        bool         const ascii85,
+        bool         const setpage,
+        bool         const psFilter,
+        unsigned int const dictSize) {
 /*----------------------------------------------------------------------------
-   Write out to Standard Output the headers stuff for the Postscript
-   program (everything up to the raster).
+  Write out to Standard Output the headers stuff for the Postscript
+  program (everything up to the raster).
 -----------------------------------------------------------------------------*/
     /* The numbers in the %! line often confuse people. They are NOT the
        PostScript language level.  The first is the level of the DSC comment
@@ -1285,29 +1362,29 @@ putInit(unsigned int const postscriptLevel,
     printf("%%%%Title: %s.ps\n", name);
     printf("%%%%Pages: 1\n");
     printf(
-    "%%%%BoundingBox: %d %d %d %d\n",
-    (int) llx, (int) lly,
-    (int) (llx + scols + 0.5), (int) (lly + srows + 0.5));
+        "%%%%BoundingBox: %d %d %d %d\n",
+        (int) llx, (int) lly,
+        (int) (llx + scols + 0.5), (int) (lly + srows + 0.5));
     printf("%%%%EndComments\n");
 
     putSetup(dictSize, psFilter, rle, color, icols, bitsPerSample);
 
     printf("%%%%Page: 1 1\n");
     if (setpage)
-    printf("<< /PageSize [ %d %d ] /ImagingBBox null >> setpagedevice\n",
-           pagewid, pagehgt);
+        printf("<< /PageSize [ %d %d ] /ImagingBBox null >> setpagedevice\n",
+               pagewid, pagehgt);
     printf("gsave\n");
     printf("%g %g translate\n", llx, lly);
     printf("%g %g scale\n", scols, srows);
     if (turned)
-    printf("0.5 0.5 translate  90 rotate  -0.5 -0.5 translate\n");
+        printf("0.5 0.5 translate  90 rotate  -0.5 -0.5 translate\n");
     printf("%d %d %d\n", icols, irows, bitsPerSample);
     printf("[ %d 0 0 -%d 0 %d ]\n", icols, irows, irows);
 
     if (psFilter)
-    putInitPsFilter(postscriptLevel, rle, flate, ascii85, color);
+        putInitPsFilter(postscriptLevel, rle, flate, ascii85, color);
     else
-    putInitReadstringNative(color);
+        putInitReadstringNative(color);
 
     printf("\n");
     fflush(stdout);
@@ -1323,28 +1400,28 @@ putEnd(bool         const showpage,
        bool         const vmreclaim) {
 
     if (psFilter) {
-    if (ascii85)
-        printf("%s\n", "~>");
-    else
-        printf("%s\n", ">");
+        if (ascii85)
+            printf("%s\n", "~>");
+        else
+            printf("%s\n", ">");
     } else {
-    printf("currentdict /inputf undef\n");
-    printf("currentdict /picstr undef\n");
-    printf("currentdict /rpicstr undef\n");
-    printf("currentdict /gpicstr undef\n");
-    printf("currentdict /bpicstr undef\n");
+        printf("currentdict /inputf undef\n");
+        printf("currentdict /picstr undef\n");
+        printf("currentdict /rpicstr undef\n");
+        printf("currentdict /gpicstr undef\n");
+        printf("currentdict /bpicstr undef\n");
     }
 
     if (dictSize > 0)
-    printf("end\n");
+        printf("end\n");
 
     if (vmreclaim)
-    printf("1 vmreclaim\n");
+        printf("1 vmreclaim\n");
 
     printf("grestore\n");
 
     if (showpage)
-    printf("showpage\n");
+        printf("showpage\n");
     printf("%%%%Trailer\n");
 }
 
@@ -1352,46 +1429,46 @@ putEnd(bool         const showpage,
 
 static void
 validateBpsRequest(unsigned int const bitsPerSampleReq,
-           unsigned int const postscriptLevel,
-           bool         const psFilter) {
+                   unsigned int const postscriptLevel,
+                   bool         const psFilter) {
 
     if (postscriptLevel < 2 && bitsPerSampleReq > 8)
-    pm_error("You requested %u bits per sample, but in Postscript "
-         "level 1, 8 is the maximum.  You can get 12 with "
-         "-level 2 and -psfilter", bitsPerSampleReq);
+        pm_error("You requested %u bits per sample, but in Postscript "
+                 "level 1, 8 is the maximum.  You can get 12 with "
+                 "-level 2 and -psfilter", bitsPerSampleReq);
     else if (!psFilter && bitsPerSampleReq > 8)
-    pm_error("You requested %u bits per sample, but without "
-         "-psfilter, the maximum is 8", bitsPerSampleReq);
+        pm_error("You requested %u bits per sample, but without "
+                 "-psfilter, the maximum is 8", bitsPerSampleReq);
 }
 
     
 
 static unsigned int
 bpsFromInput(unsigned int const bitsRequiredByMaxval,
-         unsigned int const postscriptLevel,
-         bool         const psFilter) {
+             unsigned int const postscriptLevel,
+             bool         const psFilter) {
 
     unsigned int retval;
 
     if (bitsRequiredByMaxval <= 1)
-    retval = 1;
+        retval = 1;
     else if (bitsRequiredByMaxval <= 2)
-    retval = 2;
+        retval = 2;
     else if (bitsRequiredByMaxval <= 4)
-    retval = 4;
+        retval = 4;
     else if (bitsRequiredByMaxval <= 8)
-    retval = 8;
-    else {
-    /* Post script level 2 defines a format with 12 bits per sample,
-       but I don't know the details of that format (both RLE and
-       non-RLE variations) and existing native raster generation code
-       simply can't handle bps > 8.  But the built-in filters know
-       how to do 12 bps.
-    */
-    if (postscriptLevel >= 2 && psFilter)
-        retval = 12;
-    else
         retval = 8;
+    else {
+        /* Post script level 2 defines a format with 12 bits per sample,
+           but I don't know the details of that format (both RLE and
+           non-RLE variations) and existing native raster generation code
+           simply can't handle bps > 8.  But the built-in filters know
+           how to do 12 bps.
+        */
+        if (postscriptLevel >= 2 && psFilter)
+            retval = 12;
+        else
+            retval = 8;
     }
     return retval;
 }
@@ -1400,188 +1477,198 @@ bpsFromInput(unsigned int const bitsRequiredByMaxval,
 
 static void
 warnUserAboutReducedDepth(unsigned int const bitsGot,
-              unsigned int const bitsWanted,
-              bool         const userRequested,
-              unsigned int const postscriptLevel,
-              bool         const psFilter) {
+                          unsigned int const bitsWanted,
+                          bool         const userRequested,
+                          unsigned int const postscriptLevel,
+                          bool         const psFilter) {
 
     if (bitsGot < bitsWanted) {
-    pm_message("Postscript will have %u bits of color resolution, "
-           "though the input has %u bits.",
-           bitsGot, bitsWanted);
-
-    if (!userRequested) {
-        if (postscriptLevel < 2)
-        pm_message("Postscript level %u has a maximum depth of "
-               "8 bits.  "
-               "You could get up to 12 with -level=2 "
-               "and -psfilter.",
-               postscriptLevel);
-        else {
-        if (!psFilter)
-            pm_message("You can get up to 12 bits with -psfilter");
-        else
-            pm_message("The Postscript maximum is 12.");
+        pm_message("Postscript will have %u bits of color resolution, "
+                   "though the input has %u bits.",
+                   bitsGot, bitsWanted);
+
+        if (!userRequested) {
+            if (postscriptLevel < 2)
+                pm_message("Postscript level %u has a maximum depth of "
+                           "8 bits.  "
+                           "You could get up to 12 with -level=2 "
+                           "and -psfilter.",
+                           postscriptLevel);
+            else {
+                if (!psFilter)
+                    pm_message("You can get up to 12 bits with -psfilter");
+                else
+                    pm_message("The Postscript maximum is 12.");
+            }
         }
     }
-    }
 }
 
 
 
 static void
 computeDepth(xelval         const inputMaxval,
-         unsigned int   const postscriptLevel, 
-         bool           const psFilter,
-         unsigned int   const bitsPerSampleReq,
-         unsigned int * const bitsPerSampleP) {
+             unsigned int   const postscriptLevel, 
+             bool           const psFilter,
+             unsigned int   const bitsPerSampleReq,
+             unsigned int * const bitsPerSampleP) {
 /*----------------------------------------------------------------------------
-   Figure out how many bits will represent each sample in the Postscript
-   program, and the maxval of the Postscript program samples.  The maxval
-   is just the maximum value allowable in the number of bits.
+  Figure out how many bits will represent each sample in the Postscript
+  program, and the maxval of the Postscript program samples.  The maxval
+  is just the maximum value allowable in the number of bits.
 
-   'bitsPerSampleReq' is the bits per sample that the user requests, or
-   zero if he made no request.
+  'bitsPerSampleReq' is the bits per sample that the user requests, or
+  zero if he made no request.
 -----------------------------------------------------------------------------*/
     unsigned int const bitsRequiredByMaxval = pm_maxvaltobits(inputMaxval);
 
     if (bitsPerSampleReq != 0) {
-    validateBpsRequest(bitsPerSampleReq, postscriptLevel, psFilter);
-    *bitsPerSampleP = bitsPerSampleReq;
+        validateBpsRequest(bitsPerSampleReq, postscriptLevel, psFilter);
+        *bitsPerSampleP = bitsPerSampleReq;
     } else {
-    *bitsPerSampleP = bpsFromInput(bitsRequiredByMaxval,
-                       postscriptLevel, psFilter);
+        *bitsPerSampleP = bpsFromInput(bitsRequiredByMaxval,
+                                       postscriptLevel, psFilter);
     }
     warnUserAboutReducedDepth(*bitsPerSampleP, bitsRequiredByMaxval,
-                  bitsPerSampleReq != 0,
-                  postscriptLevel, psFilter);
+                              bitsPerSampleReq != 0,
+                              postscriptLevel, psFilter);
 
     if (verbose) {
-    unsigned int const psMaxval = pm_bitstomaxval(*bitsPerSampleP);
-    pm_message("Input maxval is %u.  Postscript raster will have "
-           "%u bits per sample, so maxval = %u",
-           inputMaxval, *bitsPerSampleP, psMaxval);
+        unsigned int const psMaxval = pm_bitstomaxval(*bitsPerSampleP);
+        pm_message("Input maxval is %u.  Postscript raster will have "
+                   "%u bits per sample, so maxval = %u",
+                   inputMaxval, *bitsPerSampleP, psMaxval);
     }
 }    
 
+
+
 /*===========================================================================
   The bit accumulator
 ===========================================================================*/
 
 typedef struct {
-  unsigned int value;
-  int consumed;
+    unsigned int value;
+    unsigned int consumed;
 } BitAccumulator;
 
 
+
+static void
+ba_init(BitAccumulator * const baP) {
+
+    baP->value    = 0;
+    baP->consumed = 0;
+}
+
+
+
 static void
-bits12_add(BitAccumulator * const baP,
-       unsigned int     const new12,
-       FILE           * const fp) {
+ba_add12(BitAccumulator * const baP,
+         unsigned int     const new12,
+         FILE           * const fP) {
 /*----------------------------------------------------------------------------
-   Read a 12-bit string into the bit accumulator baP->value.
-   On every other call, combine two 12-bit strings and write out three bytes.
+  Read a 12-bit string into the bit accumulator baP->value.
+  On every other call, combine two 12-bit strings and write out three bytes.
 -----------------------------------------------------------------------------*/
-
-  assert (baP->consumed ==12 || baP->consumed ==0);
-
-      if ( baP->consumed == 12){
-    char const oldHi8 = (baP->value) >> 4;
-    char const oldLo4 = (baP->value) & 0x0f;
-    char const newHi4 = new12 >> 8;
-    char const newLo8 = new12 & 0xff;
-
-    fputc(oldHi8, fp);
-    fputc( (oldLo4 << 4) | newHi4 , fp);
-    fputc(newLo8, fp);
-    baP->value = 0; baP->consumed = 0;
-      } 
-      else {
-    baP->value = new12;  baP->consumed = 12;
-      }
+    assert (baP->consumed == 12 || baP->consumed == 0);
+
+    if (baP->consumed == 12){
+        char const oldHi8 = (baP->value) >> 4;
+        char const oldLo4 = (baP->value) & 0x0f;
+        char const newHi4 = new12 >> 8;
+        char const newLo8 = new12 & 0xff;
+
+        fputc(oldHi8, fP);
+        fputc((oldLo4 << 4) | newHi4 , fP);
+        fputc(newLo8, fP);
+        baP->value = 0; baP->consumed = 0;
+    } else {
+        baP->value = new12;  baP->consumed = 12;
+    }
 }
 
 
 
 static void
-bits_add(BitAccumulator * const baP,
-        unsigned int     const b,
-        int              const bitsPerSample,
-        FILE           * const fp) {
+ba_add(BitAccumulator * const baP,
+       unsigned int     const b,
+       unsigned int     const bitsPerSample,
+       FILE           * const fP) {
 /*----------------------------------------------------------------------------
-   Combine bit sequences that do not fit into a byte.
+  Combine bit sequences that do not fit into a byte.
 
-   Used when bitsPerSample =1, 2, 4.  
-   Logic also works for bitsPerSample = 8, 16.
+  Used when bitsPerSample =1, 2, 4.  
+  Logic also works for bitsPerSample = 8, 16.
 
-   The accumulator, baP->value is unsigned int (usually 32 bits), but
-   only 8 bits are used.
+  The accumulator, baP->value is unsigned int (usually 32 bits), but
+  only 8 bits are used.
 -----------------------------------------------------------------------------*/
-      int const bufSize = 8;
+    unsigned int const bufSize = 8;
 
-      assert (bitsPerSample ==1 || bitsPerSample ==2 ||
-          bitsPerSample ==4 );
+    assert (bitsPerSample == 1 || bitsPerSample == 2 || bitsPerSample == 4);
 
-      baP->value = (baP->value << bitsPerSample) | b ;
-      baP->consumed += bitsPerSample;
-      if ( baP->consumed == bufSize ) {     /* flush */
-    fputc( baP->value, fp);
-    baP->value = 0;
-    baP->consumed = 0;
-      }
+    baP->value = (baP->value << bitsPerSample) | b ;
+    baP->consumed += bitsPerSample;
+    if (baP->consumed == bufSize) {
+        /* flush */
+        fputc( baP->value, fP);
+        baP->value = 0;
+        baP->consumed = 0;
+    }
 }
 
 
 
 static void
-bits_flush(BitAccumulator * const baP, FILE * const fp) {
+ba_flush(BitAccumulator * const baP,
+         FILE *           const fP) {
 /*----------------------------------------------------------------------------
-    Flush partial bits in baP->consumed.
+  Flush partial bits in baP->consumed.
 -----------------------------------------------------------------------------*/
-
     if (baP->consumed == 12) {
-      char const oldHi8 = (baP->value) >> 4;
-      char const oldLo4 = (baP->value) & 0x0f;
-      fputc(oldHi8, fp);
-      fputc(oldLo4 << 4, fp);
-    }
-
-    else if (baP->consumed == 8)
-      fputc( baP->value , fp);
-
+        char const oldHi8 = (baP->value) >> 4;
+        char const oldLo4 = (baP->value) & 0x0f;
+        fputc(oldHi8, fP);
+        fputc(oldLo4 << 4, fP);
+    } else if (baP->consumed == 8)
+        fputc(baP->value , fP);
     else if (baP->consumed > 0) {
-      int const leftShift = 8 - baP->consumed;
-      baP->value <<= leftShift;
-      fputc( baP->value , fp);
+        unsigned int const leftShift = 8 - baP->consumed;
+        assert(baP->consumed <= 8);  /* why? */
+        baP->value <<= leftShift;
+        fputc(baP->value , fP);
     }
-
     baP->value = 0;
     baP->consumed = 0;
 }
 
 
-static __inline__ void
-outputSample(BitAccumulator      * const baP,
-          unsigned int     const sampleValue,
-          unsigned int     const bitsPerSample,
-          FILE           * const fp) {
+
+static void
+outputSample(BitAccumulator * const baP,
+             unsigned int     const sampleValue,
+             unsigned int     const bitsPerSample,
+             FILE           * const fP) {
 
     if (bitsPerSample == 8)
-      fputc( sampleValue, fp);
+        fputc(sampleValue, fP);
     else if (bitsPerSample == 12)
-      bits12_add(baP, sampleValue, fp);
-    else {
-      bits_add(baP, sampleValue, bitsPerSample, fp); 
-    }
+        ba_add12(baP, sampleValue, fP);
+    else
+        ba_add(baP, sampleValue, bitsPerSample, fP);
 }
 
 
 
 static void
-flushOutput(BitAccumulator * const baP, FILE * const fp) {
-  bits_flush(baP, fp);
+flushOutput(BitAccumulator * const baP,
+            FILE *           const fP) {
+    ba_flush(baP, fP);
 }
 
+
+
 /*----------------------------------------------------------------------
   Row converters
 
@@ -1594,11 +1681,11 @@ flushOutput(BitAccumulator * const baP, FILE * const fp) {
   convertRowNative and convertRowPsFilter are the general converters.
   They are quite similar, the differences being:
   (1) Native output separates the color planes: 
-      (RRR...RRR GGG...GGG BBB...BBB),
-      whereas psFilter does not:
-      (RGB RGB RGB RGB ......... RGB).
+  (RRR...RRR GGG...GGG BBB...BBB),
+  whereas psFilter does not:
+  (RGB RGB RGB RGB ......... RGB).
   (2) Native flushes the run-length encoder at the end of each row if
-      grayscale, at the end of each plane if color.
+  grayscale, at the end of each plane if color.
 
   Both convertRowNative and convertRowPsFilter can handle PBM, though we
   don't use them.
@@ -1606,13 +1693,13 @@ flushOutput(BitAccumulator * const baP, FILE * const fp) {
   If studying the code, read convertRowPbm first.  convertRowNative and
   convertRowPsFilter are constructs that pack raster data into a form
   similar to a binary PBM bitrow.
-----------------------------------------------------------------------*/
+  ----------------------------------------------------------------------*/
 
 static void
 convertRowPbm(struct pam *     const pamP,
-          unsigned char  * const bitrow,
-          bool             const psFilter,
-          FILE * fp) {
+              unsigned char  * const bitrow,
+              bool             const psFilter,
+              FILE *           const fP) {
 /*---------------------------------------------------------------------
   Feed PBM raster data directly to the output encoder.
   Invert bits: 0 is "white" in PBM, 0 is "black" in postscript.
@@ -1624,64 +1711,67 @@ convertRowPbm(struct pam *     const pamP,
     pbm_readpbmrow_packed(pamP->file, bitrow, pamP->width, pamP->format);
 
     for (colChar = 0; colChar < colChars; ++colChar)
-      bitrow[colChar] =  ~ bitrow[colChar];
+        bitrow[colChar] =  ~ bitrow[colChar];
 
-    if(padRight > 0) {
-      bitrow[colChars-1] >>= padRight;  /* Zero clear padding beyond */
-      bitrow[colChars-1] <<= padRight;  /* right edge */
+    if (padRight > 0) {
+        bitrow[colChars-1] >>= padRight;  /* Zero clear padding beyond */
+        bitrow[colChars-1] <<= padRight;  /* right edge */
     }
 
-    fwrite(bitrow, 1, colChars, fp); 
+    fwrite(bitrow, 1, colChars, fP); 
 }
 
 
 
 static void
 convertRowNative(struct pam *     const pamP, 
-         tuple *                tuplerow, 
-         unsigned int     const bitsPerSample,
-         FILE           * const fp) { 
+                 tuple *                tuplerow, 
+                 unsigned int     const bitsPerSample,
+                 FILE           * const fP) { 
 
-    unsigned int plane;
     unsigned int const psMaxval = pm_bitstomaxval(bitsPerSample);
+
+    unsigned int plane;
     BitAccumulator ba;
-    ba.value = ba.consumed =0;
+
+    ba_init(&ba);
 
     pnm_readpamrow(pamP, tuplerow);
     pnm_scaletuplerow(pamP, tuplerow, tuplerow, psMaxval);
 
     for (plane = 0; plane < pamP->depth; ++plane) {
-    unsigned int col;
-    for (col= 0; col < pamP->width; ++col) {
-      outputSample(&ba, tuplerow[col][plane], bitsPerSample, fp);
-    }
+        unsigned int col;
+        for (col= 0; col < pamP->width; ++col)
+            outputSample(&ba, tuplerow[col][plane], bitsPerSample, fP);
 
-    flushOutput(&ba, fp);
+        flushOutput(&ba, fP);
     }
-
 }
 
 
 
 static void
 convertRowPsFilter(struct pam *     const pamP,
-           tuple *                tuplerow,
-           unsigned int     const bitsPerSample,
-           FILE           * const fp) { 
-    unsigned int col;
+                   tuple *                tuplerow,
+                   unsigned int     const bitsPerSample,
+                   FILE           * const fP) { 
+
     unsigned int const psMaxval = pm_bitstomaxval(bitsPerSample);
+
+    unsigned int col;
     BitAccumulator ba;
-    ba.value = ba.consumed =0;
+
+    ba_init(&ba);
 
     pnm_readpamrow(pamP, tuplerow);
     pnm_scaletuplerow(pamP, tuplerow, tuplerow, psMaxval);
 
     for (col = 0; col < pamP->width; ++col) {
-    unsigned int plane;
-    for (plane = 0; plane < pamP->depth; ++plane)
-      outputSample(&ba, tuplerow[col][plane], bitsPerSample, fp);
+        unsigned int plane;
+        for (plane = 0; plane < pamP->depth; ++plane)
+            outputSample(&ba, tuplerow[col][plane], bitsPerSample, fP);
     }
-    flushOutput(&ba, fp);
+    flushOutput(&ba, fP);
 
 }
 
@@ -1689,16 +1779,16 @@ convertRowPsFilter(struct pam *     const pamP,
 
 static void
 selectPostscriptLevel(bool           const levelIsGiven,
-              unsigned int   const levelGiven,
-              bool           const color,
-              bool           const dict,
-              bool           const flate,
-              bool           const ascii85,
-              bool           const psFilter,
-              unsigned int * const postscriptLevelP) {
+                      unsigned int   const levelGiven,
+                      bool           const color,
+                      bool           const dict,
+                      bool           const flate,
+                      bool           const ascii85,
+                      bool           const psFilter,
+                      unsigned int * const postscriptLevelP) {
 
     unsigned int const maxPermittedLevel = 
-    levelIsGiven ? levelGiven : UINT_MAX;
+        levelIsGiven ? levelGiven : UINT_MAX;
     unsigned int minPossibleLevel;
 
     /* Until we know, later in this function, that we needs certain
@@ -1710,178 +1800,165 @@ selectPostscriptLevel(bool           const levelIsGiven,
        various features are required:
     */
     if (color) {
-    minPossibleLevel = MAX(minPossibleLevel, 2);
-    if (2 > maxPermittedLevel)
-        pm_error("Color requires at least Postscript level 2");
+        minPossibleLevel = MAX(minPossibleLevel, 2);
+        if (2 > maxPermittedLevel)
+            pm_error("Color requires at least Postscript level 2");
     }
     if (flate) {
-    minPossibleLevel = MAX(minPossibleLevel, 3);
-    if (2 > maxPermittedLevel)
-        pm_error("flate compression requires at least Postscript level 3");
+        minPossibleLevel = MAX(minPossibleLevel, 3);
+        if (2 > maxPermittedLevel)
+            pm_error("flate compression requires at least Postscript level 3");
     }
     if (ascii85) {
-    minPossibleLevel = MAX(minPossibleLevel, 2);
-    if (2 > maxPermittedLevel)
-        pm_error("ascii85 encoding requires at least Postscript level 2");
+        minPossibleLevel = MAX(minPossibleLevel, 2);
+        if (2 > maxPermittedLevel)
+            pm_error("ascii85 encoding requires at least Postscript level 2");
     }
     if (psFilter) {
-    minPossibleLevel = MAX(minPossibleLevel, 2);
-    if (2 > maxPermittedLevel)
-        pm_error("-psfilter requires at least Postscript level 2");
+        minPossibleLevel = MAX(minPossibleLevel, 2);
+        if (2 > maxPermittedLevel)
+            pm_error("-psfilter requires at least Postscript level 2");
     }
     if (levelIsGiven)
-    *postscriptLevelP = levelGiven;
+        *postscriptLevelP = levelGiven;
     else
-    *postscriptLevelP = minPossibleLevel;
+        *postscriptLevelP = minPossibleLevel;
+}
+
+
+
+static void
+convertRaster(struct pam * const inpamP,
+              unsigned int const bitsPerSample,
+              bool         const psFilter,
+              FILE *       const fP) {
+
+    if (PAM_FORMAT_TYPE(inpamP->format) == PBM_TYPE && bitsPerSample == 1)  {
+        unsigned char * bitrow;
+        unsigned int row;
+
+        bitrow = pbm_allocrow_packed(inpamP->width);
+
+        for (row = 0; row < inpamP->height; ++row)
+            convertRowPbm(inpamP, bitrow, psFilter, fP);
+
+        pbm_freerow(bitrow);
+    } else  {
+        tuple *tuplerow;
+        unsigned int row;
+        
+        tuplerow = pnm_allocpamrow(inpamP);
+
+        for (row = 0; row < inpamP->height; ++row) {
+            if (psFilter)
+                convertRowPsFilter(inpamP, tuplerow, bitsPerSample, fP);
+            else
+                convertRowNative(inpamP, tuplerow, bitsPerSample, fP);
+        }
+        pnm_freepamrow(tuplerow);
+    }
 }
 
 
 
 static void
 convertPage(FILE *       const ifP, 
-        int          const turnflag, 
-        int          const turnokflag, 
-        bool         const psFilter,
-        bool         const rle, 
-        bool         const flate,
-        bool         const ascii85,
-        bool         const setpage,
-        bool         const showpage,
-        bool         const center, 
-        float        const scale,
-        int          const dpiX, 
-        int          const dpiY, 
-        int          const pagewid, 
-        int          const pagehgt,
-        int          const imagewidth, 
-        int          const imageheight, 
-        bool         const equalpixels,
-        unsigned int const bitsPerSampleReq,
-        char         const name[],
-        bool         const dict,
-        bool         const vmreclaim,
-        bool         const levelIsGiven,
-        bool         const levelGiven) {
+            int          const turnflag, 
+            int          const turnokflag, 
+            bool         const psFilter,
+            bool         const rle, 
+            bool         const flate,
+            bool         const ascii85,
+            bool         const setpage,
+            bool         const showpage,
+            bool         const center, 
+            float        const scale,
+            int          const dpiX, 
+            int          const dpiY, 
+            int          const pagewid, 
+            int          const pagehgt,
+            int          const imagewidth, 
+            int          const imageheight, 
+            bool         const equalpixels,
+            unsigned int const bitsPerSampleReq,
+            char         const name[],
+            bool         const dict,
+            bool         const vmreclaim,
+            bool         const levelIsGiven,
+            bool         const levelGiven) {
     
     struct pam inpam;
-    int row;
     float scols, srows;
     float llx, lly;
     bool turned;
     bool color;
     unsigned int postscriptLevel;
     unsigned int bitsPerSample;
-    unsigned int dictSize;
-    /* Size of Postscript dictionary we should define */
-    OutputEncoder * oeP;
-
-    int feed;
-    FILE * fp;
+    unsigned int dictSize;  
+        /* Size of Postscript dictionary we should define */
+    OutputEncoder oe;
+    pid_t filterPidList[MAX_FILTER_CT + 1];
+
+    FILE * feedFileP;
+        /* The file stream which is the head of the filter chain; we write to
+           this and filtered stuff comes out the other end.
+        */
 
     pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
 
     validateCompDimension(inpam.width, 16, "Input image width");
     
     if (!STRSEQ(inpam.tuple_type, PAM_PBM_TUPLETYPE) &&
-    !STRSEQ(inpam.tuple_type, PAM_PGM_TUPLETYPE) &&
-    !STRSEQ(inpam.tuple_type, PAM_PPM_TUPLETYPE))
-    pm_error("Unrecognized tuple type %s.  This program accepts only "
-         "PBM, PGM, PPM, and equivalent PAM input images", 
-         inpam.tuple_type);
+        !STRSEQ(inpam.tuple_type, PAM_PGM_TUPLETYPE) &&
+        !STRSEQ(inpam.tuple_type, PAM_PPM_TUPLETYPE))
+        pm_error("Unrecognized tuple type %s.  This program accepts only "
+                 "PBM, PGM, PPM, and equivalent PAM input images", 
+                 inpam.tuple_type);
 
     color = STRSEQ(inpam.tuple_type, PAM_PPM_TUPLETYPE);
     
     selectPostscriptLevel(levelIsGiven, levelGiven, color, 
-              dict, flate, ascii85, psFilter, &postscriptLevel);
+                          dict, flate, ascii85, psFilter, &postscriptLevel);
     
     if (color)
-    pm_message("generating color Postscript program.");
+        pm_message("generating color Postscript program.");
 
     computeDepth(inpam.maxval, postscriptLevel, psFilter, bitsPerSampleReq,
-         &bitsPerSample);
+                 &bitsPerSample);
 
     /* In positioning/scaling the image, we treat the input image as if
        it has a density of 72 pixels per inch.
     */
     computeImagePosition(dpiX, dpiY, inpam.width, inpam.height, 
-             turnflag, turnokflag, center,
-             pagewid, pagehgt, scale, imagewidth, imageheight,
-             equalpixels,
-             &scols, &srows, &llx, &lly, &turned);
+                         turnflag, turnokflag, center,
+                         pagewid, pagehgt, scale, imagewidth, imageheight,
+                         equalpixels,
+                         &scols, &srows, &llx, &lly, &turned);
 
     determineDictionaryRequirement(dict, psFilter, &dictSize);
     
     putInit(postscriptLevel, name, inpam.width, inpam.height, 
-        scols, srows, llx, lly, bitsPerSample, 
-        pagewid, pagehgt, color,
-        turned, rle, flate, ascii85, setpage, psFilter, dictSize);
+            scols, srows, llx, lly, bitsPerSample, 
+            pagewid, pagehgt, color,
+            turned, rle, flate, ascii85, setpage, psFilter, dictSize);
 
-    MALLOCVAR_NOFAIL(oeP);
+    initOutputEncoder(&oe, inpam.width, bitsPerSample,
+                      rle, flate, ascii85, psFilter);
 
-    initOutputEncoder (oeP, inpam.width, bitsPerSample, rle,
-               flate, ascii85, psFilter);
-    activateFilters(&feed, oeP);
+    spawnFilters(stdout, &oe, &feedFileP, filterPidList);
  
-    fp=fdopen (feed, "w");
+    convertRaster(&inpam, bitsPerSample, psFilter, feedFileP);
 
-    if( PAM_FORMAT_TYPE(inpam.format) == PBM_TYPE && bitsPerSample==1 )  {
-    unsigned char * const bitrow = pbm_allocrow_packed(inpam.width);
+    fflush(feedFileP);
+    fclose(feedFileP);
 
-    for (row = 0; row < inpam.height; ++row)
-      convertRowPbm(&inpam, bitrow, psFilter, fp);
-    pbm_freerow(bitrow);
-    }
-    else  {
-    tuple * const tuplerow = pnm_allocpamrow(&inpam);
-
-    for (row = 0; row < inpam.height; ++row) {
-        if (psFilter)
-        convertRowPsFilter(&inpam, tuplerow, bitsPerSample, fp);
-        else
-        convertRowNative(&inpam, tuplerow, bitsPerSample, fp);
-        }
-
-    pnm_freepamrow(tuplerow);
-    }
-
-    fclose (fp);
-
-    waitForChildren(oeP->pid);
-    free(oeP);
+    waitForChildren(filterPidList);
 
     putEnd(showpage, psFilter, ascii85, dictSize, vmreclaim);
 }
 
 
 
-static const char *
-basebasename(const char * const filespec) {
-/*----------------------------------------------------------------------------
-    Return filename up to first period
------------------------------------------------------------------------------*/
-    char const dirsep = '/';
-    const char * const lastSlashPos = strrchr(filespec, dirsep);
-
-    char * name;
-    const char * filename;
-
-    if (lastSlashPos)
-    filename = lastSlashPos + 1;
-    else
-    filename = filespec;
-
-    name = strdup(filename);
-    if (name != NULL) {
-    char * const dotPosition = strchr(name, '.');
-
-    if (dotPosition)
-        *dotPosition = '\0';
-    }
-    return name;
-}
-
-
-
 int
 main(int argc, const char * argv[]) {
 
@@ -1895,44 +1972,49 @@ main(int argc, const char * argv[]) {
 
     verbose = cmdline.verbose;
 
+    if (cmdline.flate && !progIsFlateCapable())
+        pm_error("This program cannot do flate compression.  "
+                 "(There are other versions of the program that do, "
+                 "though -- it's a build-time option");
+
     ifP = pm_openr(cmdline.inputFileName);
 
     if (streq(cmdline.inputFileName, "-"))
-    name = strdup("noname");
+        name = strdup("noname");
     else
-    name = basebasename(cmdline.inputFileName);
+        name = basebasename(cmdline.inputFileName);
     {
-    int eof;  /* There are no more images in the input file */
-    unsigned int imageSeq;
-
-    /* I don't know if this works at all for multi-image PNM input.
-       Before July 2000, it ignored everything after the first image,
-       so this probably is at least as good -- it should be identical
-       for a single-image file, which is the only kind which was legal
-       before July 2000.
-
-       Maybe there needs to be some per-file header and trailers stuff
-       in the Postscript program, with some per-page header and trailer
-       stuff inside.  I don't know Postscript.  - Bryan 2000.06.19.
-    */
+        int eof;  /* There are no more images in the input file */
+        unsigned int imageSeq;
+
+        /* I don't know if this works at all for multi-image PNM input.
+           Before July 2000, it ignored everything after the first image,
+           so this probably is at least as good -- it should be identical
+           for a single-image file, which is the only kind which was legal
+           before July 2000.
+
+           Maybe there needs to be some per-file header and trailers stuff
+           in the Postscript program, with some per-page header and trailer
+           stuff inside.  I don't know Postscript.  - Bryan 2000.06.19.
+        */
 
-    eof = FALSE;  /* There is always at least one image */
-    for (imageSeq = 0; !eof; ++imageSeq) {
-        convertPage(ifP, cmdline.mustturn, cmdline.canturn, 
-            cmdline.psfilter,
-            cmdline.rle, cmdline.flate, cmdline.ascii85, 
-            cmdline.setpage, cmdline.showpage,
-            cmdline.center, cmdline.scale,
-            cmdline.dpiX, cmdline.dpiY,
-            cmdline.width, cmdline.height, 
-            cmdline.imagewidth, cmdline.imageheight, 
-            cmdline.equalpixels,
-            cmdline.bitspersampleSpec ? cmdline.bitspersample : 0,
-            name, 
-            cmdline.dict, cmdline.vmreclaim,
-            cmdline.levelSpec, cmdline.level);
-        pnm_nextimage(ifP, &eof);
-    }
+        eof = FALSE;  /* There is always at least one image */
+        for (imageSeq = 0; !eof; ++imageSeq) {
+            convertPage(ifP, cmdline.mustturn, cmdline.canturn, 
+                        cmdline.psfilter,
+                        cmdline.rle, cmdline.flate, cmdline.ascii85, 
+                        cmdline.setpage, cmdline.showpage,
+                        cmdline.center, cmdline.scale,
+                        cmdline.dpiX, cmdline.dpiY,
+                        cmdline.width, cmdline.height, 
+                        cmdline.imagewidth, cmdline.imageheight, 
+                        cmdline.equalpixels,
+                        cmdline.bitspersampleSpec ? cmdline.bitspersample : 0,
+                        name, 
+                        cmdline.dict, cmdline.vmreclaim,
+                        cmdline.levelSpec, cmdline.level);
+            pnm_nextimage(ifP, &eof);
+        }
     }
     pm_strfree(name);