about summary refs log tree commit diff
path: root/converter
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-12-31 08:08:29 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-12-31 08:08:29 +0000
commit31fc573df625b06a5f7b8b8e769e9f35cbfdaf91 (patch)
treecaf153af4ea24150e1f54e77c35b9ee51e727055 /converter
parent2cc04cae07f40a7c58616e4614e88cf0ae8e63c7 (diff)
downloadnetpbm-mirror-31fc573df625b06a5f7b8b8e769e9f35cbfdaf91.tar.gz
netpbm-mirror-31fc573df625b06a5f7b8b8e769e9f35cbfdaf91.tar.xz
netpbm-mirror-31fc573df625b06a5f7b8b8e769e9f35cbfdaf91.zip
Release 10.37.0
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@187 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter')
-rw-r--r--converter/other/Makefile2
-rw-r--r--converter/other/giftopnm.c4
-rw-r--r--converter/other/hdifftopam.c2
-rw-r--r--converter/other/jpeg2000/libjasper/Makefile.common2
-rw-r--r--converter/other/pamtogif.c1864
-rw-r--r--converter/other/pamtopnm.c59
-rw-r--r--converter/other/pamtosvg/curve.h8
-rw-r--r--converter/other/pamtosvg/fit.c1127
-rw-r--r--converter/other/pgmtopbm.c5
-rw-r--r--converter/other/pgmtoppm.c343
-rw-r--r--converter/other/pngtopnm.c22
-rw-r--r--converter/other/pnmtoddif.c4
-rw-r--r--converter/other/pnmtojpeg.c698
-rw-r--r--converter/other/pnmtopalm/Makefile3
-rw-r--r--converter/other/pnmtopng.c16
-rw-r--r--converter/pbm/Makefile4
-rw-r--r--converter/pbm/cmuwmtopbm.c181
-rw-r--r--converter/pbm/mgrtopbm.c171
-rw-r--r--converter/pbm/pbmtocmuwm.c167
-rw-r--r--converter/pbm/pbmtogem.c6
-rw-r--r--converter/pbm/pbmtogo.c10
-rw-r--r--converter/pbm/pbmtoicon.c252
-rw-r--r--converter/pbm/pbmtomgr.c192
-rw-r--r--converter/pbm/pbmtopi3.c6
-rw-r--r--converter/pbm/pbmtoptx.c6
-rw-r--r--converter/pbm/pbmtox10bm45
-rw-r--r--converter/pbm/pbmtox10bm.c120
-rw-r--r--converter/pbm/pbmtoxbm.c394
-rw-r--r--converter/pbm/pbmtoybm.c6
-rw-r--r--converter/pbm/xbmtopbm.c567
-rw-r--r--converter/pgm/pgmtofs.c6
-rw-r--r--converter/pgm/pgmtolispm.c6
-rw-r--r--converter/ppm/ppmtogif.c1544
-rw-r--r--converter/ppm/ppmtoilbm.c42
-rw-r--r--converter/ppm/ppmtomitsu.c844
-rw-r--r--converter/ppm/ppmtomitsu.test12
-rw-r--r--converter/ppm/ppmtompeg/Makefile10
-rw-r--r--converter/ppm/ppmtompeg/bframe.c1
-rw-r--r--converter/ppm/ppmtompeg/bsearch.c1
-rw-r--r--converter/ppm/ppmtompeg/frames.c58
-rw-r--r--converter/ppm/ppmtompeg/headers/bitio.h4
-rw-r--r--converter/ppm/ppmtompeg/headers/block.h44
-rw-r--r--converter/ppm/ppmtompeg/headers/frame.h16
-rw-r--r--converter/ppm/ppmtompeg/headers/frames.h168
-rw-r--r--converter/ppm/ppmtompeg/headers/iframe.h118
-rw-r--r--converter/ppm/ppmtompeg/headers/motion_search.h3
-rw-r--r--converter/ppm/ppmtompeg/headers/mpeg.h5
-rw-r--r--converter/ppm/ppmtompeg/headers/mproto.h8
-rw-r--r--converter/ppm/ppmtompeg/headers/parallel.h2
-rw-r--r--converter/ppm/ppmtompeg/headers/prototypes.h9
-rw-r--r--converter/ppm/ppmtompeg/headers/subsample.h39
-rw-r--r--converter/ppm/ppmtompeg/iframe.c209
-rw-r--r--converter/ppm/ppmtompeg/jpeg.c1
-rw-r--r--converter/ppm/ppmtompeg/mheaders.c712
-rw-r--r--converter/ppm/ppmtompeg/mpeg.c116
-rw-r--r--converter/ppm/ppmtompeg/pframe.c2
-rw-r--r--converter/ppm/ppmtompeg/psearch.c2
-rw-r--r--converter/ppm/ppmtompeg/subsample.c1
-rw-r--r--converter/ppm/ppmtopict.c7
-rw-r--r--converter/ppm/sldtoppm.c726
-rw-r--r--converter/ppm/spctoppm.c7
61 files changed, 6062 insertions, 4947 deletions
diff --git a/converter/other/Makefile b/converter/other/Makefile
index 6cde424d..0273c523 100644
--- a/converter/other/Makefile
+++ b/converter/other/Makefile
@@ -79,7 +79,7 @@ endif
 
 PORTBINARIES =  bmptopnm fitstopnm \
 		gemtopnm giftopnm hdifftopam infotopam \
-		pamtodjvurle pamtofits \
+		pamtodjvurle pamtofits pamtogif \
 		pamtohdiff pamtohtmltbl pamtopfm pamtopnm pamtouil \
 		pamtoxvmini \
 		pbmtopgm pfmtopam \
diff --git a/converter/other/giftopnm.c b/converter/other/giftopnm.c
index d3d02fde..d7d54775 100644
--- a/converter/other/giftopnm.c
+++ b/converter/other/giftopnm.c
@@ -652,7 +652,7 @@ termStack(struct stack * const stackP) {
    max_dataVal.  The first byte in the stream tells you what dataWidth
    is.
 
-   LZW codes 0 - max_dataVal are direct codes.  Each on represents
+   LZW codes 0 - max_dataVal are direct codes.  Each one represents
    the true data element whose value is that of the LZW code itself.
    No decompression is required.
 
@@ -805,7 +805,7 @@ expandCodeOntoStack(struct decompressor * const decompP,
            represents and push it onto the code stack so the
            leftmost code is on top.  Set decompP->firstcode to the
            first (leftmost) code in that string.
-            */
+        */
 
         unsigned int stringCount;
         stringCount = 0;
diff --git a/converter/other/hdifftopam.c b/converter/other/hdifftopam.c
index 444d6068..0f1a5ca3 100644
--- a/converter/other/hdifftopam.c
+++ b/converter/other/hdifftopam.c
@@ -96,7 +96,7 @@ main(int argc, char *argv[]) {
     tuple * outrow;
     tuple * prevrow;
 
-    pnm_init( &argc, argv );
+    pnm_init(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
diff --git a/converter/other/jpeg2000/libjasper/Makefile.common b/converter/other/jpeg2000/libjasper/Makefile.common
index 7737f2c0..d2cb7d42 100644
--- a/converter/other/jpeg2000/libjasper/Makefile.common
+++ b/converter/other/jpeg2000/libjasper/Makefile.common
@@ -26,7 +26,7 @@ INCLUDES = -I$(JASPERSRCDIR)/include -Iimportinc
 DEFS = -DHAVE_LIBM=1 -DSTDC_HEADERS=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STDDEF_H=1 -DEXCLUDE_BMP_SUPPORT -DEXCLUDE_RAS_SUPPORT -DEXCLUDE_MIF_SUPPORT -DEXCLUDE_JPG_SUPPORT -DEXCLUDE_PGX_SUPPORT -DEXCLUDE_PNM_SUPPORT
 
 $(LIB_OBJECTS):%.o:%.c
-	$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFS) $(CADD) $<
+	$(CC) -c $(CPPFLAGS) $(CFLAGS) $(INCLUDES) $(DEFS) $(CADD) $<
 
 $(LIB_OBJECTS): importinc
 
diff --git a/converter/other/pamtogif.c b/converter/other/pamtogif.c
new file mode 100644
index 00000000..ef3441cb
--- /dev/null
+++ b/converter/other/pamtogif.c
@@ -0,0 +1,1864 @@
+/*=============================================================================
+                              pamtogif
+===============================================================================
+  Convert a Netpbm image to GIF
+
+  History and copyright information is at the end of the file.
+=============================================================================*/
+
+#include <assert.h>
+#include <string.h>
+
+#include "mallocvar.h"
+#include "shhopt.h"
+#include "nstring.h"
+#include "pam.h"
+#include "pammap.h"
+
+#define MAXCMAPSIZE 256
+
+static unsigned int const gifMaxval = 255;
+
+static bool verbose;
+
+typedef int stringCode;
+    /* A code to be place in the GIF raster.  It represents
+       a string of one or more pixels.  You interpret this in the context
+       of a current code size.  The lower half of the values representable
+       in the current code size represent singleton strings and the value
+       is simply the value of the one pixel in the string.  The first two
+       values in the upper half of the range are the clear code and EOF
+       code, respectively.  The rest of the values represent multi-pixel
+       strings.  The mapping between value and the sequence of pixels
+       changes throughout the image.
+
+       A variable of this type sometimes has the value -1 instead of
+       a string code due to cheesy programming.
+
+       Ergo, this data structure must be signed and at least BITS bits
+       wide plus sign bit.
+
+       TODO: Some variables that should be of this type are defined as
+             "long".
+    */
+
+
+struct cmap {
+    /* This is the information for the GIF colormap (aka palette). */
+
+    struct pam pam;
+        /* Gives depth and maxval for colors in color[] */
+    tuple color[MAXCMAPSIZE];
+        /* Maps a color index, as is found in the raster part of the
+           GIF, to color.
+        */
+    int perm[MAXCMAPSIZE], permi[MAXCMAPSIZE];
+        /* perm[i] is the position in the sorted colormap of the color which
+           is at position i in the unsorted colormap.  permi[] is the inverse
+           function of perm[].
+           
+           The sort colormap is the one that goes into the GIF.  The
+           unsorted one is the one that is hashed so we can find colors
+           in it.
+        */
+    unsigned int cmapSize;
+        /* Number of entries in the GIF colormap.  I.e. number of colors
+           in the image, plus possibly one fake transparency color.
+        */
+    bool haveTransparent;
+        /* The colormap contains an entry for transparent pixels */
+    unsigned int transparent;
+        /* color index number in GIF palette of the color that is to
+           be transparent.  This is a post-sort index.
+
+           Meaningful only if 'haveTransparent' is true.
+        */
+    tuplehash tuplehash;
+        /* A hash table to translate color to GIF (presort) colormap index. */
+};
+
+struct cmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char *input_filespec; /* Filespec of input file */
+    const char *alphacolor;     /* -alphacolor option value or default */
+    unsigned int interlace;     /* -interlace option value */
+    unsigned int sort;          /* -sort option value */
+    const char *mapfile;        /* -mapfile option value.  NULL if none. */
+    const char *transparent;    /* -transparent option value.  NULL if none. */
+    const char *comment;        /* -comment option value; NULL if none */
+    unsigned int nolzw;         /* -nolzw option */
+    unsigned int verbose;
+};
+
+
+static unsigned int
+nSignificantBits(unsigned int const arg) {
+
+    unsigned int i;
+
+    i = 0;
+   
+    while (arg >> i != 0)
+        ++i;
+
+    return i;
+}
+
+
+
+static unsigned int
+pamAlphaPlane(struct pam * const pamP) {
+
+    unsigned int alphaPlane;
+
+    if (STREQ(pamP->tuple_type, "RGB_ALPHA"))
+        alphaPlane = 3;
+    else if (STREQ(pamP->tuple_type, "GRAYSCALE_ALPHA"))
+        alphaPlane = 2;
+    else if (STREQ(pamP->tuple_type, "BLACKANDWHITE_ALPHA"))
+        alphaPlane = 2;
+    else
+        alphaPlane = 0;
+    
+    if (alphaPlane >= pamP->depth)
+        pm_error("Tuple type is '%s', but depth (%u) is less than %u",
+                 pamP->tuple_type, pamP->depth, alphaPlane + 1);
+
+    return alphaPlane;
+}
+
+
+
+static void
+parseCommandLine(int argc, char ** argv,
+                 struct cmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Parse the program arguments (given by argc and argv) into a form
+   the program can deal with more easily -- a cmdline_info structure.
+   If the syntax is invalid, issue a message and exit the program via
+   pm_error().
+
+   Note that the file spec array we return is stored in the storage that
+   was passed to us as the argv array.
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;  /* malloc'ed */
+    optStruct3 opt;  /* set by OPTENT3 */
+    unsigned int option_def_index;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0,   "interlace",   OPT_FLAG,   
+            NULL,                       &cmdlineP->interlace, 0);
+    OPTENT3(0,   "sort",        OPT_FLAG,   
+            NULL,                       &cmdlineP->sort, 0);
+    OPTENT3(0,   "nolzw",       OPT_FLAG,   
+            NULL,                       &cmdlineP->nolzw, 0);
+    OPTENT3(0,   "mapfile",     OPT_STRING, 
+            &cmdlineP->mapfile,        NULL, 0);
+    OPTENT3(0,   "transparent", OPT_STRING, 
+            &cmdlineP->transparent,    NULL, 0);
+    OPTENT3(0,   "comment",     OPT_STRING, 
+            &cmdlineP->comment,        NULL, 0);
+    OPTENT3(0,   "alphacolor",  OPT_STRING, 
+            &cmdlineP->alphacolor,     NULL, 0);
+    OPTENT3(0,   "verbose",     OPT_FLAG, 
+            NULL,                       &cmdlineP->verbose, 0);
+    
+    /* Set the defaults */
+    cmdlineP->mapfile = NULL;
+    cmdlineP->transparent = NULL;  /* no transparency */
+    cmdlineP->comment = NULL;      /* no comment */
+    cmdlineP->alphacolor = "rgb:0/0/0";      
+        /* We could say "black" here, but then we depend on the color names
+           database existing.
+        */
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (argc-1 == 0) 
+        cmdlineP->input_filespec = "-";
+    else if (argc-1 != 1)
+        pm_error("Program takes zero or one argument (filename).  You "
+                 "specified %d", argc-1);
+    else
+        cmdlineP->input_filespec = argv[1];
+}
+
+
+
+/*
+ * Write out a word to the GIF file
+ */
+static void
+Putword(int const w, FILE * const fp) {
+
+    fputc( w & 0xff, fp );
+    fputc( (w / 256) & 0xff, fp );
+}
+
+
+
+static int
+closestColor(tuple         const color,
+             struct pam *  const pamP,
+             struct cmap * const cmapP) {
+/*----------------------------------------------------------------------------
+   Return the pre-sort colormap index of the color in the colormap *cmapP
+   that is closest to the color 'color', whose format is specified by 
+   *pamP.
+
+   Also add 'color' to the colormap hash, with the colormap index we
+   are returning.  Caller must ensure that the color is not already in
+   there.
+-----------------------------------------------------------------------------*/
+    unsigned int const nComp = pamP->depth >= 3 ? 3 : 1;
+        /* Number of color components (not alpha) in 'color' */
+    
+    unsigned int i;
+    unsigned int imin, dmin;
+    bool fits;
+
+    dmin = UINT_MAX;
+    imin = 0;
+    for (i = 0; i < cmapP->cmapSize; ++i) {
+        unsigned int distance;
+        unsigned int plane;
+
+        for (distance = 0, plane = 0; plane < nComp; ++plane)
+            /* Divide by 4 is to avoid arithmetic overflow */
+            distance += SQR(color[plane] - cmapP->color[i][plane]) / 4;
+
+        if (distance < dmin) {
+            dmin = distance;
+            imin = i; 
+        } 
+    }
+    pnm_addtotuplehash(pamP, cmapP->tuplehash, color, imin, &fits);
+
+    return imin;
+}
+
+
+
+enum pass {MULT8PLUS0, MULT8PLUS4, MULT4PLUS2, MULT2PLUS1};
+
+
+typedef struct {
+    struct pam pam;
+        /* Description of input file/image.  The position of the file
+           is also part of the state of this rowReader.
+        */
+    pm_filepos rasterPos;
+        /* Position in file fileP of the start of the raster */
+    bool interlace;
+        /* We're accessing the image in interlace fashion */
+    bool eof;
+        /* The image is at EOF (we have returned all of the rows) */
+    unsigned int nextRow;
+        /* Number of row to which input file is positioned;
+           meaningless if 'eof'.
+        */
+    enum pass pass;
+        /* The interlace pass.  Undefined if !interlace */
+    tuple * discardBuffer;
+        /* A bitbucket for rows we read in order to advance the file
+           position.
+        */
+} rowReader;
+
+
+
+static rowReader *
+rowReader_create(struct pam * const pamP,
+                 pm_filepos   const rasterPos,
+                 bool         const interlace) {
+
+    rowReader * rdrP;
+
+    MALLOCVAR_NOFAIL(rdrP);
+
+    rdrP->pam         = *pamP;
+    rdrP->rasterPos   = rasterPos;
+    rdrP->interlace   = interlace;
+    rdrP->eof         = FALSE;
+    rdrP->pass        = MULT8PLUS0;
+
+    pm_seek2(rdrP->pam.file, &rasterPos, sizeof(rasterPos));
+    rdrP->nextRow = 0;
+
+    rdrP->discardBuffer = pnm_allocpamrow(&rdrP->pam);
+
+    return rdrP;
+}
+
+
+
+static void
+rowReader_destroy(rowReader * const rdrP) {
+
+    pnm_freepamrow(rdrP->discardBuffer);
+    free(rdrP);
+}
+
+
+
+static void
+rowReaderSkipRows(rowReader *  const rdrP,
+                  unsigned int const rowCount,
+                  bool *       const eofP) {
+/*----------------------------------------------------------------------------
+   Skip over the next 'rowCount' rows of the input file.
+
+   Iff there aren't at least 'rowCount' rows left, return *eofP == TRUE.
+-----------------------------------------------------------------------------*/
+    if (rdrP->nextRow + rowCount >= rdrP->pam.height)
+        *eofP = TRUE;
+    else {
+        /* This could be made faster if need be by adding a libnetpbm
+           row skip function.  Except with the plain formats, that could
+           just compute the next row position and fseek() to it.
+           pnm_readpamrow() with NULL for the output pointer would be a
+           good interface for a row skip function.
+        */
+        unsigned int i;
+
+        *eofP = FALSE;
+
+        for (i = 0; i < rowCount; ++i)
+            pnm_readpamrow(&rdrP->pam, rdrP->discardBuffer);
+
+        rdrP->nextRow += rowCount;
+    }
+}
+
+
+
+static void
+rowReaderGotoNextInterlaceRow(rowReader * const rdrP) {
+/*----------------------------------------------------------------------------
+  Position reader to the next row in the interlace pattern, assuming it
+  is now positioned immediately after the current row.
+-----------------------------------------------------------------------------*/
+    bool endOfPass;
+
+    /* There are 4 passes:
+       MULT8PLUS0: Rows 0, 8, 16, 24, 32, etc.
+       MULT8PLUS4: Rows 4, 12, 20, 28, etc.
+       MULT4PLUS2: Rows 2, 6, 10, 14, etc.
+       MULT2PLUS1: Rows 1, 3, 5, 7, 9, etc.
+    */
+    
+    switch (rdrP->pass) {
+    case MULT8PLUS0:
+        rowReaderSkipRows(rdrP, 7, &endOfPass);
+        break;
+    case MULT8PLUS4:
+        rowReaderSkipRows(rdrP, 7, &endOfPass);
+        break;
+    case MULT4PLUS2:
+        rowReaderSkipRows(rdrP, 3, &endOfPass);
+        break;
+    case MULT2PLUS1:
+        rowReaderSkipRows(rdrP, 1, &endOfPass);
+        break;
+    }
+
+    /* Note that if there are more than 4 rows, the sequence of passes
+       is sequential, but when there are fewer than 4, reading may skip
+       e.g. from MULT8PLUS0 to MULT4PLUS2.
+    */
+    while (endOfPass && !rdrP->eof) {
+        pm_seek2(rdrP->pam.file, &rdrP->rasterPos, sizeof(rdrP->rasterPos));
+        rdrP->nextRow = 0;
+
+        switch (rdrP->pass) {
+        case MULT8PLUS0:
+            rdrP->pass = MULT8PLUS4;
+            rowReaderSkipRows(rdrP, 4, &endOfPass);
+            break;
+        case MULT8PLUS4:
+            rdrP->pass = MULT4PLUS2;
+            rowReaderSkipRows(rdrP, 2, &endOfPass);
+            break;
+        case MULT4PLUS2:
+            rdrP->pass = MULT2PLUS1;
+            rowReaderSkipRows(rdrP, 1, &endOfPass);
+            break;
+        case MULT2PLUS1:
+            rdrP->eof = TRUE;
+            break;
+        }
+    }
+}
+
+
+
+
+static void
+rowReaderGotoNextStraightRow(rowReader * const rdrP) {
+/*----------------------------------------------------------------------------
+  Position reader to the next row in a straight, non-interlace
+  pattern, assuming the file is now positioned immediately after the
+  current row.
+
+  This is trivial, since the next row _is_ immediately after the current
+  row, except in the case that there are no more rows.
+-----------------------------------------------------------------------------*/
+    if (rdrP->nextRow >= rdrP->pam.height)
+        rdrP->eof = TRUE;
+}
+
+
+
+static void
+rowReader_read(rowReader * const rdrP,
+               tuple *     const tuplerow) {
+
+    if (rdrP->eof)
+        pm_error("INTERNAL ERROR: rowReader attempted to read beyond end "
+                 "of image");
+
+    pnm_readpamrow(&rdrP->pam, tuplerow);
+    ++rdrP->nextRow;
+    
+    if (rdrP->interlace)
+        rowReaderGotoNextInterlaceRow(rdrP);
+    else
+        rowReaderGotoNextStraightRow(rdrP);
+}
+
+
+
+static unsigned int
+gifPixel(struct pam *   const pamP,
+         tuple          const tuple,
+         unsigned int   const alphaPlane,
+         sample         const alphaThreshold, 
+         struct cmap *  const cmapP) {
+/*----------------------------------------------------------------------------
+   Return as *colorIndexP the colormap index of the tuple 'tuple',
+   whose format is described by *pamP, using colormap *cmapP.
+
+   'alphaThreshold' is the alpha level below which we consider a
+   pixel transparent for GIF purposes.
+-----------------------------------------------------------------------------*/
+    unsigned int colorIndex;
+
+    if (alphaPlane && tuple[alphaPlane] < alphaThreshold &&
+        cmapP->haveTransparent)
+        colorIndex = cmapP->transparent;
+    else {
+        int presortColorindex;
+        int found;
+
+        pnm_lookuptuple(pamP, cmapP->tuplehash, tuple,
+                        &found, &presortColorindex);
+        
+        if (!found)
+            presortColorindex = closestColor(tuple, pamP, cmapP);
+
+        colorIndex = cmapP->perm[presortColorindex];
+    }
+    return colorIndex;
+}
+
+
+
+static void
+writeTransparentColorIndexExtension(FILE *       const ofP,
+                                    unsigned int const transColorIndex) {
+/*----------------------------------------------------------------------------
+   Write out extension for transparent color index.
+-----------------------------------------------------------------------------*/
+    fputc('!',  ofP);
+    fputc(0xf9, ofP);
+    fputc(4,    ofP);
+    fputc(1,    ofP);
+    fputc(0,    ofP);
+    fputc(0,    ofP);
+    fputc(transColorIndex, ofP);
+    fputc(0,    ofP);
+}
+
+
+
+static void
+writeCommentExtension(FILE * const ofP,
+                      char   const comment[]) {
+/*----------------------------------------------------------------------------
+   Write out extension for a comment
+-----------------------------------------------------------------------------*/
+    unsigned int const maxSegmentSize = 255;
+
+    const char * segment;
+    
+    fputc('!',  ofP);   /* Identifies an extension */
+    fputc(0xfe, ofP);   /* Identifies a comment */
+
+    /* Write it out in segments no longer than 255 characters */
+    for (segment = &comment[0]; 
+         segment < comment + strlen(comment); 
+         segment += maxSegmentSize) {
+
+        unsigned int const lengthThisSegment =
+            MIN(maxSegmentSize, strlen(segment));
+
+        fputc(lengthThisSegment, ofP);
+
+        fwrite(segment, 1, lengthThisSegment, ofP);
+    }
+
+    fputc(0, ofP);   /* No more comment blocks in this extension */
+}
+
+
+
+/***************************************************************************
+ *
+ *  GIFCOMPR.C       - GIF Image compression routines
+ *
+ *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
+ *  David Rowley (mgardi@watdcsu.waterloo.edu)
+ *
+ ***************************************************************************/
+
+/*
+ * General DEFINEs
+ */
+
+#define BITS    12
+
+#define HSIZE  5003            /* 80% occupancy */
+
+/*
+ *
+ * GIF Image compression - modified 'compress'
+ *
+ * Based on: compress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
+ *              Jim McKie               (decvax!mcvax!jim)
+ *              Steve Davies            (decvax!vax135!petsd!peora!srd)
+ *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
+ *              James A. Woods          (decvax!ihnp4!ames!jaw)
+ *              Joe Orost               (decvax!vax135!petsd!joe)
+ *
+ */
+
+
+static stringCode const maxCodeLimitLzw = (stringCode)1 << BITS;
+       /* One beyond the largest string code that can exist in GIF */ 
+       /* Used only in assertions  */
+
+
+struct hashTableEntry {
+    long fcode;   /* -1 means unused slot */
+    unsigned int ent;
+};    
+
+
+
+/***************************************************************************
+*                          BYTE OUTPUTTER                 
+***************************************************************************/
+
+typedef struct {
+    FILE * fileP;  /* The file to which to output */
+    unsigned int count;
+        /* Number of bytes so far in the current data block */
+    unsigned char buffer[256];
+        /* The current data block, under construction */
+} byteBuffer;
+
+
+
+static byteBuffer *
+byteBuffer_create(FILE * const fileP) {
+
+    byteBuffer * byteBufferP;
+
+    MALLOCVAR_NOFAIL(byteBufferP);
+
+    byteBufferP->fileP = fileP;
+    byteBufferP->count = 0;
+
+    return byteBufferP;
+}
+
+
+
+static void
+byteBuffer_destroy(byteBuffer * const byteBufferP) {
+
+    free(byteBufferP);
+}
+
+
+
+static void
+byteBuffer_flush(byteBuffer * const byteBufferP) {
+/*----------------------------------------------------------------------------
+   Write the current data block to the output file, then reset the current 
+   data block to empty.
+-----------------------------------------------------------------------------*/
+    if (byteBufferP->count > 0 ) {
+        if (verbose)
+            pm_message("Writing %u byte block", byteBufferP->count);
+        fputc(byteBufferP->count, byteBufferP->fileP);
+        fwrite(byteBufferP->buffer, 1, byteBufferP->count, byteBufferP->fileP);
+        byteBufferP->count = 0;
+    }
+}
+
+
+
+static void
+byteBuffer_flushFile(byteBuffer * const byteBufferP) {
+    
+    fflush(byteBufferP->fileP);
+    
+    if (ferror(byteBufferP->fileP))
+        pm_error("error writing output file");
+}
+
+
+
+static void
+byteBuffer_out(byteBuffer *  const byteBufferP,
+               unsigned char const c) {
+/*----------------------------------------------------------------------------
+  Add a byte to the end of the current data block, and if it is now 254
+  characters, flush the data block to the output file.
+-----------------------------------------------------------------------------*/
+    byteBufferP->buffer[byteBufferP->count++] = c;
+    if (byteBufferP->count >= 254)
+        byteBuffer_flush(byteBufferP);
+}
+
+
+
+/***************************************************************************
+*                          GIF CODE OUTPUTTER                 
+***************************************************************************/
+
+typedef struct {
+    byteBuffer * byteBufferP;
+    unsigned int initBits;
+    unsigned int nBits;
+        /* Number of bits to put in output for each code */
+    stringCode maxCode;                  /* maximum code, given n_bits */
+    stringCode maxCodeLimit;
+        /* LZW: One beyond the largest string code that can exist in GIF.
+           Uncompressed: a ceiling to prevent code size from ratcheting up.
+           In either case, output code never reaches this value.
+        */  
+    unsigned long curAccum;
+    int curBits;
+    unsigned int codeCount;
+        /* Number of codes that have been output to this buffer (doesn't
+           matter if they have gone out the other side yet or not) since
+           the last flush (or ever, if no last flush).  The main use of this
+           is debugging -- when something fails, you can see in a debugger
+           where in the image it was, then set a trap for there.
+        */
+} codeBuffer;
+
+
+
+static codeBuffer *
+codeBuffer_create(FILE *       const ofP,
+                  unsigned int const initBits,
+                  bool         const lzw) {
+
+    codeBuffer * codeBufferP;
+
+    MALLOCVAR_NOFAIL(codeBufferP);
+
+    codeBufferP->initBits    = initBits;
+    codeBufferP->nBits       = codeBufferP->initBits;
+    codeBufferP->maxCode     = (1 << codeBufferP->nBits) - 1;
+    codeBufferP->maxCodeLimit = lzw ?
+        (stringCode)1 << BITS : (stringCode) (1 << codeBufferP->nBits) - 1; 
+    codeBufferP->byteBufferP = byteBuffer_create(ofP);
+    codeBufferP->curAccum    = 0;
+    codeBufferP->curBits     = 0;
+    codeBufferP->codeCount   = 0;
+
+    return codeBufferP;
+}
+
+
+
+static void
+codeBuffer_destroy(codeBuffer * const codeBufferP) {
+
+    byteBuffer_destroy(codeBufferP->byteBufferP);
+
+    free(codeBufferP);
+}
+
+
+
+static void
+codeBuffer_resetCodeSize(codeBuffer * const codeBufferP) {
+
+    codeBufferP->nBits = codeBufferP->initBits;
+
+    assert(codeBufferP->nBits <= BITS);
+
+    codeBufferP->maxCode = (1 << codeBufferP->nBits) - 1;
+}
+
+
+
+static void
+codeBuffer_increaseCodeSize(codeBuffer * const codeBufferP) {
+
+    ++codeBufferP->nBits;
+
+    assert(codeBufferP->nBits <= BITS);
+
+    codeBufferP->maxCode = (1 << codeBufferP->nBits) - 1;
+}
+
+
+
+static unsigned long const masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+                                       0x001F, 0x003F, 0x007F, 0x00FF,
+                                       0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+                                       0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+static void
+codeBuffer_output(codeBuffer * const codeBufferP,
+                  stringCode   const code) {
+/*----------------------------------------------------------------------------
+   Output one GIF code to the file, through the code buffer.
+
+   The code is represented as N bits in the file -- the lower
+   N bits of 'code'.  N is a the current code size of *codeBufferP.
+   
+   Id 'code' is the maximum possible code for the current code size
+   for *codeBufferP, increase that code size (unless it's already 
+   maxed out).
+-----------------------------------------------------------------------------*/
+    assert (code <= codeBufferP->maxCode);
+
+    codeBufferP->curAccum &= masks[codeBufferP->curBits];
+
+    if (codeBufferP->curBits > 0)
+        codeBufferP->curAccum |= ((long)code << codeBufferP->curBits);
+    else
+        codeBufferP->curAccum = code;
+
+    codeBufferP->curBits += codeBufferP->nBits;
+
+    while (codeBufferP->curBits >= 8) {
+        byteBuffer_out(codeBufferP->byteBufferP,
+                       codeBufferP->curAccum & 0xff);
+        codeBufferP->curAccum >>= 8;
+        codeBufferP->curBits -= 8;
+    }
+
+    ++codeBufferP->codeCount;
+}
+
+
+
+static void
+codeBuffer_flush(codeBuffer * const codeBufferP) {
+
+    /* Output the possible partial byte in the buffer */
+
+    if (codeBufferP->curBits > 0) {
+        byteBuffer_out(codeBufferP->byteBufferP,
+                       codeBufferP->curAccum & 0xff);
+        codeBufferP->curBits = 0;
+    }
+    byteBuffer_flush(codeBufferP->byteBufferP);
+    
+    byteBuffer_flushFile(codeBufferP->byteBufferP);
+
+    if (verbose)
+        pm_message("%u strings of pixels written to file",
+                   codeBufferP->codeCount);
+    codeBufferP->codeCount = 0;
+}
+
+
+
+typedef struct {
+    codeBuffer * codeBufferP;
+        /* The place to which we write our string codes.
+
+           Constant.
+        */
+    bool lzw;
+        /* We're actually doing LZW compression.  False means we follow
+           the algorithm enough tht an LZW decompressor will recover the
+           proper data, but always using one code per pixel, and therefore
+           not effecting any compression and not using the LZW patent.
+        */
+    unsigned int hshift;
+        /* This is how many bits we shift left a string code in forming the
+           primary hash of the concatenation of that string with another.
+           Constant.
+        */
+
+    /* Codes less than 'clearCode' are singleton pixel codes - each
+       represents the pixel value equal to it.
+
+       Codes greater than 'eofCode' are multipixel string codes.  Each
+       represents a string of pixels that is defined by the preceding
+       stream.
+    */
+    stringCode clearCode;
+        /* The code in an LZW stream that means to clear the string
+           dictionary and start fresh.
+
+           Constant.
+        */
+    stringCode eofCode;
+        /* The code in an LZW stream that means there's no more coming
+
+           Constant.
+        */
+    stringCode initCodeLimit;
+        /* The value of 'codeLimit' at the start of a block.
+
+           Constant.
+        */
+
+    stringCode codeLimit;
+        /* One beyond the maximum code possible with the current code
+           size.
+        */
+
+    struct hashTableEntry * hashTable;
+    stringCode nextUnusedCode;
+        /* Numerically next code available to assign to a a multi-pixel
+           string.  Note that codes for multi-pixel strings are in the
+           upper half of the range of codes, always greater than
+           'clearCode'.
+        */
+
+    stringCode stringSoFar;
+        /* The code for the string we have built so far.  This code indicates
+           one or more pixels that we have encoded but not yet output
+           because we're hoping to match an even longer string.
+
+           Valid only when 'buildingString' is true.
+
+           In the non-lzw case the single pixel to output.
+        */
+    bool buildingString;
+        /* We are in the middle of building a string; 'stringSoFar' describes
+           the pixels in it so far.  The only time this is false is at the
+           very beginning of the stream.
+ 
+           Ignored in the non-lzw case. 
+        */
+} lzwCompressor;
+
+
+
+static lzwCompressor *
+lzw_create(FILE *       const ofP,
+           unsigned int const initBits,
+           bool         const lzw) {
+
+    lzwCompressor * lzwP;
+
+    MALLOCVAR_NOFAIL(lzwP);
+
+    MALLOCARRAY(lzwP->hashTable, HSIZE);
+
+    if (lzwP->hashTable == NULL)
+        pm_error("Couldn't get memory for %u-entry hash table.", HSIZE);
+
+    /* Constants */
+    lzwP->lzw = lzw;
+    lzwP->hshift =
+        nSignificantBits(HSIZE-1) - 1 - nSignificantBits(MAXCMAPSIZE-1);
+    lzwP->clearCode = 1 << (initBits - 1);
+    lzwP->eofCode = lzwP->clearCode + 1;
+    lzwP->initCodeLimit = 1 << initBits;
+
+    lzwP->buildingString = FALSE;
+
+    lzwP->codeBufferP = codeBuffer_create(ofP, initBits, lzw);
+
+    return lzwP;
+}
+
+
+
+static void
+lzw_destroy(lzwCompressor * const lzwP) {
+
+    codeBuffer_destroy(lzwP->codeBufferP);
+
+    free(lzwP->hashTable);
+
+    free(lzwP);
+}
+
+
+
+static void
+lzwHashClear(lzwCompressor * const lzwP) {
+
+    /* Empty the code table */
+
+    unsigned int i;
+
+    for (i = 0; i < HSIZE; ++i)
+        lzwP->hashTable[i].fcode = -1;
+
+    lzwP->nextUnusedCode = lzwP->clearCode + 2;
+
+    
+}
+
+
+
+static void
+lzw_clearBlock(lzwCompressor * const lzwP) {
+/*----------------------------------------------------------------------------
+  
+-----------------------------------------------------------------------------*/
+    lzwHashClear(lzwP);
+
+    codeBuffer_output(lzwP->codeBufferP, lzwP->clearCode);
+
+    codeBuffer_resetCodeSize(lzwP->codeBufferP);
+
+    lzwP->codeLimit = lzwP->initCodeLimit;
+}
+
+
+
+static void
+lzwAdjustCodeSize(lzwCompressor * const lzwP,
+                  stringCode      const newCode) {
+/*----------------------------------------------------------------------------
+   Assuming we just defined code 'newCode', increase the code size as
+   required so that this code fits.
+
+   The decompressor is mimicking our assignment of that code, so knows that
+   we are making this adjustment, so expects codes of the new size.
+-----------------------------------------------------------------------------*/
+    assert(newCode <= lzwP->codeLimit);
+
+    if (newCode == lzwP->codeLimit) {
+        lzwP->codeLimit *= 2;
+        codeBuffer_increaseCodeSize(lzwP->codeBufferP);
+
+        assert(lzwP->codeLimit <= maxCodeLimitLzw);
+    }
+}
+
+
+
+static void
+lzwOutputCurrentString(lzwCompressor * const lzwP) {
+/*----------------------------------------------------------------------------
+   Put a code for the currently built-up string in the output stream.
+
+   Doing this causes a new string code to be defined (code is
+   lzwP->nextUnusedCode), so Caller must add that to the hash.  If
+   that code's size is beyond the overall limit, we reset the hash
+   (which means future codes will start back at the minimum size) and
+   put a clear code in the stream to tell the decompressor to do the
+   same.  So Caller must add it to the hash _before_ calling us.
+
+   Note that in the non-compressing case, the overall limit is small
+   enough to prevent us from ever defining string codes; we'll always
+   reset the hash.
+
+   There's an odd case that always screws up any attempt to make this
+   code cleaner: At the end of the LZW stream, you have to output the
+   code for the final string even though you don't have a following
+   pixel that would make a longer string.  So there's nothing to add
+   to the hash table and no point in allocating a new string code.
+   But the decompressor doesn't know that we're done, so he allocates
+   the next string code and may therefore increase his code length.
+   If we don't do the same, we will write our one last code -- the EOF
+   code -- in a code length smaller than what the decompressor is
+   expecting, and he will have a premature end of stream.
+
+   So this subroutine does run for that final code flush and does some
+   of the motions of defining a new string code, but this subroutine
+   can't update the hash because in that particular case, there's
+   nothing to add.
+-----------------------------------------------------------------------------*/
+    codeBuffer_output(lzwP->codeBufferP, lzwP->stringSoFar);
+    if (lzwP->nextUnusedCode < lzwP->codeBufferP->maxCodeLimit) {
+        /* Allocate the code for the extended string, which Caller
+           should have already put in the hash so he can use it in the
+           future.  Decompressor knows when it sees the code output
+           above to define a string on its end too, using the same
+           string code we do.
+        */
+        stringCode const newCode = lzwP->nextUnusedCode++;
+
+        /* This code may be too big to fit in the current code size, in
+           which case we have to increase the code size (and decompressor
+           will do the same).
+        */
+        lzwAdjustCodeSize(lzwP, newCode);
+    } else {
+        /* Forget all the strings so far; start building again; tell
+           decompressor to do the same.
+        */
+        lzw_clearBlock(lzwP);
+    }
+}
+
+
+
+static void
+lzw_flush(lzwCompressor * const lzwP) {
+
+    if (lzwP->lzw)
+        lzwOutputCurrentString(lzwP);
+        /* Put out the code for the final string. */
+
+    codeBuffer_output(lzwP->codeBufferP, lzwP->eofCode);
+
+    codeBuffer_flush(lzwP->codeBufferP);
+}
+
+
+
+static unsigned int
+primaryHash(stringCode   const baseString,
+            stringCode   const additionalPixel,
+            unsigned int const hshift) {
+
+    unsigned int hash;
+
+    assert(baseString < maxCodeLimitLzw);
+    assert(additionalPixel < MAXCMAPSIZE);
+
+    hash = (additionalPixel << hshift) ^ baseString;
+
+    assert(hash < HSIZE);
+
+    return hash;
+}
+
+    
+
+static void
+lookupInHash(lzwCompressor *  const lzwP,
+             unsigned int     const gifPixel,
+             long             const fcode,
+             bool *           const foundP,
+             unsigned short * const codeP,
+             unsigned int *   const hashP) {
+
+    int disp;
+        /* secondary hash stride (after G. Knott) */
+    int i;
+        /* Index into hash table */
+
+    i = primaryHash(lzwP->stringSoFar, gifPixel, lzwP->hshift);
+    disp = (i == 0) ? 1 : HSIZE - i;
+
+    while (lzwP->hashTable[i].fcode != fcode &&
+           lzwP->hashTable[i].fcode >= 0) {
+        i -= disp;
+        if (i < 0)
+            i += HSIZE;
+    }
+
+    if (lzwP->hashTable[i].fcode == fcode) {
+        /* Found fcode in hash table */
+        *foundP = TRUE;
+        *codeP = lzwP->hashTable[i].ent;
+    } else {
+        /* Found where it _should_ be (but it's not) with primary hash */
+        *foundP = FALSE;
+        *hashP = i;
+    }
+}
+
+
+
+static void
+lzw_encodePixel(lzwCompressor * const lzwP,
+                unsigned int    const gifPixel) {
+
+    bool found;
+    unsigned short code;
+    unsigned int hash;
+        /* Index into hash table where the value should go */
+    
+    assert(gifPixel < 256);
+
+    if (!lzwP->buildingString) {
+        /* Start a new string with just this pixel */
+        lzwP->stringSoFar = gifPixel;
+        lzwP->buildingString = TRUE;
+    } else {
+        long const fcode = ((long) gifPixel << BITS) + lzwP->stringSoFar;
+            /* The encoding of the string we've already recognized plus the
+               instant pixel, to be looked up in the hash of knows strings.
+            */
+    
+        lookupInHash(lzwP, gifPixel, fcode, &found, &code, &hash);
+
+        if (found)
+            /* With this new pixel, it is still a known string; 'code' is
+               its code
+            */
+            lzwP->stringSoFar = code;
+        else {
+            /* It's no longer a known string.  Output the code for the
+               known prefix of the string, thus defining a new string
+               code for possible later use.  Warning:
+               lzwOutputCurrentString() does more than you think. 
+            */
+
+            lzwP->hashTable[hash].ent   = lzwP->nextUnusedCode;
+            lzwP->hashTable[hash].fcode = fcode;
+
+            lzwOutputCurrentString(lzwP);
+
+            /* This singleton pixel starts the next string */
+            lzwP->stringSoFar = gifPixel;
+        }
+    }
+}
+
+
+
+/*
+ * compress stdin to stdout
+ *
+ * Algorithm:  use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination.  We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe.  Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation.  Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills.  The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor.  Late addition:  construct the table according to
+ * file size for noticeable speed improvement on small files.  Please direct
+ * questions about this implementation to ames!jaw.
+ */
+
+static void
+writePixelUncompressed(lzwCompressor * const lzwP,
+                       unsigned int    const gifPixel) {
+                      
+    lzwP->stringSoFar = gifPixel;
+    lzwOutputCurrentString(lzwP);
+
+}    
+
+static void
+writeRaster(struct pam *  const pamP,
+            rowReader *   const rowReaderP,
+            unsigned int  const alphaPlane,
+            unsigned int  const alphaThreshold,
+            struct cmap * const cmapP, 
+            unsigned int  const initBits,
+            FILE *        const ofP,
+            bool          const lzw) {
+/*----------------------------------------------------------------------------
+   Write the raster to file 'ofP'.
+
+   Get the raster to write from 'rowReaderP', which gives tuples whose
+   format is described by 'pamP'.
+
+   Use the colormap 'cmapP' to generate the raster ('rowReaderP' gives
+   pixel values as RGB samples; the GIF raster is colormap indices).
+
+   Write the raster using LZW compression, or uncompressed depending
+   on 'lzw'.
+-----------------------------------------------------------------------------*/
+    lzwCompressor * lzwP;
+    tuple * tuplerow;
+    unsigned int nRowsDone;
+        /* Number of rows we have read so far from the the input (the
+           last of which is the one we're working on now).  Note that
+           in case of interlace, this is not the same thing as the row
+           number of the current row.
+        */
+    
+    lzwP = lzw_create(ofP, initBits, lzw);
+
+    tuplerow = pnm_allocpamrow(pamP);
+
+    lzw_clearBlock(lzwP);
+
+    nRowsDone = 0;
+    
+    while (nRowsDone < pamP->height) {
+        unsigned int col;
+
+        rowReader_read(rowReaderP, tuplerow);
+
+        for (col = 0; col < pamP->width; ++col) {
+            unsigned int const colorIndex =
+                gifPixel(pamP, tuplerow[col], alphaPlane, alphaThreshold,
+                         cmapP);
+            
+                /* The value for the pixel in the GIF image.  I.e. the colormap
+                   index.
+                */
+            if (lzw)
+                lzw_encodePixel(lzwP, colorIndex);
+            else
+                writePixelUncompressed(lzwP, colorIndex);    
+        }
+        ++nRowsDone;
+    }
+    /* Gif is no good with no pixels; fortunately, that's impossible: */
+    assert(nRowsDone > 0);
+
+    lzw_flush(lzwP);
+
+    pnm_freepamrow(tuplerow);
+    
+    lzw_destroy(lzwP);
+}
+
+
+
+
+
+
+
+
+
+static void
+writeGlobalColorMap(FILE *              const ofP,
+                    const struct cmap * const cmapP,
+                    unsigned int        const bitsPerPixel) {
+/*----------------------------------------------------------------------------
+  Write out the Global Color Map
+
+  Note that the Global Color Map is always a power of two colors
+  in size, but *cmapP could be smaller than that.  So we pad with
+  black.
+-----------------------------------------------------------------------------*/
+    unsigned int const colorMapSize = 1 << bitsPerPixel;
+
+    struct pam pam;
+    unsigned int i;
+    tuple tupleRgb255;
+
+    if (verbose)
+        pm_message("Writing %u-entry global colormap for %u colors",
+                   colorMapSize, cmapP->cmapSize);
+
+    pam = cmapP->pam;
+    pam.size = PAM_STRUCT_SIZE(allocation_depth);
+    pam.len = pam.size;
+    pnm_setminallocationdepth(&pam, 3);
+
+    tupleRgb255 = pnm_allocpamtuple(&pam);
+
+    for (i = 0; i < colorMapSize; ++i) {
+        if (i < cmapP->cmapSize) {
+            tuple const color = cmapP->color[cmapP->permi[i]];
+
+            assert(cmapP->permi[i] < cmapP->cmapSize);
+
+            pnm_scaletuple(&pam, tupleRgb255, color, 255);
+            pnm_maketuplergb(&pam, tupleRgb255);
+
+            fputc(tupleRgb255[PAM_RED_PLANE], ofP);
+            fputc(tupleRgb255[PAM_GRN_PLANE], ofP);
+            fputc(tupleRgb255[PAM_BLU_PLANE], ofP);
+        } else {
+            fputc(0, ofP);
+            fputc(0, ofP);
+            fputc(0, ofP);
+        }
+    }
+    pnm_freepamtuple(tupleRgb255);
+}
+        
+
+
+static void
+writeGifHeader(FILE *              const ofP,
+               unsigned int        const width,
+               unsigned int        const height, 
+               unsigned int        const background, 
+               unsigned int        const bitsPerPixel,
+               const struct cmap * const cmapP,
+               char                const comment[]) {
+
+    unsigned int const resolution = bitsPerPixel;
+
+    unsigned char b;
+
+    /* Write the Magic header */
+    if (cmapP->haveTransparent || comment)
+        fwrite("GIF89a", 1, 6, ofP);
+    else
+        fwrite("GIF87a", 1, 6, ofP);
+
+    /* Write out the screen width and height */
+    Putword(width,  ofP);
+    Putword(height, ofP);
+
+    /* Indicate that there is a global color map */
+    b = 0x80;       /* Yes, there is a color map */
+
+    /* OR in the resolution */
+    b |= (resolution - 1) << 4;
+
+    /* OR in the Bits per Pixel */
+    b |= (bitsPerPixel - 1);
+
+    /* Write it out */
+    fputc(b, ofP);
+
+    /* Write out the Background color */
+    assert((unsigned char)background == background);
+    fputc(background, ofP);
+
+    /* Byte of 0's (future expansion) */
+    fputc(0x00, ofP);
+
+    writeGlobalColorMap(ofP, cmapP, bitsPerPixel);
+
+    if (cmapP->haveTransparent) 
+        writeTransparentColorIndexExtension(ofP, cmapP->transparent);
+
+    if (comment)
+        writeCommentExtension(ofP, comment);
+}
+
+
+
+static void
+writeImageHeader(FILE *       const ofP,
+                 unsigned int const leftOffset,
+                 unsigned int const topOffset,
+                 unsigned int const gWidth,
+                 unsigned int const gHeight,
+                 bool         const gInterlace,
+                 unsigned int const initCodeSize) {
+
+    Putword(leftOffset, ofP);
+    Putword(topOffset,  ofP);
+    Putword(gWidth,     ofP);
+    Putword(gHeight,    ofP);
+
+    /* Write out whether or not the image is interlaced */
+    if (gInterlace)
+        fputc(0x40, ofP);
+    else
+        fputc(0x00, ofP);
+
+    /* Write out the initial code size */
+    fputc(initCodeSize, ofP);
+}
+
+
+
+static void
+reportImageInfo(bool         const interlace,
+                unsigned int const background,
+                unsigned int const bitsPerPixel) {
+
+    if (verbose) {
+        if (interlace)
+            pm_message("interlaced");
+        else
+            pm_message("not interlaced");
+        pm_message("Background color index = %u", background);
+        pm_message("%u bits per pixel", bitsPerPixel);
+    }
+}
+
+
+
+static void
+gifEncode(struct pam *  const pamP,
+          FILE *        const ofP, 
+          pm_filepos    const rasterPos,
+          bool          const gInterlace,
+          int           const background, 
+          unsigned int  const bitsPerPixel,
+          struct cmap * const cmapP,
+          char          const comment[],
+          bool          const lzw) {
+
+    unsigned int const leftOffset = 0;
+    unsigned int const topOffset  = 0;
+
+    unsigned int const initCodeSize = bitsPerPixel <= 1 ? 2 : bitsPerPixel;
+        /* The initial code size */
+
+    sample const alphaThreshold = (pamP->maxval + 1) / 2;
+        /* Levels below this in the alpha plane indicate transparent
+           pixels in the output image.
+        */
+
+    unsigned int const alphaPlane = pamAlphaPlane(pamP);
+
+    rowReader * rowReaderP;
+
+    reportImageInfo(gInterlace, background, bitsPerPixel);
+
+    writeGifHeader(ofP, pamP->width, pamP->height, background,
+                   bitsPerPixel, cmapP, comment);
+
+    /* Write an Image separator */
+    fputc(',', ofP);
+
+    writeImageHeader(ofP, leftOffset, topOffset, pamP->width, pamP->height,
+                     gInterlace, initCodeSize);
+
+    rowReaderP = rowReader_create(pamP, rasterPos, gInterlace);
+
+    /* Write the actual raster */
+
+    writeRaster(pamP, rowReaderP, alphaPlane, alphaThreshold,
+                cmapP, initCodeSize + 1, ofP, lzw);
+
+    rowReader_destroy(rowReaderP);
+
+    /* Write out a zero length data block (to end the series) */
+    fputc(0, ofP);
+
+    /* Write the GIF file terminator */
+    fputc(';', ofP);
+}
+
+
+
+static void
+reportTransparent(struct cmap * const cmapP) {
+
+    if (verbose) {
+        if (cmapP->haveTransparent) {
+            tuple const color = cmapP->color[cmapP->permi[cmapP->transparent]];
+            pm_message("Color %u (%lu, %lu, %lu) is transparent",
+                       cmapP->transparent,
+                       color[PAM_RED_PLANE],
+                       color[PAM_GRN_PLANE],
+                       color[PAM_BLU_PLANE]);
+        } else
+            pm_message("No transparent color");
+    }
+}
+
+
+
+static void
+computeTransparent(char          const colorarg[], 
+                   bool          const usingFakeTrans,
+                   unsigned int  const fakeTransparent,
+                   struct cmap * const cmapP) {
+/*----------------------------------------------------------------------------
+   Figure out the color index (index into the colormap) of the color
+   that is to be transparent in the GIF.
+
+   colorarg[] is the string that specifies the color the user wants to
+   be transparent (e.g. "red", "#fefefe").  Its maxval is the maxval
+   of the colormap.  'cmap' is the full colormap except that its
+   'transparent' component isn't valid.
+
+   colorarg[] is a standard Netpbm color specification, except that
+   may have a "=" prefix, which means it specifies a particular exact
+   color, as opposed to without the "=", which means "the color that
+   is closest to this and actually in the image."
+
+   colorarg[] null means the color didn't ask for a particular color
+   to be transparent.
+
+   Establish no transparent color if colorarg[] specifies an exact
+   color and that color is not in the image.  Also issue an
+   informational message.
+
+   'usingFakeTrans' means pixels will be transparent because of something
+   other than their foreground color, and 'fakeTransparent' is the
+   color map index for transparent colors.
+-----------------------------------------------------------------------------*/
+    if (colorarg) {
+        const char * colorspec;
+        bool exact;
+        tuple transcolor;
+        bool found;
+        int presortColorindex;
+        
+        if (colorarg[0] == '=') {
+            colorspec = &colorarg[1];
+            exact = TRUE;
+        } else {
+            colorspec = colorarg;
+            exact = FALSE;
+        }
+
+        transcolor = pnm_parsecolor(colorspec, cmapP->pam.maxval);
+        pnm_lookuptuple(&cmapP->pam, cmapP->tuplehash, transcolor, &found,
+                        &presortColorindex);
+        
+        if (found) {
+            cmapP->haveTransparent = TRUE;
+            cmapP->transparent = cmapP->perm[presortColorindex];
+        } else if (!exact) {
+            cmapP->haveTransparent = TRUE;
+            cmapP->transparent =
+                cmapP->perm[closestColor(transcolor, &cmapP->pam, cmapP)];
+        } else {
+            cmapP->haveTransparent = FALSE;
+            pm_message("Warning: specified transparent color "
+                       "does not occur in image.");
+        }
+    } else if (usingFakeTrans) {
+        cmapP->haveTransparent = TRUE;
+        cmapP->transparent = fakeTransparent;
+    } else
+        cmapP->haveTransparent = FALSE;
+
+    reportTransparent(cmapP);
+}
+
+
+
+static unsigned int
+sortOrder(tuple        const tuple,
+          struct pam * const pamP) {
+    
+    if (pamP->depth < 3)
+        return tuple[0];
+    else
+        return ((tuple[0] * MAXCMAPSIZE) + tuple[1]) * MAXCMAPSIZE + tuple[2];
+}
+
+
+
+
+static void
+sortColormap(bool          const sort,
+             struct cmap * const cmapP) {
+/*----------------------------------------------------------------------------
+   Sort (in place) the colormap *cmapP.
+
+   Create the perm[] and permi[] mappings for the colormap.
+
+   'sort' is logical:  true means to sort the colormap by red intensity,
+   then by green intensity, then by blue intensity.  False means a null
+   sort -- leave it in the same order in which we found it.
+-----------------------------------------------------------------------------*/
+    tuple * const color = cmapP->color;
+    int * const perm = cmapP->perm;
+    int * const permi = cmapP->permi;
+    struct pam * const pamP = &cmapP->pam;
+    unsigned int const cmapSize = cmapP->cmapSize;
+    
+    unsigned int i;
+
+    /* We will sort permi[].  So we first set up permi[] to reflect the
+       original, unsorted order.
+    */
+    for (i=0; i < cmapSize; i++)
+        permi[i] = i;
+
+    if (sort) {
+        pm_message("sorting colormap");
+        for (i = 0; i < cmapSize; ++i) {
+            unsigned int j;
+            for (j = i+1; j < cmapSize; ++j) {
+                if (sortOrder(color[permi[i]], pamP) >
+                    sortOrder(color[permi[j]], pamP)) {
+
+                    sample tmp;
+                    
+                    tmp = permi[i]; permi[i] = permi[j]; permi[j] = tmp;
+                }
+            }
+        }
+    }
+    for (i = 0; i < cmapSize; ++i)
+        perm[permi[i]] = i;
+}
+
+
+
+static void
+addToColormap(struct cmap *  const cmapP, 
+              const char *   const colorspec, 
+              unsigned int * const newIndexP) {
+/*----------------------------------------------------------------------------
+  Add a new entry to the colormap.  Make the color that specified by
+  'colorspec', and return the index of the new entry as *newIndexP.
+
+  'colorspec' is a color specification given by the user, e.g.
+  "red" or "rgb:ff/03/0d".  The maxval for this color specification is
+  that for the colormap *cmapP.
+-----------------------------------------------------------------------------*/
+    tuple const transcolor = pnm_parsecolor(colorspec, cmapP->pam.maxval);
+
+    unsigned int const colorIndex = cmapP->cmapSize++;
+
+    cmapP->color[colorIndex] = pnm_allocpamtuple(&cmapP->pam);
+
+    if (cmapP->pam.depth < 3) {
+        if (!pnm_rgbtupleisgray(transcolor))
+            pm_error("Image is grayscale, but color '%s' is not gray.  "
+                     "It is (%lu, %lu, %lu)",
+                     colorspec,
+                     transcolor[PAM_RED_PLANE],
+                     transcolor[PAM_GRN_PLANE],
+                     transcolor[PAM_BLU_PLANE]);
+        else
+            cmapP->color[colorIndex][0] = transcolor[0];
+    } else {
+        pnm_assigntuple(&cmapP->pam, cmapP->color[colorIndex], transcolor);
+    }
+    *newIndexP = colorIndex;
+}
+
+
+
+static void
+colormapFromFile(char               const filespec[],
+                 unsigned int       const maxcolors,
+                 tupletable *       const tupletableP, 
+                 struct pam *       const mapPamP,
+                 unsigned int *     const colorCountP) {
+/*----------------------------------------------------------------------------
+   Read a colormap from the Netpbm file filespec[].  Return a
+   tupletable of the colors in it (which is practically a colormap) as
+   *tupletableP and the format of those tuples as *mapPamP.  Return
+   the number of colors as *colorsCountP.
+-----------------------------------------------------------------------------*/
+    FILE * mapfileP;
+    tuple ** colors;
+    unsigned int colorCount;
+
+    mapfileP = pm_openr(filespec);
+    colors = pnm_readpam(mapfileP, mapPamP, PAM_STRUCT_SIZE(tuple_type));
+    pm_close(mapfileP);
+
+    pm_message("computing other colormap ...");
+    
+    pnm_computetuplefreqtable(mapPamP, colors, maxcolors, &colorCount);
+
+    *colorCountP = colorCount;
+
+    pnm_freepamarray(colors, mapPamP); 
+}
+
+
+
+static void
+computeColormapFromInput(struct pam *   const pamP,
+                         unsigned int   const maxcolors,
+                         unsigned int   const nInputComp,
+                         struct pam *   const mapPamP,
+                         unsigned int * const colorCountP,
+                         tupletable *   const tuplefreqP) {
+    
+    tupletable tuplefreq;
+
+    pm_message("computing colormap...");
+
+    tuplefreq = pnm_computetuplefreqtable3(
+        pamP, NULL, maxcolors, nInputComp, pamP->maxval, colorCountP);
+
+    *mapPamP = *pamP;
+    mapPamP->depth = nInputComp;
+
+    *tuplefreqP = tuplefreq;
+}
+
+
+
+static void
+computeLibnetpbmColormap(struct pam *   const pamP,
+                         bool           const haveAlpha,
+                         const char *   const mapfile,
+                         tuple *        const color,
+                         tuplehash *    const tuplehashP,
+                         struct pam *   const mapPamP,
+                         unsigned int * const colorCountP) {
+/*----------------------------------------------------------------------------
+   Compute a colormap, libnetpbm style, for the image described by
+   'pamP', which is positioned to the raster.
+
+   If 'mapfile' is non-null, Use the colors in that (Netpbm) file for
+   the color map instead of the colors in 'pamP'.
+
+   Return the colormap as color[] and *tuplehashP.  Return the format
+   of those tuples as *mapPamP.
+
+   The tuples of the color map have a meaningful depth of 1 (grayscale) or 3
+   (color) and *mapPamP reflects that.
+
+   While we're at it, count the colors and validate that there aren't
+   too many.  Return the count as *colorCountP.  In determining if there are
+   too many, allow one slot for a fake transparency color if 'haveAlpha'
+   is true.  If there are too many, issue an error message and abort the
+   program.
+-----------------------------------------------------------------------------*/
+    unsigned int const maxcolors = haveAlpha ? MAXCMAPSIZE - 1 : MAXCMAPSIZE;
+        /* The most colors we can tolerate in the image.  If we have
+           our own made-up entry in the colormap for transparency, it
+           isn't included in this count.
+        */
+    unsigned int const nInputComp = haveAlpha ? pamP->depth - 1 : pamP->depth;
+        /* Number of color components (not alpha) in the input image */
+
+    unsigned int i;
+    tupletable tuplefreq;
+    unsigned int colorCount;
+
+    if (mapfile) {
+        /* Read the colormap from a separate colormap file. */
+        colormapFromFile(mapfile, maxcolors, &tuplefreq, mapPamP,
+                         &colorCount);
+
+        if (mapPamP->depth != nInputComp)
+            pm_error("Depth of map file (%u) does not match number of "
+                     "color components in input file (%u)",
+                      mapPamP->depth, pamP->depth);
+        if (mapPamP->maxval != pamP->maxval)
+            pm_error("Maxval of map file (%lu) does not match maxval of "
+                     "input file (%lu)", mapPamP->maxval, pamP->maxval);
+    } else
+        computeColormapFromInput(pamP, maxcolors, nInputComp, 
+                                 mapPamP, &colorCount, &tuplefreq);
+    
+    if (tuplefreq == NULL)
+        pm_error("too many colors - try doing a 'pnmquant %u'", maxcolors);
+
+    pm_message("%u colors found", colorCount);
+
+    for (i = 0; i < colorCount; ++i) {
+        color[i] = pnm_allocpamtuple(mapPamP);
+        pnm_assigntuple(mapPamP, color[i], tuplefreq[i]->tuple);
+    }
+
+    /* And make a hash table for fast lookup. */
+    *tuplehashP =
+        pnm_computetupletablehash(mapPamP, tuplefreq, colorCount);
+
+    *colorCountP = colorCount;
+
+    pnm_freetupletable(mapPamP, tuplefreq);
+}
+
+
+
+static void
+destroyCmap(struct cmap * const cmapP) {
+
+    unsigned int colorIndex;
+    
+    for (colorIndex = 0; colorIndex < cmapP->cmapSize; ++colorIndex)
+        pnm_freepamtuple(cmapP->color[colorIndex]);
+
+    pnm_destroytuplehash(cmapP->tuplehash);
+}
+
+
+
+int
+main(int argc, char *argv[]) {
+    struct cmdlineInfo cmdline;
+    FILE * ifP;
+    struct pam pam;
+    unsigned int bitsPerPixel;
+    pm_filepos rasterPos;
+
+    struct cmap cmap;
+        /* The colormap, with all its accessories */
+    unsigned int fakeTransparent;
+        /* colormap index of the fake transparency color we're using to
+           implement the alpha mask.  Undefined if we're not doing an alpha
+           mask.
+        */
+    
+    pnm_init(&argc, argv);
+    
+    parseCommandLine(argc, argv, &cmdline);
+    
+    verbose = cmdline.verbose;
+    
+    ifP = pm_openr_seekable(cmdline.input_filespec);
+    
+    pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type));
+    
+    pm_tell2(ifP, &rasterPos, sizeof(rasterPos));
+    
+    computeLibnetpbmColormap(&pam, !!pamAlphaPlane(&pam), cmdline.mapfile, 
+                             cmap.color, &cmap.tuplehash,
+                             &cmap.pam, &cmap.cmapSize);
+    
+    assert(cmap.pam.maxval == pam.maxval);
+
+    if (pamAlphaPlane(&pam)) {
+        /* Add a fake entry to the end of the colormap for transparency.  
+           Make its color black. 
+        */
+        addToColormap(&cmap, cmdline.alphacolor, &fakeTransparent);
+    }
+    sortColormap(cmdline.sort, &cmap);
+
+    bitsPerPixel = pm_maxvaltobits(cmap.cmapSize-1);
+
+    computeTransparent(cmdline.transparent,
+                       !!pamAlphaPlane(&pam), fakeTransparent, &cmap);
+
+    /* All set, let's do it. */
+    gifEncode(&pam, stdout, rasterPos,
+              cmdline.interlace, 0, bitsPerPixel, &cmap, cmdline.comment,
+              !cmdline.nolzw);
+    
+    destroyCmap(&cmap);
+
+    pm_close(ifP);
+    pm_close(stdout);
+    
+    return 0;
+}
+
+
+
+/*============================================================================
+  Original version, named 'ppmgif' was by Jef Poskanzer in 1989, based
+  on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>.A Lempel-Zim
+  compression based on "compress".
+
+  Switched to use libnetpbm PAM facilities (ergo process PAM images)
+  and renamed 'pamtogif' by Bryan Henderson November 2006.
+
+  The non-LZW GIF generation stuff was adapted from the Independent
+  JPEG Group's djpeg on 2001.09.29.  In 2006.12 the output subroutines
+  were rewritten; now no uncompressed output subroutines are derived from
+  the Independent JPEG Group's source code.
+
+ 
+  Copyright (C) 1989 by Jef Poskanzer.
+ 
+  Permission to use, copy, modify, and distribute this software and its
+  documentation for any purpose and without fee is hereby granted, provided
+  that the above copyright notice appear in all copies and that both that
+  copyright notice and this permission notice appear in supporting
+  documentation.  This software is provided "as is" without express or
+  implied warranty.
+ 
+  The Graphics Interchange Format(c) is the Copyright property of
+  CompuServe Incorporated.  GIF(sm) is a Service Mark property of
+  CompuServe Incorporated.
+============================================================================*/
diff --git a/converter/other/pamtopnm.c b/converter/other/pamtopnm.c
index cc1164da..6835b43f 100644
--- a/converter/other/pamtopnm.c
+++ b/converter/other/pamtopnm.c
@@ -108,6 +108,7 @@ main(int argc, char *argv[]) {
 
     struct cmdlineInfo cmdline;
     FILE* ifP;
+    bool eof;   /* no more images in input stream */
     struct pam inpam;   /* Input PAM image */
     struct pam outpam;  /* Output PNM image */
 
@@ -117,39 +118,45 @@ main(int argc, char *argv[]) {
 
     ifP = pm_openr(cmdline.inputFilespec);
 
-    pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
+    eof = FALSE;
+    while (!eof) {
+        pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
 
-    validateTupleType(inpam, cmdline.assume);
+        validateTupleType(inpam, cmdline.assume);
 
-    outpam = inpam;
-    outpam.file = stdout;
-    
-    if (inpam.depth < 3) {
-        outpam.depth = 1;
-        if (inpam.maxval == 1)
-            outpam.format = PBM_FORMAT;
-        else 
-            outpam.format = PGM_FORMAT;
-    } else {
-        outpam.depth = 3;
-        outpam.format = PPM_FORMAT;
-    }
+        outpam = inpam;
+        outpam.file = stdout;
+        
+        if (inpam.depth < 3) {
+            outpam.depth = 1;
+            if (inpam.maxval == 1)
+                outpam.format = PBM_FORMAT;
+            else 
+                outpam.format = PGM_FORMAT;
+        } else {
+            outpam.depth = 3;
+            outpam.format = PPM_FORMAT;
+        }
 
-    pnm_writepaminit(&outpam);
+        pnm_writepaminit(&outpam);
 
-    {
-        tuple *tuplerow;
-        
-        tuplerow = pnm_allocpamrow(&inpam);      
-        { 
-            int row;
+        {
+            tuple *tuplerow;
             
-            for (row = 0; row < inpam.height; row++) {
-                pnm_readpamrow(&inpam, tuplerow);
-                pnm_writepamrow(&outpam, tuplerow);
+            tuplerow = pnm_allocpamrow(&inpam);      
+            { 
+                int row;
+                
+                for (row = 0; row < inpam.height; row++) {
+                    pnm_readpamrow(&inpam, tuplerow);
+                    pnm_writepamrow(&outpam, tuplerow);
+                }
             }
+            pnm_freepamrow(tuplerow);        
         }
-        pnm_freepamrow(tuplerow);        
+
+        pnm_nextimage(ifP, &eof);
     }
+
     return 0;
 }
diff --git a/converter/other/pamtosvg/curve.h b/converter/other/pamtosvg/curve.h
index ee046620..2f010d45 100644
--- a/converter/other/pamtosvg/curve.h
+++ b/converter/other/pamtosvg/curve.h
@@ -77,14 +77,16 @@ extern curve_type copy_most_of_curve (curve_type c);
 /* Free the memory C uses.  */
 extern void free_curve (curve_type c);
 
+/* Like `append_pixel', for a point in real coordinates.  */
+void
+append_point(curve_type  const curve,
+             float_coord const coord);
+
 /* Append the point P to the end of C's list.  */
 void
 append_pixel(curve_type    const c,
              pm_pixelcoord const p);
 
-/* Like `append_pixel', for a point in real coordinates.  */
-extern void append_point (curve_type const c, float_coord const p);
-
 /* Write some or all, respectively, of the curve C in human-readable
    form to the log file, if logging is enabled.  */
 extern void log_curve (curve_type c, bool print_t);
diff --git a/converter/other/pamtosvg/fit.c b/converter/other/pamtosvg/fit.c
index 08db41db..2fa64500 100644
--- a/converter/other/pamtosvg/fit.c
+++ b/converter/other/pamtosvg/fit.c
@@ -54,21 +54,6 @@ typedef struct index_list
 #define INDEX_LIST_LENGTH(i_l)  ((i_l).length)
 #define GET_LAST_INDEX(i_l)  ((i_l).data[INDEX_LIST_LENGTH (i_l) - 1])
 
-static void append_index (index_list_type *, unsigned);
-static void free_index_list (index_list_type *);
-static index_list_type new_index_list (void);
-static void remove_adjacent_corners (index_list_type *, unsigned, bool,
-                     at_exception_type * exception);
-static void filter (curve_type, fitting_opts_type *);
-static void find_vectors
-  (unsigned const, pixel_outline_type const, vector_type * const, vector_type * const, unsigned const);
-static float find_error (curve_type, spline_type, unsigned *,
-               at_exception_type * exception);
-static vector_type find_half_tangent (curve_type, bool start, unsigned *, unsigned);
-static void find_tangent (curve_type, bool, bool, unsigned);
-static void remove_knee_points (curve_type const, bool const);
-static void set_initial_parameter_values (curve_type);
-static float distance (float_coord, float_coord);
 
 
 static pm_pixelcoord
@@ -86,6 +71,50 @@ real_to_int_coord(float_coord const real_coord) {
 }
 
 
+/* Lists of array indices (well, that is what we use it for).  */
+
+static index_list_type
+new_index_list (void)
+{
+  index_list_type index_list;
+
+  index_list.data = NULL;
+  INDEX_LIST_LENGTH (index_list) = 0;
+
+  return index_list;
+}
+
+static void
+free_index_list (index_list_type *index_list)
+{
+  if (INDEX_LIST_LENGTH (*index_list) > 0)
+    {
+      free (index_list->data);
+      index_list->data = NULL;
+      INDEX_LIST_LENGTH (*index_list) = 0;
+    }
+}
+
+static void
+append_index (index_list_type *list, unsigned new_index)
+{
+  INDEX_LIST_LENGTH (*list)++;
+  REALLOCARRAY_NOFAIL(list->data, INDEX_LIST_LENGTH(*list));
+  list->data[INDEX_LIST_LENGTH (*list) - 1] = new_index;
+}
+
+
+/* Return the Euclidean distance between P1 and P2.  */
+
+static float
+distance (float_coord p1, float_coord p2)
+{
+  float x = p1.x - p2.x, y = p1.y - p2.y, z = p1.z - p2.z;
+  return (float) sqrt (SQR(x) + SQR(y) + SQR(z));
+}
+
+
+
 static void
 appendCorner(index_list_type *  const cornerListP,
              unsigned int       const pixelSeq,
@@ -102,6 +131,45 @@ appendCorner(index_list_type *  const cornerListP,
 
 
 static void
+find_vectors(unsigned int       const test_index,
+             pixel_outline_type const outline,
+             vector_type *      const in,
+             vector_type *      const out,
+             unsigned int       const corner_surround) {
+/*----------------------------------------------------------------------------
+  Return the difference vectors coming in and going out of the outline
+  OUTLINE at the point whose index is TEST_INDEX.  In Phoenix,
+  Schneider looks at a single point on either side of the point we're
+  considering.  That works for him because his points are not touching.
+  But our points *are* touching, and so we have to look at
+  `corner_surround' points on either side, to get a better picture of
+  the outline's shape.
+-----------------------------------------------------------------------------*/
+    int i;
+    unsigned n_done;
+    pm_pixelcoord const candidate = O_COORDINATE(outline, test_index);
+
+    in->dx  = in->dy  = in->dz  = 0.0;
+    out->dx = out->dy = out->dz = 0.0;
+    
+    /* Add up the differences from p of the `corner_surround' points
+       before p.
+    */
+    for (i = O_PREV(outline, test_index), n_done = 0;
+         n_done < corner_surround;
+         i = O_PREV(outline, i), ++n_done)
+        *in = Vadd(*in, IPsubtract(O_COORDINATE(outline, i), candidate));
+    
+    /* And the points after p. */
+    for (i = O_NEXT (outline, test_index), n_done = 0;
+         n_done < corner_surround;
+         i = O_NEXT(outline, i), ++n_done)
+        *out = Vadd(*out, IPsubtract(O_COORDINATE(outline, i), candidate));
+}
+
+
+
+static void
 lookAheadForBetterCorner(pixel_outline_type  const outline,
                          unsigned int        const basePixelSeq,
                          float               const baseCornerAngle,
@@ -210,6 +278,287 @@ establishCornerSearchLimits(pixel_outline_type  const outline,
 
 
 static void
+remove_adjacent_corners(index_list_type *   const list,
+                        unsigned int        const last_index,
+                        bool                const remove_adj_corners,
+                        at_exception_type * const exception) {
+/*----------------------------------------------------------------------------
+   Remove adjacent points from the index list LIST.  We do this by first
+   sorting the list and then running through it.  Since these lists are
+   quite short, a straight selection sort (e.g., p.139 of the Art of
+   Computer Programming, vol.3) is good enough.  LAST_INDEX is the index
+   of the last pixel on the outline, i.e., the next one is the first
+   pixel. We need this for checking the adjacency of the last corner.
+
+   We need to do this because the adjacent corners turn into
+   two-pixel-long curves, which can only be fit by straight lines.
+-----------------------------------------------------------------------------*/
+  unsigned int j;
+  unsigned int last;
+  index_list_type new_list = new_index_list ();
+
+  for (j = INDEX_LIST_LENGTH (*list) - 1; j > 0; j--)
+    {
+      unsigned search;
+      unsigned temp;
+      /* Find maximal element below `j'.  */
+      unsigned max_index = j;
+
+      for (search = 0; search < j; search++)
+        if (GET_INDEX (*list, search) > GET_INDEX (*list, max_index))
+          max_index = search;
+
+      if (max_index != j)
+        {
+          temp = GET_INDEX (*list, j);
+          GET_INDEX (*list, j) = GET_INDEX (*list, max_index);
+          GET_INDEX (*list, max_index) = temp;
+      
+      /* xx -- really have to sort?  */
+      LOG ("needed exchange");
+      at_exception_warning(exception, "needed exchange");
+        }
+    }
+
+  /* The list is sorted.  Now look for adjacent entries.  Each time
+     through the loop we insert the current entry and, if appropriate,
+     the next entry.  */
+  for (j = 0; j < INDEX_LIST_LENGTH (*list) - 1; j++)
+    {
+      unsigned current = GET_INDEX (*list, j);
+      unsigned next = GET_INDEX (*list, j + 1);
+
+      /* We should never have inserted the same element twice.  */
+      /* assert (current != next); */
+
+      if ((remove_adj_corners) && ((next == current + 1) || (next == current)))
+        j++;
+
+      append_index (&new_list, current);
+    }
+
+  /* Don't append the last element if it is 1) adjacent to the previous
+     one; or 2) adjacent to the very first one.  */
+  last = GET_LAST_INDEX (*list);
+  if (INDEX_LIST_LENGTH (new_list) == 0
+      || !(last == GET_LAST_INDEX (new_list) + 1
+           || (last == last_index && GET_INDEX (*list, 0) == 0)))
+    append_index (&new_list, last);
+
+  free_index_list (list);
+  *list = new_list;
+}
+
+/* A ``knee'' is a point which forms a ``right angle'' with its
+   predecessor and successor.  See the documentation (the `Removing
+   knees' section) for an example and more details.
+
+   The argument CLOCKWISE tells us which direction we're moving.  (We
+   can't figure that information out from just the single segment with
+   which we are given to work.)
+
+   We should never find two consecutive knees.
+
+   Since the first and last points are corners (unless the curve is
+   cyclic), it doesn't make sense to remove those.  */
+
+/* This evaluates to true if the vector V is zero in one direction and
+   nonzero in the other.  */
+#define ONLY_ONE_ZERO(v)                                                \
+  (((v).dx == 0.0 && (v).dy != 0.0) || ((v).dy == 0.0 && (v).dx != 0.0))
+
+/* There are four possible cases for knees, one for each of the four
+   corners of a rectangle; and then the cases differ depending on which
+   direction we are going around the curve.  The tests are listed here
+   in the order of upper left, upper right, lower right, lower left.
+   Perhaps there is some simple pattern to the
+   clockwise/counterclockwise differences, but I don't see one.  */
+#define CLOCKWISE_KNEE(prev_delta, next_delta)                                                  \
+  ((prev_delta.dx == -1.0 && next_delta.dy == 1.0)                                              \
+   || (prev_delta.dy == 1.0 && next_delta.dx == 1.0)                                    \
+   || (prev_delta.dx == 1.0 && next_delta.dy == -1.0)                                   \
+   || (prev_delta.dy == -1.0 && next_delta.dx == -1.0))
+
+#define COUNTERCLOCKWISE_KNEE(prev_delta, next_delta)                                   \
+  ((prev_delta.dy == 1.0 && next_delta.dx == -1.0)                                              \
+   || (prev_delta.dx == 1.0 && next_delta.dy == 1.0)                                    \
+   || (prev_delta.dy == -1.0 && next_delta.dx == 1.0)                                   \
+   || (prev_delta.dx == -1.0 && next_delta.dy == -1.0))
+
+
+
+static void
+remove_knee_points(curve_type const curve,
+                   bool       const clockwise) {
+
+      unsigned const offset = (CURVE_CYCLIC(curve) == true) ? 0 : 1;
+      curve_type const trimmed_curve = copy_most_of_curve(curve);
+
+      pm_pixelcoord previous;
+      unsigned i;
+
+      if (!CURVE_CYCLIC(curve))
+          append_pixel(trimmed_curve,
+                       real_to_int_coord(CURVE_POINT(curve, 0)));
+
+      previous = real_to_int_coord(CURVE_POINT(curve,
+                                               CURVE_PREV(curve, offset)));
+
+      for (i = offset; i < CURVE_LENGTH (curve) - offset; ++i) {
+          pm_pixelcoord const current =
+              real_to_int_coord(CURVE_POINT(curve, i));
+          pm_pixelcoord const next =
+              real_to_int_coord(CURVE_POINT(curve, CURVE_NEXT(curve, i)));
+          vector_type const prev_delta = IPsubtract(previous, current);
+          vector_type const next_delta = IPsubtract(next, current);
+
+          if (ONLY_ONE_ZERO(prev_delta) && ONLY_ONE_ZERO(next_delta)
+              && ((clockwise && CLOCKWISE_KNEE(prev_delta, next_delta))
+                  || (!clockwise
+                      && COUNTERCLOCKWISE_KNEE(prev_delta, next_delta))))
+              LOG2(" (%d,%d)", current.col, current.row);
+          else {
+              previous = current;
+              append_pixel(trimmed_curve, current);
+          }
+      }
+
+      if (!CURVE_CYCLIC(curve))
+          append_pixel(trimmed_curve,
+                       real_to_int_coord(LAST_CURVE_POINT(curve)));
+
+      if (CURVE_LENGTH(trimmed_curve) == CURVE_LENGTH(curve))
+          LOG(" (none)");
+
+      LOG(".\n");
+
+      free_curve(curve);
+      *curve = *trimmed_curve;
+      free(trimmed_curve);      /* free_curve? --- Masatake */
+}
+
+
+
+/* Smooth the curve by adding in neighboring points.  Do this
+   `filter_iterations' times.  But don't change the corners.  */
+
+static void
+filter(curve_type          const curve,
+       fitting_opts_type * const fitting_opts) {
+
+    unsigned iteration, this_point;
+    unsigned offset = (CURVE_CYCLIC (curve) == true) ? 0 : 1;
+    float_coord prev_new_point;
+    
+    /* We must have at least three points---the previous one, the current
+       one, and the next one.  But if we don't have at least five, we will
+       probably collapse the curve down onto a single point, which means
+       we won't be able to fit it with a spline.
+    */
+    if (CURVE_LENGTH (curve) < 5) {
+        LOG1 ("Length is %u, not enough to filter.\n", CURVE_LENGTH (curve));
+        return;
+    }
+
+    prev_new_point.x = FLT_MAX;
+    prev_new_point.y = FLT_MAX;
+    prev_new_point.z = FLT_MAX;
+    
+    for (iteration = 0;
+         iteration < fitting_opts->filter_iterations;
+         ++iteration) {
+        curve_type newcurve = copy_most_of_curve (curve);
+        bool collapsed = false;
+        
+        /* Keep the first point on the curve.  */
+        if (offset)
+            append_point (newcurve, CURVE_POINT (curve, 0));
+        
+        for (this_point = offset;
+             this_point < CURVE_LENGTH (curve) - offset;
+             ++this_point) {
+            vector_type in, out, sum;
+            float_coord new_point;
+            
+            /* Calculate the vectors in and out, computed by looking
+               at n points on either side of this_point. Experimental
+               it was found that 2 is optimal.
+            */
+
+            signed int prev, prevprev; /* have to be signed */
+            unsigned int next, nextnext;
+            float_coord candidate = CURVE_POINT (curve, this_point);
+            
+            prev = CURVE_PREV (curve, this_point);
+            prevprev = CURVE_PREV (curve, prev);
+            next = CURVE_NEXT (curve, this_point);
+            nextnext = CURVE_NEXT (curve, next);
+            
+            /* Add up the differences from p of the `surround' points
+               before p.
+            */
+            in.dx = in.dy = in.dz = 0.0;
+
+            in = Vadd (in, Psubtract (CURVE_POINT (curve, prev), candidate));
+            if (prevprev >= 0)
+                in = Vadd(in,
+                          Psubtract(CURVE_POINT (curve, prevprev), candidate));
+            
+            /* And the points after p.  Don't use more points after p than we
+               ended up with before it.
+            */
+            out.dx = out.dy = out.dz = 0.0;
+            
+            out = Vadd (out, Psubtract (CURVE_POINT (curve, next), candidate));
+            if (nextnext < CURVE_LENGTH (curve))
+                out = Vadd(out,
+                           Psubtract(CURVE_POINT (curve, nextnext),
+                                     candidate));
+            
+            /* Start with the old point.  */
+            new_point = candidate;
+            sum = Vadd (in, out);
+            /* We added 2*n+2 points, so we have to divide the sum by 2*n+2 */
+            new_point.x += sum.dx / 6;
+            new_point.y += sum.dy / 6;
+            new_point.z += sum.dz / 6;
+            if (fabs (prev_new_point.x - new_point.x) < 0.3
+                && fabs (prev_new_point.y - new_point.y) < 0.3
+                && fabs (prev_new_point.z - new_point.z) < 0.3) {
+                collapsed = true;
+                break;
+            }
+            
+            
+            /* Put the newly computed point into a separate curve, so it
+               doesn't affect future computation (on this iteration).
+            */
+            append_point (newcurve, prev_new_point = new_point);
+        }
+        
+        if (collapsed)
+            free_curve (newcurve);
+        else {
+            /* Just as with the first point, we have to keep the last
+               point.
+            */
+            if (offset)
+                append_point (newcurve, LAST_CURVE_POINT (curve));
+            
+            /* Set the original curve to the newly filtered one, and go
+               again.
+            */
+            free_curve (curve);
+            *curve = *newcurve;
+        }
+        free (newcurve);
+    }
+    log_curve (curve, false);
+}
+
+
+
+static void
 removeAdjacent(index_list_type *   const cornerListP,
                pixel_outline_type  const outline,
                fitting_opts_type * const fittingOptsP,
@@ -951,6 +1300,210 @@ logSplineFit(spline_type const spline) {
 
 
 
+static vector_type
+find_half_tangent(curve_type     const c,
+                  bool           const to_start_point,
+                  unsigned int * const n_points,
+                  unsigned int   const tangent_surround) {
+/*----------------------------------------------------------------------------
+  Find the change in y and change in x for `tangent_surround' (a global)
+  points along CURVE.  Increment N_POINTS by the number of points we
+  actually look at.
+-----------------------------------------------------------------------------*/
+    unsigned int p;
+    int factor = to_start_point ? 1 : -1;
+    unsigned tangent_index = to_start_point ? 0 : c->length - 1;
+    float_coord tangent_point = CURVE_POINT (c, tangent_index);
+    vector_type tangent = { 0.0, 0.0 };
+    unsigned int surround;
+
+    if ((surround = CURVE_LENGTH(c) / 2) > tangent_surround)
+        surround = tangent_surround;
+    
+    for (p = 1; p <= surround; ++p) {
+        int const this_index = p * factor + tangent_index;
+        float_coord this_point;
+        
+        if (this_index < 0 || this_index >= (int) c->length)
+            break;
+
+        this_point = CURVE_POINT(c, p * factor + tangent_index);
+
+        /* Perhaps we should weight the tangent from `this_point' by some
+           factor dependent on the distance from the tangent point.
+        */
+        tangent = Vadd (tangent,
+                        Vmult_scalar(Psubtract(this_point, tangent_point),
+                                     (float) factor));
+        ++*n_points;
+    }
+
+    return tangent;
+}
+
+
+
+static void
+find_tangent(curve_type   const curve,
+             bool         const to_start_point,
+             bool         const cross_curve,
+             unsigned int const tangent_surround_arg) {
+/*----------------------------------------------------------------------------
+  Find an approximation to the tangent to an endpoint of CURVE (to the
+  first point if TO_START_POINT is true, else the last).  If
+  CROSS_CURVE is true, consider points on the adjacent curve to CURVE.
+  
+  It is important to compute an accurate approximation, because the
+  control points that we eventually decide upon to fit the curve will
+  be placed on the half-lines defined by the tangents and
+  endpoints...and we never recompute the tangent after this.
+-----------------------------------------------------------------------------*/
+    vector_type ** curve_tangent;
+    vector_type tangent;
+    unsigned n_points;
+    
+    LOG1("  tangent to %s: ", (to_start_point == true) ? "start" : "end");
+
+    n_points = 0;  /* initial value */
+
+    curve_tangent = to_start_point ?
+        &(CURVE_START_TANGENT(curve)) : &(CURVE_END_TANGENT(curve));
+
+    if (*curve_tangent == NULL) {
+        unsigned int tangent_surround;
+
+        tangent_surround = tangent_surround_arg;  /* initial value */
+        MALLOCVAR_NOFAIL(*curve_tangent);
+        do {
+            tangent = find_half_tangent(curve, to_start_point, &n_points,
+                                        tangent_surround);
+
+            if (cross_curve || CURVE_CYCLIC(curve)) {
+                curve_type const adjacent_curve = to_start_point ?
+                    PREVIOUS_CURVE(curve) : NEXT_CURVE(curve);
+                vector_type const tangent2 = !to_start_point ?
+                    find_half_tangent(adjacent_curve, true, &n_points,
+                                      tangent_surround) :
+                    find_half_tangent(adjacent_curve, true, &n_points,
+                                      tangent_surround);
+                
+                LOG3("(adjacent curve half tangent (%.3f,%.3f,%.3f)) ",
+                     tangent2.dx, tangent2.dy, tangent2.dz);
+                tangent = Vadd (tangent, tangent2);
+            }
+            --tangent_surround;
+        } while (tangent.dx == 0.0 && tangent.dy == 0.0);
+
+        assert(n_points > 0);
+        **curve_tangent = Vmult_scalar (tangent, (float)(1.0 / n_points));
+        if (CURVE_CYCLIC(curve) && CURVE_START_TANGENT(curve))
+            *CURVE_START_TANGENT(curve) = **curve_tangent;
+        if (CURVE_CYCLIC(curve) && CURVE_END_TANGENT(curve))
+            *CURVE_END_TANGENT(curve) = **curve_tangent;
+    } else
+        LOG("(already computed) ");
+    
+    LOG3("(%.3f,%.3f,%.3f).\n", (*curve_tangent)->dx,
+         (*curve_tangent)->dy, (*curve_tangent)->dz);
+}
+
+
+
+static float
+find_error(curve_type          const curve,
+           spline_type         const spline,
+           unsigned int *      const worst_point,
+           at_exception_type * const exception) {
+/*----------------------------------------------------------------------------
+  When this routine is called, we have computed a spline representation
+  for the digitized curve.  The question is, how good is it?  If the
+  fit is very good indeed, we might have an error of zero on each
+  point, and then WORST_POINT becomes irrelevant.  But normally, we
+  return the error at the worst point, and the index of that point in
+  WORST_POINT.  The error computation itself is the Euclidean distance
+  from the original curve CURVE to the fitted spline SPLINE.
+-----------------------------------------------------------------------------*/
+    unsigned int this_point;
+    float total_error;
+    float worst_error;
+
+    total_error = 0.0;  /* initial value */
+    worst_error = FLT_MIN; /* initial value */
+
+    *worst_point = CURVE_LENGTH(curve) + 1;   /* A sentinel value.  */
+        
+    for (this_point = 0; this_point < CURVE_LENGTH(curve); ++this_point) {
+        float_coord const curve_point = CURVE_POINT(curve, this_point);
+        float const t = CURVE_T(curve, this_point);
+        float_coord const spline_point = evaluate_spline(spline, t);
+        float const this_error = distance(curve_point, spline_point);
+        if (this_error >= worst_error) {
+            *worst_point = this_point;
+            worst_error = this_error;
+        }
+        total_error += this_error;
+    }
+
+    if (*worst_point == CURVE_LENGTH(curve) + 1) {
+        /* Didn't have any ``worst point''; the error should be zero.  */
+        if (epsilon_equal(total_error, 0.0))
+            LOG ("  Every point fit perfectly.\n");
+        else {
+            LOG("No worst point found; something is wrong");
+            at_exception_warning(exception,
+                                 "No worst point found; something is wrong");
+        }
+    } else {
+        if (epsilon_equal(total_error, 0.0))
+            LOG ("  Every point fit perfectly.\n");
+        else {
+            LOG5("  Worst error (at (%.3f,%.3f,%.3f), point #%u) was %.3f.\n",
+                 CURVE_POINT(curve, *worst_point).x,
+                 CURVE_POINT(curve, *worst_point).y,
+                 CURVE_POINT(curve, *worst_point).z,
+                 *worst_point, worst_error);
+            LOG1("  Total error was %.3f.\n", total_error);
+            LOG2("  Average error (over %u points) was %.3f.\n",
+                 CURVE_LENGTH(curve), total_error / CURVE_LENGTH(curve));
+        }
+    }
+    return worst_error;
+}
+
+
+
+static void
+set_initial_parameter_values(curve_type const curve) {
+/*----------------------------------------------------------------------------
+   Find reasonable values for t for each point on CURVE.  The method is
+   called chord-length parameterization, which is described in Plass &
+   Stone.  The basic idea is just to use the distance from one point to
+   the next as the t value, normalized to produce values that increase
+   from zero for the first point to one for the last point.
+-----------------------------------------------------------------------------*/
+    unsigned int p;
+
+    LOG("\nAssigning initial t values:\n  ");
+
+    CURVE_T(curve, 0) = 0.0;
+
+    for (p = 1; p < CURVE_LENGTH (curve); ++p) {
+        float_coord const point = CURVE_POINT(curve, p);
+        float_coord const previous_p = CURVE_POINT(curve, p - 1);
+        float const d = distance (point, previous_p);
+        CURVE_T (curve, p) = CURVE_T (curve, p - 1) + d;
+    }
+
+    assert(LAST_CURVE_T (curve) != 0.0);
+
+    for (p = 1; p < CURVE_LENGTH(curve); ++p)
+        CURVE_T(curve, p) = CURVE_T(curve, p) / LAST_CURVE_T(curve);
+
+    log_entire_curve(curve);
+}
+
+
+
 static spline_list_type *
 fit_with_least_squares(curve_type                const curve,
                        const fitting_opts_type * const fitting_opts,
@@ -1377,547 +1930,3 @@ fit_outlines_to_splines(pixel_outline_list_type  const pixelOutlineList,
 
 
 
-
-static void
-find_vectors(unsigned int       const test_index,
-             pixel_outline_type const outline,
-             vector_type *      const in,
-             vector_type *      const out,
-             unsigned int       const corner_surround) {
-/*----------------------------------------------------------------------------
-  Return the difference vectors coming in and going out of the outline
-  OUTLINE at the point whose index is TEST_INDEX.  In Phoenix,
-  Schneider looks at a single point on either side of the point we're
-  considering.  That works for him because his points are not touching.
-  But our points *are* touching, and so we have to look at
-  `corner_surround' points on either side, to get a better picture of
-  the outline's shape.
------------------------------------------------------------------------------*/
-    int i;
-    unsigned n_done;
-    pm_pixelcoord const candidate = O_COORDINATE(outline, test_index);
-
-    in->dx  = in->dy  = in->dz  = 0.0;
-    out->dx = out->dy = out->dz = 0.0;
-    
-    /* Add up the differences from p of the `corner_surround' points
-       before p.
-    */
-    for (i = O_PREV(outline, test_index), n_done = 0;
-         n_done < corner_surround;
-         i = O_PREV(outline, i), ++n_done)
-        *in = Vadd(*in, IPsubtract(O_COORDINATE(outline, i), candidate));
-    
-    /* And the points after p. */
-    for (i = O_NEXT (outline, test_index), n_done = 0;
-         n_done < corner_surround;
-         i = O_NEXT(outline, i), ++n_done)
-        *out = Vadd(*out, IPsubtract(O_COORDINATE(outline, i), candidate));
-}
-
-
-
-/* Remove adjacent points from the index list LIST.  We do this by first
-   sorting the list and then running through it.  Since these lists are
-   quite short, a straight selection sort (e.g., p.139 of the Art of
-   Computer Programming, vol.3) is good enough.  LAST_INDEX is the index
-   of the last pixel on the outline, i.e., the next one is the first
-   pixel. We need this for checking the adjacency of the last corner.
-
-   We need to do this because the adjacent corners turn into
-   two-pixel-long curves, which can only be fit by straight lines.  */
-
-static void
-remove_adjacent_corners (index_list_type *list, unsigned last_index,
-             bool remove_adj_corners,
-             at_exception_type * exception)
-             
-{
-  unsigned j;
-  unsigned last;
-  index_list_type new_list = new_index_list ();
-
-  for (j = INDEX_LIST_LENGTH (*list) - 1; j > 0; j--)
-    {
-      unsigned search;
-      unsigned temp;
-      /* Find maximal element below `j'.  */
-      unsigned max_index = j;
-
-      for (search = 0; search < j; search++)
-        if (GET_INDEX (*list, search) > GET_INDEX (*list, max_index))
-          max_index = search;
-
-      if (max_index != j)
-        {
-          temp = GET_INDEX (*list, j);
-          GET_INDEX (*list, j) = GET_INDEX (*list, max_index);
-          GET_INDEX (*list, max_index) = temp;
-      
-      /* xx -- really have to sort?  */
-      LOG ("needed exchange");
-      at_exception_warning(exception, "needed exchange");
-        }
-    }
-
-  /* The list is sorted.  Now look for adjacent entries.  Each time
-     through the loop we insert the current entry and, if appropriate,
-     the next entry.  */
-  for (j = 0; j < INDEX_LIST_LENGTH (*list) - 1; j++)
-    {
-      unsigned current = GET_INDEX (*list, j);
-      unsigned next = GET_INDEX (*list, j + 1);
-
-      /* We should never have inserted the same element twice.  */
-      /* assert (current != next); */
-
-      if ((remove_adj_corners) && ((next == current + 1) || (next == current)))
-        j++;
-
-      append_index (&new_list, current);
-    }
-
-  /* Don't append the last element if it is 1) adjacent to the previous
-     one; or 2) adjacent to the very first one.  */
-  last = GET_LAST_INDEX (*list);
-  if (INDEX_LIST_LENGTH (new_list) == 0
-      || !(last == GET_LAST_INDEX (new_list) + 1
-           || (last == last_index && GET_INDEX (*list, 0) == 0)))
-    append_index (&new_list, last);
-
-  free_index_list (list);
-  *list = new_list;
-}
-
-/* A ``knee'' is a point which forms a ``right angle'' with its
-   predecessor and successor.  See the documentation (the `Removing
-   knees' section) for an example and more details.
-
-   The argument CLOCKWISE tells us which direction we're moving.  (We
-   can't figure that information out from just the single segment with
-   which we are given to work.)
-
-   We should never find two consecutive knees.
-
-   Since the first and last points are corners (unless the curve is
-   cyclic), it doesn't make sense to remove those.  */
-
-/* This evaluates to true if the vector V is zero in one direction and
-   nonzero in the other.  */
-#define ONLY_ONE_ZERO(v)                                                \
-  (((v).dx == 0.0 && (v).dy != 0.0) || ((v).dy == 0.0 && (v).dx != 0.0))
-
-/* There are four possible cases for knees, one for each of the four
-   corners of a rectangle; and then the cases differ depending on which
-   direction we are going around the curve.  The tests are listed here
-   in the order of upper left, upper right, lower right, lower left.
-   Perhaps there is some simple pattern to the
-   clockwise/counterclockwise differences, but I don't see one.  */
-#define CLOCKWISE_KNEE(prev_delta, next_delta)                                                  \
-  ((prev_delta.dx == -1.0 && next_delta.dy == 1.0)                                              \
-   || (prev_delta.dy == 1.0 && next_delta.dx == 1.0)                                    \
-   || (prev_delta.dx == 1.0 && next_delta.dy == -1.0)                                   \
-   || (prev_delta.dy == -1.0 && next_delta.dx == -1.0))
-
-#define COUNTERCLOCKWISE_KNEE(prev_delta, next_delta)                                   \
-  ((prev_delta.dy == 1.0 && next_delta.dx == -1.0)                                              \
-   || (prev_delta.dx == 1.0 && next_delta.dy == 1.0)                                    \
-   || (prev_delta.dy == -1.0 && next_delta.dx == 1.0)                                   \
-   || (prev_delta.dx == -1.0 && next_delta.dy == -1.0))
-
-
-
-static void
-remove_knee_points(curve_type const curve,
-                   bool       const clockwise) {
-
-      unsigned const offset = (CURVE_CYCLIC(curve) == true) ? 0 : 1;
-      curve_type const trimmed_curve = copy_most_of_curve(curve);
-
-      pm_pixelcoord previous;
-      unsigned i;
-
-      if (!CURVE_CYCLIC(curve))
-          append_pixel(trimmed_curve,
-                       real_to_int_coord(CURVE_POINT(curve, 0)));
-
-      previous = real_to_int_coord(CURVE_POINT(curve,
-                                               CURVE_PREV(curve, offset)));
-
-      for (i = offset; i < CURVE_LENGTH (curve) - offset; ++i) {
-          pm_pixelcoord const current =
-              real_to_int_coord(CURVE_POINT(curve, i));
-          pm_pixelcoord const next =
-              real_to_int_coord(CURVE_POINT(curve, CURVE_NEXT(curve, i)));
-          vector_type const prev_delta = IPsubtract(previous, current);
-          vector_type const next_delta = IPsubtract(next, current);
-
-          if (ONLY_ONE_ZERO(prev_delta) && ONLY_ONE_ZERO(next_delta)
-              && ((clockwise && CLOCKWISE_KNEE(prev_delta, next_delta))
-                  || (!clockwise
-                      && COUNTERCLOCKWISE_KNEE(prev_delta, next_delta))))
-              LOG2(" (%d,%d)", current.col, current.row);
-          else {
-              previous = current;
-              append_pixel(trimmed_curve, current);
-          }
-      }
-
-      if (!CURVE_CYCLIC(curve))
-          append_pixel(trimmed_curve,
-                       real_to_int_coord(LAST_CURVE_POINT(curve)));
-
-      if (CURVE_LENGTH(trimmed_curve) == CURVE_LENGTH(curve))
-          LOG(" (none)");
-
-      LOG(".\n");
-
-      free_curve(curve);
-      *curve = *trimmed_curve;
-      free(trimmed_curve);      /* free_curve? --- Masatake */
-}
-
-
-
-/* Smooth the curve by adding in neighboring points.  Do this
-   `filter_iterations' times.  But don't change the corners.  */
-
-static void
-filter (curve_type curve, fitting_opts_type *fitting_opts)
-{
-  unsigned iteration, this_point;
-  unsigned offset = (CURVE_CYCLIC (curve) == true) ? 0 : 1;
-  float_coord prev_new_point;
-
-  /* We must have at least three points---the previous one, the current
-     one, and the next one.  But if we don't have at least five, we will
-     probably collapse the curve down onto a single point, which means
-     we won't be able to fit it with a spline.  */
-  if (CURVE_LENGTH (curve) < 5)
-    {
-      LOG1 ("Length is %u, not enough to filter.\n", CURVE_LENGTH (curve));
-      return;
-    }
-
-  prev_new_point.x = FLT_MAX;
-  prev_new_point.y = FLT_MAX;
-  prev_new_point.z = FLT_MAX;
-
-  for (iteration = 0; iteration < fitting_opts->filter_iterations;
-   iteration++)
-    {
-      curve_type newcurve = copy_most_of_curve (curve);
-      bool collapsed = false;
-
-      /* Keep the first point on the curve.  */
-      if (offset)
-        append_point (newcurve, CURVE_POINT (curve, 0));
-
-      for (this_point = offset; this_point < CURVE_LENGTH (curve) - offset;
-           this_point++)
-        {
-          vector_type in, out, sum;
-          float_coord new_point;
-
-          /* Calculate the vectors in and out, computed by looking at n points
-             on either side of this_point. Experimental it was found that 2 is
-             optimal. */
-
-          signed int prev, prevprev; /* have to be signed */
-          unsigned int next, nextnext;
-          float_coord candidate = CURVE_POINT (curve, this_point);
-
-          prev = CURVE_PREV (curve, this_point);
-          prevprev = CURVE_PREV (curve, prev);
-          next = CURVE_NEXT (curve, this_point);
-          nextnext = CURVE_NEXT (curve, next);
-
-          /* Add up the differences from p of the `surround' points
-             before p.  */
-          in.dx = in.dy = in.dz = 0.0;
-
-          in = Vadd (in, Psubtract (CURVE_POINT (curve, prev), candidate));
-          if (prevprev >= 0)
-              in = Vadd (in, Psubtract (CURVE_POINT (curve, prevprev), candidate));
-
-          /* And the points after p.  Don't use more points after p than we
-             ended up with before it.  */
-          out.dx = out.dy = out.dz = 0.0;
-
-          out = Vadd (out, Psubtract (CURVE_POINT (curve, next), candidate));
-          if (nextnext < CURVE_LENGTH (curve))
-              out = Vadd (out, Psubtract (CURVE_POINT (curve, nextnext), candidate));
-
-          /* Start with the old point.  */
-          new_point = candidate;
-          sum = Vadd (in, out);
-          /* We added 2*n+2 points, so we have to divide the sum by 2*n+2 */
-          new_point.x += sum.dx / 6;
-          new_point.y += sum.dy / 6;
-          new_point.z += sum.dz / 6;
-          if (fabs (prev_new_point.x - new_point.x) < 0.3
-              && fabs (prev_new_point.y - new_point.y) < 0.3
-              && fabs (prev_new_point.z - new_point.z) < 0.3)
-            {
-              collapsed = true;
-              break;
-            }
-
-
-          /* Put the newly computed point into a separate curve, so it
-             doesn't affect future computation (on this iteration).  */
-          append_point (newcurve, prev_new_point = new_point);
-        }
-
-      if (collapsed)
-    free_curve (newcurve);
-      else
-    {
-          /* Just as with the first point, we have to keep the last point.  */
-          if (offset)
-        append_point (newcurve, LAST_CURVE_POINT (curve));
-      
-          /* Set the original curve to the newly filtered one, and go again.  */
-          free_curve (curve);
-          *curve = *newcurve;
-    }
-      free (newcurve);
-    }
-
-  log_curve (curve, false);
-}
-
-
-
-/* Find reasonable values for t for each point on CURVE.  The method is
-   called chord-length parameterization, which is described in Plass &
-   Stone.  The basic idea is just to use the distance from one point to
-   the next as the t value, normalized to produce values that increase
-   from zero for the first point to one for the last point.  */
-
-static void
-set_initial_parameter_values (curve_type curve)
-{
-  unsigned p;
-
-  LOG ("\nAssigning initial t values:\n  ");
-
-  CURVE_T (curve, 0) = 0.0;
-
-  for (p = 1; p < CURVE_LENGTH (curve); p++)
-    {
-      float_coord point = CURVE_POINT (curve, p),
-                           previous_p = CURVE_POINT (curve, p - 1);
-      float d = distance (point, previous_p);
-      CURVE_T (curve, p) = CURVE_T (curve, p - 1) + d;
-    }
-
-  assert (LAST_CURVE_T (curve) != 0.0);
-
-  for (p = 1; p < CURVE_LENGTH (curve); p++)
-    CURVE_T (curve, p) = CURVE_T (curve, p) / LAST_CURVE_T (curve);
-
-  log_entire_curve (curve);
-}
-
-/* Find an approximation to the tangent to an endpoint of CURVE (to the
-   first point if TO_START_POINT is true, else the last).  If
-   CROSS_CURVE is true, consider points on the adjacent curve to CURVE.
-
-   It is important to compute an accurate approximation, because the
-   control points that we eventually decide upon to fit the curve will
-   be placed on the half-lines defined by the tangents and
-   endpoints...and we never recompute the tangent after this.  */
-
-static void
-find_tangent (curve_type curve, bool to_start_point, bool cross_curve,
-  unsigned tangent_surround)
-{
-  vector_type tangent;
-  vector_type **curve_tangent = (to_start_point == true) ? &(CURVE_START_TANGENT (curve))
-                                               : &(CURVE_END_TANGENT (curve));
-  unsigned n_points = 0;
-
-  LOG1 ("  tangent to %s: ", (to_start_point == true) ? "start" : "end");
-
-  if (*curve_tangent == NULL)
-    {
-        MALLOCVAR_NOFAIL(*curve_tangent);
-      do
-        {
-          tangent = find_half_tangent (curve, to_start_point, &n_points,
-            tangent_surround);
-
-          if ((cross_curve == true) || (CURVE_CYCLIC (curve) == true))
-            {
-              curve_type adjacent_curve
-                = (to_start_point == true) ? PREVIOUS_CURVE (curve) : NEXT_CURVE (curve);
-              vector_type tangent2
-                = (to_start_point == false) ? find_half_tangent (adjacent_curve, true, &n_points,
-                tangent_surround) : find_half_tangent (adjacent_curve, true, &n_points,
-                tangent_surround);
-
-              LOG3 ("(adjacent curve half tangent (%.3f,%.3f,%.3f)) ",
-                tangent2.dx, tangent2.dy, tangent2.dz);
-              tangent = Vadd (tangent, tangent2);
-            }
-          tangent_surround--;
-
-        }
-      while (tangent.dx == 0.0 && tangent.dy == 0.0);
-
-      assert (n_points > 0);
-      **curve_tangent = Vmult_scalar (tangent, (float)(1.0 / n_points));
-      if ((CURVE_CYCLIC (curve) == true) && CURVE_START_TANGENT (curve))
-          *CURVE_START_TANGENT (curve) = **curve_tangent;
-      if  ((CURVE_CYCLIC (curve) == true) && CURVE_END_TANGENT (curve))
-          *CURVE_END_TANGENT (curve) = **curve_tangent;
-    }
-  else
-    LOG ("(already computed) ");
-
-  LOG3 ("(%.3f,%.3f,%.3f).\n", (*curve_tangent)->dx, (*curve_tangent)->dy, (*curve_tangent)->dz);
-}
-
-/* Find the change in y and change in x for `tangent_surround' (a global)
-   points along CURVE.  Increment N_POINTS by the number of points we
-   actually look at.  */
-
-static vector_type
-find_half_tangent (curve_type c, bool to_start_point, unsigned *n_points,
-  unsigned tangent_surround)
-{
-  unsigned p;
-  int factor = to_start_point ? 1 : -1;
-  unsigned tangent_index = to_start_point ? 0 : c->length - 1;
-  float_coord tangent_point = CURVE_POINT (c, tangent_index);
-  vector_type tangent = { 0.0, 0.0 };
-  unsigned int surround;
-
-  if ((surround = CURVE_LENGTH (c) / 2) > tangent_surround)
-    surround = tangent_surround;
-
-  for (p = 1; p <= surround; p++)
-    {
-      int this_index = p * factor + tangent_index;
-      float_coord this_point;
-
-      if (this_index < 0 || this_index >= (int) c->length)
-        break;
-
-      this_point = CURVE_POINT (c, p * factor + tangent_index);
-
-      /* Perhaps we should weight the tangent from `this_point' by some
-         factor dependent on the distance from the tangent point.  */
-      tangent = Vadd (tangent,
-                      Vmult_scalar (Psubtract (this_point, tangent_point),
-                                    (float) factor));
-      (*n_points)++;
-    }
-
-  return tangent;
-}
-
-/* When this routine is called, we have computed a spline representation
-   for the digitized curve.  The question is, how good is it?  If the
-   fit is very good indeed, we might have an error of zero on each
-   point, and then WORST_POINT becomes irrelevant.  But normally, we
-   return the error at the worst point, and the index of that point in
-   WORST_POINT.  The error computation itself is the Euclidean distance
-   from the original curve CURVE to the fitted spline SPLINE.  */
-
-static float
-find_error (curve_type curve, spline_type spline, unsigned *worst_point,
-        at_exception_type * exception)
-{
-  unsigned this_point;
-  float total_error = 0.0;
-  float worst_error = FLT_MIN;
-
-  *worst_point = CURVE_LENGTH (curve) + 1;   /* A sentinel value.  */
-
-  for (this_point = 0; this_point < CURVE_LENGTH (curve); this_point++)
-    {
-      float_coord curve_point = CURVE_POINT (curve, this_point);
-      float t = CURVE_T (curve, this_point);
-      float_coord spline_point = evaluate_spline (spline, t);
-      float this_error = distance (curve_point, spline_point);
-      if (this_error >= worst_error)
-        {
-         *worst_point = this_point;
-          worst_error = this_error;
-        }
-      total_error += this_error;
-    }
-
-  if (*worst_point == CURVE_LENGTH (curve) + 1)
-    { /* Didn't have any ``worst point''; the error should be zero.  */
-      if (epsilon_equal (total_error, 0.0))
-        LOG ("  Every point fit perfectly.\n");
-      else
-    {
-      LOG("No worst point found; something is wrong");
-      at_exception_warning(exception, "No worst point found; something is wrong");
-    }
-    }
-  else
-    {
-      if (epsilon_equal (total_error, 0.0))
-        LOG ("  Every point fit perfectly.\n");
-      else
-        {
-          LOG5 ("  Worst error (at (%.3f,%.3f,%.3f), point #%u) was %.3f.\n",
-              CURVE_POINT (curve, *worst_point).x,
-              CURVE_POINT (curve, *worst_point).y,
-              CURVE_POINT (curve, *worst_point).z, *worst_point, worst_error);
-          LOG1 ("  Total error was %.3f.\n", total_error);
-          LOG2 ("  Average error (over %u points) was %.3f.\n",
-              CURVE_LENGTH (curve), total_error / CURVE_LENGTH (curve));
-        }
-    }
-
-  return worst_error;
-}
-
-
-/* Lists of array indices (well, that is what we use it for).  */
-
-static index_list_type
-new_index_list (void)
-{
-  index_list_type index_list;
-
-  index_list.data = NULL;
-  INDEX_LIST_LENGTH (index_list) = 0;
-
-  return index_list;
-}
-
-static void
-free_index_list (index_list_type *index_list)
-{
-  if (INDEX_LIST_LENGTH (*index_list) > 0)
-    {
-      free (index_list->data);
-      index_list->data = NULL;
-      INDEX_LIST_LENGTH (*index_list) = 0;
-    }
-}
-
-static void
-append_index (index_list_type *list, unsigned new_index)
-{
-  INDEX_LIST_LENGTH (*list)++;
-  REALLOCARRAY_NOFAIL(list->data, INDEX_LIST_LENGTH(*list));
-  list->data[INDEX_LIST_LENGTH (*list) - 1] = new_index;
-}
-
-
-/* Return the Euclidean distance between P1 and P2.  */
-
-static float
-distance (float_coord p1, float_coord p2)
-{
-  float x = p1.x - p2.x, y = p1.y - p2.y, z = p1.z - p2.z;
-  return (float) sqrt (SQR(x) + SQR(y) + SQR(z));
-}
diff --git a/converter/other/pgmtopbm.c b/converter/other/pgmtopbm.c
index 98bdc332..36b39017 100644
--- a/converter/other/pgmtopbm.c
+++ b/converter/other/pgmtopbm.c
@@ -11,10 +11,11 @@
 */
 
 #include <assert.h>
+
+#include "shhopt.h"
 #include "pgm.h"
 #include "dithers.h"
 #include "mallocvar.h"
-#include "shhopt.h"
 
 enum halftone {QT_FS, QT_THRESH, QT_DITHER8, QT_CLUSTER, QT_HILBERT};
 
@@ -445,7 +446,7 @@ createFsConverter(unsigned int const cols,
     /* Initialize Floyd-Steinberg error vectors. */
     MALLOCARRAY_NOFAIL(stateP->thiserr, cols + 2);
     MALLOCARRAY_NOFAIL(stateP->nexterr, cols + 2);
-    srand((int)(time(NULL) ^ getpid()));
+    srand(pm_randseed());
 
     {
         /* (random errors in [-fs_scale/8 .. fs_scale/8]) */
diff --git a/converter/other/pgmtoppm.c b/converter/other/pgmtoppm.c
index 7693fe0a..cface024 100644
--- a/converter/other/pgmtoppm.c
+++ b/converter/other/pgmtoppm.c
@@ -11,146 +11,229 @@
 */
 
 #include <string.h>
+
+#include "mallocvar.h"
+#include "shhopt.h"
 #include "ppm.h"
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    gray* grayrow;
-    register gray* gP;
-    pixel p;
-    pixel* pixelrow;
-    register pixel* pP;
-    pixel** mappixels;
-    int argn, rows, cols, format, maprows, mapcols, mapmaxcolor, row;
-    register int col;
-    gray maxval;
+struct cmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFilename;  /* '-' if stdin */
+    const char * map;
+    const char * colorBlack;
+    const char * colorWhite;
+};
+
+
+
+static void
+parseCommandLine(int argc, char ** argv,
+                 struct cmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   parse program command line described in Unix standard form by argc
+   and argv.  Return the information in the options as *cmdlineP.  
+
+   If command line is internally inconsistent (invalid options, etc.),
+   issue error message to stderr and abort program.
+
+   Note that the strings we return are stored in the storage that
+   was passed to us as the argv array.  We also trash *argv.
+-----------------------------------------------------------------------------*/
+    optEntry *option_def;
+        /* Instructions to optParseOptions3 on how to parse our options.
+         */
+    optStruct3 opt;
+
+    unsigned int option_def_index;
+
+    unsigned int mapSpec;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0, "map",            OPT_STRING,    &cmdlineP->map,
+            &mapSpec,            0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (!mapSpec)
+        cmdlineP->map = NULL;
+
+    if (mapSpec) {
+        /* No color argument; only argument is file name */
+        if (argc-1 < 1)
+            cmdlineP->inputFilename = "-";
+        else {
+            cmdlineP->inputFilename = argv[1];
+            if (argc-1 > 1)
+                pm_error("With -map option, there is at most one argument: "
+                         "the file name.  You specified %u", argc-1);
+        }
+    } else {
+        /* Arguments are color or color range and file name */
+        if (argc-1 < 1) {
+            cmdlineP->colorBlack = "black";
+            cmdlineP->colorWhite = "white";
+        } else {
+            char * buffer = strdup(argv[1]);
+            char * hyphenPos = strchr(buffer, '-');
+            if (hyphenPos) {
+                *hyphenPos = '\0';
+                cmdlineP->colorBlack = buffer;
+                cmdlineP->colorWhite = hyphenPos+1;
+            } else {
+                cmdlineP->colorBlack = "black";
+                cmdlineP->colorWhite = buffer;
+            }
+        }
+        if (argc-1 < 2)
+            cmdlineP->inputFilename = "-";
+        else
+            cmdlineP->inputFilename = argv[2];
+        
+        if (argc-1 > 2)
+            pm_error("Program takes at most 2 arguments:  "
+                     "color name/range and input file name.  "
+                     "You specified %u", argc-1);
+    }
+}
+
+
+
+static void
+convertWithMap(FILE * const ifP,
+               unsigned int const cols,
+               unsigned int const rows,
+               gray         const maxval,
+               int          const format,
+               const char * const mapFileName,
+               FILE *       const ofP,
+               gray *       const grayrow,
+               pixel *      const pixelrow) {
+
+    unsigned int row;
+    FILE * mapFileP;
+    int mapcols, maprows;
     pixval mapmaxval;
-    char* color0;
-    char* color1;
+    pixel ** mappixels;
+    unsigned int mapmaxcolor;
+    
+    mapFileP = pm_openr(mapFileName);
+    mappixels = ppm_readppm(mapFileP, &mapcols, &maprows, &mapmaxval);
+    pm_close(mapFileP);
+    mapmaxcolor = maprows * mapcols - 1;
+
+    ppm_writeppminit(ofP, cols, rows, mapmaxval, 0);
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+            
+        pgm_readpgmrow(ifP, grayrow, cols, maxval, format);
+
+        for (col = 0; col < cols; ++col) {
+            unsigned int c;
+            if (maxval == mapmaxcolor)
+                c = grayrow[col];
+            else
+                c = grayrow[col] * mapmaxcolor / maxval;
+            pixelrow[col] = mappixels[c / mapcols][c % mapcols];
+        }
+        ppm_writeppmrow(ofP, pixelrow, cols, mapmaxval, 0);
+    }
+    ppm_freearray(mappixels, maprows);
+}
+
+
+
+static void
+convertLinear(FILE * const ifP,
+              unsigned int const cols,
+              unsigned int const rows,
+              gray         const maxval,
+              int          const format,
+              const char * const colorNameBlack,
+              const char * const colorNameWhite,
+              FILE *       const ofP,
+              gray *       const grayrow,
+              pixel *      const pixelrow) {
+
+    pixel colorBlack, colorWhite;
     pixval red0, grn0, blu0, red1, grn1, blu1;
-    const char* const usage = "<colorspec> [pgmfile]\n                 <colorspec1>,<colorspec2> [pgmfile]\n                 -map mapfile [pgmfile]";
-
-
-    ppm_init( &argc, argv );
-
-    argn = 1;
-    mappixels = (pixel**) 0;
-
-    if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
-	{
-	if ( pm_keymatch( argv[argn], "-map", 2 ) )
-	    {
-	    ++argn;
-	    if ( argn == argc )
-		pm_usage( usage );
-	    ifp = pm_openr( argv[argn] );
-	    mappixels = ppm_readppm( ifp, &mapcols, &maprows, &mapmaxval );
-	    pm_close( ifp );
-	    mapmaxcolor = maprows * mapcols - 1;
-	    }
-	else
-	    pm_usage( usage );
-	++argn;
-	}
-
-    if ( mappixels == (pixel**) 0 )
-	{
-	if ( argn == argc )
-	    pm_usage( usage );
-	color0 = argv[argn];
-	++argn;
-	}
-
-    if ( argn != argc )
-	{
-	ifp = pm_openr( argv[argn] );
-	++argn;
-	}
-    else
-	ifp = stdin;
+    unsigned int row;
+
+    ppm_writeppminit(ofP, cols, rows, maxval, 0);
+
+    colorBlack = ppm_parsecolor(colorNameBlack, maxval);
+    colorWhite = ppm_parsecolor(colorNameWhite, maxval);
+ 
+    red0 = PPM_GETR(colorBlack);
+    grn0 = PPM_GETG(colorBlack);
+    blu0 = PPM_GETB(colorBlack);
+    red1 = PPM_GETR(colorWhite);
+    grn1 = PPM_GETG(colorWhite);
+    blu1 = PPM_GETB(colorWhite);
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+
+        pgm_readpgmrow(ifP, grayrow, cols, maxval, format);
+
+        for (col = 0; col < cols; ++col) {
+            gray const input = grayrow[col];
+            PPM_ASSIGN(
+                pixelrow[col],
+                (red0 * (maxval - input) + red1 * input) / maxval,
+                (grn0 * (maxval - input) + grn1 * input) / maxval,
+                (blu0 * (maxval - input) + blu1 * input) / maxval);
+        }
+        ppm_writeppmrow(ofP, pixelrow, cols, maxval, 0);
+    }
+}
 
-    if ( argn != argc )
-	pm_usage( usage );
 
-    pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
-    grayrow = pgm_allocrow( cols );
-    if ( mappixels == (pixel**) 0 )
-	ppm_writeppminit( stdout, cols, rows, (pixval) maxval, 0 );
-    else
-	ppm_writeppminit( stdout, cols, rows, mapmaxval, 0 );
-    pixelrow = ppm_allocrow( cols );
-
-    if ( mappixels == (pixel**) 0 )
-	{
-	color1 = strchr( color0, '-' );
-	if ( color1 == 0 )
-	    {
-	    color1 = color0;
-	    red0 = 0;
-	    grn0 = 0;
-	    blu0 = 0;
-	    }
-	else
-	    {
-	    *color1 = '\0';
-	    ++color1;
-	    p = ppm_parsecolor( color0, (pixval) maxval );
-	    red0 = PPM_GETR( p );
-	    grn0 = PPM_GETG( p );
-	    blu0 = PPM_GETB( p );
-	    }
-	p = ppm_parsecolor( color1, (pixval) maxval );
-	red1 = PPM_GETR( p );
-	grn1 = PPM_GETG( p );
-	blu1 = PPM_GETB( p );
-	}
-
-    for ( row = 0; row < rows; ++row )
-	{
-	pgm_readpgmrow( ifp, grayrow, cols, maxval, format );
-
-	if ( mappixels == (pixel**) 0 )
-	    {
-	    for ( col = 0, gP = grayrow, pP = pixelrow;
-		  col < cols;
-		  ++col, ++gP, ++pP )
-		PPM_ASSIGN(
-		    *pP,
-		    ( red0 * ( maxval - *gP ) + red1 * *gP ) / maxval,
-		    ( grn0 * ( maxval - *gP ) + grn1 * *gP ) / maxval,
-		    ( blu0 * ( maxval - *gP ) + blu1 * *gP ) / maxval );
-
-	    }
-	else
-	    {
-	    register int c;
-
-	    for ( col = 0, gP = grayrow, pP = pixelrow;
-		  col < cols;
-		  ++col, ++gP, ++pP )
-		{
-		if ( maxval == mapmaxcolor )
-		    c = *gP;
-		else
-		    c = *gP * mapmaxcolor / maxval;
-		*pP = mappixels[c / mapcols][c % mapcols];
-		}
-	    }
-
-    if (!mappixels)
-        ppm_writeppmrow( stdout, pixelrow, cols, (pixval) maxval, 0 );
+
+int
+main(int    argc,
+     char * argv[]) {
+
+    FILE * ifP;
+    struct cmdlineInfo cmdline;
+    gray * grayrow;
+    pixel * pixelrow;
+    int rows, cols, format;
+    gray maxval;
+
+    ppm_init(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFilename);
+
+    pgm_readpgminit(ifP, &cols, &rows, &maxval, &format);
+    grayrow = pgm_allocrow(cols);
+    pixelrow = ppm_allocrow(cols);
+
+    if (cmdline.map)
+        convertWithMap(ifP, cols, rows, maxval, format, cmdline.map,
+                       stdout, grayrow, pixelrow);
     else
-        ppm_writeppmrow( stdout, pixelrow, cols, mapmaxval, 0 );
-	}
+        convertLinear(ifP, cols, rows, maxval, format, 
+                      cmdline.colorBlack, cmdline.colorWhite, stdout,
+                      grayrow, pixelrow);
 
-    pm_close( ifp );
+    ppm_freerow(pixelrow);
+    pgm_freerow(grayrow);
+    pm_close(ifP);
 
     /* If the program failed, it previously aborted with nonzero completion
        code, via various function calls.
     */
     return 0;
-    }
+}
diff --git a/converter/other/pngtopnm.c b/converter/other/pngtopnm.c
index bb8afb8d..2b88bd1e 100644
--- a/converter/other/pngtopnm.c
+++ b/converter/other/pngtopnm.c
@@ -240,23 +240,12 @@ gamma_correct(png_uint_16 const v,
 
 
 
-#ifdef __STDC__
 static int iscolor (png_color c)
-#else
-static int iscolor (c)
-png_color c;
-#endif
 {
   return c.red != c.green || c.green != c.blue;
 }
 
-#ifdef __STDC__
 static void save_text (png_info *info_ptr, FILE *tfp)
-#else
-static void save_text (info_ptr, tfp)
-png_info *info_ptr;
-FILE *tfp;
-#endif
 {
   int i, j, k;
 
@@ -285,12 +274,7 @@ FILE *tfp;
   }
 }
 
-#ifdef __STDC__
 static void show_time (png_info *info_ptr)
-#else
-static void show_time (info_ptr)
-png_info *info_ptr;
-#endif
 {
     static const char * const month[] = {
         "", "January", "February", "March", "April", "May", "June",
@@ -305,13 +289,7 @@ png_info *info_ptr;
   }
 }
 
-#ifdef __STDC__
 static void pngtopnm_error_handler (png_structp png_ptr, png_const_charp msg)
-#else
-static void pngtopnm_error_handler (png_ptr, msg)
-png_structp png_ptr;
-png_const_charp msg;
-#endif
 {
   jmpbuf_wrapper  *jmpbuf_ptr;
 
diff --git a/converter/other/pnmtoddif.c b/converter/other/pnmtoddif.c
index 65152865..3a910a7b 100644
--- a/converter/other/pnmtoddif.c
+++ b/converter/other/pnmtoddif.c
@@ -166,11 +166,7 @@ wr_int(unsigned char ** buffer, int val)
     } else {
         sign = val < 0 ? 0xff : 0x00;   /* Sign bits */
         length = 4;
-#ifdef __STDC__
         mask  = 0xffu << 24;
-#else
-        mask  = 0xff << 24;
-#endif
         while ((val & mask) == sign) {  /* Find the smallest representation */
             length--;
             mask >>= 8;
diff --git a/converter/other/pnmtojpeg.c b/converter/other/pnmtojpeg.c
index 9a247633..5a4c5511 100644
--- a/converter/other/pnmtojpeg.c
+++ b/converter/other/pnmtojpeg.c
@@ -330,23 +330,6 @@ parseCommandLine(const int argc, char ** argv,
 }
 
 
-static void
-compute_rescaling_array(JSAMPLE ** const rescale_p, const pixval maxval,
-                        const struct jpeg_compress_struct cinfo);
-static void
-convert_scanlines(struct jpeg_compress_struct * const cinfo_p, FILE * const input_file,
-                  const pixval maxval, const int input_fmt,
-                  JSAMPLE xlate_table[]);
-
-static boolean read_quant_tables (j_compress_ptr cinfo, char * filename,
-                                  int scale_factor, boolean force_baseline);
-
-static boolean read_scan_script (j_compress_ptr cinfo, char * filename);
-
-static boolean set_quant_slots (j_compress_ptr cinfo, char *arg);
-
-static boolean set_sample_factors (j_compress_ptr cinfo, char *arg);
-
 
 static void
 report_compressor(const struct jpeg_compress_struct cinfo) {
@@ -423,6 +406,349 @@ setup_jpeg_density(struct jpeg_compress_struct * const cinfoP,
 
 
 
+/*----------------------------------------------------------------------------
+   The functions below here are essentially the file rdswitch.c from
+   the JPEG library.  They perform the functions specifed by the following
+   pnmtojpeg options:
+
+   -qtables file          Read quantization tables from text file
+   -scans file            Read scan script from text file
+   -qslots N[,N,...]      Set component quantization table selectors
+   -sample HxV[,HxV,...]  Set component sampling factors
+-----------------------------------------------------------------------------*/
+
+static int
+text_getc (FILE * file)
+/* Read next char, skipping over any comments (# to end of line) */
+/* A comment/newline sequence is returned as a newline */
+{
+    register int ch;
+  
+    ch = getc(file);
+    if (ch == '#') {
+        do {
+            ch = getc(file);
+        } while (ch != '\n' && ch != EOF);
+    }
+    return ch;
+}
+
+
+static boolean
+read_text_integer (FILE * file, long * result, int * termchar)
+/* Read an unsigned decimal integer from a file, store it in result */
+/* Reads one trailing character after the integer; returns it in termchar */
+{
+    register int ch;
+    register long val;
+  
+    /* Skip any leading whitespace, detect EOF */
+    do {
+        ch = text_getc(file);
+        if (ch == EOF) {
+            *termchar = ch;
+            return FALSE;
+        }
+    } while (isspace(ch));
+  
+    if (! isdigit(ch)) {
+        *termchar = ch;
+        return FALSE;
+    }
+
+    val = ch - '0';
+    while ((ch = text_getc(file)) != EOF) {
+        if (! isdigit(ch))
+            break;
+        val *= 10;
+        val += ch - '0';
+    }
+    *result = val;
+    *termchar = ch;
+    return TRUE;
+}
+
+
+static boolean
+read_scan_integer (FILE * file, long * result, int * termchar)
+/* Variant of read_text_integer that always looks for a non-space termchar;
+ * this simplifies parsing of punctuation in scan scripts.
+ */
+{
+    register int ch;
+
+    if (! read_text_integer(file, result, termchar))
+        return FALSE;
+    ch = *termchar;
+    while (ch != EOF && isspace(ch))
+        ch = text_getc(file);
+    if (isdigit(ch)) {		/* oops, put it back */
+        if (ungetc(ch, file) == EOF)
+            return FALSE;
+        ch = ' ';
+    } else {
+        /* Any separators other than ';' and ':' are ignored;
+         * this allows user to insert commas, etc, if desired.
+         */
+        if (ch != EOF && ch != ';' && ch != ':')
+            ch = ' ';
+    }
+    *termchar = ch;
+    return TRUE;
+}
+
+
+
+static boolean
+read_scan_script(j_compress_ptr const cinfo,
+                 const char *   const filename) {
+/*----------------------------------------------------------------------------
+  Read a scan script from the specified text file.
+  Each entry in the file defines one scan to be emitted.
+  Entries are separated by semicolons ';'.
+  An entry contains one to four component indexes,
+  optionally followed by a colon ':' and four progressive-JPEG parameters.
+  The component indexes denote which component(s) are to be transmitted
+  in the current scan.  The first component has index 0.
+  Sequential JPEG is used if the progressive-JPEG parameters are omitted.
+  The file is free format text: any whitespace may appear between numbers
+  and the ':' and ';' punctuation marks.  Also, other punctuation (such
+  as commas or dashes) can be placed between numbers if desired.
+  Comments preceded by '#' may be included in the file.
+  Note: we do very little validity checking here;
+  jcmaster.c will validate the script parameters.
+-----------------------------------------------------------------------------*/
+    FILE * fp;
+    unsigned int nscans;
+    unsigned int ncomps;
+    int termchar;
+    long val;
+#define MAX_SCANS  100      /* quite arbitrary limit */
+    jpeg_scan_info scans[MAX_SCANS];
+
+    fp = fopen(filename, "r");
+    if (fp == NULL) {
+        pm_message("Can't open scan definition file %s", filename);
+        return FALSE;
+    }
+    nscans = 0;
+
+    while (read_scan_integer(fp, &val, &termchar)) {
+        ++nscans;  /* We got another scan */
+        if (nscans > MAX_SCANS) {
+            pm_message("Too many scans defined in file %s", filename);
+            fclose(fp);
+            return FALSE;
+        }
+        scans[nscans-1].component_index[0] = (int) val;
+        ncomps = 1;
+        while (termchar == ' ') {
+            if (ncomps >= MAX_COMPS_IN_SCAN) {
+                pm_message("Too many components in one scan in file %s", 
+                           filename);
+                fclose(fp);
+                return FALSE;
+            }
+            if (! read_scan_integer(fp, &val, &termchar))
+                goto bogus;
+            scans[nscans-1].component_index[ncomps] = (int) val;
+            ++ncomps;
+        }
+        scans[nscans-1].comps_in_scan = ncomps;
+        if (termchar == ':') {
+            if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
+                goto bogus;
+            scans[nscans-1].Ss = (int) val;
+            if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
+                goto bogus;
+            scans[nscans-1].Se = (int) val;
+            if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
+                goto bogus;
+            scans[nscans-1].Ah = (int) val;
+            if (! read_scan_integer(fp, &val, &termchar))
+                goto bogus;
+            scans[nscans-1].Al = (int) val;
+        } else {
+            /* set non-progressive parameters */
+            scans[nscans-1].Ss = 0;
+            scans[nscans-1].Se = DCTSIZE2-1;
+            scans[nscans-1].Ah = 0;
+            scans[nscans-1].Al = 0;
+        }
+        if (termchar != ';' && termchar != EOF) {
+        bogus:
+            pm_message("Invalid scan entry format in file %s", filename);
+            fclose(fp);
+            return FALSE;
+        }
+    }
+
+    if (termchar != EOF) {
+        pm_message("Non-numeric data in file %s", filename);
+        fclose(fp);
+        return FALSE;
+    }
+
+    if (nscans > 0) {
+        /* Stash completed scan list in cinfo structure.  NOTE: in
+           this program, JPOOL_IMAGE is the right lifetime for this
+           data, but if you want to compress multiple images you'd
+           want JPOOL_PERMANENT.  
+        */
+        const unsigned int scan_info_size = nscans * sizeof(jpeg_scan_info);
+        jpeg_scan_info * const scan_info = 
+            (jpeg_scan_info *)
+            (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+                                        scan_info_size);
+        memcpy(scan_info, scans, scan_info_size);
+        cinfo->scan_info = scan_info;
+        cinfo->num_scans = nscans;
+    }
+
+    fclose(fp);
+    return TRUE;
+}
+
+
+
+static boolean
+read_quant_tables (j_compress_ptr cinfo, char * filename,
+                   int scale_factor, boolean force_baseline)
+/* Read a set of quantization tables from the specified file.
+ * The file is plain ASCII text: decimal numbers with whitespace between.
+ * Comments preceded by '#' may be included in the file.
+ * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
+ * The tables are implicitly numbered 0,1,etc.
+ * NOTE: does not affect the qslots mapping, which will default to selecting
+ * table 0 for luminance (or primary) components, 1 for chrominance components.
+ * You must use -qslots if you want a different component->table mapping.
+ */
+{
+    FILE * fp;
+    int tblno, i, termchar;
+    long val;
+    unsigned int table[DCTSIZE2];
+
+    if ((fp = fopen(filename, "rb")) == NULL) {
+        pm_message("Can't open table file %s", filename);
+        return FALSE;
+    }
+    tblno = 0;
+
+    while (read_text_integer(fp, &val, &termchar)) {
+        /* read 1st element of table */
+        if (tblno >= NUM_QUANT_TBLS) {
+            pm_message("Too many tables in file %s", filename);
+            fclose(fp);
+            return FALSE;
+        }
+        table[0] = (unsigned int) val;
+        for (i = 1; i < DCTSIZE2; i++) {
+            if (! read_text_integer(fp, &val, &termchar)) {
+                pm_message("Invalid table data in file %s", filename);
+                fclose(fp);
+                return FALSE;
+            }
+            table[i] = (unsigned int) val;
+        }
+        jpeg_add_quant_table(cinfo, tblno, table, scale_factor, 
+                             force_baseline);
+        tblno++;
+    }
+
+    if (termchar != EOF) {
+        pm_message("Non-numeric data in file %s", filename);
+        fclose(fp);
+        return FALSE;
+    }
+
+    fclose(fp);
+    return TRUE;
+}
+
+
+
+static boolean
+set_quant_slots (j_compress_ptr cinfo, char *arg)
+/* Process a quantization-table-selectors parameter string, of the form
+ *     N[,N,...]
+ * If there are more components than parameters, the last value is replicated.
+ */
+{
+    int val = 0;			/* default table # */
+    int ci;
+    char ch;
+
+    for (ci = 0; ci < MAX_COMPONENTS; ci++) {
+        if (*arg) {
+            ch = ',';			/* if not set by sscanf, will be ',' */
+            if (sscanf(arg, "%d%c", &val, &ch) < 1)
+                return FALSE;
+            if (ch != ',')		/* syntax check */
+                return FALSE;
+            if (val < 0 || val >= NUM_QUANT_TBLS) {
+                pm_message("Invalid quantization table number: %d.  "
+                           "JPEG quantization tables are numbered 0..%d",
+                           val, NUM_QUANT_TBLS - 1);
+                return FALSE;
+            }
+            cinfo->comp_info[ci].quant_tbl_no = val;
+            while (*arg && *arg++ != ',') 
+                /* advance to next segment of arg string */
+                ;
+        } else {
+            /* reached end of parameter, set remaining components to last tbl*/
+            cinfo->comp_info[ci].quant_tbl_no = val;
+        }
+    }
+    return TRUE;
+}
+
+
+static boolean
+set_sample_factors (j_compress_ptr cinfo, char *arg)
+/* Process a sample-factors parameter string, of the form
+ *     HxV[,HxV,...]
+ * If there are more components than parameters, "1x1" is assumed for the rest.
+ */
+{
+    int ci, val1, val2;
+    char ch1, ch2;
+
+    for (ci = 0; ci < MAX_COMPONENTS; ci++) {
+        if (*arg) {
+            ch2 = ',';		/* if not set by sscanf, will be ',' */
+            if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
+                return FALSE;
+            if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */
+                return FALSE;
+            if (val1 <= 0 || val1 > 4) {
+                pm_message("Invalid sampling factor: %d.  " 
+                           "JPEG sampling factors must be 1..4", val1);
+                return FALSE;
+            }
+            if (val2 <= 0 || val2 > 4) {
+                pm_message("Invalid sampling factor: %d.  "
+                           "JPEG sampling factors must be 1..4", val2);
+                return FALSE;
+            }
+            cinfo->comp_info[ci].h_samp_factor = val1;
+            cinfo->comp_info[ci].v_samp_factor = val2;
+            while (*arg && *arg++ != ',') 
+                /* advance to next segment of arg string */
+                ;
+        } else {
+            /* reached end of parameter, set remaining components 
+               to 1x1 sampling */
+            cinfo->comp_info[ci].h_samp_factor = 1;
+            cinfo->comp_info[ci].v_samp_factor = 1;
+        }
+    }
+    return TRUE;
+}
+
+
+
 static void
 setup_jpeg(struct jpeg_compress_struct * const cinfoP,
            struct jpeg_error_mgr       * const jerrP,
@@ -692,348 +1018,16 @@ convert_scanlines(struct jpeg_compress_struct * const cinfo_p,
 
 }
 
-/*----------------------------------------------------------------------------
-   The functions below here are essentially the file rdswitch.c from
-   the JPEG library.  They perform the functions specifed by the following
-   pnmtojpeg options:
-
-   -qtables file          Read quantization tables from text file
-   -scans file            Read scan script from text file
-   -qslots N[,N,...]      Set component quantization table selectors
-   -sample HxV[,HxV,...]  Set component sampling factors
------------------------------------------------------------------------------*/
-
-static int
-text_getc (FILE * file)
-/* Read next char, skipping over any comments (# to end of line) */
-/* A comment/newline sequence is returned as a newline */
-{
-    register int ch;
-  
-    ch = getc(file);
-    if (ch == '#') {
-        do {
-            ch = getc(file);
-        } while (ch != '\n' && ch != EOF);
-    }
-    return ch;
-}
-
-
-static boolean
-read_text_integer (FILE * file, long * result, int * termchar)
-/* Read an unsigned decimal integer from a file, store it in result */
-/* Reads one trailing character after the integer; returns it in termchar */
-{
-    register int ch;
-    register long val;
-  
-    /* Skip any leading whitespace, detect EOF */
-    do {
-        ch = text_getc(file);
-        if (ch == EOF) {
-            *termchar = ch;
-            return FALSE;
-        }
-    } while (isspace(ch));
-  
-    if (! isdigit(ch)) {
-        *termchar = ch;
-        return FALSE;
-    }
-
-    val = ch - '0';
-    while ((ch = text_getc(file)) != EOF) {
-        if (! isdigit(ch))
-            break;
-        val *= 10;
-        val += ch - '0';
-    }
-    *result = val;
-    *termchar = ch;
-    return TRUE;
-}
-
-
-static boolean
-read_quant_tables (j_compress_ptr cinfo, char * filename,
-                   int scale_factor, boolean force_baseline)
-/* Read a set of quantization tables from the specified file.
- * The file is plain ASCII text: decimal numbers with whitespace between.
- * Comments preceded by '#' may be included in the file.
- * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
- * The tables are implicitly numbered 0,1,etc.
- * NOTE: does not affect the qslots mapping, which will default to selecting
- * table 0 for luminance (or primary) components, 1 for chrominance components.
- * You must use -qslots if you want a different component->table mapping.
- */
-{
-    FILE * fp;
-    int tblno, i, termchar;
-    long val;
-    unsigned int table[DCTSIZE2];
-
-    if ((fp = fopen(filename, "rb")) == NULL) {
-        pm_message("Can't open table file %s", filename);
-        return FALSE;
-    }
-    tblno = 0;
-
-    while (read_text_integer(fp, &val, &termchar)) { /* read 1st element of table */
-        if (tblno >= NUM_QUANT_TBLS) {
-            pm_message("Too many tables in file %s", filename);
-            fclose(fp);
-            return FALSE;
-        }
-        table[0] = (unsigned int) val;
-        for (i = 1; i < DCTSIZE2; i++) {
-            if (! read_text_integer(fp, &val, &termchar)) {
-                pm_message("Invalid table data in file %s", filename);
-                fclose(fp);
-                return FALSE;
-            }
-            table[i] = (unsigned int) val;
-        }
-        jpeg_add_quant_table(cinfo, tblno, table, scale_factor, 
-                             force_baseline);
-        tblno++;
-    }
-
-    if (termchar != EOF) {
-        pm_message("Non-numeric data in file %s", filename);
-        fclose(fp);
-        return FALSE;
-    }
-
-    fclose(fp);
-    return TRUE;
-}
-
-
-static boolean
-read_scan_integer (FILE * file, long * result, int * termchar)
-/* Variant of read_text_integer that always looks for a non-space termchar;
- * this simplifies parsing of punctuation in scan scripts.
- */
-{
-    register int ch;
-
-    if (! read_text_integer(file, result, termchar))
-        return FALSE;
-    ch = *termchar;
-    while (ch != EOF && isspace(ch))
-        ch = text_getc(file);
-    if (isdigit(ch)) {		/* oops, put it back */
-        if (ungetc(ch, file) == EOF)
-            return FALSE;
-        ch = ' ';
-    } else {
-        /* Any separators other than ';' and ':' are ignored;
-         * this allows user to insert commas, etc, if desired.
-         */
-        if (ch != EOF && ch != ';' && ch != ':')
-            ch = ' ';
-    }
-    *termchar = ch;
-    return TRUE;
-}
-
-
-boolean
-read_scan_script (j_compress_ptr cinfo, char * filename)
-/* Read a scan script from the specified text file.
- * Each entry in the file defines one scan to be emitted.
- * Entries are separated by semicolons ';'.
- * An entry contains one to four component indexes,
- * optionally followed by a colon ':' and four progressive-JPEG parameters.
- * The component indexes denote which component(s) are to be transmitted
- * in the current scan.  The first component has index 0.
- * Sequential JPEG is used if the progressive-JPEG parameters are omitted.
- * The file is free format text: any whitespace may appear between numbers
- * and the ':' and ';' punctuation marks.  Also, other punctuation (such
- * as commas or dashes) can be placed between numbers if desired.
- * Comments preceded by '#' may be included in the file.
- * Note: we do very little validity checking here;
- * jcmaster.c will validate the script parameters.
- */
-{
-    FILE * fp;
-    int nscans, ncomps, termchar;
-    long val;
-#define MAX_SCANS  100      /* quite arbitrary limit */
-    jpeg_scan_info scans[MAX_SCANS];
-
-    if ((fp = fopen(filename, "r")) == NULL) {
-        pm_message("Can't open scan definition file %s", filename);
-        return FALSE;
-    }
-    nscans = 0;
-
-    while (read_scan_integer(fp, &val, &termchar)) {
-        nscans++;  /* We got another scan */
-        if (nscans > MAX_SCANS) {
-            pm_message("Too many scans defined in file %s", filename);
-            fclose(fp);
-            return FALSE;
-        }
-        scans[nscans-1].component_index[0] = (int) val;
-        ncomps = 1;
-        while (termchar == ' ') {
-            if (ncomps >= MAX_COMPS_IN_SCAN) {
-                pm_message("Too many components in one scan in file %s", 
-                           filename);
-                fclose(fp);
-                return FALSE;
-            }
-            if (! read_scan_integer(fp, &val, &termchar))
-                goto bogus;
-            scans[nscans-1].component_index[ncomps] = (int) val;
-            ncomps++;
-        }
-        scans[nscans-1].comps_in_scan = ncomps;
-        if (termchar == ':') {
-            if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
-                goto bogus;
-            scans[nscans-1].Ss = (int) val;
-            if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
-                goto bogus;
-            scans[nscans-1].Se = (int) val;
-            if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
-                goto bogus;
-            scans[nscans-1].Ah = (int) val;
-            if (! read_scan_integer(fp, &val, &termchar))
-                goto bogus;
-            scans[nscans-1].Al = (int) val;
-        } else {
-            /* set non-progressive parameters */
-            scans[nscans-1].Ss = 0;
-            scans[nscans-1].Se = DCTSIZE2-1;
-            scans[nscans-1].Ah = 0;
-            scans[nscans-1].Al = 0;
-        }
-        if (termchar != ';' && termchar != EOF) {
-        bogus:
-            pm_message("Invalid scan entry format in file %s", filename);
-            fclose(fp);
-            return FALSE;
-        }
-    }
-
-    if (termchar != EOF) {
-        pm_message("Non-numeric data in file %s", filename);
-        fclose(fp);
-        return FALSE;
-    }
-
-    if (nscans > 0) {
-        /* Stash completed scan list in cinfo structure.  NOTE: in
-         * this program, JPOOL_IMAGE is the right lifetime for this
-         * data, but if you want to compress multiple images you'd
-         * want JPOOL_PERMANENT.  
-         */
-        const unsigned int scan_info_size = nscans * sizeof(jpeg_scan_info);
-        jpeg_scan_info * const scan_info = 
-            (jpeg_scan_info *)
-            (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
-                                        scan_info_size);
-        memcpy(scan_info, scans, scan_info_size);
-        cinfo->scan_info = scan_info;
-        cinfo->num_scans = nscans;
-    }
-
-    fclose(fp);
-    return TRUE;
-}
-
-
-static boolean
-set_quant_slots (j_compress_ptr cinfo, char *arg)
-/* Process a quantization-table-selectors parameter string, of the form
- *     N[,N,...]
- * If there are more components than parameters, the last value is replicated.
- */
-{
-    int val = 0;			/* default table # */
-    int ci;
-    char ch;
-
-    for (ci = 0; ci < MAX_COMPONENTS; ci++) {
-        if (*arg) {
-            ch = ',';			/* if not set by sscanf, will be ',' */
-            if (sscanf(arg, "%d%c", &val, &ch) < 1)
-                return FALSE;
-            if (ch != ',')		/* syntax check */
-                return FALSE;
-            if (val < 0 || val >= NUM_QUANT_TBLS) {
-                pm_message("Invalid quantization table number: %d.  "
-                           "JPEG quantization tables are numbered 0..%d",
-                           val, NUM_QUANT_TBLS - 1);
-                return FALSE;
-            }
-            cinfo->comp_info[ci].quant_tbl_no = val;
-            while (*arg && *arg++ != ',') 
-                /* advance to next segment of arg string */
-                ;
-        } else {
-            /* reached end of parameter, set remaining components to last tbl*/
-            cinfo->comp_info[ci].quant_tbl_no = val;
-        }
-    }
-    return TRUE;
-}
-
-
-static boolean
-set_sample_factors (j_compress_ptr cinfo, char *arg)
-/* Process a sample-factors parameter string, of the form
- *     HxV[,HxV,...]
- * If there are more components than parameters, "1x1" is assumed for the rest.
- */
-{
-    int ci, val1, val2;
-    char ch1, ch2;
-
-    for (ci = 0; ci < MAX_COMPONENTS; ci++) {
-        if (*arg) {
-            ch2 = ',';		/* if not set by sscanf, will be ',' */
-            if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
-                return FALSE;
-            if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */
-                return FALSE;
-            if (val1 <= 0 || val1 > 4) {
-                pm_message("Invalid sampling factor: %d.  " 
-                           "JPEG sampling factors must be 1..4", val1);
-                return FALSE;
-            }
-            if (val2 <= 0 || val2 > 4) {
-                pm_message("Invalid sampling factor: %d.  "
-                           "JPEG sampling factors must be 1..4", val2);
-                return FALSE;
-            }
-            cinfo->comp_info[ci].h_samp_factor = val1;
-            cinfo->comp_info[ci].v_samp_factor = val2;
-            while (*arg && *arg++ != ',') 
-                /* advance to next segment of arg string */
-                ;
-        } else {
-            /* reached end of parameter, set remaining components 
-               to 1x1 sampling */
-            cinfo->comp_info[ci].h_samp_factor = 1;
-            cinfo->comp_info[ci].v_samp_factor = 1;
-        }
-    }
-    return TRUE;
-}
-
 
 
 int
-main(int argc, char ** argv) {
+main(int     argc,
+     char ** argv) {
 
     struct cmdlineInfo cmdline;
     struct jpeg_compress_struct cinfo;
     struct jpeg_error_mgr jerr;
-    FILE *input_file;
+    FILE * input_file;
     FILE * output_file;
     int height;  
         /* height of the input image in rows, as specified by its header */
diff --git a/converter/other/pnmtopalm/Makefile b/converter/other/pnmtopalm/Makefile
index d7bf2829..3d802ed6 100644
--- a/converter/other/pnmtopalm/Makefile
+++ b/converter/other/pnmtopalm/Makefile
@@ -25,7 +25,8 @@ $(BINARIES): %: %.o palmcolormap.o $(NETPBMLIB) $(LIBOPT)
 	  $(MATHLIB) $(LDLIBS) $(RPATH) $(LADD)
 
 gen_palm_colormap : % : %.c palmcolormap.o
-	$(CC) -I importinc $(CFLAGS) $(LDFLAGS) -o $@ $< palmcolormap.o \
+	$(CC) -I importinc $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
+	  $< palmcolormap.o \
 	  $(LIBOPTS) $(MATHLIB) $(LDLIBS) $(LADD)
 
 
diff --git a/converter/other/pnmtopng.c b/converter/other/pnmtopng.c
index ed245b93..4e267b99 100644
--- a/converter/other/pnmtopng.c
+++ b/converter/other/pnmtopng.c
@@ -383,7 +383,7 @@ parseCommandLine(int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
 
@@ -962,7 +962,7 @@ analyzeAlpha(FILE *     const ifp,
              gray       const alphaMaxval,
              bool *     const allOpaqueP,
              bool *     const singleColorIsTransP, 
-             pixel*     const alphaTranscolorP) {
+             pixel *    const alphaTranscolorP) {
 /*----------------------------------------------------------------------------
   Get information about the alpha mask, in combination with the masked
   image, that Caller can use to choose the most efficient way to
@@ -993,7 +993,7 @@ analyzeAlpha(FILE *     const ifp,
         */
         foundTransparentPixel = FALSE;  /* initial assumption */
         pm_seek2(ifp, &rasterPos, sizeof(rasterPos));
-        for (row = 0 ; row < rows && !foundTransparentPixel ; ++row) {
+        for (row = 0; row < rows && !foundTransparentPixel; ++row) {
             int col;
             pnm_readpnmrow(ifp, xelrow, cols, maxval, format);
             for (col = 0; col < cols && !foundTransparentPixel; ++col) {
@@ -2238,12 +2238,12 @@ convertpnm(struct cmdlineInfo const cmdline,
          of the input image.
       */
   int transexact;  
-    /* boolean: the user wants only the exact color he specified to be
-       transparent; not just something close to it.
-    */
+      /* boolean: the user wants only the exact color he specified to be
+         transparent; not just something close to it.
+      */
   int transparent;
   bool alpha;
-    /* There will be an alpha mask */
+      /* There will be an alpha mask */
   unsigned int pnm_meaningful_bits;
   pixel backcolor;
       /* The background color, with maxval equal to that of the input
@@ -2700,7 +2700,7 @@ main(int argc, char *argv[]) {
 
     int errorlevel;
     
-    pnm_init (&argc, argv);
+    pnm_init(&argc, argv);
     
     parseCommandLine(argc, argv, &cmdline);
     
diff --git a/converter/pbm/Makefile b/converter/pbm/Makefile
index 318b8e9e..f1533ab2 100644
--- a/converter/pbm/Makefile
+++ b/converter/pbm/Makefile
@@ -17,7 +17,7 @@ PORTBINARIES =	atktopbm brushtopbm cmuwmtopbm ddbugtopbm g3topbm escp2topbm \
 		pbmtomacp pbmtomatrixorbital pbmtomda pbmtomgr pbmtomrf \
 		pbmtonokia \
 		pbmtopi3 pbmtoplot pbmtopsg3 pbmtoptx pbmtowbmp \
-		pbmtox10bm pbmtoxbm pbmtoybm pbmtozinc \
+		pbmtoxbm pbmtoybm pbmtozinc \
 		pi3topbm pktopbm \
 		wbmptopbm xbmtopbm ybmtopbm	
 
@@ -29,7 +29,7 @@ endif
 #in libm?
 MATHBINARIES =	pbmtopk
 BINARIES =	$(PORTBINARIES) $(MATHBINARIES)
-SCRIPTS =
+SCRIPTS =       pbmtox10bm
 
 OBJECTS = $(BINARIES:%=%.o)
 
diff --git a/converter/pbm/cmuwmtopbm.c b/converter/pbm/cmuwmtopbm.c
index dce1d449..ce59491e 100644
--- a/converter/pbm/cmuwmtopbm.c
+++ b/converter/pbm/cmuwmtopbm.c
@@ -1,4 +1,4 @@
-/* cmuwmtopbm.c - read a CMU window manager bitmap and produce a portable bitmap
+/* cmuwmtopbm.c - read a CMU window manager bitmap and produce a PBM image.
 **
 ** Copyright (C) 1989 by Jef Poskanzer.
 **
@@ -10,105 +10,106 @@
 ** implied warranty.
 */
 
+/* 2006.10 (afu)
+   Changed bitrow from plain to raw, read function from getc() to fread(),
+   write function from pbm_writepbmrow() to pbm_writepbmrow_packed().
+   Retired bitwise transformation functions.
+
+   This program does not check the pad bits at the end of each row.
+*/
+
+
 #include "pbm.h"
 #include "cmuwm.h"
 
-static void getinit ARGS(( FILE* file, int* colsP, int* rowsP, short* depthP, int* padrightP ));
-static bit getbit ARGS(( FILE* file ));
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, padright, row, col;
-    short depth;
 
+static void
+readCmuwmHeader(FILE *         const ifP,
+                unsigned int * const colsP,
+                unsigned int * const rowsP,
+                unsigned int * const depthP) {
 
-    pbm_init( &argc, argv );
+    const char * const initReadError =
+        "CMU window manager header EOF / read error";
 
-    if ( argc > 2 )
-	pm_usage( "[cmuwmfile]" );
+    long l;
+    short s;
+    int rc;
+
+    rc = pm_readbiglong(ifP, &l);
+    if (rc == -1 )
+        pm_error(initReadError);
+    if (l != CMUWM_MAGIC)
+        pm_error("bad magic number in CMU window manager file");
+    rc = pm_readbiglong(ifP, &l);
+    if (rc == -1)
+        pm_error(initReadError);
+    *colsP = l;
+    rc = pm_readbiglong(ifP, &l);
+    if (rc == -1 )
+        pm_error(initReadError);
+    *rowsP = l;
+    rc = pm_readbigshort(ifP, &s);
+    if (rc == -1)
+        pm_error(initReadError);
+    *depthP = s;
+}
 
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
-    else
-	ifp = stdin;
-
-    getinit( ifp, &cols, &rows, &depth, &padright );
-    if ( depth != 1 )
-	pm_error(
-	    "CMU window manager file has depth of %d, must be 1",
-	    (int) depth );
-
-    pbm_writepbminit( stdout, cols, rows, 0 );
-    bitrow = pbm_allocrow( cols );
-
-    for ( row = 0; row < rows; ++row )
-	{
-	/* Get data. */
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-	    *bP = getbit( ifp );
-	/* Discard line padding */
-        for ( col = 0; col < padright; ++col )
-	    (void) getbit( ifp );
-	pbm_writepbmrow( stdout, bitrow, cols, 0 );
-	}
-
-    pm_close( ifp );
-    pm_close( stdout );
-
-    exit( 0 );
-    }
 
-static int item, bitsperitem, bitshift;
 
-static void
-getinit( file, colsP, rowsP, depthP, padrightP )
-    FILE* file;
-    int* colsP;
-    int* rowsP;
-    short* depthP;
-    int* padrightP;
-    {
-    long l;
+int
+main(int     argc,
+     char * argv[]) {
 
-    if ( pm_readbiglong( file, &l ) == -1 )
-	pm_error( "EOF / read error" );
-    if ( l != CMUWM_MAGIC )
-	pm_error( "bad magic number in CMU window manager file" );
-    if ( pm_readbiglong( file, &l ) == -1 )
-	pm_error( "EOF / read error" );
-    *colsP = (int) l;
-    if ( pm_readbiglong( file, &l ) == -1 )
-	pm_error( "EOF / read error" );
-    *rowsP = (int) l;
-    if ( pm_readbigshort( file, depthP ) == -1 )
-	pm_error( "EOF / read error" );
-    *padrightP = ( ( *colsP + 7 ) / 8 ) * 8 - *colsP;
-
-    bitsperitem = 0;
-    }
+    FILE * ifP;
+    unsigned char * bitrow;
+    unsigned int rows, cols, depth;
+    unsigned int row;
+
+    const char * inputFileName;
 
-static bit
-getbit( file )
-    FILE* file;
-    {
-    bit b;
-
-    if ( bitsperitem == 0 )
-	{
-	item = getc( file );
-	if ( item == EOF )
-	    pm_error( "EOF / read error" );
-	bitsperitem = 8;
-	bitshift = 7;
-	}
-    b = ( ( item >> bitshift) & 1 ) ? PBM_WHITE : PBM_BLACK;
-    --bitsperitem;
-    --bitshift;
-    return b;
+    pbm_init(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  "
+                 "Only argument is optional input file", argc-1);
+    if (argc-1 == 1)
+        inputFileName = argv[1];
+    else
+        inputFileName = "-";
+    
+    ifP = pm_openr(inputFileName);
+
+    readCmuwmHeader(ifP, &cols, &rows, &depth);
+    if (depth != 1)
+        pm_error("CMU window manager file has depth of %u, must be 1", depth);
+
+    pbm_writepbminit(stdout, cols, rows, 0);
+    bitrow = pbm_allocrow_packed(cols);
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int const bytesPerRow = pbm_packed_bytes(cols);
+        unsigned int byteSeq;
+        size_t bytesRead;
+
+        bytesRead = fread(bitrow, 1, bytesPerRow, ifP);
+        if (bytesRead != bytesPerRow)
+            pm_error("CWU window manager bitmap EOF / read error");
+            
+        /* Invert all bits in row - raster formats are similar.
+           CMUWM Black:0 White:1  End of row padded with 1
+           PBM   Black:1 White:0  End preferably padded with 0
+        */
+   
+        for (byteSeq = 0; byteSeq < bytesPerRow; ++byteSeq)
+            bitrow[byteSeq] = ~bitrow[byteSeq];
+                
+        pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
     }
+
+    pm_close(ifP);
+    pm_close(stdout);
+
+    return 0;
+}
diff --git a/converter/pbm/mgrtopbm.c b/converter/pbm/mgrtopbm.c
index cea4be48..9f7004a1 100644
--- a/converter/pbm/mgrtopbm.c
+++ b/converter/pbm/mgrtopbm.c
@@ -1,13 +1,10 @@
-/* mgrtopbm.c - read a MGR bitmap and produce a portable bitmap
-**
-** Copyright (C) 1989 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
+/* mgrtopbm.c - read a MGR bitmap and produce a PBM image.
+
+   Copyright information is at end of file.
+
+   You can find MGR and some MGR format test images at
+   ftp://sunsite.unc.edu/pub/Linux/apps/MGR/!INDEX.html
+
 */
 
 #include <string.h>
@@ -17,29 +14,29 @@
 #include "mgr.h"
 
 
-static unsigned char item;
-static int bitsperitem, bitshift;
 
 static void
-getinit(FILE * const file, 
-        int *  const colsP, 
-        int *  const rowsP, 
-        int *  const depthP, 
-        int *  const padrightP,
-        int *  const bitsperitemP) {
-
+readMgrHeader(FILE *          const ifP, 
+              unsigned int *  const colsP, 
+              unsigned int *  const rowsP, 
+              unsigned int *  const depthP, 
+              unsigned int *  const padrightP ) {
+    
     struct b_header head;
-    int pad;
+    unsigned int pad;
+    size_t bytesRead;
 
-    if (fread(&head, sizeof(struct old_b_header), 1, file ) != 1)
+    bytesRead = fread(&head, sizeof(struct old_b_header), 1, ifP);
+    if (bytesRead != 1)
         pm_error("Unable to read 1st byte of file.  "
                  "fread() returns errno %d (%s)",
                  errno, strerror(errno));
     if (head.magic[0] == 'y' && head.magic[1] == 'z') { 
         /* new style bitmap */
-        if (fread(&head.depth, 
-                  sizeof(head) - sizeof(struct old_b_header), 1, file) 
-             != 1 )
+        size_t bytesRead;
+        bytesRead = fread(&head.depth, 
+                          sizeof(head) - sizeof(struct old_b_header), 1, ifP);
+        if (bytesRead != 1 )
             pm_error("Unable to read header after 1st byte.  "
                      "fread() returns errno %d (%s)",
                      errno, strerror(errno));
@@ -60,7 +57,7 @@ getinit(FILE * const file,
     } else {
         pm_error("bad magic chars in MGR file: '%c%c'",
                  head.magic[0], head.magic[1] );
-        pad = -1;  /* should never reach here */
+        pad = 0;  /* should never reach here */
     }
 
     if (head.h_wide < ' ' || head.l_wide < ' ')
@@ -71,75 +68,79 @@ getinit(FILE * const file,
     *colsP = (((int)head.h_wide - ' ') << 6) + ((int)head.l_wide - ' ');
     *rowsP = (((int)head.h_high - ' ') << 6) + ((int) head.l_high - ' ');
     *padrightP = ( ( *colsP + pad - 1 ) / pad ) * pad - *colsP;
-    
-    *bitsperitemP = 8;
 }
 
 
 
-static bit
-getbit( file )
-    FILE* file;
-    {
-    bit b;
-
-    if ( bitsperitem == 8 )
-	{
-	item = getc( file );
-	bitsperitem = 0;
-	bitshift = 7;
-	}
-    bitsperitem++;
-    b = ( ( item >> bitshift) & 1 ) ? PBM_BLACK : PBM_WHITE;
-    bitshift--;
-    return b;
-    }
-
+int
+main(int    argc,
+     char * argv[]) {
+
+    FILE * ifP;
+    unsigned char * bitrow;
+    unsigned int rows, cols, depth;
+    unsigned int padright;
+    unsigned int row;
+    unsigned int itemCount;
+    const char * inputFileName;
+
+    pbm_init(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  "
+                 "Only argument is optional input file", argc-1);
+    if (argc-1 == 1)
+        inputFileName = argv[1];
+    else
+        inputFileName = "-";
+    
+    ifP = pm_openr(inputFileName);
 
+    readMgrHeader(ifP, &cols, &rows, &depth, &padright);
+    if (depth != 1)
+        pm_error("MGR file has depth of %u, must be 1", depth);
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, depth, padright, row, col;
+    pbm_writepbminit(stdout, cols, rows, 0);
 
+    bitrow = pbm_allocrow_packed(cols + padright);
+    
+    itemCount = (cols + padright ) / 8;
+
+    for (row = 0; row < rows; ++row) {
+        /* The raster formats are nearly identical.
+           MGR may have rows padded to 16 or 32 bit boundaries.
+        */
+        size_t bytesRead;
+        bytesRead = fread(bitrow, 1, itemCount, ifP);
+        if (bytesRead < itemCount)
+            pm_error("fread() failed to read mgr bitmap data");
+
+        pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
+    }
+    pm_close(ifP);
+    pm_close(stdout);
+    return 0;
+}
 
-    pbm_init( &argc, argv );
 
-    if ( argc > 2 )
-	pm_usage( "[mgrfile]" );
 
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
-    else
-	ifp = stdin;
-
-    getinit( ifp, &cols, &rows, &depth, &padright, &bitsperitem );
-    if ( depth != 1 )
-	pm_error( "MGR file has depth of %d, must be 1", depth );
-
-    pbm_writepbminit( stdout, cols, rows, 0 );
-    bitrow = pbm_allocrow( cols );
-
-    for ( row = 0; row < rows; row++ )
-	{
-	/* Get data, bit-reversed within each byte. */
-        for ( col = 0, bP = bitrow; col < cols; col++, bP++ )
-	    *bP = getbit( ifp );
-	/* Discard line padding */
-        for ( col = 0; col < padright; col ++ )
-	    (void) getbit( ifp );
-	pbm_writepbmrow( stdout, bitrow, cols, 0 );
-	}
-
-    pm_close( ifp );
-    pm_close( stdout );
-
-    exit( 0 );
-    }
+/* 2006.10 (afu)
+   Changed bitrow from plain to raw, read function from getc() to fread(),
+   write function from pbm_writepbmrow() to pbm_writepbmrow_packed().
+   Retired bitwise transformation functions.
+   
+   NOT tested for old-style format files.  Only one zz file in mgrsrc-0.69 .
+  
+*/
 
 
+/*
+** Copyright (C) 1989 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation.  This software is provided "as is" without express or
+** implied warranty.
+*/
diff --git a/converter/pbm/pbmtocmuwm.c b/converter/pbm/pbmtocmuwm.c
index 64d7af40..773d988b 100644
--- a/converter/pbm/pbmtocmuwm.c
+++ b/converter/pbm/pbmtocmuwm.c
@@ -1,4 +1,4 @@
-/* pbmtocmuwm.c - read a portable bitmap and produce a CMU window manager bitmap
+/* pbmtocmuwm.c - read a PBM image and produce a CMU window manager bitmap
 **
 ** Copyright (C) 1989 by Jef Poskanzer.
 **
@@ -10,108 +10,95 @@
 ** implied warranty.
 */
 
-#include "pbm.h"
-#include "cmuwm.h"
+/* 2006.10 (afu)
+   Changed bitrow from plain to raw, read function from pbm_readpbmrow() to
+   pbm_readpbmrow_packed(), write function from putc() to fwrite().
 
-static void putinit ARGS(( int rows, int cols ));
-static void putbit ARGS(( bit b ));
-static void putrest ARGS(( void ));
-static void putitem ARGS(( void ));
-
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, format, padright, row, col;
+   Retired bitwise transformation functions.
+*/
 
+#include "pbm.h"
+#include "cmuwm.h"
 
-    pbm_init( &argc, argv );
+static void
+putinit(unsigned int const rows,
+        unsigned int const cols) {
 
-    if ( argc > 2 )
-	pm_usage( "[pbmfile]" );
+    const char * const initWriteError =
+        "CMU window manager header write error";
 
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
-    else
-	ifp = stdin;
+    int rc;
 
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    bitrow = pbm_allocrow( cols );
-    
-    /* Round cols up to the nearest multiple of 8. */
-    padright = ( ( cols + 7 ) / 8 ) * 8 - cols;
+    rc = pm_writebiglong(stdout, CMUWM_MAGIC);
+    if (rc == -1)
+        pm_error(initWriteError);
+    rc = pm_writebiglong(stdout, cols);
+    if (rc == -1)
+        pm_error(initWriteError);
+    rc = pm_writebiglong(stdout, rows);
+    if (rc == -1)
+        pm_error(initWriteError);
+    rc = pm_writebigshort(stdout, (short) 1);
+    if (rc == -1)
+        pm_error(initWriteError);
+}
 
-    putinit( rows, cols );
-    for ( row = 0; row < rows; row++ )
-	{
-	pbm_readpbmrow( ifp, bitrow, cols, format );
-        for ( col = 0, bP = bitrow; col < cols; col++, bP++ )
-	    putbit( *bP );
-	for ( col = 0; col < padright; col++ )
-	    putbit( 0 );
-        }
 
-    pm_close( ifp );
 
-    putrest( );
+int
+main(int argc,
+     char * argv[]) {
 
-    exit( 0 );
-    }
+    FILE * ifP;
+    unsigned char * bitrow;
+    int rows, cols;
+    int format;
+    unsigned int row;
+    const char * inputFileName;
 
-static unsigned char item;
-static int bitsperitem, bitshift;
+    pbm_init(&argc, argv);
 
-static void
-putinit( rows, cols )
-    int rows, cols;
-    {
-    if ( pm_writebiglong( stdout, CMUWM_MAGIC ) == -1 )
-	pm_error( "write error" );
-    if ( pm_writebiglong( stdout, cols ) == -1 )
-	pm_error( "write error" );
-    if ( pm_writebiglong( stdout, rows ) == -1 )
-	pm_error( "write error" );
-    if ( pm_writebigshort( stdout, (short) 1 ) == -1 )
-	pm_error( "write error" );
-
-    item = 0;
-    bitsperitem = 0;
-    bitshift = 7;
-    }
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  "
+                 "Only argument is optional input file", argc-1);
+    if (argc-1 == 1)
+        inputFileName = argv[1];
+    else
+        inputFileName = "-";
+    
+    ifP = pm_openr(inputFileName);
 
-#if __STDC__
-static void
-putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
-    {
-    if ( bitsperitem == 8 )
-	putitem( );
-    if ( b == PBM_WHITE )
-	item += 1 << bitshift;
-    bitsperitem++;
-    bitshift--;
-    }
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+    bitrow = pbm_allocrow_packed(cols);
 
-static void
-putrest( )
-    {
-    if ( bitsperitem > 0 )
-	putitem( );
+    putinit(rows, cols);
+    
+    /* Convert PBM raster data to CMUWM and write */ 
+    for (row = 0; row < rows; ++row) {
+        unsigned int const bytesPerRow = pbm_packed_bytes(cols);
+        unsigned char const padding = 
+            (cols % 8 == 0) ? 0x00 : ((unsigned char) ~0 >> (cols % 8));
+
+        unsigned int i;
+        size_t bytesWritten;
+
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+
+        /* Invert all bits in row - raster formats are similar.
+           PBM   Black:1 White:0  "Don't care" bits at end of row
+           CMUWM Black:0 White:1  End of row padded with 1
+        */
+
+        for (i = 0; i < bytesPerRow; ++i)
+            bitrow[i] = ~bitrow[i];
+
+        bitrow[bytesPerRow-1] |= padding;  /* Set row end pad bits */
+        
+        bytesWritten = fwrite(bitrow, 1, bytesPerRow, stdout);
+        if (bytesWritten != bytesPerRow)
+            pm_error("fwrite() failed to write CMU window manager bitmap");
     }
 
-static void
-putitem( )
-    {
-    (void) putc( item, stdout );
-    item = 0;
-    bitsperitem = 0;
-    bitshift = 7;
-    }
+    pm_close(ifP);
+    return 0;
+}
diff --git a/converter/pbm/pbmtogem.c b/converter/pbm/pbmtogem.c
index 59f2b9cf..cefbdc95 100644
--- a/converter/pbm/pbmtogem.c
+++ b/converter/pbm/pbmtogem.c
@@ -129,14 +129,8 @@ putinit (rows, cols)
   linerepeat = -1;
 }
 
-#if __STDC__
 static void
 putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
     {
     if ( bitsperitem == 8 )
 	putitem( );
diff --git a/converter/pbm/pbmtogo.c b/converter/pbm/pbmtogo.c
index b7c12373..67fe5821 100644
--- a/converter/pbm/pbmtogo.c
+++ b/converter/pbm/pbmtogo.c
@@ -214,7 +214,7 @@ main( argc, argv )
             fflush(stdout);
 
             /* Output the plot data */
-            write(1, outbuffer, nout);
+            fwrite(outbuffer, 1, nout, stdout);
 
             /* Reset the counters */
             linerepeat = 0;
@@ -225,7 +225,7 @@ main( argc, argv )
                   putchar(linerepeat);
                   printf("%d/", nout+1);
                   fflush(stdout);
-                  write(1, outbuffer, nout);
+                  fwrite(outbuffer, 1, nout, stdout);
                   linerepeat = 0;
               }
         }
@@ -264,14 +264,8 @@ putinit()
   bitshift = 7;
 }
 
-#if __STDC__
 static void
 putbit(bit b)
-#else /*__STDC__*/
-static void
-putbit(b)
-bit b;
-#endif /*__STDC__*/
 {
   if (b == PBM_BLACK)
     item += 1 << bitshift;
diff --git a/converter/pbm/pbmtoicon.c b/converter/pbm/pbmtoicon.c
index 0e21c202..d5fefb76 100644
--- a/converter/pbm/pbmtoicon.c
+++ b/converter/pbm/pbmtoicon.c
@@ -1,4 +1,4 @@
-/* pbmtoicon.c - read a portable bitmap and produce a Sun icon file
+/* pbmtoicon.c - read a PBM image and produce a Sun icon file
 **
 ** Copyright (C) 1988 by Jef Poskanzer.
 **
@@ -10,125 +10,177 @@
 ** implied warranty.
 */
 
+/* 2006.10 (afu)
+   Changed bitrow from plain to raw, read function from pbm_readpbmrow() to
+   pbm_readpbmrow_packed.  Applied wordint to scoop up 16 bit output items.
+   putitem changed to better express the output format.
+   Retired bitwise transformation functions.
+*/
+
+#include "wordaccess.h"
 #include "pbm.h"
 
-static void putinit ARGS(( void ));
-static void putbit ARGS(( bit b ));
-static void putrest ARGS(( void ));
-static void putitem ARGS(( void ));
+static unsigned short int itemBuff[8];
+static unsigned int itemCnt;    /* takes values 0 to 8 */
+FILE * putFp;
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, format, pad, padleft, padright, row, col;
 
 
-    pbm_init( &argc, argv );
+static void
+putinit(FILE * const ofP) {
+    putFp = ofP;
+    itemCnt = 0;
+}
 
-    if ( argc > 2 )
-	pm_usage( "[pbmfile]" );
 
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
-    else
-	ifp = stdin;
 
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    bitrow = pbm_allocrow( cols );
+static void
+putitem(wordint const item) {
+
+    if (itemCnt == 8 ) {
+        /* Buffer is full.  Write out one line. */
+        int rc;
     
-    /* Round cols up to the nearest multiple of 16. */
-    pad = ( ( cols + 15 ) / 16 ) * 16 - cols;
-    padleft = pad / 2;
-    padright = pad - padleft;
-
-    printf( "/* Format_version=1, Width=%d, Height=%d", cols + pad, rows );
-    printf( ", Depth=1, Valid_bits_per_item=16\n */\n" );
-
-    putinit( );
-    for ( row = 0; row < rows; ++row )
-	{
-	pbm_readpbmrow( ifp, bitrow, cols, format );
-	for ( col = 0; col < padleft; ++col )
-	    putbit( 0 );
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-	    putbit( *bP );
-	for ( col = 0; col < padright; ++col )
-	    putbit( 0 );
-        }
+        rc = fprintf(putFp,
+                     "\t0x%04x,0x%04x,0x%04x,0x%04x,"
+                     "0x%04x,0x%04x,0x%04x,0x%04x,\n",
+                     itemBuff[0],itemBuff[1],itemBuff[2],itemBuff[3],
+                     itemBuff[4],itemBuff[5],itemBuff[6],itemBuff[7]);
+        if (rc < 0)        
+           pm_error("fprintf() failed to write Icon bitmap");
+           
+        itemCnt = 0;
+    }
+    itemBuff[itemCnt++] = item & 0xffff;  /* Only lower 16 bits are used */
+}
 
-    pm_close( ifp );
 
-    putrest( );
 
-    exit( 0 );
-    }
+static void
+putterm(void) {
 
-static int item, bitsperitem, bitshift, itemsperline, firstitem;
+    unsigned int i;
 
-static void
-putinit( )
-    {
-    itemsperline = 0;
-    bitsperitem = 0;
-    item = 0;
-    bitshift = 15;
-    firstitem = 1;
+    for (i = 0; i < itemCnt; ++i) {
+        int rc;
+        rc = fprintf(putFp, "%s0x%04x%c", i == 0  ? "\t" : "", itemBuff[i],
+                     i == itemCnt - 1 ? '\n' : ',');
+        if (rc < 0)        
+            pm_error("fprintf() failed to write Icon bitmap");
     }
+}     
+
+
 
-#if __STDC__
-static void
-putbit( bit b )
-#else /*__STDC__*/
 static void
-putbit( b )
-bit b;
-#endif /*__STDC__*/
-    {
-    if ( bitsperitem == 16 )
-	putitem( );
-    ++bitsperitem;
-    if ( b == PBM_BLACK )
-	item += 1 << bitshift;
-    --bitshift;
-    }
+writeIconHeader(FILE *       const ofP,
+                unsigned int const width,
+                unsigned int const height) {
+
+    int rc;
+
+    rc = fprintf(ofP,
+                 "/* Format_version=1, Width=%u, Height=%u", width, height);
+    if (rc < 0)
+        pm_error("fprintf() failed to write Icon header");
+        
+    rc = fprintf(ofP, ", Depth=1, Valid_bits_per_item=16\n */\n");
+    if (rc < 0)
+        pm_error("fprintf() failed to write Icon header");
+}
+
+
 
 static void
-putrest( )
-    {
-    if ( bitsperitem > 0 )
-	putitem( );
-    putchar( '\n' );
+writeIcon(FILE *       const ifP,
+          unsigned int const cols,
+          unsigned int const rows,
+          int          const format,
+          FILE *       const ofP) {
+
+    unsigned int const wordintSize = sizeof(wordint) * 8;
+        /* wordintSize is usually 32 or 64 bits.  Must be at least 24. */
+    unsigned int const items = (cols + 15) / 16;
+    unsigned int const bitrowBytes = pbm_packed_bytes(cols);
+    unsigned int const pad = items * 16 - cols;
+    /* 'padleft' is added to the output.  'padbyte' is for cleaning
+       the input
+    */
+    unsigned int const padleft = pad / 2;
+    unsigned int const padbyte = bitrowBytes * 8 - cols;
+    unsigned int const shift   = (wordintSize - 24) + padleft;
+    
+    unsigned char * bitbuffer;
+    unsigned char * bitrow;
+    unsigned int row;
+
+    bitbuffer = pbm_allocrow_packed(cols + wordintSize);
+    bitrow = &bitbuffer[1];
+    bitbuffer[0] = 0;
+    bitrow[bitrowBytes] = 0;
+    
+    writeIconHeader(ofP, cols + pad, rows);
+
+    putinit(ofP);
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int itemSeq;
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+
+        /* Clear post-data junk in final partial byte */
+        if (padbyte > 0) {
+            bitrow[bitrowBytes-1] >>= padbyte;
+            bitrow[bitrowBytes-1] <<= padbyte;
+        }
+        
+        for (itemSeq = 0; itemSeq < items; ++itemSeq) {
+            /* Scoop up bits, shift-align, send to format & print function.
+    
+               An item is 16 bits, typically spread over 3 bytes due to
+               left-padding.  We use wordint here to scoop up 4 (or more)
+               consecutive bytes.  An item always resides within the higher
+               24 bits of each scoop.  It is essential to use wordint
+               (or rather the wordaccess function bytesToWordInt() ); 
+               simple long, uint_32t, etc. do not work for they are not
+               shift-tolerant.
+            */
+            
+            wordint const scoop = bytesToWordint(&bitbuffer[itemSeq*2]);
+            putitem (scoop >> shift);
+        }
     }
+    putterm();    
+}
 
-static void
-putitem( )
-    {
-    const char* hexits = "0123456789abcdef";
 
-    if ( firstitem )
-	firstitem = 0;
+
+int
+main(int argc,
+     char * argv[]) {
+
+    FILE * ifP;
+    int rows, cols;
+    int format;
+    const char * inputFileName;
+
+    pbm_init(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  "
+                 "Only argument is optional input file", argc-1);
+    if (argc-1 == 1)
+        inputFileName = argv[1];
     else
-	putchar( ',' );
-    if ( itemsperline == 8 )
-	{
-	putchar( '\n' );
-	itemsperline = 0;
-	}
-    if ( itemsperline == 0 )
-	putchar( '\t' );
-    putchar( '0' );
-    putchar( 'x' );
-    putchar( hexits[item >> 12] );
-    putchar( hexits[( item >> 8 ) & 15] );
-    putchar( hexits[( item >> 4 ) & 15] );
-    putchar( hexits[item & 15] );
-    ++itemsperline;
-    bitsperitem = 0;
-    item = 0;
-    bitshift = 15;
-    }
+        inputFileName = "-";
+    
+    ifP = pm_openr(inputFileName);
+
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+
+    writeIcon(ifP, cols, rows, format, stdout);
+
+    pm_close(ifP);
+
+    return 0;
+}
+
diff --git a/converter/pbm/pbmtomgr.c b/converter/pbm/pbmtomgr.c
index 7a6e7fc1..2ca7c7d0 100644
--- a/converter/pbm/pbmtomgr.c
+++ b/converter/pbm/pbmtomgr.c
@@ -1,120 +1,114 @@
-/* pbmtomgr.c - read a portable bitmap and produce a MGR bitmap
-**
-** Copyright (C) 1989 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
+/* pbmtomgr.c - read a PBM image and produce a MGR bitmap
+
+   Copyright information is at end of file.
+
+   You can find MGR and some MGR format test images at
+   ftp://sunsite.unc.edu/pub/Linux/apps/MGR/!INDEX.html
 */
 
 #include "pbm.h"
 #include "mgr.h"
 
-static void putinit ARGS(( int rows, int cols ));
-static void putbit ARGS(( bit b ));
-static void putrest ARGS(( void ));
-static void putitem ARGS(( void ));
+static void
+putinit(unsigned int const rows,
+        unsigned int const cols) {
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, format, padright, row, col;
+    struct b_header head;
+    size_t writtenCount;
 
+    head.magic[0] = 'y';
+    head.magic[1] = 'z';
+    head.h_wide = ((cols >> 6) & 0x3f) + ' ';
+    head.l_wide = (cols & 0x3f) + ' ';
+    head.h_high = (( rows >> 6) & 0x3f) + ' ';
+    head.l_high = (rows & 0x3f) + ' ';
+    head.depth = (1 & 0x3f) + ' ';
+    head._reserved = ' ';
+    writtenCount = fwrite(&head, sizeof(head), 1, stdout);
+    if (writtenCount != 1)
+        pm_error("fwrite() failed to write the MGR header.");    
+}
 
-    pbm_init( &argc, argv );
 
-    if ( argc > 2 )
-	pm_usage( "[pbmfile]" );
 
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
+int
+main(int argc,
+     char * argv[]) {
+
+    FILE * ifP;
+    unsigned char * bitrow;
+    int rows;
+    int cols;
+    int format;
+    unsigned int row;
+    unsigned int bytesPerRow;
+        /* Number of packed bytes (8 columns per byte) in a row. */
+    unsigned int padright;
+        /* Number of columns added to the right of each row to get up to
+           a multiple of 8, i.e. an integral number of packed bytes.
+        */
+    const char * inputFileName;
+
+    pbm_init(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  "
+                 "Only argument is optional input file", argc-1);
+    if (argc-1 == 1)
+        inputFileName = argv[1];
     else
-	ifp = stdin;
-
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    bitrow = pbm_allocrow( cols );
+        inputFileName = "-";
     
-    /* Round cols up to the nearest multiple of 8. */
-    padright = ( ( cols + 7 ) / 8 ) * 8 - cols;
-
-    putinit( rows, cols );
-    for ( row = 0; row < rows; ++row )
-	{
-	pbm_readpbmrow( ifp, bitrow, cols, format );
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-	    putbit( *bP );
-	for ( col = 0; col < padright; ++col )
-	    putbit( 0 );
-        }
+    ifP = pm_openr(inputFileName);
 
-    pm_close( ifp );
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+    
+    bitrow = pbm_allocrow_packed(cols);
+    bytesPerRow = pbm_packed_bytes(cols);
+    padright = bytesPerRow * 8 - cols;
 
-    putrest( );
+    putinit(rows, cols);
+    
+    for (row = 0; row < rows; ++row) {
+        /* The raster formats are identical. 
+           The row end pad bits are set to 0 in mgr.
+        */
+        size_t bytesWritten;
+
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+        
+        if (padright > 0) {
+            bitrow[bytesPerRow-1] >>= padright;
+            bitrow[bytesPerRow-1] <<= padright;
+        }
 
-    exit( 0 );
+        bytesWritten = fwrite(bitrow, 1, bytesPerRow, stdout);
+        if (bytesWritten != bytesPerRow )
+            pm_error("fwrite() failed to write MGR bitmap "
+                     "to Standard Output.");    
     }
+    pm_close(ifP);
+    return 0;
+}
 
-static unsigned char item;
-static int bitsperitem, bitshift;
-
-static void
-putinit( rows, cols )
-    int rows, cols;
-    {
-    struct b_header head;
-
-    head.magic[0] = 'y';
-    head.magic[1] = 'z';
-    head.h_wide = ( ( cols >> 6 ) & 0x3f ) + ' ';
-    head.l_wide = ( cols & 0x3f ) + ' ';
-    head.h_high = ( ( rows >> 6 ) & 0x3f ) + ' ';
-    head.l_high = ( rows & 0x3f ) + ' ';
-    head.depth = ( 1 & 0x3f ) + ' ';
-    head._reserved = ' ';
-    fwrite( &head, sizeof(head), 1, stdout );
 
-    item = 0;
-    bitsperitem = 0;
-    bitshift = 7;
-    }
 
-#if __STDC__
-static void
-putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
-    {
-    if ( bitsperitem == 8 )
-	putitem( );
-    ++bitsperitem;
-    if ( b == PBM_BLACK )
-	item += 1 << bitshift;
-    --bitshift;
-    }
+/* 2006.10 (afu)
+   Changed bitrow from plain to raw, read function from pbm_readpbmrow() to
+   pbm_readpbmrow_packed(), write function from putc() to fwrite().
 
-static void
-putrest( )
-    {
-    if ( bitsperitem > 0 )
-	putitem( );
-    }
+   Retired bitwise transformation functions.
+   
+   Produces only new style bitmap (8 bit padding.)  See mgrtopbm.c .
+*/
 
-static void
-putitem( )
-    {
-    fwrite( &item, sizeof(item), 1, stdout );
-    item = 0;
-    bitsperitem = 0;
-    bitshift = 7;
-    }
+/*
+** Copyright (C) 1989 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation.  This software is provided "as is" without express or
+** implied warranty.
+*/
diff --git a/converter/pbm/pbmtopi3.c b/converter/pbm/pbmtopi3.c
index 06023d7a..6a60af62 100644
--- a/converter/pbm/pbmtopi3.c
+++ b/converter/pbm/pbmtopi3.c
@@ -89,14 +89,8 @@ putinit( )
     bitshift = 7;
     }
 
-#if __STDC__
 static void
 putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
     {
     if (bitsperitem == 8)
 	putitem( );
diff --git a/converter/pbm/pbmtoptx.c b/converter/pbm/pbmtoptx.c
index 5031efcb..8cd60326 100644
--- a/converter/pbm/pbmtoptx.c
+++ b/converter/pbm/pbmtoptx.c
@@ -67,14 +67,8 @@ putinit( )
     bitshift = 0;
     }
 
-#if __STDC__
 static void
 putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
     {
     if ( bitsperitem == 6 )
 	putitem( );
diff --git a/converter/pbm/pbmtox10bm b/converter/pbm/pbmtox10bm
new file mode 100644
index 00000000..9a1a7286
--- /dev/null
+++ b/converter/pbm/pbmtox10bm
@@ -0,0 +1,45 @@
+#! /usr/bin/perl
+
+#============================================================================
+#  This is a compatibility interface to Pbmtoxbm.
+#
+#  It exists so existing programs and procedures that rely on Pbmtox10bm
+#  syntax continue to work.  You should not make new use of Pbmtox10bm and
+#  if you modify an old use, you should upgrade it to use Pbmtoxbm.
+#
+#  Pbmtoxbm with the -x10 option is backward compatible with Pbmtox10bm.
+#============================================================================
+
+use strict;
+use File::Basename;
+use Cwd 'abs_path';
+
+my $infile;
+
+foreach (@ARGV) {
+    if (/^-/) {
+        # It's an option.  But Pbmtox10bm didn't have any options.
+        print(STDERR "Invalid option '$_'\n");
+        exit(10);
+    } else {
+        # It's a parameter
+        if (defined($infile)) {
+            print(STDERR
+                  "You may specify at most one non-option parameter.\n");
+            exit(10);
+        } else {
+            $infile = $_;
+        }
+    }
+}
+
+my $infileParm = defined($infile) ? $infile : "-";
+
+# We want to get Pbmtoxbm from the same directory we came from if
+# it's there.  Frequently, the directory containing Netpbm programs is
+# not in the PATH and we were invoked by absolute path.
+
+my $my_directory = abs_path(dirname($0));
+$ENV{"PATH"} = $my_directory . ":" . $ENV{"PATH"};
+
+exec('pbmtoxbm', '-x10', $infileParm);
diff --git a/converter/pbm/pbmtox10bm.c b/converter/pbm/pbmtox10bm.c
deleted file mode 100644
index ef31fb9b..00000000
--- a/converter/pbm/pbmtox10bm.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* pbmtox10bm.c - read a portable bitmap and produce an X10 bitmap file
-**
-** Copyright (C) 1988 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
-*/
-
-#include <string.h>
-
-#include "nstring.h"
-#include "pbm.h"
-
-int
-main(int argc, char * argv[]) {
-
-    FILE* ifp;
-    bit* bitrow;
-    bit * bP;
-    int rows, cols, format, padright, row;
-    int col;
-    char name[100];
-    char* cp;
-    int itemsperline;
-    int bitsperitem;
-    int item;
-    int firstitem;
-    const char* const hexchar = "0123456789abcdef";
-
-
-    pbm_init( &argc, argv );
-
-    if ( argc > 2 )
-        pm_usage( "[pbmfile]" );
-
-    if ( argc == 2 )
-	{
-        ifp = pm_openr( argv[1] );
-        strcpy( name, argv[1] );
-        if (STREQ( name, "-" ))
-            strcpy( name, "noname" );
-
-        if ( ( cp = strchr( name, '.' ) ) != 0 )
-            *cp = '\0';
-	}
-    else
-	{
-        ifp = stdin;
-        strcpy( name, "noname" );
-	}
-
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    bitrow = pbm_allocrow( cols );
-
-    /* Compute padding to round cols up to the nearest multiple of 16. */
-    padright = ( ( cols + 15 ) / 16 ) * 16 - cols;
-
-    printf( "#define %s_width %d\n", name, cols );
-    printf( "#define %s_height %d\n", name, rows );
-    printf( "static short %s_bits[] = {\n", name );
-
-    itemsperline = 0;
-    bitsperitem = 0;
-    item = 0;
-    firstitem = 1;
-
-#define PUTITEM \
-    { \
-        if ( firstitem ) \
-	        firstitem = 0; \
-        else \
-	        putchar( ',' ); \
-    if ( itemsperline == 11 ) \
-	{ \
-	    putchar( '\n' ); \
-	    itemsperline = 0; \
-	} \
-    if ( itemsperline == 0 ) \
-	    putchar( ' ' ); \
-    ++itemsperline; \
-    putchar('0'); \
-    putchar('x'); \
-    putchar(hexchar[item >> 12]); \
-    putchar(hexchar[(item >> 8) & 15]); \
-    putchar(hexchar[(item >> 4) & 15]); \
-    putchar(hexchar[item & 15]); \
-    bitsperitem = 0; \
-    item = 0; \
-    }
-
-#define PUTBIT(b) \
-    { \
-    if ( bitsperitem == 16 ) \
-	    PUTITEM; \
-    if ( (b) == PBM_BLACK ) \
-	    item += 1 << bitsperitem; \
-    ++bitsperitem; \
-    }
-
-    for ( row = 0; row < rows; ++row )
-	{
-        pbm_readpbmrow( ifp, bitrow, cols, format );
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-            PUTBIT(*bP);
-        for ( col = 0; col < padright; ++col )
-            PUTBIT(0);
-    }
-
-    pm_close( ifp );
-    
-    if ( bitsperitem > 0 )
-        PUTITEM;
-    printf( "};\n" );
-
-    return 0;
-}
diff --git a/converter/pbm/pbmtoxbm.c b/converter/pbm/pbmtoxbm.c
index 96830a0c..eb45f11b 100644
--- a/converter/pbm/pbmtoxbm.c
+++ b/converter/pbm/pbmtoxbm.c
@@ -1,4 +1,4 @@
-/* pbmtoxbm.c - read a portable bitmap and produce an X11 bitmap file
+/* pbmtoxbm.c - read a PBM image and produce an X11/X10 bitmap file
 **
 ** Copyright (C) 1988 by Jef Poskanzer.
 **
@@ -10,17 +10,113 @@
 ** implied warranty.
 */
 
+/* 2006.10 (afu)   
+   Changed bitrow from plain to raw, read function from pbm_readpbmrow() to
+   pbm_readpbmrow_packed().  Retired bitwise transformation functions.
+ 
+   Output function putitem rewritten to handle both X10 and X11.
+
+   Added -name option.  There is no check for the string thus given.
+
+*/
+
 #define _BSD_SOURCE 1      /* Make sure strdup() is in string.h */
 #define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
 
 #include <string.h>
 
 #include "pbm.h"
+#include "shhopt.h"
+#include "mallocvar.h"
+#include "bitreverse.h"
 #include "nstring.h"
 
 
+enum xbmVersion { X10, X11 };
+
+struct cmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char *    inputFileName;
+    const char *    name;
+    enum xbmVersion xbmVersion;
+};
+
 static void
-generateName(char const filenameArg[], const char ** const nameP) {
+parseCommandLine(int                 argc, 
+                 char **             argv,
+                 struct cmdlineInfo *cmdlineP ) {
+/*----------------------------------------------------------------------------
+   Parse program command line described in Unix standard form by argc
+   and argv.  Return the information in the options as *cmdlineP.  
+
+   If command line is internally inconsistent (invalid options, etc.),
+   issue error message to stderr and abort program.
+
+   Note that the strings we return are stored in the storage that
+   was passed to us as the argv array.  We also trash *argv.
+-----------------------------------------------------------------------------*/
+    optEntry *option_def;
+    /* Instructions to optParseOptions3 on how to parse our options. */
+
+    optStruct3 opt;
+    unsigned int option_def_index;
+    unsigned int x10, x11, nameSpec;
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+
+    OPTENT3(0, "name", OPT_STRING, &cmdlineP->name, &nameSpec, 0);
+    OPTENT3(0, "x10" , OPT_FLAG,   NULL, &x10, 0);
+    OPTENT3(0, "x11" , OPT_FLAG,   NULL, &x11, 0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (!nameSpec)
+        cmdlineP->name = NULL;
+    else if (strlen(cmdlineP->name) > 56)
+        pm_error("Image name too long: %d chars. (max 56)",
+                 strlen(cmdlineP->name));
+    else if (!ISALPHA(cmdlineP->name[0]) && cmdlineP->name[0] !='_')
+        pm_error("Image name '%s' starts with non-alphabet character.",
+                  cmdlineP->name);
+    else {
+        unsigned int i;
+        for (i = 0 ; i < strlen(cmdlineP->name); ++i)
+            if (!ISALNUM(cmdlineP->name[i]) && cmdlineP->name[i] != '_')
+                pm_error("Image name '%s' contains invalid character (%c).",
+                         cmdlineP->name, cmdlineP->name[i]);
+    }
+    
+    if (x10 && x11)
+        pm_error("You can't specify both -x10 and -x11");
+    else if (x10)
+        cmdlineP->xbmVersion = X10;
+    else 
+        cmdlineP->xbmVersion = X11;
+        
+    if (argc-1 < 1) 
+        cmdlineP->inputFileName = "-";
+    else {
+        cmdlineP->inputFileName = argv[1];
+        
+        if (argc-1 > 1)
+            pm_error("Program takes zero or one argument (filename).  You "
+                     "specified %u", argc-1);
+    }
+}
+
+
+
+static void
+generateName(char          const filenameArg[],
+             const char ** const nameP) {
 /*----------------------------------------------------------------------------
    Generate a name for the image to put in the bitmap file.  Derive it from
    the filename argument filenameArg[] and return it as a null-terminated
@@ -67,99 +163,235 @@ generateName(char const filenameArg[], const char ** const nameP) {
 
 
 
-int
-main(int argc, char * argv[]) {
+static unsigned short int itemBuff[22];
+static int itemCnt;    /* takes values 0 to 15 (x11) or 21 (x10) */
+static enum xbmVersion itemVersion;
 
-    FILE* ifp;
-    bit* bitrow;
-    int rows, cols, format;
-    int padright;
-    int row;
-    const char * inputFilename;
-    const char *name;
-    int itemsperline;
-    int bitsperitem;
-    int item;
-    int firstitem;
-    const char hexchar[] = "0123456789abcdef";
 
-    pbm_init(&argc, argv);
 
-    if (argc-1 > 1)
-        pm_error("Too many arguments (%d).  The only valid argument is an "
-                 "input file name.", argc-1);
-    else if (argc-1 == 1) 
-        inputFilename = argv[1];
-    else
-        inputFilename = "-";
+static void
+putitemX10(unsigned char const item) {
 
-    generateName(inputFilename, &name);
-    ifp = pm_openr(inputFilename);
-    
-    pbm_readpbminit(ifp, &cols, &rows, &format);
-    bitrow = pbm_allocrow(cols);
-    
-    /* Compute padding to round cols up to the nearest multiple of 8. */
-    padright = ((cols + 7)/8) * 8 - cols;
-
-    printf("#define %s_width %d\n", name, cols);
-    printf("#define %s_height %d\n", name, rows);
-    printf("static char %s_bits[] = {\n", name);
-
-    itemsperline = 0;
-    bitsperitem = 0;
-    item = 0;
-    firstitem = 1;
-
-#define PUTITEM \
-    { \
-    if ( firstitem ) \
-        firstitem = 0; \
-    else \
-        putchar( ',' ); \
-    if ( itemsperline == 15 ) \
-        { \
-        putchar( '\n' ); \
-        itemsperline = 0; \
-        } \
-    if ( itemsperline == 0 ) \
-        putchar( ' ' ); \
-    ++itemsperline; \
-    putchar('0'); \
-    putchar('x'); \
-    putchar(hexchar[item >> 4]); \
-    putchar(hexchar[item & 15]); \
-    bitsperitem = 0; \
-    item = 0; \
+    if (itemCnt == 22) {
+        /* Buffer is full.  Write out one line. */
+        int rc;
+        rc = printf(" 0x%02x%02x,0x%02x%02x,0x%02x%02x,0x%02x%02x,"
+                    "0x%02x%02x,0x%02x%02x,0x%02x%02x,0x%02x%02x,"
+                    "0x%02x%02x,0x%02x%02x,0x%02x%02x,\n",
+                    itemBuff[ 1], itemBuff[ 0], itemBuff[ 3], itemBuff[ 2],
+                    itemBuff[ 5], itemBuff[ 4], itemBuff[ 7], itemBuff[ 6],
+                    itemBuff[ 9], itemBuff[ 8], itemBuff[11], itemBuff[10],
+                    itemBuff[13], itemBuff[12], itemBuff[15], itemBuff[14],
+                    itemBuff[17], itemBuff[16], itemBuff[19], itemBuff[18],
+                    itemBuff[21], itemBuff[20]
+            );
+
+        if (rc < 0)        
+            pm_error("Error writing X10 bitmap raster item.  "
+                     "printf() failed with errno %d (%s)",
+                     errno, strerror(errno));
+        
+        itemCnt = 0;
     }
+    itemBuff[itemCnt++] = bitreverse[item];
+}
+
 
-#define PUTBIT(b) \
-    { \
-    if ( bitsperitem == 8 ) \
-        PUTITEM; \
-    if ( (b) == PBM_BLACK ) \
-        item += 1 << bitsperitem; \
-    ++bitsperitem; \
+
+static void
+putitemX11(unsigned char const item) {
+
+    if (itemCnt == 15 ) {
+        /* Buffer is full.  Write out one line. */
+        int rc;
+        rc = printf(" 0x%02x,0x%02x,0x%02x,0x%02x,"
+                    "0x%02x,0x%02x,0x%02x,0x%02x,"
+                    "0x%02x,0x%02x,0x%02x,0x%02x,"
+                    "0x%02x,0x%02x,0x%02x,\n",
+                    itemBuff[0], itemBuff[1], itemBuff[2], itemBuff[3],
+                    itemBuff[4], itemBuff[5], itemBuff[6], itemBuff[7],
+                    itemBuff[8], itemBuff[9], itemBuff[10],itemBuff[11],
+                    itemBuff[12],itemBuff[13],itemBuff[14]
+            );
+        if (rc < 0)        
+            pm_error("Error writing X11 bitmap raster item.  "
+                     "printf() failed with errno %d (%s)",
+                     errno, strerror(errno));
+        
+        itemCnt = 0;
     }
+    itemBuff[itemCnt++] = bitreverse[item];
+}
 
-    for (row = 0; row < rows; ++row) {
-        int col;
-        pbm_readpbmrow(ifp, bitrow, cols, format);
-        for (col = 0; col < cols; ++col)
-            PUTBIT(bitrow[col]);
-        for (col = 0; col < padright; ++col)
-            PUTBIT(0);
+
+
+static void
+putitem(unsigned char const item) {
+
+    switch (itemVersion) {
+    case X10: putitemX10(item); break;
+    case X11: putitemX11(item); break;
+    }
+}
+
+
+
+static void
+puttermX10(void) {
+
+    unsigned int i;
+
+    for (i = 0; i < itemCnt; i += 2) {
+        int rc;
+
+        rc = printf("%s0x%02x%02x%s",
+                    (i == 0) ? " " : "",
+                    itemBuff[i+1],
+                    itemBuff[i], 
+                    (i == itemCnt - 2) ? "};\n" : ",");
+        if (rc < 0)        
+            pm_error("Error writing end of X10 bitmap raster.  "
+                     "printf() failed with errno %d (%s)",
+                     errno, strerror(errno));
+    }
+}
+
+
+
+static void
+puttermX11(void) {
+
+    unsigned int i;
+
+    for (i = 0; i < itemCnt; ++i) {
+        int rc;
+
+        rc = printf("%s0x%02x%s",
+                    (i == 0)  ? " " : "",
+                    itemBuff[i],
+                    (i == itemCnt - 1) ? "};\n" : ",");
+
+        if (rc < 0)        
+            pm_error("Error writing end of X11 bitmap raster.  "
+                     "printf() failed with errno %d (%s)",
+                     errno, strerror(errno));
     }
+}
+
+
+
+static void
+putinit(enum xbmVersion const xbmVersion) {
+
+    itemCnt = 0;
+    itemVersion = xbmVersion;
+}
+
 
-    pm_close(ifp);
 
-    if (bitsperitem > 0)
-        PUTITEM;
-    printf("};\n");
+static void
+putterm(void) {
+
+    switch (itemVersion) {
+    case X10: puttermX10(); break;
+    case X11: puttermX11(); break;
+    }
+}
+
+
+
+static void
+writeXbmHeader(enum xbmVersion const xbmVersion,
+               const char *    const name,
+               unsigned int    const width,
+               unsigned int    const height,
+               FILE *          const ofP) {
+
+    printf("#define %s_width %d\n", name, width);
+    printf("#define %s_height %d\n", name, height);
+    printf("static %s %s_bits[] = {\n",
+           xbmVersion == X10 ? "short" : "char",
+           name);
+}
+
+
+
+static void
+convertRaster(FILE *          const ifP,
+              unsigned int    const cols,
+              unsigned int    const rows,
+              int             const format,
+              FILE *          const ofP,
+              enum xbmVersion const xbmVersion) {
+              
+    unsigned int const bitsPerUnit = xbmVersion == X10 ? 16 : 8;   
+    unsigned int const padright =
+        ((cols + bitsPerUnit - 1 ) / bitsPerUnit) * bitsPerUnit - cols;
+        /* Amount of padding to round cols up to the nearest multiple of 
+           8 (if x11) or 16 (if x10).
+        */
+    unsigned int const bitrowBytes = (cols + padright) / 8;
+
+    unsigned char * bitrow;
+    unsigned int row;
+
+    putinit(xbmVersion);
+
+    bitrow = pbm_allocrow_packed(cols + padright);
+    bitrow[bitrowBytes-1] = 0;
+    
+    for (row = 0; row < rows; ++row) {
+        int const bitrowInBytes = pbm_packed_bytes(cols);
+        int const padrightIn    = bitrowInBytes * 8 - cols;
+
+        unsigned int i;
+
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+
+        if (padrightIn > 0) {
+            bitrow[bitrowInBytes - 1] >>= padrightIn;
+            bitrow[bitrowInBytes - 1] <<= padrightIn;
+        }
+
+        for (i = 0; i < bitrowBytes; ++i)
+            putitem(bitrow[i]);
+    }
+
+    putterm();
 
     pbm_freerow(bitrow);
+}
+
+
+
+int
+main(int    argc,
+     char * argv[]) {
+
+    struct cmdlineInfo cmdline; 
+    FILE * ifP;
+    int rows, cols, format;
+    const char * name;
+
+    pbm_init(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+    if (cmdline.name == NULL) 
+        generateName(cmdline.inputFileName, &name);
+    else
+        name = strdup(cmdline.name);
+
+    ifP = pm_openr(cmdline.inputFileName);
+    
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+    
+    writeXbmHeader(cmdline.xbmVersion, name, cols, rows, stdout);
+
+    convertRaster(ifP, cols, rows, format, stdout, cmdline.xbmVersion);
 
     strfree(name);
+    pm_close(ifP);
 
-    exit(0);
+    return 0;
 }
+
diff --git a/converter/pbm/pbmtoybm.c b/converter/pbm/pbmtoybm.c
index 1d2be3d9..508e8e92 100644
--- a/converter/pbm/pbmtoybm.c
+++ b/converter/pbm/pbmtoybm.c
@@ -80,14 +80,8 @@ putinit( cols, rows )
     bitshift = 0;
     }
 
-#if __STDC__
 static void
 putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
     {
     if ( bitsperitem == 16 )
 	putitem( );
diff --git a/converter/pbm/xbmtopbm.c b/converter/pbm/xbmtopbm.c
index 7779a9b5..63be16ef 100644
--- a/converter/pbm/xbmtopbm.c
+++ b/converter/pbm/xbmtopbm.c
@@ -1,4 +1,4 @@
-/* xbmtopbm.c - read an X bitmap file and produce a portable bitmap
+/* xbmtopbm.c - read an X bitmap file and produce a PBM image
 **
 ** Copyright (C) 1988 by Jef Poskanzer.
 **
@@ -10,246 +10,381 @@
 ** implied warranty.
 */
 
+
+#include <assert.h>
 #include <string.h>
 
+#include "pm_c_util.h"
+#include "mallocvar.h"
 #include "nstring.h"
 #include "pbm.h"
+#include "bitreverse.h"
 
-#define TRUE 1
-#define FALSE 0
 
-static void ReadBitmapFile ARGS(( FILE* stream, int* widthP, int* heightP, char** dataP ));
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, row, col, charcount;
-    char* data;
-    char mask;
-
-    pbm_init( &argc, argv );
-
-    if ( argc > 2 )
-        pm_usage( "[bitmapfile]" );
-    
-    if ( argc == 2 )
-        ifp = pm_openr( argv[1] );
-    else
-        ifp = stdin;
-
-    ReadBitmapFile( ifp, &cols, &rows, &data );
-
-    pm_close( ifp );
-
-    pbm_writepbminit( stdout, cols, rows, 0 );
-    bitrow = pbm_allocrow( cols );
-
-    for ( row = 0; row < rows; ++row )
-        {
-        charcount = 0;
-        mask = 1;
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-            {
-            if ( charcount >= 8 )
-                {
-                ++data;
-                charcount = 0;
-                mask = 1;
-                }
-            *bP = ( *data & mask ) ? PBM_BLACK : PBM_WHITE;
-            ++charcount;
-            mask = mask << 1;
-            }
-        ++data;
-        pbm_writepbmrow( stdout, bitrow, cols, 0 );
-        }
+#define MAX_LINE 500
+
+static unsigned int hexTable[256];
+    /* Hexadecimal ASCII translation table.  Constant */
+
+static void
+initHexTable(void) {
+
+    unsigned int i;
+
+    for (i = 0; i < 256; ++i)
+        hexTable[i] = 256;
+
+    hexTable['0'] =  0;
+    hexTable['1'] =  1;
+    hexTable['2'] =  2;
+    hexTable['3'] =  3;
+    hexTable['4'] =  4;
+    hexTable['5'] =  5;
+    hexTable['6'] =  6;
+    hexTable['7'] =  7;
+    hexTable['8'] =  8;
+    hexTable['9'] =  9;
+    hexTable['A'] = 10;
+    hexTable['B'] = 11;
+    hexTable['C'] = 12;
+    hexTable['D'] = 13;
+    hexTable['E'] = 14;
+    hexTable['F'] = 15;
+    hexTable['a'] = 10;
+    hexTable['b'] = 11;
+    hexTable['c'] = 12;
+    hexTable['d'] = 13;
+    hexTable['e'] = 14;
+    hexTable['f'] = 15;
+}
 
-    pm_close( stdout );
-    exit( 0 );
-    }
 
-#define MAX_LINE 500
 
 static void
-ReadBitmapFile( stream, widthP, heightP, dataP )
-     FILE* stream;
-     int* widthP;
-     int* heightP;
-     char** dataP;
-{
-  char line[MAX_LINE], name_and_type[MAX_LINE];
-  char* ptr;
-  char* t;
-  int version10, raster_length, v;
-  register int bytes, bytes_per_line, padding;
-  register int c1, c2, value1, value2;
-  int hex_table[256];
-  int found_declaration;
-  /* In scanning through the bitmap file, we have found the first
-     line of the C declaration of the array (the "static char ..."
-     or whatever line)
-     */
-  int eof;
-  /* We've encountered end of file while searching file */
-
-  *widthP = *heightP = -1;
-
-  found_declaration = FALSE;    /* Haven't found it yet; haven't even looked*/
-  eof = FALSE;                  /* Haven't encountered end of file yet */
-
-  while (!found_declaration && !eof) {
-    if ( fgets( line, MAX_LINE, stream ) == NULL )
-      eof = TRUE;
-    else {
-      if ( strlen( line ) == MAX_LINE - 1 )
-        pm_error( "line too long" );
-
-      if ( sscanf( line, "#define %s %d", name_and_type, &v ) == 2 ) {
-        if ( ( t = strrchr( name_and_type, '_' ) ) == NULL )
-          t = name_and_type;
+parseWidthHeightLine(const char *   const line,
+                     bool *         const gotWidthP,
+                     unsigned int * const widthP,
+                     bool *         const gotHeightP,
+                     unsigned int * const heightP) {
+
+    int rc;
+    char nameAndType[MAX_LINE];
+    unsigned int value;
+
+    rc = sscanf(line, "#define %s %u", nameAndType, &value);
+    if (rc == 2) {
+        const char * underscorePos = strrchr(nameAndType, '_');
+        const char * type;
+        if (underscorePos)
+            type = underscorePos + 1;
         else
-          ++t;
-        if ( STREQ( "width", t ) )
-          *widthP = v;
-        else if ( STREQ( "height", t ) )
-          *heightP = v;
-        continue;
-      }
+            type = nameAndType;
+        if (STREQ(type, "width")) {
+            *gotWidthP = TRUE;
+            *widthP = value;
+        } else if (STREQ(type, "height")) {
+            *gotHeightP = TRUE;
+            *heightP = value;
+        }
+    }
+}
+
+
+
+static void
+parseDeclaration(const char * const line,
+                 bool *       const isDeclarationP,
+                 bool *       const version10P) {
+/*----------------------------------------------------------------------------
+   Parse the XBM file line 'line' as the first line of the data structure
+   declaration, i.e. the one that looks like this:
+
+      static unsigned char myImage = {
+
+   Return as *isDeclarationP whether the line actually is such a line,
+   and if so, return as nameAndType what the variable name ('myImage'
+   in the example) is and as *version10P whether it's of the type used
+   by X10 as opposed to X11.
+-----------------------------------------------------------------------------*/
+    char nameAndType[MAX_LINE];
+    int rc;
         
-      if ( sscanf( line, "static short %s = {", name_and_type ) == 1 ) {
-        version10 = TRUE;
-        found_declaration = TRUE;
-      }
-      else if ( sscanf( line, "static char %s = {", name_and_type ) == 1 ) {
-        version10 = FALSE;
-        found_declaration = TRUE;
-      }
-      else if (sscanf(line, 
-                      "static unsigned char %s = {", name_and_type ) == 1 ) {
-        version10 = FALSE;
-        found_declaration = TRUE;
-      }
+    rc = sscanf(line, "static short %s = {", nameAndType);
+    if (rc == 1) {
+        *version10P     = TRUE;
+        *isDeclarationP = TRUE;
+    } else {
+        int rc;
+        rc = sscanf(line, "static char %s = {", nameAndType);
+        if (rc == 1) {
+            *version10P     = FALSE;
+            *isDeclarationP = TRUE;
+        } else {
+            int rc;
+            rc = sscanf(line, "static unsigned char %s = {", nameAndType);
+            if (rc == 1) {
+                *version10P     = FALSE;
+                *isDeclarationP = TRUE;
+            } else
+                *isDeclarationP = FALSE;
+        }
     }
-  }
- 
-  if (!found_declaration) 
-    pm_error("Unable to find a line in the file containing the start "
-             "of C array declaration (\"static char\" or whatever)");
-
-  if ( *widthP == -1 )
-    pm_error( "invalid width" );
-  if ( *heightP == -1 )
-    pm_error( "invalid height" );
-
-  padding = 0;
-  if ( ((*widthP % 16) >= 1) && ((*widthP % 16) <= 8) && version10 )
-    padding = 1;
-
-  bytes_per_line = (*widthP+7)/8 + padding;
+}
+
+
+
+static void
+getXbmHeader(FILE *         const ifP,
+             unsigned int * const widthP,
+             unsigned int * const heightP,
+             bool *         const version10P) {
+
+    bool foundDeclaration;
+        /* In scanning through the bitmap file, we have found the first
+           line of the C declaration of the array (the "static char ..."
+           or whatever line)
+        */
+    bool gotWidth, gotHeight;
+        /* We found the line in the bitmap file that gives the width
+           or height, respectively, of the image (and have set
+           *widthP or *heightP to the value in it).
+        */
+
+    bool eof;
+        /* We've encountered end of file while searching file */
+
+    gotWidth = FALSE;
+    gotHeight = FALSE;
+    foundDeclaration = FALSE;    /* Haven't found it yet; haven't even looked*/
+    eof = FALSE;                 /* Haven't encountered end of file yet */
+
+    while (!foundDeclaration && !eof) {
+        char * rc;
+        char line[MAX_LINE];
+
+        rc = fgets(line, MAX_LINE, ifP);
+        if (rc == NULL)
+            eof = TRUE;
+        else {
+            if (strlen(line) == MAX_LINE - 1)
+                pm_error("A line in the input file is %u characters long.  "
+                         "%u is the maximum we can handle",
+                         strlen(line), MAX_LINE-1);
+
+            parseWidthHeightLine(line, &gotWidth, widthP, &gotHeight, heightP);
+
+            parseDeclaration(line, &foundDeclaration, version10P);
+        }
+    }
+
+    if (!foundDeclaration) 
+        pm_error("Unable to find a line in the file containing the start "
+                 "of C array declaration (\"static char\" or whatever)");
+
+    if (!gotWidth)
+        pm_error("Unable to find the #define statement that gives the "
+                 "width of the image, before the data structure "
+                 "declaration.");
+    if (!gotHeight)
+        pm_error("Unable to find the #define statement that gives the "
+                 "height of the image, before the data structure "
+                 "declaration.");
+}
+
+
+
+static void
+getHexByte(FILE *         const ifP,
+           unsigned int * const valueP) {
+
+    int c1, c2;
+    unsigned int value;
+
+    c1 = getc(ifP);
+    c2 = getc(ifP);
+    if (c1 == EOF || c2 == EOF)
+        pm_error("EOF / read error");
+
+    assert(c1 >= 0); assert(c1 < 256);
+    assert(c2 >= 0); assert(c2 < 256);
     
-  raster_length =  bytes_per_line * *heightP;
-  *dataP = (char*) malloc( raster_length );
-  if ( *dataP == (char*) 0 )
-    pm_error( "out of memory" );
-
-  /* Initialize hex_table. */
-  for ( c1 = 0; c1 < 256; ++c1 )
-    hex_table[c1] = 256;
-  hex_table['0'] = 0;
-  hex_table['1'] = 1;
-  hex_table['2'] = 2;
-  hex_table['3'] = 3;
-  hex_table['4'] = 4;
-  hex_table['5'] = 5;
-  hex_table['6'] = 6;
-  hex_table['7'] = 7;
-  hex_table['8'] = 8;
-  hex_table['9'] = 9;
-  hex_table['A'] = 10;
-  hex_table['B'] = 11;
-  hex_table['C'] = 12;
-  hex_table['D'] = 13;
-  hex_table['E'] = 14;
-  hex_table['F'] = 15;
-  hex_table['a'] = 10;
-  hex_table['b'] = 11;
-  hex_table['c'] = 12;
-  hex_table['d'] = 13;
-  hex_table['e'] = 14;
-  hex_table['f'] = 15;
-
-  if ( version10 )
-    for ( bytes = 0, ptr = *dataP; bytes < raster_length; bytes += 2 ) {
-      while ( ( c1 = getc( stream ) ) != 'x' )
-        if ( c1 == EOF )
-          pm_error( "EOF / read error" );
-      c1 = getc( stream );
-      c2 = getc( stream );
-      if ( c1 == EOF || c2 == EOF )
-        pm_error( "EOF / read error" );
-      value1 = ( hex_table[c1] << 4 ) + hex_table[c2];
-      if ( value1 >= 256 )
-        pm_error( "syntax error" );
-      c1 = getc( stream );
-      c2 = getc( stream );
-      if ( c1 == EOF || c2 == EOF )
-        pm_error( "EOF / read error" );
-      value2 = ( hex_table[c1] << 4 ) + hex_table[c2];
-      if ( value2 >= 256 )
-        pm_error( "syntax error" );
-      *ptr++ = value2;
-      if ( ( ! padding ) || ( ( bytes + 2 ) % bytes_per_line ) )
-        *ptr++ = value1;
+    value = (hexTable[c1] << 4) + hexTable[c2];
+    if (value >= 256)
+        pm_error("Invalid XBM input.  What should be a two digit "
+                 "hexadecimal cipher is instead '%c%c'", c1, c2);
+
+    *valueP = value;
+}
+
+
+                     
+static void
+readX10Raster(FILE *          const ifP,
+              unsigned int    const rasterLength,
+              unsigned char * const data,
+              unsigned int    const bytesPerLine,
+              bool            const mustPad) {
+
+    unsigned int bytesDone;
+    unsigned char * p;
+
+    for (bytesDone = 0, p = &data[0];
+         bytesDone < rasterLength;
+         bytesDone += 2) {
+
+        unsigned int value1;
+        unsigned int value2;
+
+        while (getc(ifP) != 'x') {}  /* Read up through the 'x' in 0x1234 */
+
+        getHexByte(ifP, &value1);  /* Read first two hex digits */
+        getHexByte(ifP, &value2);  /* Read last two hex digits */
+
+        *p++ = value2;
+
+        if (!mustPad || ((bytesDone + 2) % bytesPerLine))
+            *p++ = value1;
     }
-  else
-    for ( bytes = 0, ptr = *dataP; bytes < raster_length; ++bytes ) {
-      /*
-       ** Skip until digit is found.
-       */
-      for ( ; ; )
-        {
-          c1 = getc( stream );
-          if ( c1 == EOF )
-            pm_error( "EOF / read error" );
-          value1 = hex_table[c1];
-          if ( value1 != 256 )
-            break;
-        }
-      /*
-       ** Loop on digits.
-       */
-      for ( ; ; ) {
-        c2 = getc( stream );
-        if ( c2 == EOF )
-          pm_error( "EOF / read error" );
-        value2 = hex_table[c2];
-        if ( value2 != 256 ) {
-          value1 = (value1 << 4) | value2;
-          if ( value1 >= 256 )
-            pm_error( "syntax error" );
+}
+
+
+
+static void
+readX11Raster(FILE * const ifP,
+              unsigned int const rasterLength,
+              unsigned char * data) {
+
+    unsigned int i;
+
+    for (i = 0; i < rasterLength; ++i) {
+        unsigned int value;
+        int c;
+
+        /* Read up through the 'x' in 0x12 */
+        while ((c = getc(ifP))) {
+            if (c == EOF)
+                pm_error("EOF where 0x expected");
+            else if (toupper(c) == 'X')
+                break;
         }
-        else if ( c2 == 'x' || c2 == 'X' )
-          if ( value1 == 0 )
-            continue;
-          else pm_error( "syntax error" );
-        else break;
-      }
-      *ptr++ = value1;
+
+        getHexByte(ifP, &value);  /* Read the two hex digits */
+
+        assert(value < 256);
+
+        data[i] = value;
     }
 }
 
 
-/*  CHANGE HISTORY:
 
-  99.09.08 bryanh    Recognize "static unsigned char" declaration.
+static void
+readBitmapFile(FILE *           const ifP,
+               unsigned int *   const widthP,
+               unsigned int *   const heightP,
+               unsigned char ** const dataP) {
+
+    bool version10;
+    unsigned int rasterLength;
+    unsigned int width, height;
+    unsigned char * data;
 
+    unsigned int bytesPerLine;
+    bool mustPad;
 
+    getXbmHeader(ifP, &width, &height, &version10);
 
+    *widthP = width;
+    *heightP = height;
 
+    mustPad = (width % 16 >= 1 && width % 16 <= 8 && version10);
+
+    bytesPerLine = (width + 7) / 8 + (mustPad ? 1 : 0);
+    
+    rasterLength = bytesPerLine * height;
+
+    MALLOCARRAY(data, rasterLength);
+    if (data == NULL)
+        pm_error("Unable to allocate memory for the %u-byte raster",
+                 rasterLength);
+
+    if (version10)
+        readX10Raster(ifP, rasterLength, data, bytesPerLine, mustPad);
+    else
+        readX11Raster(ifP, rasterLength, data);
+
+    *dataP = data;
+}
+
+
+
+int
+main(int    argc,
+     char * argv[]) {
+
+    FILE * ifP;
+    bit * bitrow;
+    unsigned int rows, cols;
+    unsigned int row;
+    unsigned char * data;
+    const char * inputFileName;
+    unsigned char * p;
+        /* Cursor in raster data data[] */
+    
+    initHexTable();
+
+    pbm_init(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("The only possible argument is the input file name.  "
+                 "You specified %u arguments", argc-1);
+    
+    if (argc-1 > 0)
+        inputFileName = argv[1];
+    else
+        inputFileName = "-";
+
+    ifP = pm_openr(inputFileName);
+
+    readBitmapFile(ifP, &cols, &rows, &data);
+
+    pm_close(ifP);
+
+    pbm_writepbminit(stdout, cols, rows, 0);
+    bitrow = pbm_allocrow_packed(cols);
+
+    p = &data[0];  /* Start at beginning of raster */
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int const bytesPerRow = pbm_packed_bytes(cols);
+        unsigned int i;
+        
+        for (i = 0; i < bytesPerRow; ++i)
+            bitrow[i] = bitreverse[*p++];
+            
+        if (cols % 8 > 0) {
+            bitrow[bytesPerRow] >>= 8 - cols % 8;
+            bitrow[bytesPerRow] <<= 8 - cols % 8;
+        }
+            
+        pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
+    }
+
+    free(data);
+    pm_close(stdout);
+
+    return 0;
+}
+
+/*  CHANGE HISTORY:
+
+  99.09.08 bryanh    Recognize "static unsigned char" declaration.
+
+  06.10 (afu)
+   Changed bitrow from plain to raw, write function from pbm_writepbmrow()
+   to pbm_writepbmrow_packed().
+   Retired bitwise transformation functions.
 
 */
+
diff --git a/converter/pgm/pgmtofs.c b/converter/pgm/pgmtofs.c
index b34d77c4..53a2e7b3 100644
--- a/converter/pgm/pgmtofs.c
+++ b/converter/pgm/pgmtofs.c
@@ -128,14 +128,8 @@ putitem( )
     bitshift = 8 - bitspersample;
 }
 
-#if __STDC__
 static void
 putgray( gray g )
-#else /*__STDC__*/
-    static void
-putgray( g )
-    gray g;
-#endif /*__STDC__*/
 {
     if ( bitsperitem == 8 )
         putitem( );
diff --git a/converter/pgm/pgmtolispm.c b/converter/pgm/pgmtolispm.c
index 02f2fd1e..abb85494 100644
--- a/converter/pgm/pgmtolispm.c
+++ b/converter/pgm/pgmtolispm.c
@@ -115,14 +115,8 @@ depth_to_word_size (depth)	/* Lispm architecture specific - if a bitmap is writt
 
 
 
-#if __STDC__
 static void
 putval( gray b )
-#else /*__STDC__*/
-static void
-putval( b )
-gray b;
-#endif /*__STDC__*/
     {
     if ( bitsperitem == 32 )
 	putitem( );
diff --git a/converter/ppm/ppmtogif.c b/converter/ppm/ppmtogif.c
index 3100fea1..2b8a2596 100644
--- a/converter/ppm/ppmtogif.c
+++ b/converter/ppm/ppmtogif.c
@@ -1,101 +1,56 @@
-/* ppmtogif.c - read a portable pixmap and produce a GIF file
-**
-** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>.A
-** Lempel-Zim compression based on "compress".
-**
-** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
-**
-** The non-LZW GIF generation stuff was adapted from the Independent
-** JPEG Group's djpeg on 2001.09.29.  The uncompressed output subroutines
-** are derived directly from the corresponding subroutines in djpeg's
-** wrgif.c source file.  Its copyright notice say:
-
- * Copyright (C) 1991-1997, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
- *
-   The reference README file is README.JPEG in the Netpbm package.
-**
-** Copyright (C) 1989 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
-**
-** The Graphics Interchange Format(c) is the Copyright property of
-** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
-** CompuServe Incorporated.
-*/
+/* This is a backward compatibility interface to Pamtogif.
+
+   Pamtogif replaced Ppmtogif in Netpbm 10.37 (December 2006).
 
-/* TODO: merge the LZW and uncompressed subroutines.  They are separate
-   only because they had two different lineages and the code is too
-   complicated for me quickly to rewrite it.
+   The only significant way Pamtogif is not backward compatible with
+   old Ppmtogif is that Pamtogif does not have a -alpha option.
 */
-#include <assert.h>
+#define _BSD_SOURCE   /* Make sure strdup() is in string.h */
+#define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
+
 #include <string.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "mallocvar.h"
 #include "shhopt.h"
-#include "ppm.h"
+#include "nstring.h"
+#include "pam.h"
 
-#define MAXCMAPSIZE 256
 
-static unsigned int const gifMaxval = 255;
 
-static bool verbose;
-/*
- * a code_int must be able to hold 2**BITS values of type int, and also -1
- */
-typedef int code_int;
+static const char *
+dirname(const char * const fileName) {
 
-typedef long int          count_int;
+    char * buffer;
+    char * slashPos;
 
+    buffer = strdup(fileName);
+
+    slashPos = strchr(buffer, '/');
+
+    if (slashPos)
+        *slashPos = '\0';
+
+    return buffer;
+}
 
-struct cmap {
-    /* This is the information for the GIF colormap (aka palette). */
 
-    int red[MAXCMAPSIZE], green[MAXCMAPSIZE], blue[MAXCMAPSIZE];
-        /* These arrays arrays map a color index, as is found in
-           the raster part of the GIF, to an intensity value for the indicated
-           RGB component.
-        */
-    int perm[MAXCMAPSIZE], permi[MAXCMAPSIZE];
-        /* perm[i] is the position in the sorted colormap of the color which
-           is at position i in the unsorted colormap.  permi[] is the inverse
-           function of perm[].
-        */
-    int cmapsize;
-        /* Number of entries in the GIF colormap.  I.e. number of colors
-           in the image, plus possibly one fake transparency color.
-        */
-    int transparent;
-        /* color index number in GIF palette of the color that is to be
-           transparent.  -1 if no color is transparent.
-        */
-    colorhash_table cht;
-        /* A hash table that relates a PPM pixel value to to a pre-sort
-           GIF colormap index.
-        */
-    pixval maxval;
-        /* The maxval for the colors in 'cht'. */
-};
 
 struct cmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *input_filespec;  /* Filespec of input file */
-    const char *alpha_filespec;  /* Filespec of alpha file; NULL if none */
-    const char *alphacolor;      /* -alphacolor option value or default */
-    unsigned int interlace; /* -interlace option value */
-    unsigned int sort;     /* -sort option value */
+    const char *input_filespec; /* Filespec of input file */
+    const char *alpha_filespec; /* Filespec of alpha file; NULL if none */
+    const char *alphacolor;     /* -alphacolor option value or default */
+    unsigned int interlace;     /* -interlace option value */
+    unsigned int sort;          /* -sort option value */
     const char *mapfile;        /* -mapfile option value.  NULL if none. */
     const char *transparent;    /* -transparent option value.  NULL if none. */
     const char *comment;        /* -comment option value; NULL if none */
-    unsigned int nolzw;    /* -nolzw option */
+    unsigned int nolzw;         /* -nolzw option */
     unsigned int verbose;
 };
 
@@ -122,8 +77,8 @@ handleLatex2htmlHack(void) {
   -Bryan 2001.11.14
 -----------------------------------------------------------------------------*/
      pm_error("latex2html, you should just try the -interlace and "
-             "-transparent options to see if they work instead of "
-             "expecting a 'usage' message from -h");
+              "-transparent options to see if they work instead of "
+              "expecting a 'usage' message from -h");
 }
 
 
@@ -204,1354 +159,223 @@ parseCommandLine(int argc, char ** argv,
 
 
 
-/*
- * Write out a word to the GIF file
- */
-static void
-Putword(int const w, FILE * const fp) {
-
-    fputc( w & 0xff, fp );
-    fputc( (w / 256) & 0xff, fp );
-}
-
-
-static int
-closestcolor(pixel         const color,
-             pixval        const maxval,
-             struct cmap * const cmapP) {
-/*----------------------------------------------------------------------------
-   Return the pre-sort colormap index of the color in the colormap *cmapP
-   that is closest to the color 'color', whose maxval is 'maxval'.
-
-   Also add 'color' to the colormap hash, with the colormap index we
-   are returning.  Caller must ensure that the color is not already in
-   there.
------------------------------------------------------------------------------*/
-    unsigned int i;
-    unsigned int imin, dmin;
-
-    pixval const r = PPM_GETR(color) * gifMaxval / maxval;
-    pixval const g = PPM_GETG(color) * gifMaxval / maxval;
-    pixval const b = PPM_GETB(color) * gifMaxval / maxval;
-
-    dmin = SQR(255) * 3;
-    imin = 0;
-    for (i=0;i < cmapP->cmapsize; i++) {
-        int const d = SQR(r-cmapP->red[i]) + 
-            SQR(g-cmapP->green[i]) + 
-            SQR(b-cmapP->blue[i]);
-        if (d < dmin) {
-            dmin = d;
-            imin = i; 
-        } 
-    }
-    ppm_addtocolorhash(cmapP->cht, &color, cmapP->permi[imin]);
-
-    return cmapP->permi[imin];
-}
-
-
-
-enum pass {MULT8PLUS0, MULT8PLUS4, MULT4PLUS2, MULT2PLUS1};
-
-
-struct pixelCursor {
-    unsigned int width;
-        /* Width of the image, in columns */
-    unsigned int height;
-        /* Height of the image, in rows */
-    bool interlace;
-        /* We're accessing the image in interlace fashion */
-    unsigned int nPixelsLeft;
-        /* Number of pixels left to be read */
-    unsigned int curCol;
-        /* Location of pointed-to pixel, column */
-    unsigned int curRow;
-        /* Location of pointed-to pixel, row */
-    enum pass pass;
-        /* The interlace pass.  Undefined if !interlace */
-};
+static const char *
+pamtogifCommand(const char *       const arg0,
+                struct cmdlineInfo const cmdline) {
 
+    const char * const pamtogifName = "pamtogif";
 
+    const char * retval;
 
-static struct pixelCursor pixelCursor;
-    /* Current location in the input pixels.  */
+    const char * commandVerb;
+    const char * mapfileOpt;
+    const char * transparentOpt;
+    const char * commentOpt;
 
+    if (strchr(arg0, '/')) {
+        const char * const arg0DirName = dirname(arg0);
+        const char * progName;
 
-static void
-initPixelCursor(unsigned int const width,
-                unsigned int const height,
-                bool         const interlace) {
-
-    pixelCursor.width       = width;
-    pixelCursor.height      = height;
-    pixelCursor.interlace   = interlace;
-    pixelCursor.pass        = MULT8PLUS0;
-    pixelCursor.curCol      = 0;
-    pixelCursor.curRow      = 0;
-    pixelCursor.nPixelsLeft = width * height;
-}
+        struct stat statbuf;
 
+        asprintfN(&progName, "%s/%s", arg0DirName, pamtogifName);
 
-
-static void
-getPixel(pixel **           const pixels,
-         pixval             const inputMaxval,
-         gray **            const alpha,
-         gray               const alphaThreshold, 
-         struct cmap *      const cmapP,
-         struct pixelCursor const pixelCursor,
-         int *              const retvalP) {
-/*----------------------------------------------------------------------------
-   Return as *retvalP the colormap index of the pixel at location
-   pointed to by 'pixelCursor' in the PPM raster 'pixels', using
-   colormap *cmapP.
------------------------------------------------------------------------------*/
-    unsigned int const x = pixelCursor.curCol;
-    unsigned int const y = pixelCursor.curRow;
-
-    int colorindex;
-
-    if (alpha && alpha[y][x] < alphaThreshold)
-        colorindex = cmapP->transparent;
-    else {
-        int presortColorindex;
-
-        presortColorindex = ppm_lookupcolor(cmapP->cht, &pixels[y][x]);
-        if (presortColorindex == -1)
-            presortColorindex = 
-                closestcolor(pixels[y][x], inputMaxval, cmapP);
-        colorindex = cmapP->perm[presortColorindex];
-    }
-    *retvalP = colorindex;
-}
-
-
-
-static void
-bumpRowInterlace(struct pixelCursor * const pixelCursorP) {
-/*----------------------------------------------------------------------------
-   Move *pixelCursorP to the next row in the interlace pattern.
------------------------------------------------------------------------------*/
-    /* There are 4 passes:
-       MULT8PLUS0: Rows 8, 16, 24, 32, etc.
-       MULT8PLUS4: Rows 4, 12, 20, 28, etc.
-       MULT4PLUS2: Rows 2, 6, 10, 14, etc.
-       MULT2PLUS1: Rows 1, 3, 5, 7, 9, etc.
-    */
-    
-    switch (pixelCursorP->pass) {
-    case MULT8PLUS0:
-        pixelCursorP->curRow += 8;
-        break;
-    case MULT8PLUS4:
-        pixelCursorP->curRow += 8;
-        break;
-    case MULT4PLUS2:
-        pixelCursorP->curRow += 4;
-        break;
-    case MULT2PLUS1:
-        pixelCursorP->curRow += 2;
-        break;
-    }
-    /* Set the proper pass for the next read.  Note that if there are
-       more than 4 rows, the sequence of passes is sequential, but
-       when there are fewer than 4, we may skip e.g. from MULT8PLUS0
-       to MULT4PLUS2.
-    */
-    while (pixelCursorP->curRow >= pixelCursorP->height) {
-        switch (pixelCursorP->pass) {
-        case MULT8PLUS0:
-            pixelCursorP->pass = MULT8PLUS4;
-            pixelCursorP->curRow = 4;
-            break;
-        case MULT8PLUS4:
-            pixelCursorP->pass = MULT4PLUS2;
-            pixelCursorP->curRow = 2;
-            break;
-        case MULT4PLUS2:
-            pixelCursorP->pass = MULT2PLUS1;
-            pixelCursorP->curRow = 1;
-            break;
-        case MULT2PLUS1:
-            /* We've read the entire image; pass and current row are
-               now undefined.
-            */
-            pixelCursorP->curRow = 0;
-            break;
-        }
-    }
-}
-
-
-
-static void
-bumpPixel(struct pixelCursor * const pixelCursorP) {
-/*----------------------------------------------------------------------------
-   Bump *pixelCursorP to point to the next pixel to go into the GIF
-
-   Must not call when there are no pixels left.
------------------------------------------------------------------------------*/
-    assert(pixelCursorP->nPixelsLeft > 0);
-
-    /* Move one column to the right */
-    ++pixelCursorP->curCol;
-    
-    if (pixelCursorP->curCol >= pixelCursorP->width) {
-        /* That pushed us past the end of a row. */
-        /* Reset to the left edge ... */
-        pixelCursorP->curCol = 0;
-        
-        /* ... of the next row */
-        if (!pixelCursorP->interlace)
-            /* Go to the following row */
-            ++pixelCursorP->curRow;
+        if (stat(progName, &statbuf) == 0)
+            commandVerb = progName;
         else
-            bumpRowInterlace(pixelCursorP);
-    }
-    --pixelCursorP->nPixelsLeft;
-}
-
-
-
-static int
-gifNextPixel(pixel **      const pixels,
-             pixval        const inputMaxval,
-             gray **       const alpha,
-             gray          const alphaThreshold, 
-             struct cmap * const cmapP) {
-/*----------------------------------------------------------------------------
-   Return the pre-sort color index (index into the unsorted GIF color map)
-   of the next pixel to be processed from the input image.
-
-   'alpha_threshold' is the gray level such that a pixel in the alpha
-   map whose value is less that that represents a transparent pixel
-   in the output.
------------------------------------------------------------------------------*/
-    int retval;
-
-    if (pixelCursor.nPixelsLeft == 0 )
-        retval = EOF;
-    else {
-        getPixel(pixels, inputMaxval, alpha, alphaThreshold, cmapP, 
-                 pixelCursor, &retval);
-
-        bumpPixel(&pixelCursor);
-    }
-    return retval;
-}
-
-
-
-static void
-write_transparent_color_index_extension(FILE *fp, const int Transparent) {
-/*----------------------------------------------------------------------------
-   Write out extension for transparent color index.
------------------------------------------------------------------------------*/
-
-    fputc( '!', fp );
-    fputc( 0xf9, fp );
-    fputc( 4, fp );
-    fputc( 1, fp );
-    fputc( 0, fp );
-    fputc( 0, fp );
-    fputc( Transparent, fp );
-    fputc( 0, fp );
-}
-
-
-
-static void
-write_comment_extension(FILE *fp, const char comment[]) {
-/*----------------------------------------------------------------------------
-   Write out extension for a comment
------------------------------------------------------------------------------*/
-    char *segment;
-    
-    fputc('!', fp);   /* Identifies an extension */
-    fputc(0xfe, fp);  /* Identifies a comment */
-
-    /* Write it out in segments no longer than 255 characters */
-    for (segment = (char *) comment; 
-         segment < comment+strlen(comment); 
-         segment += 255) {
-
-        const int length_this_segment = MIN(255, strlen(segment));
-
-        fputc(length_this_segment, fp);
-
-        fwrite(segment, 1, length_this_segment, fp);
-    }
-
-    fputc(0, fp);   /* No more comment blocks in this extension */
-}
-
-
-
-/***************************************************************************
- *
- *  GIFCOMPR.C       - GIF Image compression routines
- *
- *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
- *  David Rowley (mgardi@watdcsu.waterloo.edu)
- *
- ***************************************************************************/
-
-/*
- * General DEFINEs
- */
-
-#define BITS    12
-
-#define HSIZE  5003            /* 80% occupancy */
-
-#ifdef NO_UCHAR
- typedef char   char_type;
-#else /*NO_UCHAR*/
- typedef        unsigned char   char_type;
-#endif /*NO_UCHAR*/
-
-/*
- *
- * GIF Image compression - modified 'compress'
- *
- * Based on: compress.c - File compression ala IEEE Computer, June 1984.
- *
- * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
- *              Jim McKie               (decvax!mcvax!jim)
- *              Steve Davies            (decvax!vax135!petsd!peora!srd)
- *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
- *              James A. Woods          (decvax!ihnp4!ames!jaw)
- *              Joe Orost               (decvax!vax135!petsd!joe)
- *
- */
-#include <ctype.h>
-
-#define ARGVAL() (*++(*argv) || (--argc && *++argv))
-
-static code_int const maxmaxcode = (code_int)1 << BITS;
-    /* should NEVER generate this code */
-#define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
-
-static long htab [HSIZE];
-static unsigned short codetab [HSIZE];
-#define HashTabOf(i)       htab[i]
-#define CodeTabOf(i)    codetab[i]
-
-/*
- * To save much memory, we overlay the table used by compress() with those
- * used by decompress().  The tab_prefix table is the same size and type
- * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
- * get this from the beginning of htab.  The output stack uses the rest
- * of htab, and contains characters.  There is plenty of room for any
- * possible stack (stack used to be 8000 characters).
- */
-
-#define tab_prefixof(i) CodeTabOf(i)
-#define tab_suffixof(i)        ((char_type*)(htab))[i]
-#define de_stack               ((char_type*)&tab_suffixof((code_int)1<<BITS))
-
-static code_int free_ent = 0;                  /* first unused entry */
-
-/*
- * block compression parameters -- after all codes are used up,
- * and compression rate changes, start over.
- */
-static int clear_flg = 0;
-
-static int offset;
-static long int in_count = 1;            /* length of input */
-static long int out_count = 0;           /* # of codes output (for debugging) */
-
-/*
- * compress stdin to stdout
- *
- * Algorithm:  use open addressing double hashing (no chaining) on the
- * prefix code / next character combination.  We do a variant of Knuth's
- * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
- * secondary probe.  Here, the modular division first probe is gives way
- * to a faster exclusive-or manipulation.  Also do block compression with
- * an adaptive reset, whereby the code table is cleared when the compression
- * ratio decreases, but after the table fills.  The variable-length output
- * codes are re-sized at this point, and a special CLEAR code is generated
- * for the decompressor.  Late addition:  construct the table according to
- * file size for noticeable speed improvement on small files.  Please direct
- * questions about this implementation to ames!jaw.
- */
-
-static int ClearCode;
-static int EOFCode;
-
-/***************************************************************************
-*                          BYTE OUTPUTTER                 
-***************************************************************************/
-
-typedef struct {
-    FILE * fileP;  /* The file to which to output */
-    unsigned int count;
-        /* Number of bytes so far in the current data block */
-    unsigned char buffer[256];
-        /* The current data block, under construction */
-} byteBuffer;
-
-
-
-static byteBuffer *
-byteBuffer_create(FILE * const fileP) {
-
-    byteBuffer * byteBufferP;
-
-    MALLOCVAR_NOFAIL(byteBufferP);
-
-    byteBufferP->fileP = fileP;
-    byteBufferP->count = 0;
-
-    return byteBufferP;
-}
-
-
-
-static void
-byteBuffer_destroy(byteBuffer * const byteBufferP) {
-
-    free(byteBufferP);
-}
-
-
-
-static void
-byteBuffer_flush(byteBuffer * const byteBufferP) {
-/*----------------------------------------------------------------------------
-   Write the current data block to the output file, then reset the current 
-   data block to empty.
------------------------------------------------------------------------------*/
-    if (byteBufferP->count > 0 ) {
-        if (verbose)
-            pm_message("Writing %u byte block", byteBufferP->count);
-        fputc(byteBufferP->count, byteBufferP->fileP);
-        fwrite(byteBufferP->buffer, 1, byteBufferP->count, byteBufferP->fileP);
-        byteBufferP->count = 0;
-    }
-}
-
-
-
-static void
-byteBuffer_flushFile(byteBuffer * const byteBufferP) {
-    
-    fflush(byteBufferP->fileP);
-    
-    if (ferror(byteBufferP->fileP))
-        pm_error("error writing output file");
-}
-
-
+            commandVerb = strdup(pamtogifName);
 
-static void
-byteBuffer_out(byteBuffer *  const byteBufferP,
-               unsigned char const c) {
-/*----------------------------------------------------------------------------
-  Add a byte to the end of the current data block, and if it is now 254
-  characters, flush the data block to the output file.
------------------------------------------------------------------------------*/
-    byteBufferP->buffer[byteBufferP->count++] = c;
-    if (byteBufferP->count >= 254)
-        byteBuffer_flush(byteBufferP);
-}
-
-
-
-struct gif_dest {
-    /* This structure controls output of uncompressed GIF raster */
-
-    byteBuffer * byteBufferP;  /* Where the full bytes go */
-
-    /* State for packing variable-width codes into a bitstream */
-    int n_bits;         /* current number of bits/code */
-    int maxcode;        /* maximum code, given n_bits */
-    int cur_accum;      /* holds bits not yet output */
-    int cur_bits;       /* # of bits in cur_accum */
-
-    /* State for GIF code assignment */
-    int ClearCode;      /* clear code (doesn't change) */
-    int EOFCode;        /* EOF code (ditto) */
-    int code_counter;   /* counts output symbols */
-};
-
-
-
-static unsigned long const masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
-                                       0x001F, 0x003F, 0x007F, 0x00FF,
-                                       0x01FF, 0x03FF, 0x07FF, 0x0FFF,
-                                       0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
-
-typedef struct {
-    byteBuffer * byteBufferP;
-    unsigned int initBits;
-    unsigned int n_bits;                        /* number of bits/code */
-    code_int maxcode;                  /* maximum code, given n_bits */
-    unsigned long curAccum;
-    int curBits;
-} codeBuffer;
-
-
-
-static codeBuffer *
-codeBuffer_create(FILE *       const ofP,
-                  unsigned int const initBits) {
-
-    codeBuffer * codeBufferP;
-
-    MALLOCVAR_NOFAIL(codeBufferP);
-
-    codeBufferP->initBits    = initBits;
-    codeBufferP->n_bits      = codeBufferP->initBits;
-    codeBufferP->maxcode     = MAXCODE(codeBufferP->n_bits);
-    codeBufferP->byteBufferP = byteBuffer_create(ofP);
-    codeBufferP->curAccum    = 0;
-    codeBufferP->curBits     = 0;
-
-    return codeBufferP;
-}
-
-
-
-static void
-codeBuffer_destroy(codeBuffer * const codeBufferP) {
-
-    byteBuffer_destroy(codeBufferP->byteBufferP);
-
-    free(codeBufferP);
-}
-
-
-
-static void
-codeBuffer_output(codeBuffer * const codeBufferP,
-                  code_int     const code) {
-/*----------------------------------------------------------------------------
-   Output one GIF code to the file, through the code buffer.
-
-   The code is represented as n_bits bits in the file -- the lower
-   n_bits bits of 'code'.
-
-   If the code is EOF, flush the code buffer to the file.
-
-   In some cases, change n_bits and recalculate maxcode to go with it.
------------------------------------------------------------------------------*/
-    /*
-      Algorithm:
-      Maintain a BITS character long buffer (so that 8 codes will
-      fit in it exactly).  Use the VAX insv instruction to insert each
-      code in turn.  When the buffer fills up empty it and start over.
-    */
-    
-    codeBufferP->curAccum &= masks[codeBufferP->curBits];
+        strfree(arg0DirName);
+    } else
+        commandVerb = strdup(pamtogifName);
 
-    if (codeBufferP->curBits > 0)
-        codeBufferP->curAccum |= ((long)code << codeBufferP->curBits);
+    if (cmdline.mapfile)
+        asprintfN(&mapfileOpt, "-mapfile=%s", cmdline.mapfile);
     else
-        codeBufferP->curAccum = code;
+        mapfileOpt = strdup("");
 
-    codeBufferP->curBits += codeBufferP->n_bits;
-
-    while (codeBufferP->curBits >= 8) {
-        byteBuffer_out(codeBufferP->byteBufferP,
-                       codeBufferP->curAccum & 0xff);
-        codeBufferP->curAccum >>= 8;
-        codeBufferP->curBits -= 8;
-    }
+    if (cmdline.transparent)
+        asprintfN(&transparentOpt, "-transparent=%s", cmdline.transparent);
+    else
+        transparentOpt = strdup("");
 
-    if (clear_flg) {
-        codeBufferP->n_bits = codeBufferP->initBits;
-        codeBufferP->maxcode = MAXCODE(codeBufferP->n_bits);
-        clear_flg = 0;
-    } else if (free_ent > codeBufferP->maxcode) {
-        /* The next entry is going to be too big for the code size, so
-           increase it, if possible.
-        */
-        ++codeBufferP->n_bits;
-        if (codeBufferP->n_bits == BITS)
-            codeBufferP->maxcode = maxmaxcode;
-        else
-            codeBufferP->maxcode = MAXCODE(codeBufferP->n_bits);
-    }
+    if (cmdline.comment)
+        asprintfN(&commentOpt, "-comment=%s", cmdline.comment);
+    else
+        commentOpt = strdup("");
+
+    asprintfN(&retval, "%s - -alphacolor=%s %s %s %s %s %s %s %s",
+              commandVerb,
+              cmdline.alphacolor,
+              cmdline.interlace ? "-interlace" : "",
+              cmdline.sort ? "-sort" : "",
+              mapfileOpt,
+              transparentOpt,
+              commentOpt,
+              cmdline.nolzw ? "-nolzw" : "",
+              cmdline.verbose ? "-verbose" : "");
     
-    if (code == EOFCode) {
-        /* We're at EOF.  Output the possible partial byte in the buffer */
-        if (codeBufferP->curBits > 0) {
-            byteBuffer_out(codeBufferP->byteBufferP,
-                           codeBufferP->curAccum & 0xff);
-            codeBufferP->curBits = 0;
-        }
-        byteBuffer_flush(codeBufferP->byteBufferP);
-        
-        byteBuffer_flushFile(codeBufferP->byteBufferP);
-    }
-}
-
+    strfree(mapfileOpt);
+    strfree(transparentOpt);
+    strfree(commentOpt);
 
-
-static void
-cl_hash(long const hsize) {
-    /* reset code table */
-
-    long const m1 = -1;
-
-    long * htab_p;
-    long i;
-
-    htab_p = htab + hsize;  /* initial value */
-
-    i = hsize - 16;
-    do {                            /* might use Sys V memset(3) here */
-        *(htab_p-16) = m1;
-        *(htab_p-15) = m1;
-        *(htab_p-14) = m1;
-        *(htab_p-13) = m1;
-        *(htab_p-12) = m1;
-        *(htab_p-11) = m1;
-        *(htab_p-10) = m1;
-        *(htab_p-9) = m1;
-        *(htab_p-8) = m1;
-        *(htab_p-7) = m1;
-        *(htab_p-6) = m1;
-        *(htab_p-5) = m1;
-        *(htab_p-4) = m1;
-        *(htab_p-3) = m1;
-        *(htab_p-2) = m1;
-        *(htab_p-1) = m1;
-        htab_p -= 16;
-    } while ((i -= 16) >= 0);
-
-    for (i += 16; i > 0; --i)
-        *--htab_p = m1;
+    return retval;
 }
 
 
 
 static void
-cl_block(codeBuffer * const codeBufferP) {
-/*----------------------------------------------------------------------------
-  Clear out the hash table
------------------------------------------------------------------------------*/
-    cl_hash(HSIZE);
-    free_ent = ClearCode + 2;
-    clear_flg = 1;
+feedPamtogifNoAlpha(struct pam * const inPamP,
+                    FILE *       const pipeToPamtogif) {
     
-    codeBuffer_output(codeBufferP, (code_int)ClearCode);
-}
-
-
-
-static void
-write_raster_LZW(pixel **      const pixels,
-                 pixval        const input_maxval,
-                 gray **       const alpha,
-                 gray          const alpha_maxval, 
-                 struct cmap * const cmapP, 
-                 int           const initBits,
-                 FILE *        const ofP) {
-/*----------------------------------------------------------------------------
-   Write the raster to file 'ofP'.
-
-   The raster to write is 'pixels', which has maxval 'input_maxval',
-   modified by alpha mask 'alpha', which has maxval 'alpha_maxval'.
+    unsigned int row;
+    struct pam outPam;
+    tuple * tuplerow;
 
-   Use the colormap 'cmapP' to generate the raster ('pixels' is 
-   composed of RGB samples; the GIF raster is colormap indices).
+    tuplerow = pnm_allocpamrow(inPamP);
 
-   Write the raster using LZW compression.
------------------------------------------------------------------------------*/
-    gray const alpha_threshold = (alpha_maxval + 1) / 2;
-        /* gray levels below this in the alpha mask indicate transparent
-           pixels in the output image.
-        */
-    code_int ent;
-    code_int disp;
-    int hshift;
-    bool eof;
-    codeBuffer * codeBufferP;
-    
-    codeBufferP = codeBuffer_create(ofP, initBits);
+    outPam = *inPamP;
+    outPam.file = pipeToPamtogif;
     
-    /*
-     * Set up the necessary values
-     */
-    offset = 0;
-    out_count = 0;
-    clear_flg = 0;
-    in_count = 1;
-
-    ClearCode = (1 << (initBits - 1));
-    EOFCode = ClearCode + 1;
-    free_ent = ClearCode + 2;
-
-    ent = gifNextPixel(pixels, input_maxval, alpha, alpha_threshold, cmapP);
-
-    {
-        long fcode;
-        hshift = 0;
-        for (fcode = HSIZE; fcode < 65536L; fcode *= 2L)
-            ++hshift;
-        hshift = 8 - hshift;                /* set hash code range bound */
-    }
-    cl_hash(HSIZE);            /* clear hash table */
-
-    codeBuffer_output(codeBufferP, (code_int)ClearCode);
-
-    eof = FALSE;
-    while (!eof) {
-        int gifpixel;
-            /* The value for the pixel in the GIF image.  I.e. the colormap
-               index.  Or -1 to indicate "no more pixels."
-            */
-        gifpixel = gifNextPixel(pixels, 
-                                input_maxval, alpha, alpha_threshold, cmapP);
-        if (gifpixel == EOF) eof = TRUE;
-        if (!eof) {
-            long const fcode = (long) (((long) gifpixel << BITS) + ent);
-            code_int i;
-                /* xor hashing */
-
-            ++in_count;
-
-            i = (((code_int)gifpixel << hshift) ^ ent);    
-
-            if (HashTabOf (i) == fcode) {
-                ent = CodeTabOf (i);
-                continue;
-            } else if ((long)HashTabOf(i) < 0)      /* empty slot */
-                goto nomatch;
-            disp = HSIZE - i;        /* secondary hash (after G. Knott) */
-            if (i == 0)
-                disp = 1;
-        probe:
-            if ((i -= disp) < 0)
-                i += HSIZE;
-
-            if (HashTabOf(i) == fcode) {
-                ent = CodeTabOf(i);
-                continue;
-            }
-            if ((long)HashTabOf(i) > 0)
-                goto probe;
-        nomatch:
-            codeBuffer_output(codeBufferP, (code_int)ent);
-            ++out_count;
-            ent = gifpixel;
-            if (free_ent < maxmaxcode) {
-                CodeTabOf(i) = free_ent++; /* code -> hashtable */
-                HashTabOf(i) = fcode;
-            } else
-                cl_block(codeBufferP);
-        }
-    }
-    /* Put out the final code. */
-    codeBuffer_output(codeBufferP, (code_int)ent);
-    ++out_count;
-    codeBuffer_output(codeBufferP, (code_int) EOFCode);
-
-    codeBuffer_destroy(codeBufferP);
-}
-
+    pnm_writepaminit(&outPam);
 
+    for (row = 0; row < inPamP->height; ++row) {
+        pnm_readpamrow(inPamP, tuplerow);
 
-/* Routine to convert variable-width codes into a byte stream */
-
-static void
-outputUncompressed(struct gif_dest * const dinfoP,
-                   int               const code) {
-
-    /* Emit a code of n_bits bits */
-    /* Uses cur_accum and cur_bits to reblock into 8-bit bytes */
-    dinfoP->cur_accum |= ((int) code) << dinfoP->cur_bits;
-    dinfoP->cur_bits += dinfoP->n_bits;
-
-    while (dinfoP->cur_bits >= 8) {
-        byteBuffer_out(dinfoP->byteBufferP, dinfoP->cur_accum & 0xFF);
-        dinfoP->cur_accum >>= 8;
-        dinfoP->cur_bits -= 8;
+        pnm_writepamrow(&outPam, tuplerow);
     }
-}
-
-
-static void
-writeRasterUncompressedInit(FILE *            const ofP,
-                            struct gif_dest * const dinfoP, 
-                            int               const i_bits) {
-/*----------------------------------------------------------------------------
-   Initialize pseudo-compressor
------------------------------------------------------------------------------*/
-
-    /* init all the state variables */
-    dinfoP->n_bits = i_bits;
-    dinfoP->maxcode = MAXCODE(dinfoP->n_bits);
-    dinfoP->ClearCode = (1 << (i_bits - 1));
-    dinfoP->EOFCode = dinfoP->ClearCode + 1;
-    dinfoP->code_counter = dinfoP->ClearCode + 2;
-    /* init output buffering vars */
-    dinfoP->byteBufferP = byteBuffer_create(ofP);
-    dinfoP->cur_accum = 0;
-    dinfoP->cur_bits = 0;
-    /* GIF specifies an initial Clear code */
-    outputUncompressed(dinfoP, dinfoP->ClearCode);
+    pnm_freepamrow(tuplerow);
 }
 
 
 
 static void
-writeRasterUncompressedPixel(struct gif_dest * const dinfoP, 
-                             unsigned int      const colormapIndex) {
-/*----------------------------------------------------------------------------
-   "Compress" one pixel value and output it as a symbol.
-
-   'colormapIndex' must be less than dinfoP->n_bits wide.
------------------------------------------------------------------------------*/
-    assert(colormapIndex >> dinfoP->n_bits == 0);
-
-    outputUncompressed(dinfoP, colormapIndex);
-    /* Issue Clear codes often enough to keep the reader from ratcheting up
-     * its symbol size.
-     */
-    if (dinfoP->code_counter < dinfoP->maxcode) {
-        ++dinfoP->code_counter;
-    } else {
-        outputUncompressed(dinfoP, dinfoP->ClearCode);
-        dinfoP->code_counter = dinfoP->ClearCode + 2;	/* reset the counter */
-    }
-}
-
-
-
-static void
-writeRasterUncompressedTerm(struct gif_dest * const dinfoP) {
-
-    outputUncompressed(dinfoP, dinfoP->EOFCode);
-
-    if (dinfoP->cur_bits > 0)
-        byteBuffer_out(dinfoP->byteBufferP, dinfoP->cur_accum & 0xFF);
-
-    byteBuffer_flush(dinfoP->byteBufferP);
-
-    byteBuffer_destroy(dinfoP->byteBufferP);
-}
-
-
-
-static void
-writeRasterUncompressed(FILE *         const ofP, 
-                        pixel **       const pixels,
-                        pixval         const inputMaxval,
-                        gray **        const alpha,
-                        gray           const alphaMaxval, 
-                        struct cmap *  const cmapP, 
-                        int            const initBits) {
-/*----------------------------------------------------------------------------
-   Write the raster to file 'ofP'.
-   
-   Same as write_raster_LZW(), except written out one code per
-   pixel (plus some clear codes), so no compression.  And no use
-   of the LZW patent.
------------------------------------------------------------------------------*/
-    gray const alphaThreshold = (alphaMaxval + 1) / 2;
-        /* gray levels below this in the alpha mask indicate transparent
-           pixels in the output image.
-        */
-    bool eof;
-
-    struct gif_dest gifDest;
-
-    writeRasterUncompressedInit(ofP, &gifDest, initBits);
-
-    eof = FALSE;
-    while (!eof) {
-        int gifpixel;
-            /* The value for the pixel in the GIF image.  I.e. the colormap
-               index.  Or -1 to indicate "no more pixels."
-            */
-        gifpixel = gifNextPixel(pixels, 
-                                inputMaxval, alpha, alphaThreshold, cmapP);
-        if (gifpixel == EOF)
-            eof = TRUE;
-        else
-            writeRasterUncompressedPixel(&gifDest, gifpixel);
-    }
-    writeRasterUncompressedTerm(&gifDest);
-}
-
-
-
-/******************************************************************************
- *
- * GIF Specific routines
- *
- *****************************************************************************/
-
-static void
-writeGifHeader(FILE * const fp,
-               int const Width, int const Height, 
-               int const GInterlace, int const Background, 
-               int const BitsPerPixel, struct cmap * const cmapP,
-               const char comment[]) {
-
-    int B;
-    int const Resolution = BitsPerPixel;
-    int const ColorMapSize = 1 << BitsPerPixel;
-
-    /* Write the Magic header */
-    if (cmapP->transparent != -1 || comment)
-        fwrite("GIF89a", 1, 6, fp);
-    else
-        fwrite("GIF87a", 1, 6, fp);
-
-    /* Write out the screen width and height */
-    Putword( Width, fp );
-    Putword( Height, fp );
-
-    /* Indicate that there is a global color map */
-    B = 0x80;       /* Yes, there is a color map */
-
-    /* OR in the resolution */
-    B |= (Resolution - 1) << 4;
-
-    /* OR in the Bits per Pixel */
-    B |= (BitsPerPixel - 1);
-
-    /* Write it out */
-    fputc( B, fp );
-
-    /* Write out the Background color */
-    fputc( Background, fp );
-
-    /* Byte of 0's (future expansion) */
-    fputc( 0, fp );
-
-    {
-        /* Write out the Global Color Map */
-        /* Note that the Global Color Map is always a power of two colors
-           in size, but *cmapP could be smaller than that.  So we pad with
-           black.
-        */
-        int i;
-        for ( i=0; i < ColorMapSize; ++i ) {
-            if ( i < cmapP->cmapsize ) {
-                fputc( cmapP->red[i], fp );
-                fputc( cmapP->green[i], fp );
-                fputc( cmapP->blue[i], fp );
-            } else {
-                fputc( 0, fp );
-                fputc( 0, fp );
-                fputc( 0, fp );
-            }
+copyRasterWithAlpha(struct pam * const inPamP,
+                    struct pam * const alphaPamP,
+                    struct pam * const outPamP,
+                    unsigned int const alphaPlane) {
+
+    tuple * tuplerow;
+    tuple * alpharow;
+    unsigned int row;
+
+    inPamP->allocation_depth = outPamP->depth;
+
+    tuplerow = pnm_allocpamrow(inPamP);
+    alpharow = pnm_allocpamrow(alphaPamP);
+
+    for (row = 0; row < inPamP->height; ++row) {
+        unsigned int col;
+            
+        pnm_readpamrow(inPamP, tuplerow);
+        pnm_readpamrow(alphaPamP, alpharow);
+
+        for (col = 0; col < inPamP->width; ++col) {
+            tuplerow[col][alphaPlane] = pnm_scalesample(alpharow[col][0],
+                                                        alphaPamP->maxval,
+                                                        inPamP->maxval);
         }
+        pnm_writepamrow(outPamP, tuplerow);
     }
-        
-    if ( cmapP->transparent >= 0 ) 
-        write_transparent_color_index_extension(fp, cmapP->transparent);
-
-    if ( comment )
-        write_comment_extension(fp, comment);
-}
-
-
-
-static void
-writeImageHeader(FILE *       const ofP,
-                 unsigned int const leftOffset,
-                 unsigned int const topOffset,
-                 unsigned int const gWidth,
-                 unsigned int const gHeight,
-                 unsigned int const gInterlace,
-                 unsigned int const initCodeSize) {
-
-    Putword(leftOffset, ofP);
-    Putword(topOffset,  ofP);
-    Putword(gWidth,     ofP);
-    Putword(gHeight,    ofP);
-
-    /* Write out whether or not the image is interlaced */
-    if (gInterlace)
-        fputc(0x40, ofP);
-    else
-        fputc(0x00, ofP);
-
-    /* Write out the initial code size */
-    fputc(initCodeSize, ofP);
-}
-
-
-
-static void
-gifEncode(FILE *        const ofP, 
-          pixel **      const pixels,
-          pixval        const inputMaxval,
-          int           const gWidth,
-          int           const gHeight, 
-          gray **       const alpha,
-          gray          const alphaMaxval,
-          int           const gInterlace,
-          int           const background, 
-          int           const bitsPerPixel,
-          struct cmap * const cmapP,
-          char          const comment[],
-          bool          const nolzw) {
-
-    unsigned int const leftOffset = 0;
-    unsigned int const topOffset  = 0;
-
-    unsigned int const initCodeSize = bitsPerPixel <= 1 ? 2 : bitsPerPixel;
-        /* The initial code size */
-
-    writeGifHeader(ofP, gWidth, gHeight, gInterlace, background,
-                   bitsPerPixel, cmapP, comment);
-
-    /* Write an Image separator */
-    fputc(',', ofP);
-
-    writeImageHeader(ofP, leftOffset, topOffset, gWidth, gHeight, gInterlace,
-                     initCodeSize);
-
-    initPixelCursor(gWidth, gHeight, gInterlace);
-
-    /* Write the actual raster */
-    if (nolzw)
-        writeRasterUncompressed(ofP, pixels, 
-                                inputMaxval, alpha, alphaMaxval, cmapP, 
-                                initCodeSize + 1);
-    else
-        write_raster_LZW(pixels, 
-                         inputMaxval, alpha, alphaMaxval, cmapP, 
-                         initCodeSize + 1, ofP);
-
-    /* Write out a zero length data block (to end the series) */
-    fputc(0, ofP);
-
-    /* Write the GIF file terminator */
-    fputc(';', ofP);
-}
-
-
-
-static int
-compute_transparent(const char colorarg[], 
-                    struct cmap * const cmapP) {
-/*----------------------------------------------------------------------------
-   Figure out the color index (index into the colormap) of the color
-   that is to be transparent in the GIF.
-
-   colorarg[] is the string that specifies the color the user wants to
-   be transparent (e.g. "red", "#fefefe").  Its maxval is the maxval
-   of the colormap.  'cmap' is the full colormap except that its
-   'transparent' component isn't valid.
-
-   colorarg[] is a standard Netpbm color specification, except that
-   may have a "=" prefix, which means it specifies a particular exact
-   color, as opposed to without the "=", which means "the color that
-   is closest to this and actually in the image."
-
-   Return -1 if colorarg[] specifies an exact color and that color is not
-   in the image.  Also issue an informational message.
------------------------------------------------------------------------------*/
-    int retval;
-
-    const char *colorspec;
-    bool exact;
-    int presort_colorindex;
-    pixel transcolor;
-
-    if (colorarg[0] == '=') {
-        colorspec = &colorarg[1];
-        exact = TRUE;
-    } else {
-        colorspec = colorarg;
-        exact = FALSE;
-    }
-        
-    transcolor = ppm_parsecolor((char*)colorspec, cmapP->maxval);
-    presort_colorindex = ppm_lookupcolor(cmapP->cht, &transcolor);
-    
-    if (presort_colorindex != -1)
-        retval = cmapP->perm[presort_colorindex];
-    else if (!exact)
-        retval = cmapP->perm[closestcolor(transcolor, cmapP->maxval, cmapP)];
-    else {
-        retval = -1;
-        pm_message(
-            "Warning: specified transparent color does not occur in image.");
-    }
-    return retval;
+    pnm_freepamrow(alpharow);
+    pnm_freepamrow(tuplerow);
 }
 
 
 
 static void
-sort_colormap(int const sort, struct cmap * const cmapP) {
-/*----------------------------------------------------------------------------
-   Sort (in place) the colormap *cmapP.
-
-   Create the perm[] and permi[] mappings for the colormap.
-
-   'sort' is logical:  true means to sort the colormap by red intensity,
-   then by green intensity, then by blue intensity.  False means a null
-   sort -- leave it in the same order in which we found it.
------------------------------------------------------------------------------*/
-    int * const Red = cmapP->red;
-    int * const Blue = cmapP->blue;
-    int * const Green = cmapP->green;
-    int * const perm = cmapP->perm;
-    int * const permi = cmapP->permi;
-    unsigned int const cmapsize = cmapP->cmapsize;
-    
-    int i;
-
-    for (i=0; i < cmapsize; i++)
-        permi[i] = i;
-
-    if (sort) {
-        pm_message("sorting colormap");
-        for (i=0; i < cmapsize; i++) {
-            int j;
-            for (j=i+1; j < cmapsize; j++)
-                if (((Red[i]*MAXCMAPSIZE)+Green[i])*MAXCMAPSIZE+Blue[i] >
-                    ((Red[j]*MAXCMAPSIZE)+Green[j])*MAXCMAPSIZE+Blue[j]) {
-                    int tmp;
-                    
-                    tmp=permi[i]; permi[i]=permi[j]; permi[j]=tmp;
-                    tmp=Red[i]; Red[i]=Red[j]; Red[j]=tmp;
-                    tmp=Green[i]; Green[i]=Green[j]; Green[j]=tmp;
-                    tmp=Blue[i]; Blue[i]=Blue[j]; Blue[j]=tmp; } }
+feedPamtogifWithAlpha(struct pam * const inPamP,
+                      struct pam * const alphaPamP,
+                      FILE *       const pipeToPamtogif) {
+
+    unsigned int alphaPlane;
+    struct pam outPam;
+
+    if (inPamP->width != alphaPamP->width ||
+        inPamP->height != alphaPamP->height)
+        pm_error("-alpha image dimensions (%u w x %u h) do not match "
+                 "the input image dimensions (%u x %u)",
+                 alphaPamP->width, alphaPamP->height,
+                 inPamP->width, inPamP->height);
+
+    outPam = *inPamP;
+    outPam.file        = pipeToPamtogif;
+    outPam.format      = PAM_FORMAT;
+    outPam.plainformat = 0;
+
+    if (inPamP->depth == 1) {
+        alphaPlane = 1;
+        strcpy(outPam.tuple_type, "GRAYSCALE_ALPHA");
+    } else if (inPamP->depth == 3) {
+        alphaPlane = 3;
+        strcpy(outPam.tuple_type, "RGB_ALPHA");
     }
+    outPam.depth = alphaPlane + 1;
 
-    for (i=0; i < cmapsize; i++)
-        perm[permi[i]] = i;
-}
+    pnm_writepaminit(&outPam);
 
-
-
-static void
-normalize_to_255(colorhist_vector const chv, struct cmap * const cmapP) {
-/*----------------------------------------------------------------------------
-   With a PPM color histogram vector 'chv' as input, produce a colormap
-   of integers 0-255 as output in *cmapP.
------------------------------------------------------------------------------*/
-    int i;
-    pixval const maxval = cmapP->maxval;
-
-    if ( maxval != 255 )
-        pm_message(
-            "maxval is not 255 - automatically rescaling colors" );
-
-    for ( i = 0; i < cmapP->cmapsize; ++i ) {
-        if ( maxval == 255 ) {
-            cmapP->red[i] = (int) PPM_GETR( chv[i].color );
-            cmapP->green[i] = (int) PPM_GETG( chv[i].color );
-            cmapP->blue[i] = (int) PPM_GETB( chv[i].color );
-        } else {
-            cmapP->red[i] = (int) PPM_GETR( chv[i].color ) * 255 / maxval;
-            cmapP->green[i] = (int) PPM_GETG( chv[i].color ) * 255 / maxval;
-            cmapP->blue[i] = (int) PPM_GETB( chv[i].color ) * 255 / maxval;
-        }
-    }
-}
-
-
-
-static void add_to_colormap(struct cmap * const cmapP, 
-                            const char *  const colorspec, 
-                            int *         const new_indexP) {
-/*----------------------------------------------------------------------------
-  Add a new entry to the colormap.  Make the color that specified by
-  'colorspec', and return the index of the new entry as *new_indexP.
-
-  'colorspec' is a color specification given by the user, e.g.
-  "red" or "rgb:ff/03.0d".  The maxval for this color specification is
-  that for the colormap *cmapP.
------------------------------------------------------------------------------*/
-    pixel const transcolor = ppm_parsecolor((char*)colorspec, cmapP->maxval);
-    
-    *new_indexP = cmapP->cmapsize++; 
-
-    cmapP->red[*new_indexP] = PPM_GETR(transcolor);
-    cmapP->green[*new_indexP] = PPM_GETG(transcolor); 
-    cmapP->blue[*new_indexP] = PPM_GETB(transcolor); 
+    copyRasterWithAlpha(inPamP, alphaPamP, &outPam, alphaPlane);
 }
 
 
 
 static void
-colormap_from_file(const char filespec[], unsigned int const maxcolors,
-                   colorhist_vector * const chvP, pixval * const maxvalP,
-                   int * const colorsP) {
-/*----------------------------------------------------------------------------
-   Read a colormap from the PPM file filespec[].  Return the color histogram
-   vector (which is practically a colormap) of the input image as *cvhP
-   and the maxval for that histogram as *maxvalP.
------------------------------------------------------------------------------*/
-    FILE *mapfile;
-    int cols, rows;
-    pixel ** colormap_ppm;
-
-    mapfile = pm_openr(filespec);
-    colormap_ppm = ppm_readppm(mapfile, &cols, &rows, maxvalP);
-    pm_close(mapfile);
+feedPamtogif(struct pam * const inPamP,
+             const char * const alphaFilespec,
+             FILE *       const pipeToPamtogif) {
     
-    /* Figure out the colormap from the <mapfile>. */
-    pm_message("computing other colormap...");
-    *chvP = 
-        ppm_computecolorhist(colormap_ppm, cols, rows, maxcolors, colorsP);
-    
-    ppm_freearray(colormap_ppm, rows); 
-}
-
-
-
-static void
-get_alpha(const char * const alpha_filespec, int const cols, int const rows,
-          gray *** const alphaP, gray * const maxvalP) {
-
-    if (alpha_filespec) {
-        int alpha_cols, alpha_rows;
-        *alphaP = pgm_readpgm(pm_openr(alpha_filespec),
-                              &alpha_cols, &alpha_rows, maxvalP);
-        if (alpha_cols != cols || alpha_rows != rows)
-            pm_error("alpha mask is not the same dimensions as the "
-                     "input file (alpha is %dW x %dH; image is %dW x %dH)",
-                     alpha_cols, alpha_rows, cols, rows);
-    } else 
-        *alphaP = NULL;
-}
-
-
-
-static void
-compute_ppm_colormap(pixel ** const pixels, int const cols, int const rows,
-                     int const input_maxval, bool const have_alpha, 
-                     const char * const mapfile, colorhist_vector * const chvP,
-                     colorhash_table * const chtP,
-                     pixval * const colormap_maxvalP, 
-                     int * const colorsP) {
-/*----------------------------------------------------------------------------
-   Compute a colormap, PPM style, for the image 'pixels', which is
-   'cols' by 'rows' with maxval 'input_maxval'.  If 'mapfile' is
-   non-null, Use the colors in that (PPM) file for the color map
-   instead of the colors in 'pixels'.
-
-   Return the colormap as *chvP and *chtP.  Return the maxval for that
-   colormap as *colormap_maxvalP.
-
-   While we're at it, count the colors and validate that there aren't
-   too many.  Return the count as *colorsP.  In determining if there are
-   too many, allow one slot for a fake transparency color if 'have_alpha'
-   is true.  If there are too many, issue an error message and abort the
-   program.
------------------------------------------------------------------------------*/
-    unsigned int maxcolors;
-        /* The most colors we can tolerate in the image.  If we have
-           our own made-up entry in the colormap for transparency, it
-           isn't included in this count.
-        */
-
-    if (have_alpha)
-        maxcolors = MAXCMAPSIZE - 1;
-    else
-        maxcolors = MAXCMAPSIZE;
-
-    if (mapfile) {
-        /* Read the colormap from a separate colormap file. */
-        colormap_from_file(mapfile, maxcolors, chvP, colormap_maxvalP, 
-                           colorsP);
-    } else {
-        /* Figure out the color map from the input file */
-        pm_message("computing colormap...");
-        *chvP = ppm_computecolorhist(pixels, cols, rows, maxcolors, colorsP); 
-        *colormap_maxvalP = input_maxval;
-    }
-
-    if (*chvP == NULL)
-        pm_error("too many colors - try doing a 'pnmquant %d'", maxcolors);
-    pm_message("%d colors found", *colorsP);
-
-    /* And make a hash table for fast lookup. */
-    *chtP = ppm_colorhisttocolorhash(*chvP, *colorsP);
+    if (alphaFilespec) {
+        FILE * afP;
+        struct pam alphaPam;
+        afP = pm_openr(alphaFilespec);
+        pnm_readpaminit(afP, &alphaPam, PAM_STRUCT_SIZE(tuple_type));
+        feedPamtogifWithAlpha(inPamP, &alphaPam, pipeToPamtogif);
+        pm_close(afP);
+    } else
+        feedPamtogifNoAlpha(inPamP, pipeToPamtogif);
 }
 
 
 
 int
-main(int argc, char *argv[]) {
+main(int    argc,
+     char * argv[]) {
+
     struct cmdlineInfo cmdline;
     FILE * ifP;
-    int rows, cols;
-    int BitsPerPixel;
-    pixel ** pixels;   /* The input image, in PPM format */
-    pixval input_maxval;  /* Maxval for 'pixels' */
-    gray ** alpha;     /* The supplied alpha mask; NULL if none */
-    gray alpha_maxval; /* Maxval for 'alpha' */
-
-    struct cmap cmap;
-        /* The colormap, with all its accessories */
-    colorhist_vector chv;
-    int fake_transparent;
-        /* colormap index of the fake transparency color we're using to
-           implement the alpha mask.  Undefined if we're not doing an alpha
-           mask.
-        */
+    struct pam inPam;
+    const char * command;
+    FILE * pipeToPamtogif;
+    int rc;
 
-    ppm_init( &argc, argv );
+    pnm_init(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
-    verbose = cmdline.verbose;
-
-    ifP = pm_openr(cmdline.input_filespec);
-
-    pixels = ppm_readppm(ifP, &cols, &rows, &input_maxval);
+    command = pamtogifCommand(argv[0], cmdline);
 
-    pm_close(ifP);
-
-    get_alpha(cmdline.alpha_filespec, cols, rows, &alpha, &alpha_maxval);
+    if (cmdline.verbose)
+        pm_message("Executing shell command '%s'", command);
+    
+    pipeToPamtogif = popen(command, "w");
 
-    compute_ppm_colormap(pixels, cols, rows, input_maxval, (alpha != NULL), 
-                         cmdline.mapfile, 
-                         &chv, &cmap.cht, &cmap.maxval, &cmap.cmapsize);
+    if (pipeToPamtogif == NULL)
+        pm_error("Shell command '%s', via popen(), failed.", command);
 
-    /* Now turn the ppm colormap into the appropriate GIF colormap. */
+    ifP = pm_openr(cmdline.input_filespec);
+    pnm_readpaminit(ifP, &inPam, PAM_STRUCT_SIZE(allocation_depth));
 
-    normalize_to_255(chv, &cmap);
+    feedPamtogif(&inPam, cmdline.alpha_filespec, pipeToPamtogif);
 
-    ppm_freecolorhist(chv);
+    rc = pclose(pipeToPamtogif);
 
-    if (alpha) {
-        /* Add a fake entry to the end of the colormap for transparency.  
-           Make its color black. 
-        */
-        add_to_colormap(&cmap, cmdline.alphacolor, &fake_transparent);
-    }
-    sort_colormap(cmdline.sort, &cmap);
-
-    BitsPerPixel = pm_maxvaltobits(cmap.cmapsize-1);
-
-    if (alpha) {
-        cmap.transparent = cmap.perm[fake_transparent];
-    } else {
-        if (cmdline.transparent)
-            cmap.transparent = 
-                compute_transparent(cmdline.transparent, &cmap);
-        else 
-            cmap.transparent = -1;
-    }
-    /* All set, let's do it. */
-    gifEncode(stdout, pixels, input_maxval, cols, rows, 
-              alpha, alpha_maxval, 
-              cmdline.interlace, 0, BitsPerPixel, &cmap, cmdline.comment,
-              cmdline.nolzw);
+    if (rc != 0)
+        pm_error("Pamtogif process failed.  pclose() failed.");
 
-    ppm_freearray(pixels, rows);
-    if (alpha)
-        pgm_freearray(alpha, rows);
+    strfree(command);
 
-    fclose(stdout);
+    pm_close(ifP);
+    pm_close(stdout);
 
     return 0;
 }
diff --git a/converter/ppm/ppmtoilbm.c b/converter/ppm/ppmtoilbm.c
index 6c04c9be..c0d58edb 100644
--- a/converter/ppm/ppmtoilbm.c
+++ b/converter/ppm/ppmtoilbm.c
@@ -635,20 +635,9 @@ ppm_to_ham(fp, cols, rows, maxval, colormap, colors, cmapmaxval, hamplanes)
 
 
 static long
-#ifdef __STDC__
 do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows,
             pixval maxval, pixval hammaxval, int nPlanes,
             pixel *colormap, int colors)
-#else
-do_ham_body(ifP, ofp, cols, rows, maxval, hammaxval, nPlanes, colormap, colors)
-    FILE *ifP, *ofp;
-    int cols, rows;
-    pixval maxval;      /* maxval of image color components */
-    pixval hammaxval;   /* maxval of HAM color changes */
-    int nPlanes;
-    pixel *colormap;
-    int colors;
-#endif
 {
     register int col, row, i;
     rawtype *raw_rowbuf;
@@ -876,16 +865,8 @@ ppm_to_deep(fp, cols, rows, maxval, bitspercolor)
 
 
 static long
-#if __STDC__
 do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, 
              int bitspercolor)
-#else
-do_deep_body(ifP, ofp, cols, rows, maxval, bitspercolor)
-    FILE *ifP, *ofp;
-    int cols, rows;
-    pixval maxval;
-    int bitspercolor;
-#endif
 {
     register int row, col;
     pixel *pP;
@@ -1014,16 +995,8 @@ ppm_to_dcol(fp, cols, rows, maxval, dcol)
 
 
 static long
-#if __STDC__
 do_dcol_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, 
              DirectColor *dcol)
-#else
-do_dcol_body(ifP, ofp, cols, rows, maxval, dcol)
-    FILE *ifP, *ofp;
-    int cols, rows;
-    pixval maxval;
-    DirectColor *dcol;
-#endif
 {
     register int row, col;
     pixel *pP;
@@ -1161,18 +1134,8 @@ ppm_to_std(fp, cols, rows, maxval, colormap, colors, cmapmaxval,
 
 
 static long
-#if __STDC__
 do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
             pixel *colormap, int colors, int nPlanes)
-#else
-do_std_body(ifP, ofp, cols, rows, maxval, colormap, colors, nPlanes)
-    FILE *ifP, *ofp;
-    int cols, rows;
-    pixval maxval;
-    pixel *colormap;
-    int colors;
-    int nPlanes;
-#endif
 {
     register int row, col, i;
     pixel *pP;
@@ -1783,12 +1746,7 @@ runbyte1(size)
 /************ other utility functions ************/
 
 static void
-#if __STDC__
 put_big_short(short s)
-#else
-put_big_short(s)
-    short s;
-#endif
 {
     if ( pm_writebigshort( stdout, s ) == -1 )
         pm_error( "write error" );
diff --git a/converter/ppm/ppmtomitsu.c b/converter/ppm/ppmtomitsu.c
index 3934ae45..837d9e2b 100644
--- a/converter/ppm/ppmtomitsu.c
+++ b/converter/ppm/ppmtomitsu.c
@@ -20,362 +20,70 @@ x**  - mymalloc() and check_and_rotate() functions for often used
 ** implied warranty.
 */
 
+#include <assert.h>
 #include <string.h>
+#include <stdio.h>
 
 #include "pm_c_util.h"
-#include "ppm.h"
 #include "nstring.h"
 #include "mallocvar.h"
+#include "ppm.h"
 
 #include "mitsu.h"
 
 
-#include <stdio.h>
-
 #define HASHSIZE 2048
 #define myhash(x) ((PPM_GETR(x)*3 + PPM_GETG(x)*5 + PPM_GETB(x)*7) % HASHSIZE)
 
 typedef struct hashinfo {
         pixel     color;
         long      flag;
-        struct hashinfo *next;
+        struct hashinfo * next;
 } hashinfo;
 
-#ifdef __STDC__
-static void lineputinit(int cols, int rows, int sharpness, int enlarge, int
-                        copy, struct mediasize medias);
-static void frametransferinit(int cols, int rows, int sharpness, int enlarge,
-                              int copy, struct mediasize medias);
-static void lookuptableinit(int sharpness, int enlarge, int copy,
-                            struct mediasize medias);
-static void lookuptabledata(int cols, int rows, int enlarge,
-                            struct mediasize medias);
-static void check_and_rotate(int cols, int rows, int enlarge,
-                             struct mediasize medias);
-#define CONST const
-#else /*__STDC__*/
-static int lineputinit();
-static int lookuptableinit();
-static int lookuptabledata();
-static int frametransferinit();
-static int check_and_rotate();
-#define CONST
-#endif
-
 #define cmd(arg)           fputc((arg), stdout)
 #define datum(arg)         fputc((char)(arg), stdout)
 #define data(arg,num)      fwrite((arg), sizeof(char), (num), stdout)
 
 
-#ifdef __STDC__
-int main(int argc, char *argv[] )
-#else
-int main( argc, argv )
-    int argc;
-    char* argv[];
-#endif
-    {
-    FILE             *ifp;
-    /*hashinfo         colorhashtable[HASHSIZE];*/
-    struct hashinfo  *hashrun;
-    pixel            *xP;
-    int              argn;
-    bool             dpi300;
-    int              cols, rows, format, col, row;
-    int              sharpness, enlarge, copy, tiny;
-    pixval           maxval;
-    struct mediasize medias;
-    char             media[16];
-    const char * const usage = "[-sharpness <1-4>] [-enlarge <1-3>] [-media <a,a4,as,a4s>] [-copy <1-9>] [-tiny] [-dpi300] [ppmfile]";
-
-    ppm_init(&argc, argv);
-
-    dpi300 = FALSE;
-    argn = 1;
-    sharpness = 32;
-    enlarge   = 1;
-    copy      = 1;
-    memset(media, '\0', 16);
-    tiny      = FALSE;
-
-    /* check for flags */
-    while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
-    if (pm_keymatch(argv[argn], "-sharpness", 2)) {
-        ++argn;
-        if (argn == argc || sscanf(argv[argn], "%d", &sharpness) != 1)
-            pm_usage(usage);
-        else if (sharpness < 1 || sharpness > 4)
-            pm_usage(usage);
-        }
-    else if (pm_keymatch(argv[argn], "-enlarge", 2)) {
-        ++argn;
-        if (argn == argc || sscanf(argv[argn], "%d", &enlarge) != 1)
-            pm_usage(usage);
-        else if (enlarge < 1 || enlarge > 3)
-            pm_usage(usage);
-        }
-    else if (pm_keymatch(argv[argn], "-media", 2)) {
-        ++argn;
-        if (argn == argc || sscanf(argv[argn], "%15s", media) < 1)
-            pm_usage(usage);
-        else if (TOUPPER(media[0]) != 'A')
-            pm_usage(usage);
-    }
-    else if (pm_keymatch(argv[argn], "-copy", 2)) {
-        ++argn;
-        if (argn == argc || sscanf(argv[argn], "%d", &copy) != 1)
-            pm_usage(usage);
-        else if (copy < 1 || copy > 9)
-            pm_usage(usage);
-        }
-    else if (pm_keymatch(argv[argn], "-dpi300", 2))
-        dpi300 = TRUE;
-    else if (pm_keymatch(argv[argn], "-tiny", 2))
-        tiny = TRUE;
-    else
-        pm_usage(usage);
-        ++argn;
-    }
-
-    if (argn < argc) {
-        ifp = pm_openr(argv[argn]);
-        ++argn;
-    }
-    else
-        ifp = stdin;
-
-    if (argn != argc)
-        pm_usage(usage);
-
-    if (TOUPPER(media[0]) == 'A')
-        switch (TOUPPER(media[1])) {
-        case 'S':
-            medias = MSize_AS;
-            break;
-        case '4':
-            if(TOUPPER(media[2]) == 'S')
-                medias = MSize_A4S;
-            else {
-                medias = MSize_A4;
-            }
-            break;
-        default:
-            medias = MSize_A;
-        }
-    else
-        medias = MSize_User;
 
-        if (dpi300) {
-                medias.maxcols *= 2;
-                medias.maxrows *= 2;
-        }
+static void
+check_and_rotate(int              const cols,
+                 int              const rows,
+                 int              const enlarge,
+                 struct mediasize const medias) {
 
-    if (tiny) {
-        pixel            *pixelrow;
-        char             *redrow, *greenrow, *bluerow;
-
-        ppm_readppminit(ifp, &cols, &rows, &maxval, &format);
-        pixelrow = (pixel *) ppm_allocrow(cols);
-        MALLOCARRAY_NOFAIL(redrow, cols);
-        MALLOCARRAY_NOFAIL(greenrow, cols);
-        MALLOCARRAY_NOFAIL(bluerow, cols);
-        lineputinit(cols, rows, sharpness, enlarge, copy, medias);
-
-        for ( row = 0; row < rows; ++row ) {
-            ppm_readppmrow(ifp, pixelrow, cols, maxval, format);
-            switch(PPM_FORMAT_TYPE(format)) {
-            /* color */
-            case PPM_TYPE:
-                for (col = 0, xP = pixelrow; col < cols; col++, xP++) {
-                    /* First red. */
-                    redrow[col] = PPM_GETR(*xP);
-                    /* Then green. */
-                    greenrow[col] = PPM_GETG(*xP);
-                    /* And blue. */
-                    bluerow[col] = PPM_GETB(*xP);
-                }
-                data(redrow,   cols);
-                data(greenrow, cols);
-                data(bluerow,  cols);
-                break;
-            /* grayscale */
-            default:
-                for (col = 0, xP = pixelrow; col < cols; col++, xP++)
-                    bluerow[col] = PPM_GETB(*xP);
-                data(bluerow, cols);
-                data(bluerow, cols);
-                data(bluerow, cols);
-                break;
-            }
-        }
-        pm_close(ifp);
+    if (cols > rows) {
+        ROTATEIMG(DOROTATE);                        /* rotate image */
+        if (enlarge * rows > medias.maxcols || enlarge * cols > medias.maxrows)
+            pm_error("Image too large, MaxPixels = %u x %u",
+                     medias.maxrows, medias.maxcols);
+        HPIXELS(cols);
+        VPIXELS(rows);
+        HPIXELSOFF((medias.maxcols/enlarge - rows)/2);
+        VPIXELSOFF((medias.maxrows/enlarge - cols)/2);
+        pm_message("rotating image for output");
+    } else {
+        ROTATEIMG(DONTROTATE);
+        if (enlarge * rows > medias.maxrows || enlarge * cols > medias.maxcols)
+            pm_error("Image too large, MaxPixels = %u x %u",
+                     medias.maxrows, medias.maxcols);
+        HPIXELS(cols);
+        VPIXELS(rows);
+        HPIXELSOFF((medias.maxcols/enlarge - cols)/2);
+        VPIXELSOFF((medias.maxrows/enlarge - rows)/2);
     }
-    else {
-        pixel            **pixelpic;
-        int              colanz, colval;
-        int                 i;
-        colorhist_vector table;
-
-        ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
-        pixelpic = ppm_allocarray( cols, rows );
-        for (row = 0; row < rows; row++)
-            ppm_readppmrow( ifp, pixelpic[row], cols, maxval, format );
-        pm_close(ifp);
-
-        /* first check wether we can use the lut transfer */
+}
 
-        table = ppm_computecolorhist(pixelpic, cols, rows, MAXLUTCOL+1, 
-                                     &colanz);
-        if (table != NULL) {
-            hashinfo *colorhashtable;
 
-            MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE);
-            for (i=0; i<HASHSIZE; i++) {
-                colorhashtable[i].flag = -1;
-                colorhashtable[i].next = NULL;
-            }
 
-            /* we can use the lookuptable */
-            pm_message("found %d colors - using the lookuptable-method",
-                       colanz);
-            lookuptableinit(sharpness, enlarge, copy, medias);
-            switch(PPM_FORMAT_TYPE(format)) {
-            /* color */
-            case PPM_TYPE:
-                for (colval=0; colval<colanz; colval++) {
-                    cmd('$');
-                    datum(colval);
-                    datum(PPM_GETR((table[colval]).color));
-                    datum(PPM_GETG((table[colval]).color));
-                    datum(PPM_GETB((table[colval]).color));
-
-                    hashrun = &colorhashtable[myhash((table[colval]).color)];
-                    if (hashrun->flag == -1) {
-                        hashrun->color = (table[colval]).color;
-                        hashrun->flag  = colval;
-                    }
-                    else {
-                        while (hashrun->next != NULL)
-                            hashrun = hashrun->next;
-                        MALLOCVAR_NOFAIL(hashrun->next);
-                        hashrun = hashrun->next;
-                        hashrun->color = (table[colval]).color;
-                        hashrun->flag  = colval;
-                        hashrun->next  = NULL;
-                    }
-                }
-                break;
-            /* other */
-            default:
-                for (colval=0; colval<colanz; colval++) {
-                    cmd('$');
-                    datum(colval);
-                    datum(PPM_GETB((table[colval]).color));
-                    datum(PPM_GETB((table[colval]).color));
-                    datum(PPM_GETB((table[colval]).color));
-
-                    hashrun = &colorhashtable[myhash((table[colval]).color)];
-                    if (hashrun->flag == -1) {
-                        hashrun->color = (table[colval]).color;
-                        hashrun->flag  = colval;
-                    }
-                    else {
-                        while (hashrun->next != NULL)
-                            hashrun = hashrun->next;
-                        MALLOCVAR_NOFAIL(hashrun->next);
-                        hashrun = hashrun->next;
-                        hashrun->color = (table[colval]).color;
-                        hashrun->flag  = colval;
-                        hashrun->next  = NULL;
-                    }
-                }
-            }
-            lookuptabledata(cols, rows, enlarge, medias);
-            for (row=0; row<rows; row++) {
-                xP = pixelpic[row];
-                for (col=0; col<cols; col++, xP++) {
-                    hashrun = &colorhashtable[myhash(*xP)];
-                    while (!PPM_EQUAL((hashrun->color), *xP))
-                        if (hashrun->next != NULL)
-                            hashrun = hashrun->next;
-                        else {
-                            pm_error("you just found a lethal bug.");
-                        }
-                    datum(hashrun->flag);
-                }
-            }
-            free(colorhashtable);
-        }
-        else {
-        /* $#%@^!& no lut possible, so send the pic as 24bit */
-            pm_message("found too many colors for fast lookuptable mode");
-            frametransferinit(cols, rows, sharpness, enlarge, copy, medias);
-            switch(PPM_FORMAT_TYPE(format)) {
-            /* color */
-            case PPM_TYPE:
-                COLORDES(RED);
-                DATASTART;                    /* red coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETR(*xP));
-                }
-                COLORDES(GREEN);
-                DATASTART;                    /* green coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETG(*xP));
-                }
-                COLORDES(BLUE);
-                DATASTART;                    /* blue coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETB(*xP));
-                }
-                break;
-            /* grayscale */
-            default:
-                COLORDES(RED);
-                DATASTART;                    /* red coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETB(*xP));
-                }
-                COLORDES(GREEN);
-                DATASTART;                    /* green coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETB(*xP));
-                }
-                COLORDES(BLUE);
-                DATASTART;                    /* blue coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETB(*xP));
-                }
-            }
-        }
-    }
-    PRINTIT;
-    exit(0);
-}
-
-#ifdef __STDC__
-static void lineputinit(int cols, int rows,
-                        int sharpness, int enlarge, int copy,
-                        struct mediasize medias)
-#else /*__STDC__*/
-static int lineputinit(cols, rows, sharpness, enlarge, copy, medias)
-    int cols, rows;
-    int sharpness, enlarge, copy;
-    struct mediasize medias;
-#endif /*__STDC__*/
-{
+static void
+lineputinit(int              const cols,
+            int              const rows,
+            int              const sharpness,
+            int              const enlarge,
+            int              const copy,
+            struct mediasize const medias) {
     ONLINE;
     CLRMEM;
     MEDIASIZE(medias);
@@ -426,18 +134,16 @@ static int lineputinit(cols, rows, sharpness, enlarge, copy, medias)
     }
     check_and_rotate(cols, rows, enlarge, medias);
     DATASTART;
-    return;
 }
 
-#ifdef __STDC__
-static void lookuptableinit(int sharpness, int enlarge, int copy,
-                            struct mediasize medias)
-#else /*__STDC__*/
-static int lookuptableinit(sharpness, enlarge, copy, medias)
-    int sharpness, enlarge, copy;
-    struct mediasize medias;
-#endif /*__STDC__*/
-{
+
+
+static void
+lookuptableinit(int              const sharpness,
+                int              const enlarge,
+                int              const copy,
+                struct mediasize const medias) {
+
     ONLINE;
     CLRMEM;
     MEDIASIZE(medias);
@@ -486,36 +192,31 @@ static int lookuptableinit(sharpness, enlarge, copy, medias)
     }
 
     LOADLOOKUPTABLE;
-    return;
 }
 
-#ifdef __STDC__
-static void lookuptabledata(int cols, int rows, int enlarge,
-                                                        struct mediasize medias)
-#else /*__STDC__*/
-static int lookuptabledata(cols, rows, enlarge, medias)
-    int   rows, cols;
-    int   enlarge;
-    struct mediasize medias;
-#endif /*__STDC__*/
-{
+
+
+static void
+lookuptabledata(int              const cols,
+                int              const rows,
+                int              const enlarge,
+                struct mediasize const medias) {
+
     DONELOOKUPTABLE;
     check_and_rotate(cols, rows, enlarge, medias);
     DATASTART;
-    return;
 }
 
-#ifdef __STDC__
-static void frametransferinit(int cols, int rows, int sharpness,
-                              int enlarge, int copy, struct mediasize medias)
-#else
-static int frametransferinit(cols, rows, sharpness, enlarge, copy, medias)
 
-    int     rows, cols;
-    int     sharpness, enlarge, copy;
-    struct mediasize medias;
-#endif
-{
+
+static void
+frametransferinit(int              const cols,
+                  int              const rows,
+                  int              const sharpness,
+                  int              const enlarge,
+                  int              const copy,
+                  struct mediasize const medias) {
+
     ONLINE;
     CLRMEM;
     MEDIASIZE(medias);
@@ -565,40 +266,411 @@ static int frametransferinit(cols, rows, sharpness, enlarge, copy, medias)
         SHARPNESS(SP_USER);
     }
     check_and_rotate(cols, rows, enlarge, medias);
-    return;
 }
 
 
-#ifdef __STDC__
+
+static void
+colorRow(colorhist_vector const table,
+         unsigned int     const colanz,
+         hashinfo *       const colorhashtable) {
+                
+    unsigned int colval;
+    for (colval = 0; colval < colanz; ++colval) {
+        struct hashinfo * const hashchain =
+            &colorhashtable[myhash((table[colval]).color)];
+
+        struct hashinfo * hashrun;
+
+        cmd('$');
+        datum(colval);
+        datum(PPM_GETR((table[colval]).color));
+        datum(PPM_GETG((table[colval]).color));
+        datum(PPM_GETB((table[colval]).color));
+        
+        hashrun = hashchain;  /* start at beginning of chain */
+
+        if (hashrun->flag == -1) {
+            hashrun->color = (table[colval]).color;
+            hashrun->flag  = colval;
+        } else {
+            while (hashrun->next != NULL)
+                hashrun = hashrun->next;
+            MALLOCVAR_NOFAIL(hashrun->next);
+            hashrun = hashrun->next;
+            hashrun->color = (table[colval]).color;
+            hashrun->flag  = colval;
+            hashrun->next  = NULL;
+        }
+    }
+}
+
+
+
 static void
-check_and_rotate(int cols, int rows, int enlarge, struct mediasize medias)
-#else
-static int
-check_and_rotate(cols, rows, enlarge, medias)
-    int cols, rows, enlarge;
+grayRow(colorhist_vector const table,
+        unsigned int     const colanz,
+        hashinfo *       const colorhashtable) {
+
+    unsigned int colval;
+    for (colval = 0; colval < colanz; ++colval) {
+        struct hashinfo * const hashchain =
+            &colorhashtable[myhash((table[colval]).color)];
+        struct hashinfo * hashrun;
+
+        cmd('$');
+        datum(colval);
+        datum(PPM_GETB((table[colval]).color));
+        datum(PPM_GETB((table[colval]).color));
+        datum(PPM_GETB((table[colval]).color));
+        
+        hashrun = hashchain;  /* start at beginning of chain */
+
+        if (hashrun->flag == -1) {
+            hashrun->color = (table[colval]).color;
+            hashrun->flag  = colval;
+                    }
+        else {
+            while (hashrun->next != NULL)
+                hashrun = hashrun->next;
+            MALLOCVAR_NOFAIL(hashrun->next);
+            hashrun = hashrun->next;
+            hashrun->color = (table[colval]).color;
+            hashrun->flag  = colval;
+            hashrun->next  = NULL;
+        }
+    }
+}
+
+
+
+static void
+useLookupTable(pixel **         const pixels,
+               colorhist_vector const table,
+               int              const sharpness,
+               int              const enlarge,
+               int              const copy,
+               struct mediasize const medias,
+               unsigned int     const cols,
+               unsigned int     const rows,
+               int              const format,
+               unsigned int     const colanz) {
+
+    hashinfo * colorhashtable;
+
+    pm_message("found %u colors - using the lookuptable-method", colanz);
+
+    MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE);
+    {
+        unsigned int i;
+        for (i = 0; i < HASHSIZE; ++i) {
+            colorhashtable[i].flag = -1;
+                    colorhashtable[i].next = NULL;
+        }
+    }
+
+    lookuptableinit(sharpness, enlarge, copy, medias);
+    switch(PPM_FORMAT_TYPE(format)) {
+    case PPM_TYPE:
+        colorRow(table, colanz, colorhashtable);
+        break;
+    default:
+        grayRow(table, colanz, colorhashtable);
+    }
+    lookuptabledata(cols, rows, enlarge, medias);
+    {
+        unsigned int row;
+        for (row = 0; row < rows; ++row) {
+            unsigned int col;
+            for (col = 0; col < cols; ++col) {
+                pixel * const pixrow = pixels[row];
+                struct hashinfo * const hashchain =
+                    &colorhashtable[myhash(pixrow[col])];
+                struct hashinfo * p;
+                
+                p = hashchain;
+                while (!PPM_EQUAL((p->color), pixrow[col])) {
+                    assert(p->next);
+                    p = p->next;
+                }
+                datum(p->flag);
+            }
+        }
+    }
+    free(colorhashtable);
+}
+
+
+
+static void
+noLookupColor(pixel **     const pixels,
+              unsigned int const cols,
+              unsigned int const rows) {
+
+    unsigned int row;
+    COLORDES(RED);
+    DATASTART;                    /* red coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETR(pixrow[col]));
+    }
+    COLORDES(GREEN);
+    DATASTART;                    /* green coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETG(pixrow[col]));
+    }
+    COLORDES(BLUE);
+    DATASTART;                    /* blue coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETB(pixrow[col]));
+    }
+}
+
+
+
+static void
+noLookupGray(pixel **     const pixels,
+             unsigned int const cols,
+             unsigned int const rows) {
+
+    unsigned int row;
+    COLORDES(RED);
+    DATASTART;                    /* red coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETB(pixrow[col]));
+    }
+    COLORDES(GREEN);
+    DATASTART;                    /* green coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETB(pixrow[col]));
+    }
+    COLORDES(BLUE);
+    DATASTART;                    /* blue coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETB(pixrow[col]));
+    }
+}
+
+
+
+static void
+useNoLookupTable(pixel **         const pixels,
+                 int              const sharpness,
+                 int              const enlarge,
+                 int              const copy,
+                 struct mediasize const medias,
+                 unsigned int     const cols,
+                 unsigned int     const rows,
+                 int              const format) {
+
+    /* $#%@^!& no lut possible, so send the pic as 24bit */
+
+    pm_message("found too many colors for fast lookuptable mode");
+
+    frametransferinit(cols, rows, sharpness, enlarge, copy, medias);
+    switch(PPM_FORMAT_TYPE(format)) {
+    case PPM_TYPE:
+        noLookupColor(pixels, cols, rows);
+        break;
+    default:
+        noLookupGray(pixels, cols, rows);
+    }
+}
+
+
+
+static void
+doTiny(FILE *           const ifP,
+       unsigned int     const cols,
+       unsigned int     const rows,
+       pixval           const maxval,
+       int              const format,
+       int              const sharpness,
+       int              const enlarge,
+       int              const copy,
+       struct mediasize const medias) {
+       
+    pixel * pixelrow;
+    unsigned char * redrow;
+    unsigned char * grnrow;
+    unsigned char * blurow;
+    unsigned int row;
+
+    pixelrow = ppm_allocrow(cols);
+    MALLOCARRAY_NOFAIL(redrow, cols);
+    MALLOCARRAY_NOFAIL(grnrow, cols);
+    MALLOCARRAY_NOFAIL(blurow, cols);
+    lineputinit(cols, rows, sharpness, enlarge, copy, medias);
+
+    for (row = 0; row < rows; ++row) {
+        ppm_readppmrow(ifP, pixelrow, cols, maxval, format);
+        switch(PPM_FORMAT_TYPE(format)) {
+        case PPM_TYPE: {            /* color */
+            unsigned int col;
+            for (col = 0; col < cols; ++col) {
+                redrow[col] = PPM_GETR(pixelrow[col]);
+                grnrow[col] = PPM_GETG(pixelrow[col]);
+                blurow[col] = PPM_GETB(pixelrow[col]);
+            }
+            data(redrow, cols);
+            data(grnrow, cols);
+            data(blurow, cols);
+        } break;
+        default: {           /* grayscale */
+            unsigned int col;
+            for (col = 0; col < cols; ++col)
+                blurow[col] = PPM_GETB(pixelrow[col]);
+            data(blurow, cols);
+            data(blurow, cols);
+            data(blurow, cols);
+            }
+        }
+    }
+}
+
+
+
+int
+main(int argc, char * argv[]) {
+    FILE * ifP;
+    int              argn;
+    bool             dpi300;
+    int              cols, rows, format;
+    pixval           maxval;
+    int              sharpness, enlarge, copy, tiny;
     struct mediasize medias;
-#endif
-{
-    if (cols > rows) {
-        ROTATEIMG(DOROTATE);                        /* rotate image */
-        if (enlarge*rows > medias.maxcols || enlarge*cols > medias.maxrows) {
-            pm_error("Image too large, MaxPixels = %d x %d", medias.maxrows, medias.maxcols);
+    char             media[16];
+    const char * const usage = "[-sharpness <1-4>] [-enlarge <1-3>] [-media <a,a4,as,a4s>] [-copy <1-9>] [-tiny] [-dpi300] [ppmfile]";
+
+    ppm_init(&argc, argv);
+
+    dpi300 = FALSE;
+    argn = 1;
+    sharpness = 32;
+    enlarge   = 1;
+    copy      = 1;
+    memset(media, '\0', 16);
+    tiny      = FALSE;
+
+    /* check for flags */
+    while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
+    if (pm_keymatch(argv[argn], "-sharpness", 2)) {
+        ++argn;
+        if (argn == argc || sscanf(argv[argn], "%d", &sharpness) != 1)
+            pm_usage(usage);
+        else if (sharpness < 1 || sharpness > 4)
+            pm_usage(usage);
         }
-        HPIXELS(cols);
-        VPIXELS(rows);
-        HPIXELSOFF((medias.maxcols/enlarge - rows)/2);
-        VPIXELSOFF((medias.maxrows/enlarge - cols)/2);
-        pm_message("rotating image for output");
+    else if (pm_keymatch(argv[argn], "-enlarge", 2)) {
+        ++argn;
+        if (argn == argc || sscanf(argv[argn], "%d", &enlarge) != 1)
+            pm_usage(usage);
+        else if (enlarge < 1 || enlarge > 3)
+            pm_usage(usage);
+        }
+    else if (pm_keymatch(argv[argn], "-media", 2)) {
+        ++argn;
+        if (argn == argc || sscanf(argv[argn], "%15s", media) < 1)
+            pm_usage(usage);
+        else if (TOUPPER(media[0]) != 'A')
+            pm_usage(usage);
     }
-    else {
-        ROTATEIMG(DONTROTATE);
-        if (enlarge*rows > medias.maxrows || enlarge*cols > medias.maxcols) {
-            pm_error("Image too large, MaxPixels = %d x %d", medias.maxrows, medias.maxcols);
+    else if (pm_keymatch(argv[argn], "-copy", 2)) {
+        ++argn;
+        if (argn == argc || sscanf(argv[argn], "%d", &copy) != 1)
+            pm_usage(usage);
+        else if (copy < 1 || copy > 9)
+            pm_usage(usage);
         }
-        HPIXELS(cols);
-        VPIXELS(rows);
-        HPIXELSOFF((medias.maxcols/enlarge - cols)/2);
-        VPIXELSOFF((medias.maxrows/enlarge - rows)/2);
+    else if (pm_keymatch(argv[argn], "-dpi300", 2))
+        dpi300 = TRUE;
+    else if (pm_keymatch(argv[argn], "-tiny", 2))
+        tiny = TRUE;
+    else
+        pm_usage(usage);
+        ++argn;
     }
+
+    if (argn < argc) {
+        ifP = pm_openr(argv[argn]);
+        ++argn;
+    }
+    else
+        ifP = stdin;
+
+    if (argn != argc)
+        pm_usage(usage);
+
+    if (TOUPPER(media[0]) == 'A')
+        switch (TOUPPER(media[1])) {
+        case 'S':
+            medias = MSize_AS;
+            break;
+        case '4':
+            if(TOUPPER(media[2]) == 'S')
+                medias = MSize_A4S;
+            else {
+                medias = MSize_A4;
+            }
+            break;
+        default:
+            medias = MSize_A;
+        }
+    else
+        medias = MSize_User;
+
+    if (dpi300) {
+        medias.maxcols *= 2;
+        medias.maxrows *= 2;
+    }
+
+    ppm_readppminit(ifP, &cols, &rows, &maxval, &format);
+    
+    if (tiny) {
+        doTiny(ifP, cols, rows, maxval, format,
+               sharpness, enlarge, copy, medias);
+
+    } else {
+        pixel ** pixels;
+        int colanz;
+        colorhist_vector table;
+        unsigned int row;
+
+        pixels = ppm_allocarray(cols, rows);
+        for (row = 0; row < rows; row++)
+            ppm_readppmrow(ifP, pixels[row], cols, maxval, format);
+
+        /* first check wether we can use the lut transfer */
+
+        table = ppm_computecolorhist(pixels, cols, rows, MAXLUTCOL+1, 
+                                     &colanz);
+        if (table)
+            useLookupTable(pixels, table, sharpness, enlarge, copy, medias,
+                           cols, rows, format, colanz);
+        else
+            useNoLookupTable(pixels, sharpness, enlarge, copy, medias,
+                             cols, rows, format);
+        ppm_freearray(pixels, rows);
+    }
+    PRINTIT;
+    pm_close(ifP);
+    return 0;
 }
 
diff --git a/converter/ppm/ppmtomitsu.test b/converter/ppm/ppmtomitsu.test
new file mode 100644
index 00000000..1805838a
--- /dev/null
+++ b/converter/ppm/ppmtomitsu.test
@@ -0,0 +1,12 @@
+echo Test 1.  Should print 3110813682 101562
+./ppmtomitsu ../../testimg.ppm | cksum 
+echo Test 2.  Should print 239186803 34399
+pnmquant 100 ../../testimg.ppm | ./ppmtomitsu | cksum 
+echo Test 3.  Should print 816221676 310
+./ppmtomitsu ../../testgrid.pbm | cksum 
+echo Test 4.  Should print 629834989 752
+./ppmtomitsu -tiny ../../testgrid.pbm | cksum 
+echo Test 5.  Should print 3999654426 101549
+./ppmtomitsu -tiny ../../testimg.ppm | cksum 
+echo Test 2.  Should print 3078685526 101549
+pnmquant 100 ../../testimg.ppm | ./ppmtomitsu -tiny | cksum 
diff --git a/converter/ppm/ppmtompeg/Makefile b/converter/ppm/ppmtompeg/Makefile
index 6db72ea9..e5ad6c58 100644
--- a/converter/ppm/ppmtompeg/Makefile
+++ b/converter/ppm/ppmtompeg/Makefile
@@ -39,7 +39,15 @@ endif
 #
 
 MP_BASE_OBJS = mfwddct.o postdct.o huff.o bitio.o mheaders.o
-MP_ENCODE_OBJS = iframe.o pframe.o bframe.o psearch.o bsearch.o block.o 
+MP_ENCODE_OBJS = \
+  frames.o \
+  iframe.o \
+  pframe.o \
+  bframe.o \
+  psearch.o \
+  bsearch.o \
+  block.o 
+
 MP_OTHER_OBJS = mpeg.o subsample.o param.o rgbtoycc.o \
 	readframe.o combine.o jrevdct.o frame.o fsize.o frametype.o \
 	specifics.o rate.o opts.o input.o gethostname.o
diff --git a/converter/ppm/ppmtompeg/bframe.c b/converter/ppm/ppmtompeg/bframe.c
index 5dfb76d3..1dbc1846 100644
--- a/converter/ppm/ppmtompeg/bframe.c
+++ b/converter/ppm/ppmtompeg/bframe.c
@@ -84,7 +84,6 @@ static struct bframeStats {
  *====================*/
 
 extern Block **dct, **dctr, **dctb;
-extern dct_data_type **dct_data;
 #define NO_MOTION 0
 #define MOTION 1
 #define SKIP 2  /* used in useMotion in dct_data */
diff --git a/converter/ppm/ppmtompeg/bsearch.c b/converter/ppm/ppmtompeg/bsearch.c
index 142987f5..70edfef6 100644
--- a/converter/ppm/ppmtompeg/bsearch.c
+++ b/converter/ppm/ppmtompeg/bsearch.c
@@ -77,6 +77,7 @@
 #include "frames.h"
 #include "motion_search.h"
 #include "fsize.h"
+#include "block.h"
 
 
 /*==================*
diff --git a/converter/ppm/ppmtompeg/frames.c b/converter/ppm/ppmtompeg/frames.c
new file mode 100644
index 00000000..a0764890
--- /dev/null
+++ b/converter/ppm/ppmtompeg/frames.c
@@ -0,0 +1,58 @@
+#include "mallocvar.h"
+#include "fsize.h"
+
+#include "frames.h"
+
+
+Block **dct=NULL, **dctr=NULL, **dctb=NULL;
+dct_data_type   **dct_data; /* used in p/bframe.c */
+
+
+/*===========================================================================*
+ *
+ * AllocDctBlocks
+ *
+ *  allocate memory for dct blocks
+ *
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    creates dct, dctr, dctb
+ *
+ *===========================================================================*/
+void
+AllocDctBlocks(void) {
+
+    int dctx, dcty;
+    int i;
+
+    dctx = Fsize_x / DCTSIZE;
+    dcty = Fsize_y / DCTSIZE;
+
+    MALLOCARRAY(dct, dcty);
+    ERRCHK(dct, "malloc");
+    for (i = 0; i < dcty; ++i) {
+        dct[i] = (Block *) malloc(sizeof(Block) * dctx);
+        ERRCHK(dct[i], "malloc");
+    }
+
+    MALLOCARRAY(dct_data, dcty);
+    ERRCHK(dct_data, "malloc");
+    for (i = 0; i < dcty; ++i) {
+        MALLOCARRAY(dct_data[i], dctx);
+        ERRCHK(dct[i], "malloc");
+    }
+
+    MALLOCARRAY(dctr, dcty/2);
+    ERRCHK(dctr, "malloc");
+    MALLOCARRAY(dctb, dcty/2);
+    ERRCHK(dctb, "malloc");
+    for (i = 0; i < dcty/2; ++i) {
+        MALLOCARRAY(dctr[i], dctx/2);
+        ERRCHK(dctr[i], "malloc");
+        MALLOCARRAY(dctb[i], dctx/2);
+        ERRCHK(dctb[i], "malloc");
+    }
+}
+
+
+
diff --git a/converter/ppm/ppmtompeg/headers/bitio.h b/converter/ppm/ppmtompeg/headers/bitio.h
index 89e61fbb..a24c21cd 100644
--- a/converter/ppm/ppmtompeg/headers/bitio.h
+++ b/converter/ppm/ppmtompeg/headers/bitio.h
@@ -60,9 +60,7 @@
 #define BIT_IO_INCLUDED
 
 
-/*==============*
- * HEADER FILES *
- *==============*/
+#include <stdio.h>
 
 #include "general.h"
 #include "ansi.h"
diff --git a/converter/ppm/ppmtompeg/headers/block.h b/converter/ppm/ppmtompeg/headers/block.h
index 46050492..22d306a1 100644
--- a/converter/ppm/ppmtompeg/headers/block.h
+++ b/converter/ppm/ppmtompeg/headers/block.h
@@ -1,3 +1,46 @@
+#ifndef BLOCK_H_INCLUDED
+
+#include "frame.h"
+#include "mtypes.h"
+
+/* DIFFERENCE FUNCTIONS */
+
+int32
+LumBlockMAD(const LumBlock * const currentBlockP,
+            const LumBlock * const motionBlockP,
+            int32            const bestSoFar);
+
+int32
+LumBlockMSE(const LumBlock * const currentBlockP,
+            const LumBlock * const motionBlockP,
+            int32            const bestSoFar);
+
+int32
+LumMotionError(const LumBlock * const currentBlockP,
+               MpegFrame *      const prev,
+               int              const by,
+               int              const bx,
+               vector           const m,
+               int32            const bestSoFar);
+
+int32
+LumAddMotionError(const LumBlock * const currentBlockP,
+                  const LumBlock * const blockSoFarP,
+                  MpegFrame *      const prev,
+                  int              const by,
+                  int              const bx,
+                  vector           const m,
+                  int32            const bestSoFar);
+
+int32
+LumMotionErrorSubSampled(const LumBlock * const currentBlockP,
+                         MpegFrame *      const prevFrame,
+                         int              const by,
+                         int              const bx,
+                         vector           const m,
+                         int              const startY,
+                         int              const startX);
+
 void
 ComputeDiffDCTs(MpegFrame * const current,
                 MpegFrame * const prev,
@@ -51,3 +94,4 @@ AddBMotionBlock(Block          block,
 void
 BlockifyFrame(MpegFrame * const frameP);
 
+#endif
diff --git a/converter/ppm/ppmtompeg/headers/frame.h b/converter/ppm/ppmtompeg/headers/frame.h
index 6df3d19f..acd74419 100644
--- a/converter/ppm/ppmtompeg/headers/frame.h
+++ b/converter/ppm/ppmtompeg/headers/frame.h
@@ -130,18 +130,4 @@ Frame_Resize(MpegFrame * const omf,
              int         const outsize_x,
              int         const outsize_y);
 
-
-extern void	  Frame_Free _ANSI_ARGS_((MpegFrame * const frame));
-extern void	  Frame_Exit _ANSI_ARGS_((void));
-extern void	  Frame_AllocPPM _ANSI_ARGS_((MpegFrame * frame));
-extern void	  Frame_AllocYCC _ANSI_ARGS_((MpegFrame * const mf));
-extern void	  Frame_AllocDecoded _ANSI_ARGS_((MpegFrame * const frame,
-						  boolean const makeReference));
-extern void	  Frame_AllocHalf _ANSI_ARGS_((MpegFrame * const frame));
-extern void	  Frame_AllocBlocks _ANSI_ARGS_((MpegFrame * const mf));
-extern void	  Frame_Resize _ANSI_ARGS_((MpegFrame * const omf, MpegFrame * const mf,
-					    int const insize_x, int const insize_y,
-					    int const outsize_x, int const outsize_y));
-
-
-#endif /* FRAME_INCLUDED */
+#endif
diff --git a/converter/ppm/ppmtompeg/headers/frames.h b/converter/ppm/ppmtompeg/headers/frames.h
index 14304c48..17820127 100644
--- a/converter/ppm/ppmtompeg/headers/frames.h
+++ b/converter/ppm/ppmtompeg/headers/frames.h
@@ -16,6 +16,7 @@
 #include "ansi.h"
 #include "mtypes.h"
 #include "mheaders.h"
+#include "iframe.h"
 #include "frame.h"
 
 
@@ -86,11 +87,13 @@ typedef struct dct_data_tye_struct {
   int fmotionX, fmotionY, bmotionX, bmotionY;
 } dct_data_type;
 
-void    EncodeYDC _ANSI_ARGS_((int32 const dc_term, int32 * const pred_term, BitBucket * const bb));
-void
-EncodeCDC(int32       const dc_term,
-          int32     * const pred_term,
-          BitBucket * const bb);
+
+/*==================*
+ * GLOBAL VARIABLES *
+ *==================*/
+
+extern Block    **dct, **dctr, **dctb;
+extern dct_data_type **dct_data;
 
 
 /*========*
@@ -101,63 +104,6 @@ EncodeCDC(int32       const dc_term,
 #define int_ceil_div(a,b,c)     ((b*(c = a/b) < a) ? (c+1) : c)
 #define int_floor_div(a,b,c)    ((b*(c = a/b) > a) ? (c-1) : c)
 
-/* assumes many things:
- * block indices are (y,x)
- * variables y_dc_pred, cr_dc_pred, and cb_dc_pred
- * flat block fb exists
- */
-#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) {                   \
-    boolean overflow, overflowChange=FALSE;                             \
-        int overflowValue = 0;                                              \
-        do {                                                                \
-      overflow =  Mpost_QuantZigBlock(dct[y][x], fb[0],                 \
-             qscale, TRUE)==MPOST_OVERFLOW;                     \
-          overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1],               \
-                 qscale, TRUE)==MPOST_OVERFLOW;                     \
-      overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2],               \
-                         qscale, TRUE)==MPOST_OVERFLOW;                     \
-      overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3],             \
-                         qscale, TRUE)==MPOST_OVERFLOW;                     \
-      overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1],             \
-                         fb[4], qscale, TRUE)==MPOST_OVERFLOW;              \
-      overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1],             \
-             fb[5], qscale, TRUE)==MPOST_OVERFLOW;              \
-          if ((overflow) && (qscale!=31)) {                                 \
-           overflowChange = TRUE; overflowValue++;                          \
-       qscale++;                                                        \
-       } else overflow = FALSE;                                         \
-    } while (overflow);                                                 \
-        Mhead_GenMBHeader(bb,                           \
-            frameType /* pict_code_type */, mbAI /* addr_incr */,   \
-            qscale /* q_scale */,                               \
-            0 /* forw_f_code */, 0 /* back_f_code */,           \
-            0 /* horiz_forw_r */, 0 /* vert_forw_r */,          \
-            0 /* horiz_back_r */, 0 /* vert_back_r */,          \
-            0 /* motion_forw */, 0 /* m_horiz_forw */,          \
-            0 /* m_vert_forw */, 0 /* motion_back */,           \
-            0 /* m_horiz_back */, 0 /* m_vert_back */,          \
-            0 /* mb_pattern */, TRUE /* mb_intra */);           \
-                                        \
-    /* Y blocks */                              \
-        EncodeYDC(fb[0][0], &y_dc_pred, bb);                            \
-    Mpost_RLEHuffIBlock(fb[0], bb);                         \
-    EncodeYDC(fb[1][0], &y_dc_pred, bb);                        \
-        Mpost_RLEHuffIBlock(fb[1], bb);                             \
-    EncodeYDC(fb[2][0], &y_dc_pred, bb);                        \
-    Mpost_RLEHuffIBlock(fb[2], bb);                         \
-    EncodeYDC(fb[3][0], &y_dc_pred, bb);                        \
-    Mpost_RLEHuffIBlock(fb[3], bb);                         \
-                                        \
-    /* CB block */                              \
-    EncodeCDC(fb[4][0], &cb_dc_pred, bb);                   \
-    Mpost_RLEHuffIBlock(fb[4], bb);                     \
-                                        \
-    /* CR block */                              \
-    EncodeCDC(fb[5][0], &cr_dc_pred, bb);                   \
-    Mpost_RLEHuffIBlock(fb[5], bb);                     \
-    if (overflowChange) qscale -= overflowValue;                        \
-    }
-
 #define BLOCK_TO_FRAME_COORD(bx1, bx2, x1, x2) {    \
     x1 = (bx1)*DCTSIZE;             \
     x2 = (bx2)*DCTSIZE;             \
@@ -254,6 +200,9 @@ encodeMotionVector(int      const x,
  *===============================*/
 
 void
+AllocDctBlocks(void);
+
+void
 ComputeBMotionLumBlock(MpegFrame * const prev,
                        MpegFrame * const next,
                        int         const by,
@@ -271,8 +220,6 @@ BMotionSearch(const LumBlock * const currentBlockP,
               motion *         const motionP,
               int              const oldMode);
 
-void GenIFrame (BitBucket * const bb,
-                MpegFrame * const mf);
 void GenPFrame (BitBucket * const bb,
                 MpegFrame * const current,
                 MpegFrame * const prev);
@@ -280,11 +227,6 @@ void GenBFrame (BitBucket * const bb,
                 MpegFrame * const curr,
                 MpegFrame * const prev,
                 MpegFrame * const next);
-void    AllocDctBlocks _ANSI_ARGS_((void ));
-
-
-float
-IFrameTotalTime(void);
 
 float
 PFrameTotalTime(void);
@@ -293,11 +235,6 @@ float
 BFrameTotalTime(void);
 
 void
-ShowIFrameSummary(unsigned int const inputFrameBits, 
-                  unsigned int const totalBits, 
-                  FILE *       const fpointer);
-
-void
 ShowPFrameSummary(unsigned int const inputFrameBits, 
                   unsigned int const totalBits, 
                   FILE *       const fpointer);
@@ -307,87 +244,6 @@ ShowBFrameSummary(unsigned int const inputFrameBits,
                   unsigned int const totalBits, 
                   FILE *       const fpointer);
 
-/* DIFFERENCE FUNCTIONS */
-
-int32
-LumBlockMAD(const LumBlock * const currentBlockP,
-            const LumBlock * const motionBlockP,
-            int32            const bestSoFar);
-
-int32
-LumBlockMSE(const LumBlock * const currentBlockP,
-            const LumBlock * const motionBlockP,
-            int32            const bestSoFar);
-
-int32
-LumMotionError(const LumBlock * const currentBlockP,
-               MpegFrame *      const prev,
-               int              const by,
-               int              const bx,
-               vector           const m,
-               int32            const bestSoFar);
-
-int32
-LumAddMotionError(const LumBlock * const currentBlockP,
-                  const LumBlock * const blockSoFarP,
-                  MpegFrame *      const prev,
-                  int              const by,
-                  int              const bx,
-                  vector           const m,
-                  int32            const bestSoFar);
-
-int32
-LumMotionErrorA(const LumBlock * const currentBlockP,
-                MpegFrame *      const prevFrame,
-                int              const by,
-                int              const bx,
-                vector           const m,
-                int32            const bestSoFar);
-
-int32
-LumMotionErrorB(const LumBlock * const currentP,
-                MpegFrame *      const prevFrame,
-                int              const by,
-                int              const bx,
-                vector           const m,
-                int32            const bestSoFar);
-
-int32
-LumMotionErrorC(const LumBlock * const currentP,
-                MpegFrame *      const prevFrame,
-                int              const by,
-                int              const bx,
-                vector           const m,
-                int32            const bestSoFar);
-
-int32
-LumMotionErrorD(const LumBlock * const currentP,
-                MpegFrame *      const prevFrame,
-                int              const by,
-                int              const bx,
-                vector           const m,
-                int32            const bestSoFar);
-
-int32
-LumMotionErrorSubSampled(const LumBlock * const currentBlockP,
-                         MpegFrame *      const prevFrame,
-                         int              const by,
-                         int              const bx,
-                         vector           const m,
-                         int              const startY,
-                         int              const startX);
-
-void
-BlockComputeSNR(MpegFrame * const current,
-                float *     const snr,
-                float *     const psnr);
-
-int32
-time_elapsed(void);
-
-void
-AllocDctBlocks(void);
-
 /*==================*
  * GLOBAL VARIABLES *
  *==================*/
@@ -413,7 +269,7 @@ extern int  fCodeI,fCodeP,fCodeB;
 extern boolean    forceEncodeLast;
 extern int TIME_RATE;
 
-#endif /* FRAMES_INCLUDED */
+#endif
 
 
 /*
diff --git a/converter/ppm/ppmtompeg/headers/iframe.h b/converter/ppm/ppmtompeg/headers/iframe.h
new file mode 100644
index 00000000..c4f77c74
--- /dev/null
+++ b/converter/ppm/ppmtompeg/headers/iframe.h
@@ -0,0 +1,118 @@
+#ifndef IFRAME_H_INCLUDED
+#define IFRAME_H_INCLUDED
+
+#include "frame.h"
+
+void
+SetFCode(void);
+
+void
+SetSlicesPerFrame(int const number);
+
+void
+SetBlocksPerSlice(void);
+
+void
+SetIQScale(int const qI);
+
+int
+GetIQScale(void);
+
+void
+GenIFrame(BitBucket * const bb, 
+          MpegFrame * const current);
+
+void
+ResetIFrameStats(void);
+
+float
+IFrameTotalTime(void);
+
+
+void
+ShowIFrameSummary(unsigned int const inputFrameBits, 
+                  unsigned int const totalBits, 
+                  FILE *       const fpointer);
+
+void
+EncodeYDC(int32       const dc_term,
+          int32 *     const pred_term,
+          BitBucket * const bb);
+
+void
+EncodeCDC(int32       const dc_term,
+          int32     * const pred_term,
+          BitBucket * const bb);
+
+void
+BlockComputeSNR(MpegFrame * const current,
+                float *     const snr,
+                float *     const psnr);
+
+void
+WriteDecodedFrame(MpegFrame * const frame);
+
+void
+PrintItoIBitRate(int const numBits,
+                 int const frameNum);
+
+int32 time_elapsed(void);
+
+/* assumes many things:
+ * block indices are (y,x)
+ * variables y_dc_pred, cr_dc_pred, and cb_dc_pred
+ * flat block fb exists
+ */
+#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) {                   \
+    boolean overflow, overflowChange=FALSE;                             \
+        int overflowValue = 0;                                              \
+        do {                                                                \
+      overflow =  Mpost_QuantZigBlock(dct[y][x], fb[0],                 \
+             qscale, TRUE)==MPOST_OVERFLOW;                     \
+          overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1],               \
+                 qscale, TRUE)==MPOST_OVERFLOW;                     \
+      overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2],               \
+                         qscale, TRUE)==MPOST_OVERFLOW;                     \
+      overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3],             \
+                         qscale, TRUE)==MPOST_OVERFLOW;                     \
+      overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1],             \
+                         fb[4], qscale, TRUE)==MPOST_OVERFLOW;              \
+      overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1],             \
+             fb[5], qscale, TRUE)==MPOST_OVERFLOW;              \
+          if ((overflow) && (qscale!=31)) {                                 \
+           overflowChange = TRUE; overflowValue++;                          \
+       qscale++;                                                        \
+       } else overflow = FALSE;                                         \
+    } while (overflow);                                                 \
+        Mhead_GenMBHeader(bb,                           \
+            frameType /* pict_code_type */, mbAI /* addr_incr */,   \
+            qscale /* q_scale */,                               \
+            0 /* forw_f_code */, 0 /* back_f_code */,           \
+            0 /* horiz_forw_r */, 0 /* vert_forw_r */,          \
+            0 /* horiz_back_r */, 0 /* vert_back_r */,          \
+            0 /* motion_forw */, 0 /* m_horiz_forw */,          \
+            0 /* m_vert_forw */, 0 /* motion_back */,           \
+            0 /* m_horiz_back */, 0 /* m_vert_back */,          \
+            0 /* mb_pattern */, TRUE /* mb_intra */);           \
+                                        \
+    /* Y blocks */                              \
+        EncodeYDC(fb[0][0], &y_dc_pred, bb);                            \
+    Mpost_RLEHuffIBlock(fb[0], bb);                         \
+    EncodeYDC(fb[1][0], &y_dc_pred, bb);                        \
+        Mpost_RLEHuffIBlock(fb[1], bb);                             \
+    EncodeYDC(fb[2][0], &y_dc_pred, bb);                        \
+    Mpost_RLEHuffIBlock(fb[2], bb);                         \
+    EncodeYDC(fb[3][0], &y_dc_pred, bb);                        \
+    Mpost_RLEHuffIBlock(fb[3], bb);                         \
+                                        \
+    /* CB block */                              \
+    EncodeCDC(fb[4][0], &cb_dc_pred, bb);                   \
+    Mpost_RLEHuffIBlock(fb[4], bb);                     \
+                                        \
+    /* CR block */                              \
+    EncodeCDC(fb[5][0], &cr_dc_pred, bb);                   \
+    Mpost_RLEHuffIBlock(fb[5], bb);                     \
+    if (overflowChange) qscale -= overflowValue;                        \
+    }
+
+#endif
diff --git a/converter/ppm/ppmtompeg/headers/motion_search.h b/converter/ppm/ppmtompeg/headers/motion_search.h
index ab83cbca..62f3abab 100644
--- a/converter/ppm/ppmtompeg/headers/motion_search.h
+++ b/converter/ppm/ppmtompeg/headers/motion_search.h
@@ -100,6 +100,9 @@ PMotionSearch(const LumBlock * const currentBlockP,
               int              const bx, 
               vector *         const motionP);
 
+void
+MotionSearchPreComputation(MpegFrame * const frameP);
+
 /*==================*
  * GLOBAL VARIABLES *
  *==================*/
diff --git a/converter/ppm/ppmtompeg/headers/mpeg.h b/converter/ppm/ppmtompeg/headers/mpeg.h
index 23875c2c..56862c42 100644
--- a/converter/ppm/ppmtompeg/headers/mpeg.h
+++ b/converter/ppm/ppmtompeg/headers/mpeg.h
@@ -90,8 +90,9 @@ void
 ReadDecodedRefFrame(MpegFrame *  const frameP, 
                     unsigned int const frameNumber);
 
-extern void	WriteDecodedFrame _ANSI_ARGS_((MpegFrame * const frame));
-extern void	SetBitRateFileName _ANSI_ARGS_((char *fileName));
+void
+SetBitRateFileName(const char * const fileName);
+
 extern void	SetFrameRate _ANSI_ARGS_((void));
 
 
diff --git a/converter/ppm/ppmtompeg/headers/mproto.h b/converter/ppm/ppmtompeg/headers/mproto.h
index c3b0f4b3..d8fefd84 100644
--- a/converter/ppm/ppmtompeg/headers/mproto.h
+++ b/converter/ppm/ppmtompeg/headers/mproto.h
@@ -74,7 +74,6 @@
 #include "bitio.h"
 
 
-#define DCTSIZE2    DCTSIZE*DCTSIZE
 typedef short DCTELEM;
 typedef DCTELEM DCTBLOCK[DCTSIZE2];
 
@@ -111,9 +110,6 @@ void	ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, int width,
 boolean	ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer));
 void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf));
 
-void	MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame));
-boolean	PMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev,
-				   int by, int bx, int *motionY, int *motionX));
 void	ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame));
 void mp_validate_size _ANSI_ARGS_((int *x, int *y));
 void AllocYCC _ANSI_ARGS_((MpegFrame * mf));
@@ -126,7 +122,3 @@ void j_rev_dct _ANSI_ARGS_((DCTBLOCK data ));
 void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos ));
 void j_rev_dct _ANSI_ARGS_((DCTBLOCK data ));
 
-/* block.c */
-void	BlockToData _ANSI_ARGS_((uint8 **data, Block block, int by, int bx));
-void	AddMotionBlock _ANSI_ARGS_((Block block, uint8 **prev, int by, int bx,
-		       int my, int mx));
diff --git a/converter/ppm/ppmtompeg/headers/parallel.h b/converter/ppm/ppmtompeg/headers/parallel.h
index 90edd874..cf27ce66 100644
--- a/converter/ppm/ppmtompeg/headers/parallel.h
+++ b/converter/ppm/ppmtompeg/headers/parallel.h
@@ -87,7 +87,7 @@ void
 NoteFrameDone(int frameStart, int frameEnd);
 
 void
-SetIOConvert(boolean const separate);
+SetIOConvert(bool const separate);
 
 void
 SetRemoteShell(const char * const shell);
diff --git a/converter/ppm/ppmtompeg/headers/prototypes.h b/converter/ppm/ppmtompeg/headers/prototypes.h
index a284888f..b421af35 100644
--- a/converter/ppm/ppmtompeg/headers/prototypes.h
+++ b/converter/ppm/ppmtompeg/headers/prototypes.h
@@ -44,33 +44,26 @@ void    ResetBFrameStats _ANSI_ARGS_((void));
 void    ResetPFrameStats _ANSI_ARGS_((void));
 void SetSearchRange (int const pixelsP,
                      int const pixelsB);
-void    ResetIFrameStats _ANSI_ARGS_((void));
 void
 SetPixelSearch(const char * const searchType);
-void    SetIQScale _ANSI_ARGS_((int const qI));
 void    SetPQScale _ANSI_ARGS_((int qP));
 void    SetBQScale _ANSI_ARGS_((int qB));
-float   EstimateSecondsPerIFrame _ANSI_ARGS_((void));
 float   EstimateSecondsPerPFrame _ANSI_ARGS_((void));
 float   EstimateSecondsPerBFrame _ANSI_ARGS_((void));
 void    SetGOPSize _ANSI_ARGS_((int size));
 void
 SetStatFileName(const char * const fileName);
-void    SetSlicesPerFrame _ANSI_ARGS_((int const number));
-void    SetBlocksPerSlice _ANSI_ARGS_((void));
 
 
 void DCTFrame _ANSI_ARGS_((MpegFrame * mf));
 
 void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf));
 
-void    MotionSearchPreComputation _ANSI_ARGS_((MpegFrame * const frame));
+void    MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame));
 
 void    ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame));
 void mp_validate_size _ANSI_ARGS_((int *x, int *y));
 
-extern void SetFCode _ANSI_ARGS_((void));
-
 
 /* psearch.c */
 void    ShowPMVHistogram _ANSI_ARGS_((FILE *fpointer));
diff --git a/converter/ppm/ppmtompeg/headers/subsample.h b/converter/ppm/ppmtompeg/headers/subsample.h
new file mode 100644
index 00000000..deedf251
--- /dev/null
+++ b/converter/ppm/ppmtompeg/headers/subsample.h
@@ -0,0 +1,39 @@
+#ifndef SUBSAMPLE_H_INCLUDED
+#define SUBSAMPLE_H_INCLUDED
+
+#include "frame.h"
+#include "mtypes.h"
+
+int32
+LumMotionErrorA(const LumBlock * const currentBlockP,
+                MpegFrame *      const prevFrame,
+                int              const by,
+                int              const bx,
+                vector           const m,
+                int32            const bestSoFar);
+
+int32
+LumMotionErrorB(const LumBlock * const currentP,
+                MpegFrame *      const prevFrame,
+                int              const by,
+                int              const bx,
+                vector           const m,
+                int32            const bestSoFar);
+
+int32
+LumMotionErrorC(const LumBlock * const currentP,
+                MpegFrame *      const prevFrame,
+                int              const by,
+                int              const bx,
+                vector           const m,
+                int32            const bestSoFar);
+
+int32
+LumMotionErrorD(const LumBlock * const currentP,
+                MpegFrame *      const prevFrame,
+                int              const by,
+                int              const bx,
+                vector           const m,
+                int32            const bestSoFar);
+
+#endif
diff --git a/converter/ppm/ppmtompeg/iframe.c b/converter/ppm/ppmtompeg/iframe.c
index f4d7665a..c6735505 100644
--- a/converter/ppm/ppmtompeg/iframe.c
+++ b/converter/ppm/ppmtompeg/iframe.c
@@ -11,10 +11,9 @@
  *  GetIQScale                               *
  *  ResetIFrameStats                             *
  *  ShowIFrameSummary                            *
- *  EstimateSecondsPerIFrame                         *
  *  EncodeYDC                                *
  *  EncodeCDC                                *
- *      time_elapsed                                                         *
+ *  time_elapsed                                                         *
  *                                       *
  *===========================================================================*/
 
@@ -67,6 +66,8 @@
 #include "specifics.h"
 #include "opts.h"
 
+#include "iframe.h"
+
 /*==================*
  * STATIC VARIABLES *
  *==================*/
@@ -128,24 +129,11 @@ int fCodeI, fCodeP, fCodeB;
 boolean printSNR = FALSE;
 boolean printMSE = FALSE;
 boolean decodeRefFrames = FALSE;
-Block **dct=NULL, **dctr=NULL, **dctb=NULL;
-dct_data_type   **dct_data; /* used in p/bframe.c */
 int  TIME_RATE;
 
 
-/*=====================*
- * EXPORTED PROCEDURES *
- *=====================*/
-extern void PrintItoIBitRate _ANSI_ARGS_((int const numBits, int const frameNum));
-
-/*===============================*
- * INTERNAL PROCEDURE prototypes *
- *===============================*/
-void AllocDctBlocks(void );
-int SetFCodeHelper (int const sr);
-void CalcDistortion (MpegFrame * const current, int const y, int const x);
 
-int
+static int
 SetFCodeHelper(int const SR) {
 
     int     range,fCode;
@@ -296,6 +284,68 @@ GetIQScale(void) {
 
 
 
+static void
+CalcDistortion(MpegFrame * const current,
+               int         const y,
+               int         const x) {
+
+    int qscale, distort=0;
+    Block decblk;
+    FlatBlock fblk;
+    int datarate = 0;
+  
+    for (qscale = 1; qscale < 32; qscale ++) {
+        distort = 0;
+        datarate = 0;
+        Mpost_QuantZigBlock(dct[y][x], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->y_blocks[y][x], decblk);
+
+        Mpost_QuantZigBlock(dct[y][x+1], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->y_blocks[y][x+1], decblk);
+
+        Mpost_QuantZigBlock(dct[y+1][x], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->y_blocks[y+1][x], decblk);
+
+        Mpost_QuantZigBlock(dct[y+1][x+1], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->y_blocks[y+1][x+1], decblk);
+
+        Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->cb_blocks[y>>1][x>>1], decblk);
+
+        Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->cr_blocks[y >> 1][x >> 1], decblk);
+
+        if (!collect_distortion_detailed) {
+            fprintf(distortion_fp, "\t%d\n", distort);
+        } else if (collect_distortion_detailed == 1) {
+            fprintf(distortion_fp, "\t%d\t%d\n", distort, datarate);
+        } else {
+            fprintf(fp_table_rate[qscale-1], "%d\n", datarate);
+            fprintf(fp_table_dist[qscale-1], "%d\n", distort);
+        }
+    }
+}
+
+
+
 /*===========================================================================*
  *
  * GenIFrame
@@ -618,24 +668,6 @@ ShowIFrameSummary(unsigned int const inputFrameBits,
 
 /*===========================================================================*
  *
- * EstimateSecondsPerIFrame
- *
- *  estimates the number of seconds required per I-frame
- *
- * RETURNS: seconds (floating point value)
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-float
-EstimateSecondsPerIFrame()
-{
-    return (float)totalTime/((float)TIME_RATE*(float)numFrames);
-}
-
-
-/*===========================================================================*
- *
  * EncodeYDC
  *
  *  Encode the DC portion of a DCT of a luminance block
@@ -926,53 +958,6 @@ PrintItoIBitRate(int const numBits,
 
 
 
-/*===========================================================================*
- *
- * AllocDctBlocks
- *
- *  allocate memory for dct blocks
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS:    creates dct, dctr, dctb
- *
- *===========================================================================*/
-void
-AllocDctBlocks(void) {
-    int dctx, dcty;
-    int i;
-
-    dctx = Fsize_x / DCTSIZE;
-    dcty = Fsize_y / DCTSIZE;
-
-    dct = (Block **) malloc(sizeof(Block *) * dcty);
-    ERRCHK(dct, "malloc");
-    for (i = 0; i < dcty; i++) {
-        dct[i] = (Block *) malloc(sizeof(Block) * dctx);
-        ERRCHK(dct[i], "malloc");
-    }
-
-    dct_data = (dct_data_type **) malloc(sizeof(dct_data_type *) * dcty);
-    ERRCHK(dct_data, "malloc");
-    for (i = 0; i < dcty; i++) {
-        dct_data[i] = (dct_data_type *) malloc(sizeof(dct_data_type) * dctx);
-        ERRCHK(dct[i], "malloc");
-    }
-
-    dctr = (Block **) malloc(sizeof(Block *) * (dcty >> 1));
-    dctb = (Block **) malloc(sizeof(Block *) * (dcty >> 1));
-    ERRCHK(dctr, "malloc");
-    ERRCHK(dctb, "malloc");
-    for (i = 0; i < (dcty >> 1); i++) {
-        dctr[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1));
-        dctb[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1));
-        ERRCHK(dctr[i], "malloc");
-        ERRCHK(dctb[i], "malloc");
-    }
-}
-
-
-
 /*======================================================================*
  *
  * time_elapsed
@@ -997,66 +982,4 @@ int32 time_elapsed(void) {
 
 
 
-void
-CalcDistortion(MpegFrame * const current,
-               int         const y,
-               int         const x) {
-
-    int qscale, distort=0;
-    Block decblk;
-    FlatBlock fblk;
-    int datarate = 0;
-  
-    for (qscale = 1; qscale < 32; qscale ++) {
-        distort = 0;
-        datarate = 0;
-        Mpost_QuantZigBlock(dct[y][x], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->y_blocks[y][x], decblk);
-
-        Mpost_QuantZigBlock(dct[y][x+1], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->y_blocks[y][x+1], decblk);
-
-        Mpost_QuantZigBlock(dct[y+1][x], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->y_blocks[y+1][x], decblk);
-
-        Mpost_QuantZigBlock(dct[y+1][x+1], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->y_blocks[y+1][x+1], decblk);
-
-        Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->cb_blocks[y>>1][x>>1], decblk);
-
-        Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->cr_blocks[y >> 1][x >> 1], decblk);
-
-        if (!collect_distortion_detailed) {
-            fprintf(distortion_fp, "\t%d\n", distort);
-        } else if (collect_distortion_detailed == 1) {
-            fprintf(distortion_fp, "\t%d\t%d\n", distort, datarate);
-        } else {
-            fprintf(fp_table_rate[qscale-1], "%d\n", datarate);
-            fprintf(fp_table_dist[qscale-1], "%d\n", distort);
-        }
-    }
-}
-
-
-
 
diff --git a/converter/ppm/ppmtompeg/jpeg.c b/converter/ppm/ppmtompeg/jpeg.c
index 3aad6364..a6e1eced 100644
--- a/converter/ppm/ppmtompeg/jpeg.c
+++ b/converter/ppm/ppmtompeg/jpeg.c
@@ -15,6 +15,7 @@
  * HEADER FILES *
  *==============*/
 #define _XOPEN_SOURCE    /* Make sure stdio.h contains fileno() */
+#include <unistd.h>
 #include <stdio.h>
 #include "all.h"
 /* With the lossless jpeg patch applied to the Jpeg library
diff --git a/converter/ppm/ppmtompeg/mheaders.c b/converter/ppm/ppmtompeg/mheaders.c
index 8a51c089..4cfe49ac 100644
--- a/converter/ppm/ppmtompeg/mheaders.c
+++ b/converter/ppm/ppmtompeg/mheaders.c
@@ -278,24 +278,350 @@ const double VidRateNum[9]={1.0, 23.976, 24.0, 25.0, 29.97, 30.0,
                              50.0 ,59.94, 60.0};
 
 
-/*===============================*
- * INTERNAL PROCEDURE prototypes *
- *===============================*/
-
-static void	GenMBAddrIncr _ANSI_ARGS_((BitBucket *bb, uint32 addr_incr));
-static void	GenPictHead _ANSI_ARGS_((BitBucket *bb, uint32 temp_ref,
-		    uint32 code_type, uint32 vbv_delay,
-		    int32 full_pel_forw_flag, uint32 forw_f_code,
-		    int32 full_pel_back_flag, uint32 back_f_code,
-		    uint8 *extra_info, uint32 extra_info_size,
-		    uint8 *ext_data, uint32 ext_data_size,
-		    uint8 *user_data, uint32 user_data_size));
-static void	GenMBType _ANSI_ARGS_((BitBucket *bb, uint32 pict_code_type,
-		  uint32 mb_quant, uint32 motion_forw, uint32 motion_back,
-		  uint32 mb_pattern, uint32 mb_intra));
-static void	GenMotionCode _ANSI_ARGS_((BitBucket * const bb, int32 const vector));
-static void	GenBlockPattern _ANSI_ARGS_((BitBucket *bb,
-					     uint32 mb_pattern));
+/*=====================*
+ * INTERNAL PROCEDURES *
+ *=====================*/
+
+/*===========================================================================*
+ *
+ * GenMBType
+ *
+ *	generate macroblock type with given attributes
+ *	append result to the specified bitstream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back,
+          mb_pattern, mb_intra)
+    BitBucket *bbPtr;
+    uint32 pict_code_type;
+    uint32 mb_quant;
+    uint32 motion_forw;
+    uint32 motion_back;
+    uint32 mb_pattern;
+    uint32 mb_intra;
+{
+    int code;
+
+    switch (pict_code_type) {
+    case 1:
+        if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) {
+            perror("Illegal parameters for macroblock type.");
+            exit(-1);
+        }
+        if (mb_quant) {
+            Bitio_Write(bbPtr, 0x1, 2);
+        } else {
+            Bitio_Write(bbPtr, 0x1, 1);
+        }
+        break;
+
+    case 2:
+        code = 0;
+        if (mb_quant) {
+            code += 16;
+        }
+        if (motion_forw) {
+            code += 8;
+        }
+        if (motion_back) {
+            code += 4;
+        }
+        if (mb_pattern) {
+            code += 2;
+        }
+        if (mb_intra) {
+            code += 1;
+        }
+
+        switch (code) {
+        case 1:
+            Bitio_Write(bbPtr, 0x3, 5);
+            break;
+        case 2:
+            Bitio_Write(bbPtr, 0x1, 2);
+            break;
+        case 8:
+            Bitio_Write(bbPtr, 0x1, 3);
+            break;
+        case 10:
+            Bitio_Write(bbPtr, 0x1, 1);
+            break;
+        case 17:
+            Bitio_Write(bbPtr, 0x1, 6);
+            break;
+        case 18:
+            Bitio_Write(bbPtr, 0x1, 5);
+            break;
+        case 26:
+            Bitio_Write(bbPtr, 0x2, 5);
+            break;
+        default:
+            perror("Illegal parameters for macroblock type.");
+            exit(-1);
+            break;
+        }
+        break;
+
+    case 3:
+        code = 0;
+        if (mb_quant) {
+            code += 16;
+        }
+        if (motion_forw) {
+            code += 8;
+        }
+        if (motion_back) {
+            code += 4;
+        }
+        if (mb_pattern) {
+            code += 2;
+        }
+        if (mb_intra) {
+            code += 1;
+        }
+
+        switch (code) {
+        case 12:
+            Bitio_Write(bbPtr, 0x2, 2);
+            break;
+        case 14:
+            Bitio_Write(bbPtr, 0x3, 2);
+            break;
+        case 4:
+            Bitio_Write(bbPtr, 0x2, 3);
+            break;
+        case 6:
+            Bitio_Write(bbPtr, 0x3, 3);
+            break;
+        case 8:
+            Bitio_Write(bbPtr, 0x2, 4);
+            break;
+        case 10:
+            Bitio_Write(bbPtr, 0x3, 4);
+            break;
+        case 1:
+            Bitio_Write(bbPtr, 0x3, 5);
+            break;
+        case 30:
+            Bitio_Write(bbPtr, 0x2, 5);
+            break;
+        case 26:
+            Bitio_Write(bbPtr, 0x3, 6);
+            break;
+        case 22:
+            Bitio_Write(bbPtr, 0x2, 6);
+            break;
+        case 17:
+            Bitio_Write(bbPtr, 0x1, 6);
+            break;
+        default:
+            perror("Illegal parameters for macroblock type.");
+            exit(-1);
+            break;
+        }
+        break;
+    }
+}
+
+
+/*===========================================================================*
+ *
+ * GenMotionCode
+ *
+ *	generate motion vector output with given value
+ *	append result to the specified bitstream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+GenMotionCode(BitBucket * const bbPtr,
+              int32       const vector) {
+
+    uint32 code, num;
+
+    if ((vector < -16) || (vector > 16)) {
+        perror("Motion vector out of range.");
+        fprintf(stderr, "Motion vector out of range:  vector = %d\n", vector);
+        exit(-1);
+    }
+    code = mbMotionVectorTable[vector + 16][0];
+    num = mbMotionVectorTable[vector + 16][1];
+
+    Bitio_Write(bbPtr, code, num);
+}
+
+
+/*===========================================================================*
+ *
+ * GenBlockPattern
+ *
+ *	generate macroblock pattern output
+ *	append result to the specified bitstream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+GenBlockPattern(bbPtr, mb_pattern)
+    BitBucket *bbPtr;
+    uint32 mb_pattern;
+{
+    uint32 code, num;
+
+    code = mbPatTable[mb_pattern][0];
+    num = mbPatTable[mb_pattern][1];
+
+    Bitio_Write(bbPtr, code, num);
+}
+
+
+/*===========================================================================*
+ *
+ * GenMBAddrIncr
+ *
+ *	generate macroblock address increment output
+ *	append result to the specified bitstream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+GenMBAddrIncr(bbPtr, addr_incr)
+    BitBucket *bbPtr;
+    uint32 addr_incr;
+{
+    uint32 code;
+    uint32 num;
+
+    code = mbAddrIncrTable[addr_incr][0];
+    num = mbAddrIncrTable[addr_incr][1];
+
+    Bitio_Write(bbPtr, code, num);
+}
+
+
+/*===========================================================================*
+ *
+ * GenPictHead
+ *
+ *	generate picture header with given attributes
+ *	append result to the specified bitstream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+GenPictHead(bbPtr, temp_ref, code_type, vbv_delay, full_pel_forw_flag,
+            forw_f_code, full_pel_back_flag, back_f_code, extra_info,
+            extra_info_size, ext_data, ext_data_size, user_data,
+            user_data_size)
+    BitBucket *bbPtr;
+    uint32 temp_ref;
+    uint32 code_type;
+    uint32 vbv_delay;
+    int32 full_pel_forw_flag;
+    uint32 forw_f_code;
+    int32 full_pel_back_flag;
+    uint32 back_f_code;
+    uint8 *extra_info;
+    uint32 extra_info_size;
+    uint8 *ext_data;
+    uint32 ext_data_size;
+    uint8 *user_data;
+    uint32 user_data_size;
+{
+    /* Write picture start code. */
+    Bitio_Write(bbPtr, PICT_START_CODE, 32);
+
+    /* Temp reference. */
+    Bitio_Write(bbPtr, temp_ref, 10);
+
+    /* Code_type. */
+    if (code_type == 0)
+        code_type = 1;
+
+    Bitio_Write(bbPtr, code_type, 3);
+
+    /* vbv_delay. */
+    vbv_delay = 0xffff;		    /* see page 36 (section 2.4.3.4) */
+    Bitio_Write(bbPtr, vbv_delay, 16);
+
+    if ((code_type == 2) || (code_type == 3)) {
+
+        /* Full pel forw flag. */
+
+        if (full_pel_forw_flag)
+            Bitio_Write(bbPtr, 0x01, 1);
+        else
+            Bitio_Write(bbPtr, 0x00, 1);
+
+        /* Forw f code. */
+
+        Bitio_Write(bbPtr, forw_f_code, 3);
+    }
+    if (code_type == 3) {
+
+        /* Full pel back flag. */
+
+        if (full_pel_back_flag)
+            Bitio_Write(bbPtr, 0x01, 1);
+        else
+            Bitio_Write(bbPtr, 0x00, 1);
+
+        /* Back f code. */
+
+        Bitio_Write(bbPtr, back_f_code, 3);
+    }
+    /* Extra bit picture info. */
+
+    if (extra_info != NULL) {
+        unsigned int i;
+        for (i = 0; i < extra_info_size; ++i) {
+            Bitio_Write(bbPtr, 0x01, 1);
+            Bitio_Write(bbPtr, extra_info[i], 8);
+        }
+    }
+    Bitio_Write(bbPtr, 0x00, 1);
+
+    /* next start code */
+    Bitio_BytePad(bbPtr);
+
+    /* Write ext data if present. */
+
+    if (ext_data != NULL) {
+        unsigned int i;
+
+        Bitio_Write(bbPtr, EXT_START_CODE, 32);
+
+        for (i = 0; i < ext_data_size; ++i)
+            Bitio_Write(bbPtr, ext_data[i], 8);
+        Bitio_BytePad(bbPtr);
+    }
+    /* Write user data if present. */
+    if (user_data != NULL) {
+        unsigned int i;
+        Bitio_Write(bbPtr, USER_START_CODE, 32);
+
+        for (i = 0; i < user_data_size; ++i)
+            Bitio_Write(bbPtr, user_data[i], 8);
+
+        Bitio_BytePad(bbPtr);
+    }
+}
 
 
 /*=====================*
@@ -767,7 +1093,8 @@ if ( addr_incr != 1 )
     }
 
     /* Generate mb type code. */
-    GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, mb_pattern, mb_intra);
+    GenMBType(bbPtr, pict_code_type, mb_quant,
+              motion_forw, motion_back, mb_pattern, mb_intra);
 
     /* MB quant. */
     if (mb_quant) {
@@ -831,353 +1158,6 @@ if ( addr_incr != 1 )
 }
 
 
-/*=====================*
- * INTERNAL PROCEDURES *
- *=====================*/
-
-/*===========================================================================*
- *
- * GenMBType
- *
- *	generate macroblock type with given attributes
- *	append result to the specified bitstream
- *
- * RETURNS:	nothing
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-static void
-GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back,
-	  mb_pattern, mb_intra)
-    BitBucket *bbPtr;
-    uint32 pict_code_type;
-    uint32 mb_quant;
-    uint32 motion_forw;
-    uint32 motion_back;
-    uint32 mb_pattern;
-    uint32 mb_intra;
-{
-    int code;
-
-    switch (pict_code_type) {
-    case 1:
-	if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) {
-	    perror("Illegal parameters for macroblock type.");
-	    exit(-1);
-	}
-	if (mb_quant) {
-	    Bitio_Write(bbPtr, 0x1, 2);
-	} else {
-	    Bitio_Write(bbPtr, 0x1, 1);
-	}
-	break;
-
-    case 2:
-	code = 0;
-	if (mb_quant) {
-	    code += 16;
-	}
-	if (motion_forw) {
-	    code += 8;
-	}
-	if (motion_back) {
-	    code += 4;
-	}
-	if (mb_pattern) {
-	    code += 2;
-	}
-	if (mb_intra) {
-	    code += 1;
-	}
-
-	switch (code) {
-	case 1:
-	    Bitio_Write(bbPtr, 0x3, 5);
-	    break;
-	case 2:
-	    Bitio_Write(bbPtr, 0x1, 2);
-	    break;
-	case 8:
-	    Bitio_Write(bbPtr, 0x1, 3);
-	    break;
-	case 10:
-	    Bitio_Write(bbPtr, 0x1, 1);
-	    break;
-	case 17:
-	    Bitio_Write(bbPtr, 0x1, 6);
-	    break;
-	case 18:
-	    Bitio_Write(bbPtr, 0x1, 5);
-	    break;
-	case 26:
-	    Bitio_Write(bbPtr, 0x2, 5);
-	    break;
-	default:
-	    perror("Illegal parameters for macroblock type.");
-	    exit(-1);
-	    break;
-	}
-	break;
-
-    case 3:
-	code = 0;
-	if (mb_quant) {
-	    code += 16;
-	}
-	if (motion_forw) {
-	    code += 8;
-	}
-	if (motion_back) {
-	    code += 4;
-	}
-	if (mb_pattern) {
-	    code += 2;
-	}
-	if (mb_intra) {
-	    code += 1;
-	}
-
-	switch (code) {
-	case 12:
-	    Bitio_Write(bbPtr, 0x2, 2);
-	    break;
-	case 14:
-	    Bitio_Write(bbPtr, 0x3, 2);
-	    break;
-	case 4:
-	    Bitio_Write(bbPtr, 0x2, 3);
-	    break;
-	case 6:
-	    Bitio_Write(bbPtr, 0x3, 3);
-	    break;
-	case 8:
-	    Bitio_Write(bbPtr, 0x2, 4);
-	    break;
-	case 10:
-	    Bitio_Write(bbPtr, 0x3, 4);
-	    break;
-	case 1:
-	    Bitio_Write(bbPtr, 0x3, 5);
-	    break;
-	case 30:
-	    Bitio_Write(bbPtr, 0x2, 5);
-	    break;
-	case 26:
-	    Bitio_Write(bbPtr, 0x3, 6);
-	    break;
-	case 22:
-	    Bitio_Write(bbPtr, 0x2, 6);
-	    break;
-	case 17:
-	    Bitio_Write(bbPtr, 0x1, 6);
-	    break;
-	default:
-	    perror("Illegal parameters for macroblock type.");
-	    exit(-1);
-	    break;
-	}
-	break;
-    }
-}
-
-
-/*===========================================================================*
- *
- * GenMotionCode
- *
- *	generate motion vector output with given value
- *	append result to the specified bitstream
- *
- * RETURNS:	nothing
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-static void
-GenMotionCode(BitBucket * const bbPtr,
-              int32       const vector) {
-
-    uint32 code, num;
-
-    if ((vector < -16) || (vector > 16)) {
-	perror("Motion vector out of range.");
-	fprintf(stderr, "Motion vector out of range:  vector = %d\n", vector);
-	exit(-1);
-    }
-    code = mbMotionVectorTable[vector + 16][0];
-    num = mbMotionVectorTable[vector + 16][1];
-
-    Bitio_Write(bbPtr, code, num);
-}
-
-
-/*===========================================================================*
- *
- * GenBlockPattern
- *
- *	generate macroblock pattern output
- *	append result to the specified bitstream
- *
- * RETURNS:	nothing
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-static void
-GenBlockPattern(bbPtr, mb_pattern)
-    BitBucket *bbPtr;
-    uint32 mb_pattern;
-{
-    uint32 code, num;
-
-    code = mbPatTable[mb_pattern][0];
-    num = mbPatTable[mb_pattern][1];
-
-    Bitio_Write(bbPtr, code, num);
-}
-
-
-/*===========================================================================*
- *
- * GenMBAddrIncr
- *
- *	generate macroblock address increment output
- *	append result to the specified bitstream
- *
- * RETURNS:	nothing
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-static void
-GenMBAddrIncr(bbPtr, addr_incr)
-    BitBucket *bbPtr;
-    uint32 addr_incr;
-{
-    uint32 code;
-    uint32 num;
-
-    code = mbAddrIncrTable[addr_incr][0];
-    num = mbAddrIncrTable[addr_incr][1];
-
-    Bitio_Write(bbPtr, code, num);
-}
-
-
-/*===========================================================================*
- *
- * GenPictHead
- *
- *	generate picture header with given attributes
- *	append result to the specified bitstream
- *
- * RETURNS:	nothing
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-static void
-GenPictHead(bbPtr, temp_ref, code_type, vbv_delay, full_pel_forw_flag,
-	    forw_f_code, full_pel_back_flag, back_f_code, extra_info,
-	    extra_info_size, ext_data, ext_data_size, user_data,
-	    user_data_size)
-    BitBucket *bbPtr;
-    uint32 temp_ref;
-    uint32 code_type;
-    uint32 vbv_delay;
-    int32 full_pel_forw_flag;
-    uint32 forw_f_code;
-    int32 full_pel_back_flag;
-    uint32 back_f_code;
-    uint8 *extra_info;
-    uint32 extra_info_size;
-    uint8 *ext_data;
-    uint32 ext_data_size;
-    uint8 *user_data;
-    uint32 user_data_size;
-{
-    int i;
-
-    /* Write picture start code. */
-    Bitio_Write(bbPtr, PICT_START_CODE, 32);
-
-    /* Temp reference. */
-    Bitio_Write(bbPtr, temp_ref, 10);
-
-    /* Code_type. */
-    if (code_type == 0) {
-	code_type = 1;
-    }
-    Bitio_Write(bbPtr, code_type, 3);
-
-    /* vbv_delay. */
-    vbv_delay = 0xffff;		    /* see page 36 (section 2.4.3.4) */
-    Bitio_Write(bbPtr, vbv_delay, 16);
-
-    if ((code_type == 2) || (code_type == 3)) {
-
-	/* Full pel forw flag. */
-
-	if (full_pel_forw_flag) {
-	    Bitio_Write(bbPtr, 0x01, 1);
-	} else {
-	    Bitio_Write(bbPtr, 0x00, 1);
-	}
-
-	/* Forw f code. */
-
-	Bitio_Write(bbPtr, forw_f_code, 3);
-    }
-    if (code_type == 3) {
-
-	/* Full pel back flag. */
-
-	if (full_pel_back_flag) {
-	    Bitio_Write(bbPtr, 0x01, 1);
-	} else {
-	    Bitio_Write(bbPtr, 0x00, 1);
-	}
-
-	/* Back f code. */
-
-	Bitio_Write(bbPtr, back_f_code, 3);
-    }
-    /* Extra bit picture info. */
-
-    if (extra_info != NULL) {
-	for (i = 0; i < extra_info_size; i++) {
-	    Bitio_Write(bbPtr, 0x01, 1);
-	    Bitio_Write(bbPtr, extra_info[i], 8);
-	}
-    }
-    Bitio_Write(bbPtr, 0x00, 1);
-
-    /* next start code */
-    Bitio_BytePad(bbPtr);
-
-    /* Write ext data if present. */
-
-    if (ext_data != NULL) {
-	Bitio_Write(bbPtr, EXT_START_CODE, 32);
-
-	for (i = 0; i < ext_data_size; i++) {
-	    Bitio_Write(bbPtr, ext_data[i], 8);
-	}
-	Bitio_BytePad(bbPtr);
-    }
-    /* Write user data if present. */
-    if (user_data != NULL) {
-	Bitio_Write(bbPtr, USER_START_CODE, 32);
-
-	for (i = 0; i < user_data_size; i++) {
-	    Bitio_Write(bbPtr, user_data[i], 8);
-	}
-	Bitio_BytePad(bbPtr);
-    }
-}
-
-
 #ifdef UNUSED_PROCEDURES
 
 /* GenMBEnd only used for `D` pictures. Shouldn't really ever be called. */
diff --git a/converter/ppm/ppmtompeg/mpeg.c b/converter/ppm/ppmtompeg/mpeg.c
index fafbb97a..de662e88 100644
--- a/converter/ppm/ppmtompeg/mpeg.c
+++ b/converter/ppm/ppmtompeg/mpeg.c
@@ -276,9 +276,8 @@ SetReferenceFrameType(const char * const type) {
 
 
 void
-SetBitRateFileName(fileName)
-    char *fileName;
-{
+SetBitRateFileName(const char * const fileName) {
+
     strcpy(bitRateFileName, fileName);
 }
 
@@ -318,7 +317,7 @@ finishFrameOutput(MpegFrame * const frameP,
 
 static void
 outputIFrame(MpegFrame * const frameP,
-             BitBucket * const bb,
+             BitBucket * const bbP,
              int         const realStart,
              int         const realEnd,
              MpegFrame * const pastRefFrameP,
@@ -326,7 +325,7 @@ outputIFrame(MpegFrame * const frameP,
       
     /* only start a new GOP with I */
     /* don't start GOP if only doing frames */
-    if ((!separateFiles) && (currentGOP >= gopSize)) {
+    if (!separateFiles && currentGOP >= gopSize) {
         boolean const closed = 
             (totalFramesSent == frameP->id || pastRefFrameP == NULL);
 
@@ -344,7 +343,7 @@ outputIFrame(MpegFrame * const frameP,
             }
       
             Mhead_GenSequenceHeader(
-                bb, Fsize_x, Fsize_y,
+                bbP, Fsize_x, Fsize_y,
                 /* pratio */    aspectRatio,
                 /* pict_rate */ frameRate, /* bit_rate */ bit_rate,
                 /* buf_size */  buf_size,  /* c_param_flag */ 1,
@@ -359,7 +358,7 @@ outputIFrame(MpegFrame * const frameP,
                        closed ? "YES" : "NO", frameP->id);
     
         ++num_gop;
-        Mhead_GenGOPHeader(bb,  /* drop_frame_flag */ 0,
+        Mhead_GenGOPHeader(bbP,  /* drop_frame_flag */ 0,
                            tc_hrs, tc_min, tc_sec, tc_pict,
                            closed, /* broken_link */ 0,
                            /* ext_data */ NULL, /* ext_data_size */ 0,
@@ -368,16 +367,16 @@ outputIFrame(MpegFrame * const frameP,
         if (pastRefFrameP == NULL)
             SetGOPStartTime(0);
         else
-            SetGOPStartTime(pastRefFrameP->id+1);
+            SetGOPStartTime(pastRefFrameP->id + 1);
     }
       
-    if ((frameP->id >= realStart) && (frameP->id <= realEnd))
-        GenIFrame(bb, frameP);
+    if (frameP->id >= realStart && frameP->id <= realEnd)
+        GenIFrame(bbP, frameP);
       
-    numI--;
+    --numI;
     timeMask &= 0x6;
       
-    currentGOP++;
+    ++currentGOP;
     IncrementTCTime();
 }
 
@@ -393,10 +392,10 @@ outputPFrame(MpegFrame * const frameP,
     if ((frameP->id >= realStart) && (frameP->id <= realEnd))
         GenPFrame(bbP, frameP, pastRefFrameP);
 
-    numP--;
+    --numP;
     timeMask &= 0x5;
     
-    currentGOP++;
+    ++currentGOP;
     IncrementTCTime();
 }
 
@@ -498,6 +497,9 @@ processBFrames(MpegFrame *          const pastRefFrameP,
 
    But do only those B frames whose frame numbers are within the range
    'realStart' through 'realEnd'.
+
+   Output the frames to the output stream 'wholeStreamBbP'.  If NULL,
+   output each frame to its own individual file instead.
 -----------------------------------------------------------------------------*/
     boolean const separateFiles = (wholeStreamBbP == NULL);
     unsigned int const firstBFrameNum = pastRefFrameP->id + 1;
@@ -551,7 +553,7 @@ processBFrames(MpegFrame *          const pastRefFrameP,
 
 static void
 processRefFrame(MpegFrame *    const frameP, 
-                BitBucket *    const bb_arg,
+                BitBucket *    const wholeStreamBbP,
                 int            const realStart,
                 int            const realEnd,
                 MpegFrame *    const pastRefFrameP,
@@ -564,26 +566,28 @@ processRefFrame(MpegFrame *    const frameP,
 
    But only if its frame number is within the range 'realStart'
    through 'realEnd'.
+
+   Output the frame to the output stream 'wholeStreamBbP'.  If NULL,
+   output it to its own individual file instead.
 -----------------------------------------------------------------------------*/
     if (frameP->id >= realStart && frameP->id <= realEnd) {
-        boolean separateFiles;
-        BitBucket * bb;
+        bool const separateFiles = (wholeStreamBbP == NULL);
   
-        separateFiles = (bb_arg == NULL);
+        BitBucket * bbP;
   
-        if ( separateFiles )
-            bb = bitioNew(outputFileName, frameP->id, remoteIO);
+        if (separateFiles)
+            bbP = bitioNew(outputFileName, frameP->id, remoteIO);
         else
-            bb = bb_arg;
+            bbP = wholeStreamBbP;
   
         /* first, output this reference frame */
         switch (frameP->type) {
         case TYPE_IFRAME:
-            outputIFrame(frameP, bb, realStart, realEnd, pastRefFrameP, 
+            outputIFrame(frameP, bbP, realStart, realEnd, pastRefFrameP, 
                          separateFiles);
             break;
         case TYPE_PFRAME:
-            outputPFrame(frameP, bb, realStart, realEnd, pastRefFrameP);
+            outputPFrame(frameP, bbP, realStart, realEnd, pastRefFrameP);
             ShowRemainingTime(childProcess);
             break;
         default:
@@ -593,7 +597,7 @@ processRefFrame(MpegFrame *    const frameP,
         
         ++(*framesOutputP);
         
-        finishFrameOutput(frameP, bb, separateFiles, referenceFrame,
+        finishFrameOutput(frameP, bbP, separateFiles, referenceFrame,
                           childProcess, remoteIO);
     }
 }
@@ -702,7 +706,7 @@ readAndSaveFrame(struct inputSource * const inputSourceP,
 static void
 doFirstFrameStuff(enum frameContext const context,
                   const char *      const userDataFileName,
-                  BitBucket *       const bb,
+                  BitBucket *       const bbP,
                   int               const fsize_x,
                   int               const fsize_y,
                   int               const aspectRatio,
@@ -713,8 +717,12 @@ doFirstFrameStuff(enum frameContext const context,
 /*----------------------------------------------------------------------------
    Do stuff we have to do after reading the first frame in a sequence
    of frames requested of GenMPEGStream().
+
+   *bbP is the output stream to which to write any header stuff we have
+   to write.  If 'context' is such that there is no header stuff to write,
+   then 'bbP' is irrelevant.
 -----------------------------------------------------------------------------*/
-    *inputFrameBitsP = 24*Fsize_x*Fsize_y;
+    *inputFrameBitsP = 24 * Fsize_x * Fsize_y;
     SetBlocksPerSlice();
           
     if (context == CONTEXT_WHOLESTREAM) {
@@ -722,7 +730,7 @@ doFirstFrameStuff(enum frameContext const context,
         char * userData;
         unsigned int userDataSize;
 
-        assert(bb != NULL);
+        assert(bbP != NULL);
 
         DBG_PRINT(("Generating sequence header\n"));
         if (bitstreamMode == FIXED_RATE) {
@@ -770,7 +778,7 @@ doFirstFrameStuff(enum frameContext const context,
             userDataSize = strlen(userData);
             strfree(userDataString);
         }
-        Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y,
+        Mhead_GenSequenceHeader(bbP, Fsize_x, Fsize_y,
                                 /* pratio */ aspectRatio,
                                 /* pict_rate */ frameRate, 
                                 /* bit_rate */ bit_rate,
@@ -990,13 +998,21 @@ doAFrame(unsigned int         const frameNumber,
          unsigned int *       const framesReadP,
          unsigned int *       const framesOutputP,
          bool *               const firstFrameDoneP,
-         BitBucket *          const bbP,
+         BitBucket *          const wholeStreamBbP,
          unsigned int *       const inputFrameBitsP,
          bool *               const endOfStreamP) {
 /*----------------------------------------------------------------------------
    *endOfStreamP returned means we were unable to do a frame because
    the input stream has ended.  In that case, none of the other outputs
    are valid.
+
+   Process an input frame.  This can involve writing its description
+   to the output stream, saving it for later use, and/or writing
+   descriptions of previously saved frames to the output stream
+   because we now have enough information to do so.
+
+   Output the frames to the output stream 'wholeStreamBbP'.  If NULL,
+   output each frame to its own individual file instead.
 -----------------------------------------------------------------------------*/
     char const frameType = FType_Type(frameNumber);
     
@@ -1026,21 +1042,21 @@ doAFrame(unsigned int         const frameNumber,
             *endOfStreamP = FALSE;
 
             if (!*firstFrameDoneP) {
-                doFirstFrameStuff(context, userDataFileName,
-                                  bbP, Fsize_x, Fsize_y, aspectRatio,
+                doFirstFrameStuff(context, userDataFileName, wholeStreamBbP,
+                                  Fsize_x, Fsize_y, aspectRatio,
                                   frameRate, qtable, niqtable, 
                                   inputFrameBitsP);
             
                 *firstFrameDoneP = TRUE;
             }
-            processRefFrame(frameP, bbP, frameStart, frameEnd,
+            processRefFrame(frameP, wholeStreamBbP, frameStart, frameEnd,
                             pastRefFrameP, childProcess, outputFileName, 
                             framesReadP, framesOutputP);
                 
             if (pastRefFrameP) {
                 processBFrames(pastRefFrameP, frameP, realStart, realEnd,
                                inputSourceP, remoteIO, childProcess, 
-                               &IOtime, bbP, outputFileName,
+                               &IOtime, wholeStreamBbP, outputFileName,
                                framesReadP, framesOutputP, &currentGOP);
             }
             if (pastRefFrameP != NULL)
@@ -1086,17 +1102,20 @@ GenMPEGStream(struct inputSource * const inputSourceP,
    we stop where the stream ends if that is before 'frameEnd'.
 
 -----------------------------------------------------------------------------*/
-    BitBucket * bbP;
+    BitBucket * streamBbP;
+        /* The output stream to which we write all the frames.  NULL
+           means the frames are going to individual frame files.
+        */
     unsigned int frameNumber;
     bool endOfStream;
     bool firstFrameDone;
     int numBits;
     unsigned int firstFrame, lastFrame;
-    /* Frame numbers of the first and last frames we look at.  This
-       could be more than the the frames we actually encode because
-       we may need context (i.e. to encode a B frame, we need the subsequent
-       I or P frame).
-    */
+        /* Frame numbers of the first and last frames we look at.
+           This could be more than the the frames we actually encode
+           because we may need context (i.e. to encode a B frame, we
+           need the subsequent I or P frame).
+        */
     unsigned int framesRead;
         /* Number of frames we have read; for statistical purposes */
     MpegFrame * pastRefFrameP;
@@ -1150,10 +1169,10 @@ GenMPEGStream(struct inputSource * const inputSourceP,
     if (showBitRatePerFrame)
         OpenBitRateFile();  /* May modify showBitRatePerFrame */
 
-    if (context == CONTEXT_WHOLESTREAM || context == CONTEXT_GOP)
-        bbP = Bitio_New(ofP);
+    if (context == CONTEXT_JUSTFRAMES)
+        streamBbP = NULL;
     else
-        bbP = NULL;
+        streamBbP = Bitio_New(ofP);
 
     initTCTime(firstFrame);
 
@@ -1171,7 +1190,7 @@ GenMPEGStream(struct inputSource * const inputSourceP,
                  frameStart, frameEnd, realStart, realEnd,
                  childProcess, outputFileName,
                  pastRefFrameP, &pastRefFrameP,
-                 &framesRead, &framesOutput, &firstFrameDone, bbP,
+                 &framesRead, &framesOutput, &firstFrameDone, streamBbP,
                  inputFrameBitsP, &endOfStream);
     }
     
@@ -1180,10 +1199,10 @@ GenMPEGStream(struct inputSource * const inputSourceP,
     
     /* SEQUENCE END CODE */
     if (context == CONTEXT_WHOLESTREAM)
-        Mhead_GenSequenceEnder(bbP);
+        Mhead_GenSequenceEnder(streamBbP);
     
-    if (context == CONTEXT_WHOLESTREAM)
-        numBits = bbP->cumulativeBits;
+    if (streamBbP)
+        numBits = streamBbP->cumulativeBits;
     else {
         /* What should the correct value be?  Most likely 1.  "numBits" is
            used below, so we need to make sure it's properly initialized 
@@ -1192,9 +1211,8 @@ GenMPEGStream(struct inputSource * const inputSourceP,
         numBits = 1;
     }
 
-    if (context != CONTEXT_JUSTFRAMES) {
-        Bitio_Flush(bbP);
-        bbP = NULL;
+    if (streamBbP) {
+        Bitio_Flush(streamBbP);
         fclose(ofP);
     }
     handleBitRate(realEnd, numBits, childProcess, showBitRatePerFrame);
diff --git a/converter/ppm/ppmtompeg/pframe.c b/converter/ppm/ppmtompeg/pframe.c
index e72fe5d6..de91e32c 100644
--- a/converter/ppm/ppmtompeg/pframe.c
+++ b/converter/ppm/ppmtompeg/pframe.c
@@ -60,8 +60,6 @@ static int32    totalTime = 0;
 static int      qscaleP;
 static float    totalSNR = 0.0;
 static float    totalPSNR = 0.0;
-extern Block    **dct, **dctr, **dctb;
-extern dct_data_type   **dct_data;
 
 /*=====================*
  * INTERNAL PROCEDURES *
diff --git a/converter/ppm/ppmtompeg/psearch.c b/converter/ppm/ppmtompeg/psearch.c
index aea1a29b..83c62d04 100644
--- a/converter/ppm/ppmtompeg/psearch.c
+++ b/converter/ppm/ppmtompeg/psearch.c
@@ -16,6 +16,8 @@
 #include "prototypes.h"
 #include "fsize.h"
 #include "param.h"
+#include "subsample.h"
+#include "block.h"
 
 
 /*==================*
diff --git a/converter/ppm/ppmtompeg/subsample.c b/converter/ppm/ppmtompeg/subsample.c
index 5ec71814..69401a1d 100644
--- a/converter/ppm/ppmtompeg/subsample.c
+++ b/converter/ppm/ppmtompeg/subsample.c
@@ -43,6 +43,7 @@
 #include "bitio.h"
 #include "prototypes.h"
 
+#include "subsample.h"
 
 
 static void
diff --git a/converter/ppm/ppmtopict.c b/converter/ppm/ppmtopict.c
index e2428fb6..22456857 100644
--- a/converter/ppm/ppmtopict.c
+++ b/converter/ppm/ppmtopict.c
@@ -282,15 +282,8 @@ int i;
 	(void) putc(i & 0xff, fd);
 }
 
-#if __STDC__
 static void
 putLong( FILE *fd, long i )
-#else /*__STDC__*/
-static void
-putLong(fd, i)
-FILE *fd;
-long i;
-#endif /*__STDC__*/
 {
 	(void) putc((int)((i >> 24) & 0xff), fd);
 	(void) putc(((int)(i >> 16) & 0xff), fd);
diff --git a/converter/ppm/sldtoppm.c b/converter/ppm/sldtoppm.c
index 6b51f291..e0760448 100644
--- a/converter/ppm/sldtoppm.c
+++ b/converter/ppm/sldtoppm.c
@@ -66,15 +66,9 @@ struct svector {
     struct spoint t;          /* To point */
 };
 
-static int extend ARGS((smallint ch));
-static int sli ARGS((void));
-static int slib ARGS((void));
-static void vscale ARGS((int *px, int *py));
-static void slider ARGS((void (*slvec) ARGS((struct svector *vec, int color)),
-                    void (*slflood) ARGS((struct spolygon *poly, int color)) ));
-static void slidefind ARGS((char *sname, int dironly, int ucasen));
-static void draw ARGS((struct svector *vec, int color));
-static void flood ARGS((struct spolygon *const poly, int const color));
+typedef void (slvecfn)(struct svector * vec, int color);
+typedef void (slfloodfn)(struct spolygon * poly, int color);
+
 
 static int ixdots, iydots;        /* Screen size in dots */
 static FILE *slfile;              /* Slide file descriptor */
@@ -104,21 +98,26 @@ static int adjust = FALSE;        /* Adjust to correct aspect ratio ? */
 static struct slhead slfrof;          /* Slide file header */
 static long xfac, yfac;           /* Aspect ratio scale factors */
 
-static int sdrawkcab;             /* Slide drawing kinematic conversion of
-                     ass-backwards data flag */
+static int sdrawkcab;
+    /* Slide drawing kinematic conversion of ass-backwards data flag */
+
+
 
 /*  EXTEND  --  Turn a smallint into an int with sign extension, whether
-        or not that happens automatically.  */
+    or not that happens automatically.
+*/
 
-static int extend(smallint ch)
-{
+static int
+extend(smallint ch) {
     return ((int) ((ch & 0x80) ? (ch | ~0xFF) : ch));
 }
 
+
+
 /*  SLI  --  Input word from slide file  */
 
-static int sli()
-{
+static int
+sli(void) {
     short wd;
 
     if (fread(&wd, sizeof wd, 1, slfile) != 1) {
@@ -131,10 +130,12 @@ static int sli()
     return wd;
 }
 
+
+
 /*  SLIB  --  Input byte from slide file  */
 
-static int slib()
-{
+static int 
+slib(void) {
     smallint ch = 0;
 
     if (fread(&ch, sizeof ch, 1, slfile) != 1) {
@@ -143,25 +144,171 @@ static int slib()
     return extend(ch);
 }
 
+
+
 /*  VSCALE -- scale screen coordinates for mismatched display.  */
 
-static void vscale(px, py)
-  int *px, *py;
-{
+static void
+vscale(int * const px,
+       int * const py) {
+
     *px = (((unsigned) *px) * xfac) >> 16;
     *py = (((unsigned) *py) * yfac) >> 16;
 }
 
+
+
+/*  SLIDEFIND  --  Find  a  slide  in  a  library  or,  if  DIRONLY is
+           nonzero, print a directory listing of the  library.
+           If  UCASEN  is nonzero, the requested slide name is
+           converted to upper case. */
+
+static void
+slidefind(const char * const sname,
+          bool         const dironly,
+          bool         const ucasen) {
+
+    char uname[32];
+    unsigned char libent[36];
+    long pos;
+
+    if (dironly)
+        pm_message("Slides in library:");
+    else {
+        int i;
+        const char * ip;
+        
+        ip = sname; /* initial value */
+        
+        for (i = 0; i < 31; i++) {
+            char ch = *ip++;
+            if (ch == EOS)
+                break;
+            if (ucasen && ISLOWER(ch))
+                ch = TOUPPER(ch);
+            uname[i] = ch;
+        }
+        uname[i] = EOS;
+    }
+    
+    /* Read slide library header and verify. */
+    
+    if ((fread(libent, 32, 1, slfile) != 1) ||
+        (!STREQ((char *)libent, "AutoCAD Slide Library 1.0\015\012\32"))) {
+        pm_error("not an AutoCAD slide library file.");
+    }
+    pos = 32;
+    
+    /* Search for a slide with the requested name. */
+    
+    while (TRUE) {
+        if ((fread(libent, 36, 1, slfile) != 1) ||
+            (strlen((char *)libent) == 0)) {
+            if (dironly) {
+                return;
+            }
+            pm_error("slide %s not in library.", sname);
+        }
+        pos += 36;
+        if (dironly) {
+            pm_message("  %s", libent);
+        } else if (STREQ((char *)libent, uname)) {
+            long dpos = (((((libent[35] << 8) | libent[34]) << 8) |
+                          libent[33]) << 8) | libent[32];
+            if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
+                dpos -= pos;
+        
+                while (dpos-- > 0)
+                    getc(slfile);
+            }
+            break;
+        }
+    }
+}
+
+
+
+/*  DRAW  --  Draw a vector in the given AutoCAD color.  */
+
+static slvecfn draw;
+
+static void
+draw(struct svector * vec,
+     int              color) {
+
+    pixel rgbcolor;
+
+    if (blither) {
+        pm_message("Vector (%d, %d) - (%d, %d)  Color %d",
+           vec->f.x, vec->f.y, vec->t.x, vec->t.y, color);
+    }
+    assert(vec->f.x >= 0 && vec->f.x < pixcols);
+    assert(vec->f.y >= 0 && vec->f.y < pixrows);
+    assert(vec->t.x >= 0 && vec->t.x < pixcols);
+    assert(vec->t.y >= 0 && vec->t.y < pixrows);
+    PPM_ASSIGN(rgbcolor,
+               acadcol[color][0], acadcol[color][1], acadcol[color][2]);
+    ppmd_line(pixels, pixcols, pixrows, pixmaxval,
+              vec->f.x, iydots - vec->f.y, vec->t.x, iydots - vec->t.y,
+              PPMD_NULLDRAWPROC,
+              (char *) &rgbcolor);
+}
+
+
+
+/*  FLOOD  --  Draw a filled polygon.  */
+
+static slfloodfn flood;
+
+static void
+flood(struct spolygon * const poly,
+      int               const color) {
+
+    unsigned int i;
+    struct fillobj * handle;
+    pixel rgbcolor;
+
+    handle = ppmd_fill_create();
+
+    if (blither) {
+        unsigned int i;
+        pm_message("Polygon: %d points, fill type %d, color %d",
+                   poly->npoints, poly->fill, color);
+        for (i = 0; i < poly->npoints; i++) {
+            pm_message("   Point %d:  (%d, %d)", i + 1,
+                       poly->pt[i].x, poly->pt[i].y);
+        }
+    }
+
+    PPM_ASSIGN(rgbcolor,
+               acadcol[color][0], acadcol[color][1], acadcol[color][2]);
+    for (i = 0; i < poly->npoints; i++) {
+        assert(poly->pt[i].x >= 0 && poly->pt[i].x < pixcols);
+        assert(poly->pt[i].y >= 0 && poly->pt[i].y < pixrows);
+        ppmd_line(pixels, pixcols, pixrows, pixmaxval,
+                  poly->pt[i].x, iydots - poly->pt[i].y, 
+                  poly->pt[(i + 1) % poly->npoints].x,
+                  iydots - poly->pt[(i + 1) % poly->npoints].y,
+                  ppmd_fill_drawproc, handle);
+    }
+    ppmd_fill(pixels, pixcols, pixrows, pixmaxval,
+              handle, PPMD_NULLDRAWPROC, (char *) &rgbcolor);
+    
+    ppmd_fill_destroy(handle);
+}
+
+
+
 /*  SLIDER  --  Read slide file.  This is called with the name of the
         file to be read and function pointers to the routines
         which process vectors and polygon fill requests
         respectively.
 */
 
-static void slider(slvec, slflood)
-  void (*slvec) ARGS((struct svector *vec, int color));
-  void (*slflood) ARGS((struct spolygon *poly, int color));
-{
+static void
+slider(slvecfn   slvec,
+       slfloodfn slflood) {
+
     int i, rescale;
     unsigned char ubfr[4];        /* Utility character buffer */
     int lx, ly;               /* Last x and y point */
@@ -174,14 +321,14 @@ static void slider(slvec, slflood)
     short rtest;              /* Value to test byte reversal */
     short btest = 0x1234;         /* Value to test byte-reversal */
     static struct slhead slhi =       /* Master slide header sample */
-        {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0};
+    {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0};
     int curcolor = 7;             /* Current vector color */
     pixel rgbcolor;           /* Pixel used to clear pixmap */
-
+    
     lx = ly = 32000;
-
+    
     /* Process the header of the slide file.  */
-
+    
     sdrawkcab = FALSE;            /* Initially guess byte order is OK */
     fread(slfrof.slh, 17, 1, slfile);
     fread(&slfrof.sntype, sizeof(char), 1, slfile);
@@ -194,48 +341,46 @@ static void slider(slvec, slflood)
 
     /* Verify that slide format is compatible with this program. */
 
-    if (STREQ(slfrof.slh, slhi.slh)) {
+    if (STREQ(slfrof.slh, slhi.slh))
         pm_error("this is not an AutoCAD slide file.");
-    }
 
     /* Verify that the number format and file level in the header  are
        compatible.  All slides written by versions of AutoCAD released
        since September of 1987 are compatible with this format.  */
 
-    if ((slfrof.sntype != slhi.sntype) || (slfrof.slevel != slhi.slevel)) {
+    if ((slfrof.sntype != slhi.sntype) || (slfrof.slevel != slhi.slevel))
         pm_error("incompatible slide file format");
-    }
 
     /* Build SDSAR value from long scaled version. */
-
+    
     ldsar = 0L;
-    for (i = 3; i >= 0; i--) {
-    ldsar = (ldsar << 8) | ubfr[i];
-    }
+    for (i = 3; i >= 0; --i)
+        ldsar = (ldsar << 8) | ubfr[i];
     slfrof.sdsar = ((double) ldsar) / 1E7;
-
+    
     /* Examine the byte order test value.   If it's backwards, set the
        byte-reversal flag and correct all of the values we've read  in
-       so far. */
+       so far.
+    */
 
     if (btest != rtest) {
-    sdrawkcab = TRUE;
+        sdrawkcab = TRUE;
 #define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8)
-    rshort(slfrof.sxdots);
-    rshort(slfrof.sydots);
-    rshort(slfrof.shwfill);
+        rshort(slfrof.sxdots);
+        rshort(slfrof.sydots);
+        rshort(slfrof.shwfill);
 #undef rshort
     }
-
+    
     /* Dump the header if we're blithering. */
 
     if (blither || info) {
         pm_message("Slide file type %d, level %d, hwfill type %d.",
-        slfrof.sntype, slfrof.slevel, slfrof.shwfill);
+                   slfrof.sntype, slfrof.slevel, slfrof.shwfill);
         pm_message("Original screen size %dx%d, aspect ratio %.3f.",
-        slfrof.sxdots + 1, slfrof.sydots + 1, slfrof.sdsar);
+                   slfrof.sxdots + 1, slfrof.sydots + 1, slfrof.sdsar);
         pm_message("Byte order is %s.",
-            sdrawkcab ? "being reversed" : "the same");
+                   sdrawkcab ? "being reversed" : "the same");
     }
 
     /* If the display aspect ratio indicates that the  pixels  on  the
@@ -246,405 +391,284 @@ static void slider(slvec, slflood)
        We  always  correct  the aspect ratio by adjusting the width of
        the image.  This guarantees that output from the SHADE command,
        which  is  essentially  scan-line  data written in vector form,
-       will not be corrupted. */
+       will not be corrupted.
+    */
 
     dsar = ((double) slfrof.sxdots) / slfrof.sydots;
     if (fabs(slfrof.sdsar - dsar) > 0.0001) {
-    if (adjust) {
-        ixdots = slfrof.sxdots * (slfrof.sdsar / dsar) + 0.5;
-        iydots = slfrof.sydots;
-        dsar = ((double) ixdots) / iydots;
+        if (adjust) {
+            ixdots = slfrof.sxdots * (slfrof.sdsar / dsar) + 0.5;
+            iydots = slfrof.sydots;
+            dsar = ((double) ixdots) / iydots;
+        } else {
+            pm_message("Warning - pixels on source screen were non-square.  "
+                       "Specifying -adjust will correct image width "
+                       "to compensate.");
+            ixdots = slfrof.sxdots;
+            iydots = slfrof.sydots;
+            dsar = slfrof.sdsar;
+        }
     } else {
-            pm_message("Warning - pixels on source screen were non-square.");
-            pm_message("          Specifying -adjust will correct image width to compensate.");
+        /* Source pixels were square. */
         ixdots = slfrof.sxdots;
         iydots = slfrof.sydots;
         dsar = slfrof.sdsar;
-    }
-    } else {
-    /* Source pixels were square. */
-    ixdots = slfrof.sxdots;
-    iydots = slfrof.sydots;
-    dsar = slfrof.sdsar;
-    adjust = FALSE;           /* Mark no adjustment needed */
+        adjust = FALSE;           /* Mark no adjustment needed */
     }
 
     /* If there's a uniform scale factor specified, apply it. */
 
     if (uscale > 0) {
-    ixdots = (ixdots * uscale) + 0.5;
-    iydots = (iydots * uscale) + 0.5;
+        ixdots = (ixdots * uscale) + 0.5;
+        iydots = (iydots * uscale) + 0.5;
     }
 
     /* If the image is to be stretched  to  a  given  width,  set  the
        output  image  sizes accordingly.  If only a height or width is
        given, scale the other direction proportionally to preserve the
-       aspect ratio. */
+       aspect ratio.
+    */
 
     if (sxsize > 0) {
-    if (sysize > 0) {
-        iydots = sysize - 1;
-    } else {
-        iydots = ((((long) iydots) * (sxsize - 1)) +
-              (iydots / 2)) / ixdots;
-    }
-    ixdots = sxsize - 1;
-    } else if (sysize > 0) {
-    if (sxsize > 0) {
+        if (sysize > 0) {
+            iydots = sysize - 1;
+        } else {
+            iydots = ((((long) iydots) * (sxsize - 1)) +
+                      (iydots / 2)) / ixdots;
+        }
         ixdots = sxsize - 1;
-    } else {
-        ixdots = ((((long) ixdots) * (sysize - 1)) +
-              (ixdots / 2)) / iydots;
-    }
-    iydots = sysize - 1;
+    } else if (sysize > 0) {
+        if (sxsize > 0) {
+            ixdots = sxsize - 1;
+        } else {
+            ixdots = ((((long) ixdots) * (sysize - 1)) +
+                      (ixdots / 2)) / iydots;
+        }
+        iydots = sysize - 1;
     }
-
+    
     if (adjust) {
-    pm_message(
+        pm_message(
             "Resized from %dx%d to %dx%d to correct pixel aspect ratio.",
-        slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1);
+            slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1);
     }
-
+    
     /* Allocate image buffer and clear it to black. */
-
+    
     pixels = ppm_allocarray(pixcols = ixdots + 1, pixrows = iydots + 1);
     PPM_ASSIGN(rgbcolor, 0, 0, 0);
     ppmd_filledrectangle(pixels, pixcols, pixrows, pixmaxval, 0, 0,
                          pixcols, pixrows, PPMD_NULLDRAWPROC,
                          (char *) &rgbcolor);
-
+    
     if ((rescale = slfrof.sxdots != ixdots ||
-    slfrof.sydots != iydots ||
-    slfrof.sdsar != dsar) != 0) {
-
+         slfrof.sydots != iydots ||
+         slfrof.sdsar != dsar) != 0) {
+        
         /* Rescale all coords. so they'll look (more or less)
-       right on this display.  */
-
-    xfac = (ixdots + 1) * 0x10000L;
-    xfac /= (long) (slfrof.sxdots + 1);
-    yfac = (iydots + 1) * 0x10000L;
-    yfac /= (long) (slfrof.sydots + 1);
-    if (dsar < slfrof.sdsar) {
-        yfac = yfac * dsar / slfrof.sdsar;
-       } else {
-        xfac = xfac * slfrof.sdsar / dsar;
-    }
+           right on this display.
+        */
+        
+        xfac = (ixdots + 1) * 0x10000L;
+        xfac /= (long) (slfrof.sxdots + 1);
+        yfac = (iydots + 1) * 0x10000L;
+        yfac /= (long) (slfrof.sydots + 1);
+        if (dsar < slfrof.sdsar) {
+            yfac = yfac * dsar / slfrof.sdsar;
+        } else {
+            xfac = xfac * slfrof.sdsar / dsar;
+        }
     }
 
     poly.npoints = 0;             /* No flood in progress. */
-
+    
     while ((cw = sli()) != 0xFC00) {
-    switch (cw & 0xFF00) {
+        switch (cw & 0xFF00) {
         case 0xFB00:          /*  Short vector compressed  */
-        vec.f.x = lx + extend(cw & 0xFF);
-        vec.f.y = ly + slib();
-        vec.t.x = lx + slib();
-        vec.t.y = ly + slib();
-        lx = vec.f.x;
-        ly = vec.f.y;
-        if (rescale) {
-            vscale(&vec.f.x, &vec.f.y);
-            vscale(&vec.t.x, &vec.t.y);
-        }
-        (*slvec)(&vec, curcolor);/* Draw vector on screen */
-        slx = vec.f.x;        /* Save scaled point */
-        sly = vec.f.y;
-        break;
-
+            vec.f.x = lx + extend(cw & 0xFF);
+            vec.f.y = ly + slib();
+            vec.t.x = lx + slib();
+            vec.t.y = ly + slib();
+            lx = vec.f.x;
+            ly = vec.f.y;
+            if (rescale) {
+                vscale(&vec.f.x, &vec.f.y);
+                vscale(&vec.t.x, &vec.t.y);
+            }
+            (*slvec)(&vec, curcolor);/* Draw vector on screen */
+            slx = vec.f.x;        /* Save scaled point */
+            sly = vec.f.y;
+            break;
+            
         case 0xFC00:          /*  End of file  */
-        break;
-
+            break;
+            
         case 0xFD00:          /*  Flood command  */
-        vec.f.x = sli();
-        vec.f.y = sli();
-        if ((int) vec.f.y < 0) { /* start or end */
-            if (poly.npoints != 0) { /* end?  */
-            if (poly.npoints > 2 && poly.npoints < 11) {
-                (*slflood)(&poly, curcolor);
-            } else {
-                            pm_error("Bad polygon vertex count (%d)",
-                   poly.npoints);
-            }
-            poly.npoints = 0;
-            } else {
-            poly.fill = -vec.f.y;  /* Start */
+            vec.f.x = sli();
+            vec.f.y = sli();
+            if ((int) vec.f.y < 0) { /* start or end */
+                if (poly.npoints != 0) { /* end?  */
+                    if (poly.npoints > 2 && poly.npoints < 11) {
+                        (*slflood)(&poly, curcolor);
+                    } else {
+                        pm_error("Bad polygon vertex count (%d)",
+                                 poly.npoints);
+                    }
+                    poly.npoints = 0;
+                } else {
+                    poly.fill = -vec.f.y;  /* Start */
+                }
+            } else {          /* Polygon vertex */
+                if (poly.npoints < 10) {
+                    if (rescale) {
+                        vscale(&vec.f.x, &vec.f.y);
+                    }
+                    poly.pt[poly.npoints].x = vec.f.x;
+                    poly.pt[poly.npoints].y = vec.f.y;
+                }
+                poly.npoints++;
             }
-        } else {          /* Polygon vertex */
-            if (poly.npoints < 10) {
+            break;
+            
+        case 0xFE00:          /*  Common endpoint compressed  */
+            vec.f.x = lx + extend(cw & 0xFF);
+            vec.f.y = ly + slib();
+            lx = vec.f.x;
+            ly = vec.f.y;
+            vec.t.x = slx;
+            vec.t.y = sly;
             if (rescale) {
                 vscale(&vec.f.x, &vec.f.y);
             }
-            poly.pt[poly.npoints].x = vec.f.x;
-            poly.pt[poly.npoints].y = vec.f.y;
-            }
-            poly.npoints++;
-        }
-        break;
-
-        case 0xFE00:          /*  Common endpoint compressed  */
-        vec.f.x = lx + extend(cw & 0xFF);
-        vec.f.y = ly + slib();
-        lx = vec.f.x;
-        ly = vec.f.y;
-        vec.t.x = slx;
-        vec.t.y = sly;
-        if (rescale) {
-            vscale(&vec.f.x, &vec.f.y);
-        }
-        (*slvec)(&vec, curcolor);/* Draw vector */
-        slx = vec.f.x;        /* Save scaled point */
-        sly = vec.f.y;
-        break;
-
+            (*slvec)(&vec, curcolor);/* Draw vector */
+            slx = vec.f.x;        /* Save scaled point */
+            sly = vec.f.y;
+            break;
+            
         case 0xFF00:          /*  Change color  */
-        curcolor = cw & 0xFF;
-        break;
+            curcolor = cw & 0xFF;
+            break;
 
         default:              /*  Co-ordinates  */
-        lx = vec.f.x = cw;
-        ly = vec.f.y = sli();
-        vec.t.x = sli();
-        vec.t.y = sli();
-        if (rescale) {
-           vscale(&vec.f.x, &vec.f.y);
-           vscale(&vec.t.x, &vec.t.y);
-        }
-        (*slvec)(&vec, curcolor);
-        slx = vec.f.x;        /* Save scaled point */
-        sly = vec.f.y;
-        break;
-    }
-    }
-}
-
-/*  SLIDEFIND  --  Find  a  slide  in  a  library  or,  if  DIRONLY is
-           nonzero, print a directory listing of the  library.
-           If  UCASEN  is nonzero, the requested slide name is
-           converted to upper case. */
-
-static void slidefind(sname, dironly, ucasen)
-  char *sname;
-  int dironly, ucasen;
-{
-    char uname[32];
-    unsigned char libent[36];
-    long pos;
-
-    if (dironly) {
-        pm_message("Slides in library:");
-    } else {
-    int i;
-    char *ip = sname;
-
-    for (i = 0; i < 31; i++) {
-        char ch = *ip++;
-        if (ch == EOS) {
-        break;
-        }
-        if (ucasen && ISLOWER(ch)) {
-        ch = TOUPPER(ch);
-        }
-        uname[i] = ch;
-    }
-    uname[i] = EOS;
-    }
-
-    /* Read slide library header and verify. */
-
-    if ((fread(libent, 32, 1, slfile) != 1) ||
-        (!STREQ((char *)libent, "AutoCAD Slide Library 1.0\015\012\32"))) {
-        pm_error("not an AutoCAD slide library file.");
-    }
-    pos = 32;
-
-    /* Search for a slide with the requested name. */
-
-    while (TRUE) {
-    if ((fread(libent, 36, 1, slfile) != 1) ||
-        (strlen((char *)libent) == 0)) {
-        if (dironly) {
-        return;
-        }
-            pm_error("slide %s not in library.", sname);
-    }
-    pos += 36;
-    if (dironly) {
-            pm_message("  %s", libent);
-    } else if (STREQ((char *)libent, uname)) {
-        long dpos = (((((libent[35] << 8) | libent[34]) << 8) |
-                 libent[33]) << 8) | libent[32];
-        if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
-        dpos -= pos;
-
-        while (dpos-- > 0) {
-            (void) getc(slfile);
-        }
+            lx = vec.f.x = cw;
+            ly = vec.f.y = sli();
+            vec.t.x = sli();
+            vec.t.y = sli();
+            if (rescale) {
+                vscale(&vec.f.x, &vec.f.y);
+                vscale(&vec.t.x, &vec.t.y);
+            }
+            (*slvec)(&vec, curcolor);
+            slx = vec.f.x;        /* Save scaled point */
+            sly = vec.f.y;
+            break;
         }
-        break;
-    }
     }
 }
 
-/*  DRAW  --  Draw a vector in the given AutoCAD color.  */
 
-static void draw(vec, color)
-  struct svector *vec;
-  int color;
-{
-    pixel rgbcolor;
-
-    if (blither) {
-        pm_message("Vector (%d, %d) - (%d, %d)  Color %d",
-           vec->f.x, vec->f.y, vec->t.x, vec->t.y, color);
-    }
-    assert(vec->f.x >= 0 && vec->f.x < pixcols);
-    assert(vec->f.y >= 0 && vec->f.y < pixrows);
-    assert(vec->t.x >= 0 && vec->t.x < pixcols);
-    assert(vec->t.y >= 0 && vec->t.y < pixrows);
-    PPM_ASSIGN(rgbcolor,
-           acadcol[color][0], acadcol[color][1], acadcol[color][2]);
-    ppmd_line(pixels, pixcols, pixrows, pixmaxval,
-          vec->f.x, iydots - vec->f.y, vec->t.x, iydots - vec->t.y,
-          PPMD_NULLDRAWPROC,
-          (char *) &rgbcolor);
-}
-
-/*  FLOOD  --  Draw a filled polygon.  */
-
-static void
-flood(struct spolygon * const poly,
-      int               const color) {
-
-    int i;
-    struct fillobj * handle;
-    pixel rgbcolor;
-
-    handle = ppmd_fill_create();
-
-    if (blither) {
-        pm_message("Polygon: %d points, fill type %d, color %d",
-                   poly->npoints, poly->fill, color);
-        for (i = 0; i < poly->npoints; i++) {
-            pm_message("   Point %d:  (%d, %d)", i + 1,
-                       poly->pt[i].x, poly->pt[i].y);
-        }
-    }
-
-    PPM_ASSIGN(rgbcolor,
-               acadcol[color][0], acadcol[color][1], acadcol[color][2]);
-    for (i = 0; i < poly->npoints; i++) {
-        assert(poly->pt[i].x >= 0 && poly->pt[i].x < pixcols);
-        assert(poly->pt[i].y >= 0 && poly->pt[i].y < pixrows);
-        ppmd_line(pixels, pixcols, pixrows, pixmaxval,
-                  poly->pt[i].x, iydots - poly->pt[i].y, 
-                  poly->pt[(i + 1) % poly->npoints].x,
-                  iydots - poly->pt[(i + 1) % poly->npoints].y,
-                  ppmd_fill_drawproc, handle);
-    }
-    ppmd_fill(pixels, pixcols, pixrows, pixmaxval,
-              handle, PPMD_NULLDRAWPROC, (char *) &rgbcolor);
-
-    ppmd_fill_destroy(handle);
-}
 
 /*  Main program. */
 
-int main(argc, argv)
-  int argc;
-  char *argv[];
-{
+int
+main(int    argc,
+     char * argv[]) {
+
     int argn;
     const char * const usage = "[-verbose] [-info] [-adjust] [-scale <s>]\n\
-                 [-dir] [-lib|-Lib <name>]\n\
-                 [-xsize|-width <x>] [-ysize|-height <y>] [sldfile]";
+[-dir] [-lib|-Lib <name>]\n\
+[-xsize|-width <x>] [-ysize|-height <y>] [sldfile]";
     int scalespec = FALSE, widspec = FALSE, hgtspec = FALSE, dironly = FALSE,
-    ucasen;
-    char *slobber = (char *) 0;       /* Slide library item */
+        ucasen;
+    const char * slobber;       /* Slide library item */
 
 
+    slobber = NULL;
+
     ppm_init(&argc, argv);
     argn = 1;
 
     while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
         if (pm_keymatch(argv[argn], "-verbose", 2)) {
-        blither = TRUE;
+            blither = TRUE;
         } else if (pm_keymatch(argv[argn], "-adjust", 2)) {
-        adjust = TRUE;
+            adjust = TRUE;
         } else if (pm_keymatch(argv[argn], "-dir", 2)) {
-        dironly = TRUE;
+            dironly = TRUE;
         } else if (pm_keymatch(argv[argn], "-info", 2)) {
-        info = TRUE;
+            info = TRUE;
         } else if (pm_keymatch(argv[argn], "-lib", 2)) {
-        if (slobber != (char *) 0) {
+            if (slobber)
                 pm_error("already specified a library item");
-        }
             ucasen = argv[argn][1] != 'L';
-        argn++;
-        if (argn == argc) {
-        pm_usage(usage);
-        }
-        slobber = argv[argn];
+            argn++;
+            if (argn == argc) {
+                pm_usage(usage);
+            }
+            slobber = argv[argn];
         } else if (pm_keymatch(argv[argn], "-scale", 2)) {
-        if (scalespec) {
+            if (scalespec) {
                 pm_error("already specified a scale factor");
-        }
-        argn++;
+            }
+            argn++;
             if ((argn == argc) || (sscanf(argv[argn], "%lf", &uscale) != 1))
-        pm_usage(usage);
-        if (uscale <= 0.0) {
+                pm_usage(usage);
+            if (uscale <= 0.0) {
                 pm_error("scale factor must be greater than 0");
-        }
-        scalespec = TRUE;
+            }
+            scalespec = TRUE;
         } else if (pm_keymatch(argv[argn], "-xsize", 2) ||
                    pm_keymatch(argv[argn], "-width", 2)) {
-        if (widspec) {
+            if (widspec) {
                 pm_error("already specified a width/xsize");
-        }
-        argn++;
+            }
+            argn++;
             if ((argn == argc) || (sscanf(argv[argn], "%d", &sxsize) != 1))
-        pm_usage(usage);
-        widspec = TRUE;
+                pm_usage(usage);
+            widspec = TRUE;
         } else if (pm_keymatch(argv[argn], "-ysize", 2) ||
                    pm_keymatch(argv[argn], "-height", 2)) {
-        if (hgtspec) {
+            if (hgtspec) {
                 pm_error("already specified a height/ysize");
+            }
+            argn++;
+            if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1))
+                pm_usage(usage);
+            hgtspec = TRUE;
+        } else {
+            pm_usage(usage);
         }
         argn++;
-            if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1))
-        pm_usage(usage);
-        hgtspec = TRUE;
-    } else {
-        pm_usage(usage);
-    }
-    argn++;
     }
 
     /* If a file name is specified, open it.  Otherwise read from
-       standard input. */
+       standard input. 
+    */
 
     if (argn < argc) {
-    slfile = pm_openr(argv[argn]);
-    argn++;
+        slfile = pm_openr(argv[argn]);
+        argn++;
     } else {
-    slfile = stdin;
+        slfile = stdin;
     }
-
+    
     if (argn != argc) {           /* Extra bogus arguments ? */
-    pm_usage(usage);
+        pm_usage(usage);
     }
-
+    
     /* If we're extracting an item from a slide library, position the
-       input stream to the start of the chosen slide. */
-
-    if (dironly || (slobber != (char *) 0)) {
-    slidefind(slobber, dironly, ucasen);
-    }
-
+       input stream to the start of the chosen slide.
+    */
+ 
+    if (dironly || slobber)
+        slidefind(slobber, dironly, ucasen);
+ 
     if (!dironly) {
-    slider(draw, flood);
-    ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE);
+        slider(draw, flood);
+        ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE);
     }
     pm_close(slfile);
     pm_close(stdout);
-    exit(0);
+    
+    return 0;
 }
diff --git a/converter/ppm/spctoppm.c b/converter/ppm/spctoppm.c
index 3eea7821..d2a48187 100644
--- a/converter/ppm/spctoppm.c
+++ b/converter/ppm/spctoppm.c
@@ -165,15 +165,8 @@ DoBitmap( ifp )
 	sscreen[i] = ( screen[i<<1] << 8 ) + ( 0xff & screen[(i<<1)+1] );
     }
 
-#if __STDC__
 static void
 DoChar( int n, char c )
-#else /*__STDC__*/
-static void
-DoChar( n, c )
-    int n;
-    char c;
-#endif /*__STDC__*/
     {
     int i;