about summary refs log tree commit diff
path: root/converter/ppm
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm')
-rw-r--r--converter/ppm/ilbmtoppm.c446
-rw-r--r--converter/ppm/mitsu.h1
-rw-r--r--converter/ppm/picttoppm.c632
-rw-r--r--converter/ppm/ppmtomitsu.c143
-rw-r--r--converter/ppm/ppmtomitsu.test4
-rw-r--r--converter/ppm/ppmtopict.c4
6 files changed, 762 insertions, 468 deletions
diff --git a/converter/ppm/ilbmtoppm.c b/converter/ppm/ilbmtoppm.c
index d140d088..0c365834 100644
--- a/converter/ppm/ilbmtoppm.c
+++ b/converter/ppm/ilbmtoppm.c
@@ -1,4 +1,4 @@
-/* ilbmtoppm.c - read an IFF ILBM file and produce a portable pixmap
+/* ilbmtoppm.c - read an IFF ILBM file and produce a PPM
 **
 ** Copyright (C) 1989 by Jef Poskanzer.
 **
@@ -43,11 +43,10 @@
 #include <string.h>
 
 #include "pm_c_util.h"
-#include "ppm.h"
-#include "ilbm.h"
 #include "mallocvar.h"
-
-/*#define DEBUG*/
+#include "intcode.h"
+#include "ilbm.h"
+#include "ppm.h"
 
 typedef struct {
     int reg;            /* color register to change */
@@ -765,10 +764,15 @@ multi_free(cmap)
  ****************************************************************************/
 
 static void
-check_cmap(bmhd, cmap)
-    BitMapHeader *bmhd;
-    ColorMap *cmap;
-{
+prepareCmap(const BitMapHeader * const bmhd,
+            ColorMap *           const cmap) {
+/*----------------------------------------------------------------------------
+   This is a really ugly subroutine that 1) analyzes a colormap and its
+   context (returning the analysis in global variables); and 2) modifies that
+   color map, because it's really one type of data structure as input and
+   another as output.
+
+-----------------------------------------------------------------------------*/
     pixval colmaxval = 0;
     int shifted = 1;
     int i, r, g, b;
@@ -987,6 +991,8 @@ std_to_ppm(FILE *         const ifp,
            ColorMap *     const cmap, 
            long           const viewportmodes);
 
+
+
 static void
 ham_to_ppm(FILE *         const ifp, 
            long           const chunksize, 
@@ -1342,16 +1348,10 @@ dcol_to_ppm(FILE *         const ifP,
 
 
 static void
-cmap_to_ppm(cmap)
-    ColorMap *cmap;
-{
-    ppm_colorrowtomapfile(stdout, cmap->color, cmap->ncolors, MAXCOLVAL);
-#if 0
-    int i;
-    ppm_writeppminit(stdout, cmap->ncolors, 1, MAXCOLVAL, 1);
-    for( i = 0; i < cmap->ncolors; i++ )
-        ppm_writeppmrow(stdout, &(cmap->color[i]), 1, MAXCOLVAL, 1);
-#endif
+cmapToPpm(FILE *     const ofP,
+            ColorMap * const cmapP) {
+
+    ppm_colorrowtomapfile(ofP, cmapP->color, cmapP->ncolors, MAXCOLVAL);
 }
 
 
@@ -1656,39 +1656,41 @@ PCHG_DecompHuff(src, dest, tree, origsize)
 }
 
 
+
 static void
-PCHG_Decompress(PCHG, CompHdr, compdata, compsize, comptree, data)
-    PCHGHeader *PCHG;
-    PCHGCompHeader *CompHdr;
-    unsigned char *compdata;
-    unsigned long compsize;
-    unsigned char *comptree;
-    unsigned char *data;
-{
-    short *hufftree;
-    unsigned long huffsize, i;
-    unsigned long treesize = CompHdr->CompInfoSize;
+PCHG_Decompress(PCHGHeader *     const PCHG,
+                PCHGCompHeader * const CompHdr,
+                unsigned char *  const compdata,
+                unsigned long    const compsize,
+                unsigned char *  const comptree,
+                unsigned char *  const data) {
 
-    switch( PCHG->Compression ) {
-        case PCHG_COMP_HUFFMAN:
+    switch(PCHG->Compression) {
+    case PCHG_COMP_HUFFMAN: {
+        unsigned long const treesize = CompHdr->CompInfoSize;
+        unsigned long const huffsize = treesize / 2;
+        const bigend16 * const bigendComptree = (const void *)comptree;
 
-#ifdef DEBUG
-            pm_message("PCHG Huffman compression");
-#endif
-            /* turn big-endian 2-byte shorts into native format */
-            huffsize = treesize/2;
-            MALLOCARRAY_NOFAIL(hufftree, huffsize);
-            for( i = 0; i < huffsize; i++ ) {
-                hufftree[i] = (short)BIG_WORD(comptree);
-                comptree += 2;
-            }
+        short * hufftree;
+        unsigned long i;
 
-            /* decompress the change structure data */
-            PCHG_DecompHuff(compdata, data, &hufftree[huffsize-1], 
-                            CompHdr->OriginalDataSize);
+        /* Convert big-endian 2-byte shorts to C shorts */
 
-            free(hufftree);
-            break;
+        MALLOCARRAY(hufftree, huffsize);
+
+        if (!hufftree)
+            pm_error("Couldn't get memory for %lu-byte Huffman tree",
+                     huffsize);
+
+        for (i = 0; i < huffsize; ++i)
+            hufftree[i] = pm_uintFromBigend16(bigendComptree[i]);
+
+        /* decompress the change structure data */
+        PCHG_DecompHuff(compdata, data, &hufftree[huffsize-1], 
+                        CompHdr->OriginalDataSize);
+        
+        free(hufftree);
+    } break;
         default:
             pm_error("unknown PCHG compression type %d", PCHG->Compression);
     }
@@ -1797,94 +1799,119 @@ fail2:
 }
 
 
+
 static void
-PCHG_ConvertBig(PCHG, cmap, mask, datasize)
-    PCHGHeader *PCHG;
-    ColorMap *cmap;
-    unsigned char *mask;
-    unsigned long datasize;
-{
-    unsigned char *data;
+PCHG_ConvertBig(PCHGHeader *    const PCHG,
+                ColorMap *      const cmap,
+                unsigned char * const maskStart,
+                unsigned long   const datasize) {
+
+    unsigned char * data;
     unsigned char thismask;
-    int bits, row, i, changes, masklen, reg;
-    unsigned long totalchanges = 0;
-    int changedlines = PCHG->ChangedLines;
+    int bits;
+    unsigned int row;
+    int changes;
+    int masklen;
+    int reg;
+    unsigned long totalchanges;
+    int changedlines;
+    unsigned long dataRemaining;
+    unsigned char * mask;
+
+    mask = maskStart;  /* initial value */
+    dataRemaining = datasize;  /* initial value */
+    changedlines = PCHG->ChangedLines;  /* initial value */
+    totalchanges = 0;  /* initial value */
 
     masklen = 4 * MaskLongWords(PCHG->LineCount);
-    data = mask + masklen; datasize -= masklen;
+    data = mask + masklen; dataRemaining -= masklen;
 
-    bits = 0;
-    for( row = PCHG->StartLine; changedlines && row < 0; row++ ) {
-        if( bits == 0 ) {
-            if( masklen == 0 ) goto fail2;
+    for (row = PCHG->StartLine, bits = 0; changedlines && row < 0; ++row) {
+        if (bits == 0) {
+            if (masklen == 0)
+                pm_error("insufficient data in line mask");
             thismask = *mask++;
             --masklen;
             bits = 8;
         }
-        if( thismask & (1<<7) ) {
-            if( datasize < 2 ) goto fail;
-            changes = BIG_WORD(data); data += 2; datasize -= 2;
+        if (thismask & (1<<7)) {
+            unsigned int i;
+
+            if (dataRemaining < 2)
+                pm_error("insufficient data in BigLineChanges structures");
+
+            changes = BIG_WORD(data); data += 2; dataRemaining -= 2;
+
+            for (i = 0; i < changes; ++i) {
+                if (totalchanges >= PCHG->TotalChanges)
+                    pm_error("insufficient data in BigLineChanges structures");
+
+                if (dataRemaining < 6)
+                    pm_error("insufficient data in BigLineChanges structures");
 
-            for( i = 0; i < changes; i++ ) {
-                if( totalchanges >= PCHG->TotalChanges ) goto fail;
-                if( datasize < 6 ) goto fail;
                 reg = BIG_WORD(data); data += 2;
                 cmap->mp_init[reg - PCHG->MinReg].reg = reg;
                 ++data; /* skip alpha */
                 cmap->mp_init[reg - PCHG->MinReg].r = *data++;
                 cmap->mp_init[reg - PCHG->MinReg].b = *data++;  /* yes, RBG */
                 cmap->mp_init[reg - PCHG->MinReg].g = *data++;
-                datasize -= 6;
+                dataRemaining -= 6;
                 ++totalchanges;
             }
             --changedlines;
         }
         thismask <<= 1;
-        bits--;
+        --bits;
     }
 
-    for( row = PCHG->StartLine; changedlines && row < cmap->mp_rows; row++ ) {
-        if( bits == 0 ) {
-            if( masklen == 0 ) goto fail2;
+    for (row = PCHG->StartLine; changedlines && row < cmap->mp_rows; ++row) {
+        if (bits == 0) {
+            if (masklen == 0)
+                pm_error("insufficient data in line mask");
+
             thismask = *mask++;
             --masklen;
             bits = 8;
         }
-        if( thismask & (1<<7) ) {
-            if( datasize < 2 ) goto fail;
-            changes = BIG_WORD(data); data += 2; datasize -= 2;
+        if (thismask & (1<<7)) {
+            unsigned int i;
+
+            if (dataRemaining < 2)
+                pm_error("insufficient data in BigLineChanges structures");
+
+            changes = BIG_WORD(data); data += 2; dataRemaining -= 2;
 
             MALLOCARRAY_NOFAIL(cmap->mp_change[row], changes + 1);
-            for( i = 0; i < changes; i++ ) {
-                if( totalchanges >= PCHG->TotalChanges ) goto fail;
-                if( datasize < 6 ) goto fail;
+            for (i = 0; i < changes; ++i) {
+                if (totalchanges >= PCHG->TotalChanges)
+                    pm_error("insufficient data in BigLineChanges structures");
+
+                if (dataRemaining < 6)
+                    pm_error("insufficient data in BigLineChanges structures");
+
                 reg = BIG_WORD(data); data += 2;
                 cmap->mp_change[row][i].reg = reg;
                 ++data; /* skip alpha */
                 cmap->mp_change[row][i].r = *data++;
                 cmap->mp_change[row][i].b = *data++;    /* yes, RBG */
                 cmap->mp_change[row][i].g = *data++;
-                datasize -= 6;
+                dataRemaining -= 6;
                 ++totalchanges;
             }
             cmap->mp_change[row][changes].reg = MP_REG_END;
             --changedlines;
         }
         thismask <<= 1;
-        bits--;
+        --bits;
     }
-    if( totalchanges != PCHG->TotalChanges )
+    if (totalchanges != PCHG->TotalChanges)
         pm_message("warning - got %ld change structures, "
                    "chunk header reports %ld", 
                    totalchanges, PCHG->TotalChanges);
-    return;
-fail:
-    pm_error("insufficient data in BigLineChanges structures");
-fail2:
-    pm_error("insufficient data in line mask");
 }
 
 
+
 static void
 read_pchg(FILE *     const ifp,
           IFF_ID     const iffid,
@@ -1938,7 +1965,7 @@ read_pchg(FILE *     const ifp,
             read_bytes(ifp, treesize, comptree, iffid, &remainingChunksize);
 
             compsize = remainingChunksize;
-            MALLOCARRAY_NOFAIL(compdata, remainingChunksize);
+            MALLOCARRAY_NOFAIL(compdata, compsize);
             read_bytes(ifp, compsize, compdata, iffid, &remainingChunksize);
 
             datasize = CompHdr.OriginalDataSize;
@@ -2032,7 +2059,7 @@ process_body( FILE *          const ifp,
         pm_error("%s chunk without %s chunk", 
                  ID2string(ID_BODY), ID2string(ID_BMHD));
 
-    check_cmap(bmhdP, cmap);
+    prepareCmap(bmhdP, cmap);
 
     pixelrow = ppm_allocrow(bmhdP->w);
     if( maskfile ) {
@@ -2080,21 +2107,21 @@ process_body( FILE *          const ifp,
 
 
 static void 
-process_chunk(FILE *          const ifp,
-              long            const formsize,
-              IFF_ID          const ignorelist[],
-              unsigned int    const ignorecount,
-              int             const fakeviewport,
-              int             const viewportmask,
-              int             const isdeepopt,
-              bool            const cmaponly,
-              bool *          const bodyChunkProcessedP,
-              bool *          const endchunkP,
-              BitMapHeader ** const bmhdP,
-              ColorMap *      const cmap,
-              DirectColor **  const dcolP,
-              int *           const viewportmodesP,
-              long *          const bytesReadP
+processChunk(FILE *          const ifP,
+             long            const formsize,
+             IFF_ID          const ignorelist[],
+             unsigned int    const ignorecount,
+             int             const fakeviewport,
+             int             const viewportmask,
+             int             const isdeepopt,
+             bool            const cmaponly,
+             bool *          const bodyChunkProcessedP,
+             bool *          const endchunkP,
+             BitMapHeader ** const bmhdP,
+             ColorMap *      const cmap,
+             DirectColor **  const dcolP,
+             int *           const viewportmodesP,
+             long *          const bytesReadP
     ) {
 
     IFF_ID iffid;
@@ -2103,129 +2130,168 @@ process_chunk(FILE *          const ifp,
 
     bytesread = 0;
 
-    iffid = get_big_long(ifp, ID_FORM, NULL);
-    chunksize = get_big_long(ifp, iffid, NULL);
+    iffid = get_big_long(ifP, ID_FORM, NULL);
+    chunksize = get_big_long(ifP, iffid, NULL);
     bytesread += 8;
 
     if (debug)
-        pm_message("reading %s chunk: %ld bytes", 
-                   ID2string(iffid), chunksize);
+        pm_message("reading %s chunk: %ld bytes", ID2string(iffid), chunksize);
 
-    if( ignored_iffid(iffid, ignorelist, ignorecount) ) {
+    if (ignored_iffid(iffid, ignorelist, ignorecount)) {
         pm_message("ignoring %s chunk", ID2string(iffid));
-        skip_chunk(ifp, iffid, chunksize);
-    } else if( iffid == ID_END ) {
+        skip_chunk(ifP, iffid, chunksize);
+    } else if (iffid == ID_END) {
         /* END chunks are not officially valid in IFF, but
            suggested as a future expansion for stream-writing,
            see Amiga RKM Devices, 3rd Ed, page 376 
         */
-        if( chunksize != 0 ) {
+        if (chunksize != 0 ) {
             pm_message("warning - non-0 %s chunk", ID2string(iffid));
-            skip_chunk(ifp, iffid, chunksize);
+            skip_chunk(ifP, iffid, chunksize);
         }
-        if( formsize != 0xffffffff )
+        if (formsize != 0xffffffff)
             pm_message("warning - %s chunk with FORM size 0x%08lx "
                        "(should be 0x%08x)",
                        ID2string(iffid), formsize, 0xffffffff);
         *endchunkP = 1;
-    } else if( *bodyChunkProcessedP ) {
+    } else if (*bodyChunkProcessedP) {
         pm_message("%s chunk found after %s chunk - skipping", 
                    ID2string(iffid), ID2string(ID_BODY));
-        skip_chunk(ifp, iffid, chunksize);
+        skip_chunk(ifP, iffid, chunksize);
     } else
-        switch( iffid ) {
+        switch (iffid) {
         case ID_BMHD:
-            *bmhdP = read_bmhd(ifp, iffid, chunksize);
+            *bmhdP = read_bmhd(ifP, iffid, chunksize);
             break;
         case ID_CMAP:
-            read_cmap(ifp, iffid, chunksize, cmap);
+            read_cmap(ifP, iffid, chunksize, cmap);
             break;
         case ID_CMYK:
-            read_cmyk(ifp, iffid, chunksize, cmap);
+            read_cmyk(ifP, iffid, chunksize, cmap);
             break;
         case ID_CLUT:
-            read_clut(ifp, iffid, chunksize, cmap);
+            read_clut(ifP, iffid, chunksize, cmap);
             break;
         case ID_CAMG:
-            if( chunksize != CAMGChunkSize )
+            if (chunksize != CAMGChunkSize)
                 pm_error("%s chunk size mismatch", ID2string(iffid));
-            *viewportmodesP = get_big_long(ifp, ID_CAMG, NULL);
+            *viewportmodesP = get_big_long(ifP, ID_CAMG, NULL);
             *viewportmodesP &= viewportmask;      /* -isnotham/-isnotehb */
             break;
         case ID_PCHG:
-            read_pchg(ifp, iffid, chunksize, cmap);
+            read_pchg(ifP, iffid, chunksize, cmap);
             break;
         case ID_CTBL:
         case ID_SHAM:
-            read_4bit_mp(ifp, iffid, chunksize, cmap);
+            read_4bit_mp(ifP, iffid, chunksize, cmap);
             break;
         case ID_DCOL:
-            if( chunksize != DirectColorSize )
+            if (chunksize != DirectColorSize)
                 pm_error("%s chunk size mismatch", ID2string(iffid));
             MALLOCVAR_NOFAIL(*dcolP);
-            (*dcolP)->r = get_byte(ifp, iffid, NULL);
-            (*dcolP)->g = get_byte(ifp, iffid, NULL);
-            (*dcolP)->b = get_byte(ifp, iffid, NULL);
-            (void)get_byte(ifp, iffid, NULL);       /* skip pad byte */
+            (*dcolP)->r = get_byte(ifP, iffid, NULL);
+            (*dcolP)->g = get_byte(ifP, iffid, NULL);
+            (*dcolP)->b = get_byte(ifP, iffid, NULL);
+            get_byte(ifP, iffid, NULL);       /* skip pad byte */
             break;
         case ID_BODY: 
-            if( cmaponly || (*bmhdP && (*bmhdP)->nPlanes == 0 )) {
-                skip_chunk(ifp, ID_BODY,  chunksize);
-                return;
-            }
-    
-            process_body(ifp, chunksize, *bmhdP, cmap, 
-                         maskfile, fakeviewport, isdeepopt, *dcolP,
-                         viewportmodesP);
-
-            *bodyChunkProcessedP = TRUE;
+            if (cmaponly || (*bmhdP && (*bmhdP)->nPlanes == 0))
+                skip_chunk(ifP, ID_BODY,  chunksize);
+            else {
+                process_body(ifP, chunksize, *bmhdP, cmap, 
+                             maskfile, fakeviewport, isdeepopt, *dcolP,
+                             viewportmodesP);
 
-            break;
+                *bodyChunkProcessedP = TRUE;
+            } break;
         case ID_GRAB:   case ID_DEST:   case ID_SPRT:   case ID_CRNG:
         case ID_CCRT:   case ID_DYCP:   case ID_DPPV:   case ID_DRNG:
         case ID_EPSF:   case ID_JUNK:   case ID_CNAM:   case ID_PRVW:
         case ID_TINY:   case ID_DPPS:
-            skip_chunk(ifp, iffid, chunksize);
+            skip_chunk(ifP, iffid, chunksize);
             break;
         case ID_copy:   case ID_AUTH:   case ID_NAME:   case ID_ANNO:
         case ID_TEXT:   case ID_FVER:
-            if( verbose )
-                display_chunk(ifp, iffid, chunksize);
+            if (verbose)
+                display_chunk(ifP, iffid, chunksize);
             else
-                skip_chunk(ifp, iffid, chunksize);
+                skip_chunk(ifP, iffid, chunksize);
             break;
-        case ID_DPI:
-        {
+        case ID_DPI: {
             int x, y;
 
-            x = get_big_short(ifp, ID_DPI, NULL);
-            y = get_big_short(ifp, ID_DPI, NULL);
-            if( verbose )
+            x = get_big_short(ifP, ID_DPI, NULL);
+            y = get_big_short(ifP, ID_DPI, NULL);
+            if (verbose)
                 pm_message("%s chunk:  dpi_x = %d    dpi_y = %d", 
                            ID2string(ID_DPI), x, y);
-        }
-        break;
+        } break;
         default:
             pm_message("unknown chunk type %s - skipping", 
                        ID2string(iffid));
-            skip_chunk(ifp, iffid, chunksize);
+            skip_chunk(ifP, iffid, chunksize);
             break;
         }
 
     bytesread += chunksize;
 
-    if( ODD(chunksize) ) {
-        (void) get_byte(ifp, iffid, NULL);
+    if (ODD(chunksize)) {
+        get_byte(ifP, iffid, NULL);
         bytesread += 1;
     } 
     *bytesReadP = bytesread;
 }
 
 
+
+static void
+maybeWriteColorMap(FILE *               const ofP,
+                   const BitMapHeader * const bmhdP,
+                   ColorMap *           const cmapP,
+                   bool                 const bodyChunkProcessed,
+                   bool                 const cmaponly) {
+/*----------------------------------------------------------------------------
+   Write to file *ofP the color map *cmapP as a PPM, if appropriate.
+
+   The logic (not just here -- in the program as a whole) for deciding whether
+   to write the image or the colormap is quite twisted.  If I thought anyone
+   was actually using this program, I would take the time to straighten it
+   out.
+
+   What's really sick about this subroutine is that in choosing to write
+   a color map, it has to know that Caller hasn't already written
+   the image.  Huge modularity violation.
+-----------------------------------------------------------------------------*/
+    if (cmaponly) {
+        if (HAS_COLORMAP(cmapP)) {
+            prepareCmap(bmhdP, cmapP);
+            cmapToPpm(ofP, cmapP);
+        } else
+            pm_error("You specified -cmaponly, but the ILBM "
+                     "has no colormap");
+    } else if (bmhdP && bmhdP->nPlanes == 0) {
+        if (HAS_COLORMAP(cmapP)) {
+            prepareCmap(bmhdP, cmapP);
+            cmapToPpm(ofP, cmapP);
+        } else
+            pm_error("ILBM has neither a color map nor color planes");
+    } else if (!bodyChunkProcessed) {
+        if (HAS_COLORMAP(cmapP)) {
+            pm_message("input is a colormap file");
+            prepareCmap(bmhdP, cmapP);
+            cmapToPpm(ofP, cmapP);
+        } else
+            pm_error("ILBM has neither %s or %s chunk", 
+                     ID2string(ID_BODY), ID2string(ID_CMAP));
+    }
+}
+
+
+
 int
 main(int argc, char *argv[]) {
 
-    FILE *ifp;
+    FILE * ifP;
     int argn;
     short cmaponly = 0, isdeepopt = 0;
     bool endchunk;
@@ -2299,25 +2365,25 @@ main(int argc, char *argv[]) {
     }    
 
     if( argn < argc ) {
-        ifp = pm_openr( argv[argn] );
+        ifP = pm_openr( argv[argn] );
         argn++;
     } else
-        ifp = stdin;
+        ifP = stdin;
 
     if( argn != argc )
         pm_usage(usage);
 
     /* Read in the ILBM file. */
 
-    firstIffid = get_big_long(ifp, ID_FORM, NULL);
-    if( firstIffid != ID_FORM )
+    firstIffid = get_big_long(ifP, ID_FORM, NULL);
+    if (firstIffid != ID_FORM)
         pm_error("input is not a FORM type IFF file");
-    formsize = get_big_long(ifp, ID_FORM, NULL);
-    typeid = get_big_long(ifp, ID_FORM, NULL);
-    if( typeid != ID_ILBM && typeid != ID_RGBN && typeid != ID_RGB8 && 
-        typeid != ID_PBM )
-        pm_error( "input is not an ILBM, RGBN, RGB8 or PBM "
-                  "type FORM IFF file" );
+    formsize = get_big_long(ifP, ID_FORM, NULL);
+    typeid = get_big_long(ifP, ID_FORM, NULL);
+    if (typeid != ID_ILBM && typeid != ID_RGBN && typeid != ID_RGB8 && 
+        typeid != ID_PBM)
+        pm_error("input is not an ILBM, RGBN, RGB8 or PBM "
+                 "type FORM IFF file");
     bytesread = 4;  /* FORM and formsize do not count */
 
     cmap = alloc_cmap();
@@ -2325,55 +2391,41 @@ main(int argc, char *argv[]) {
     /* Main loop, parsing the IFF FORM. */
     bodyChunkProcessed = FALSE;
     endchunk = FALSE;
-    while( !endchunk && formsize-bytesread >= 8 ) {
-        long bytes_read_for_chunk;
+    while (!endchunk && formsize-bytesread >= 8) {
+        long bytesReadForChunk;
 
-        process_chunk(ifp, formsize, ignorelist, ignorecount,
-                      fakeviewport, viewportmask,
-                      isdeepopt, cmaponly,
-                      &bodyChunkProcessed,
-                      &endchunk, &bmhdP, cmap, &dcol,
-                      &viewportmodes, &bytes_read_for_chunk);
+        processChunk(ifP, formsize, ignorelist, ignorecount,
+                     fakeviewport, viewportmask,
+                     isdeepopt, cmaponly,
+                     &bodyChunkProcessed,
+                     &endchunk, &bmhdP, cmap, &dcol,
+                     &viewportmodes, &bytesReadForChunk);
 
-        bytesread += bytes_read_for_chunk;
+        bytesread += bytesReadForChunk;
     }
 
-    if( maskfile ) {
+    if (maskfile) {
         pm_close(maskfile);
-        if( !wrotemask )
+        if (!wrotemask)
             remove(maskname);
         pbm_freerow(maskrow);
     }
 
-    if( cmaponly || (bmhdP && bmhdP->nPlanes == 0 )) {
-        if( HAS_COLORMAP(cmap) ) {
-            check_cmap(bmhdP, cmap);
-            cmap_to_ppm(cmap);
-        } else
-            pm_error("no colormap");
-    } else if( !bodyChunkProcessed ) {
-        if( HAS_COLORMAP(cmap) ) {
-            pm_message("input is a colormap file");
-            check_cmap(bmhdP, cmap);
-            cmap_to_ppm(cmap);
-        } else
-            pm_error("no %s or %s chunk found", 
-                     ID2string(ID_BODY), ID2string(ID_CMAP));
-    }
+    maybeWriteColorMap(stdout, bmhdP, cmap, bodyChunkProcessed, cmaponly);
 
     {
         unsigned int skipped;
         
-        for( skipped = 0; fgetc(ifp) != EOF; ++skipped )
-            bytesread++;
+        for (skipped = 0; fgetc(ifP) != EOF; ++skipped)
+            ++bytesread;
 
-        if( skipped > 0 )
+        if (skipped > 0)
             pm_message("skipped %u extraneous byte%s after last chunk",
                        skipped, (skipped == 1 ? "" : "s"));
     }
-    pm_close(ifp);
+    pm_close(ifP);
 
-    if( !endchunk && bytesread != formsize ) {
+    if (!endchunk && bytesread != formsize) {
         pm_message("warning - file length/FORM size field mismatch "
                    "(%ld != %ld+8)",
                    bytesread+8 /* FORM+size */, formsize);
diff --git a/converter/ppm/mitsu.h b/converter/ppm/mitsu.h
index 8676a39d..bca4fbdf 100644
--- a/converter/ppm/mitsu.h
+++ b/converter/ppm/mitsu.h
@@ -1,7 +1,6 @@
 #ifndef MITSU_H_INCLUDED
 #define MITSU_H_INCLUDED
 
-/* static char SCCSid[] = "@(#)mitsu.h\t\t1.3\t(SPZ)\t3/11/92\n"; */
 #define MAXLUTCOL   255
 
 #define A4_MAXCOLS  1184
diff --git a/converter/ppm/picttoppm.c b/converter/ppm/picttoppm.c
index b7da0c79..9a7d8e7c 100644
--- a/converter/ppm/picttoppm.c
+++ b/converter/ppm/picttoppm.c
@@ -142,15 +142,6 @@ static int ps_cent_x;
 static int ps_cent_y;
 static int ps_cent_set;
 
-typedef void (drawFn)(struct canvas *, int);
-
-struct opdef {
-    const char* name;
-    int len;
-    drawFn * impl;
-    const char* description;
-};
-
 struct raster {
 /*----------------------------------------------------------------------------
    An image raster.  May be either truecolor or paletted.
@@ -265,13 +256,30 @@ struct blit_info {
     struct raster      srcplane;
     int                pixSize;
     struct Rect        dstRect;
-    struct RGBColor *  color_map;
+    struct RGBColor *  colorMap;
     int                mode;
     struct blit_info * next;
 };
 
-static struct blit_info* blit_list = 0;
-static struct blit_info** last_bl = &blit_list;
+typedef struct {
+    struct blit_info * firstP;
+    struct blit_info ** connectorP;
+    bool unblittableText;
+        /* The image contains text opcodes, and we don't know how to put that
+           in a blit list (I really don't even know what a blit _is_), so
+           the image information here is incomplete.
+        */
+} blitList;
+
+
+typedef void (drawFn)(struct canvas *, blitList *, int);
+
+struct opdef {
+    const char* name;
+    int len;
+    drawFn * impl;
+    const char* description;
+};
 
 #define WORD_LEN (-1)
 
@@ -610,6 +618,7 @@ static drawFn ShortComment;
 
 static void
 ShortComment(struct canvas * const canvasP,
+             blitList *      const blitListP,
              int             const version) {
 
     picComment(read_word(), 0);
@@ -621,6 +630,7 @@ static drawFn LongComment;
 
 static void
 LongComment(struct canvas * const canvasP,
+            blitList *      const blitListP,
             int             const version) {
 
     word type;
@@ -635,6 +645,7 @@ static drawFn skip_poly_or_region;
 
 static void
 skip_poly_or_region(struct canvas * const canvasP,
+                    blitList *      const blitListP,
                     int             const version) {
 
     stage = "skipping polygon or region";
@@ -765,24 +776,33 @@ load_fontdir(const char * const dirfile) {
 
 
 static void
+dumpRect(const char * const label,
+         struct Rect  const rectangle) {
+
+    pm_message("%s (%u,%u) (%u,%u)",
+               label,
+               rectangle.left,  rectangle.top,
+               rectangle.right, rectangle.bottom);
+}
+
+
+
+static void
 read_rect(struct Rect * const r) {
 
     r->top    = read_word();
     r->left   = read_word();
     r->bottom = read_word();
     r->right  = read_word();
-}
-
 
+    if (r->top > r->bottom || r->right < r->left)
+        dumpRect("Invalid rectangle", *r);
 
-static void
-dumpRect(const char * const label,
-         struct Rect  const rectangle) {
-
-    pm_message("%s (%u,%u) (%u,%u)",
-               label,
-               rectangle.left,  rectangle.top,
-               rectangle.right, rectangle.bottom);
+    if (r->top > r->bottom)
+        pm_error("Invalid PICT: a rectangle has a top below its bottom");
+    if (r->right < r->left)
+        pm_error("Invalid PICT: a rectangle has a right edge "
+                 "left of its left edge");
 }
 
 
@@ -802,10 +822,10 @@ rectheight(const struct Rect * const r) {
 
 
 static bool
-rectsamesize(const struct Rect * const r1, 
-             const struct Rect * const r2) {
-    return r1->right - r1->left == r2->right - r2->left &&
-           r1->bottom - r1->top == r2->bottom - r2->top ;
+rectsamesize(struct Rect const r1, 
+             struct Rect const r2) {
+    return r1.right - r1.left == r2.right - r2.left &&
+           r1.bottom - r1.top == r2.bottom - r2.top ;
 }
 
 
@@ -835,20 +855,45 @@ rectscale(struct Rect * const r,
 
 
 
-static struct blit_info* 
-add_blit_list(void) {
+static void
+    initBlitList(blitList * const blitListP) {
 
-    struct blit_info * bi;
+    blitListP->firstP          = NULL;
+    blitListP->connectorP      = &blitListP->firstP;
+    blitListP->unblittableText = false;
+}
+
+
+
+static void
+addBlitList(blitList *        const blitListP,
+            struct Rect       const srcRect,
+            struct Rect       const srcBounds,
+            struct raster     const srcplane,
+            int               const pixSize,
+            struct Rect       const dstRect,
+            struct RGBColor * const colorMap,
+            int               const mode) {
+
+    struct blit_info * biP;
     
-    MALLOCVAR(bi);
-    if (bi == NULL)
+    MALLOCVAR(biP);
+    if (biP == NULL)
         pm_error("out of memory for blit list");
-    
-    bi->next = 0;
-    *last_bl = bi;
-    last_bl = &bi->next;
-    
-    return bi;
+    else {
+        biP->srcRect   = srcRect;
+        biP->srcBounds = srcBounds;
+        biP->srcplane  = srcplane;
+        biP->pixSize   = pixSize;
+        biP->dstRect   = dstRect;
+        biP->colorMap  = colorMap;
+        biP->mode      = mode;
+
+        biP->next = NULL;
+
+        *blitListP->connectorP = biP;
+        blitListP->connectorP = &biP->next;
+    }
 }
 
 
@@ -1327,8 +1372,6 @@ doSameSize(transfer_func           trf,
            struct rgbPlanes  const dst,
            unsigned int      const dstwid) {
 /*----------------------------------------------------------------------------
-   Generalized (but slow) blit.
-
    Transfer pixels from 'src' to 'dst', applying the transfer function
    'trf'.
 
@@ -1501,19 +1544,30 @@ blitIdempotent(unsigned int          const pixSize,
 
 
 static void
-generalBlit(struct Rect       const srcRect, 
-            struct Rect       const srcBounds, 
-            struct raster     const srcplane,
-            struct rgbPlanes  const planes,
-            int               const pixSize, 
-            struct Rect       const dstRect, 
-            struct Rect       const dstBounds, 
-            int               const dstwid, 
-            struct RGBColor * const color_map, 
-            int               const mode,
-            struct Rect       const clipsrc,
-            struct Rect       const clipdst) {
-    
+doBlit(struct Rect       const srcRect, 
+       struct Rect       const dstRect, 
+       struct Rect       const srcBounds, 
+       struct raster     const srcplane,
+       struct Rect       const dstBounds, 
+       struct rgbPlanes  const canvasPlanes,
+       int               const pixSize, 
+       int               const dstwid, 
+       struct RGBColor * const color_map, 
+       int               const mode) {
+/*----------------------------------------------------------------------------
+   Transfer some pixels from 'srcplane' to 'canvasPlanes', applying the
+   transfer function 'trf'.
+
+   'srcplane' contains the rectangle 'srcBounds' of the image.
+   'canvasPlanes' contains the rectangle 'dstRect' of the image.
+
+   Take the rectangle 'srcRect' of the source image and copy it to the
+   rectangle 'dstRec' of the destination image.
+
+   Each plane of 'canvasPlanes' is one word per pixel and contains actual
+   colors, never a palette index.  It is an array in row-major order
+   with 'dstwid' words per row.
+-----------------------------------------------------------------------------*/
     unsigned char * src;
     struct rgbPlanes dst;
     int dstoff;
@@ -1523,31 +1577,31 @@ generalBlit(struct Rect       const srcRect,
     transfer_func trf;
 
     if (verbose) {
-        dumpRect("copying from:", clipsrc);
-        dumpRect("to:          ", clipdst);
+        dumpRect("copying from:", srcRect);
+        dumpRect("to:          ", dstRect);
         pm_message("a %u x %u area to a %u x %u area",
-                   rectwidth(&clipsrc), rectheight(&clipsrc),
-                   rectwidth(&clipdst), rectheight(&clipdst));
+                   rectwidth(&srcRect), rectheight(&srcRect),
+                   rectwidth(&dstRect), rectheight(&dstRect));
     }
 
     {
         unsigned int const pkpixsize = pixSize == 16 ? 2 : 1;
-        unsigned int const srcRowNumber = clipsrc.top - srcBounds.top;
+        unsigned int const srcRowNumber = srcRect.top - srcBounds.top;
         unsigned int const srcRowOffset =
-            (clipsrc.left - srcBounds.left) * pkpixsize;
+            (srcRect.left - srcBounds.left) * pkpixsize;
         assert(srcRowNumber < srcplane.rowCount);
         assert(srcRowOffset < srcplane.rowSize);
         src = srcplane.bytes + srcRowNumber * srcplane.rowSize + srcRowOffset;
-        xsize = clipsrc.right - clipsrc.left;
-        ysize = clipsrc.bottom - clipsrc.top;
+        xsize = rectwidth(&srcRect);
+        ysize = rectheight(&srcRect);
         srcadd = srcplane.rowSize - xsize * pkpixsize;
     }
 
-    dstoff = (clipdst.top - dstBounds.top) * dstwid +
-        (clipdst.left - dstBounds.left);
-    dst.red = planes.red + dstoff;
-    dst.grn = planes.grn + dstoff;
-    dst.blu = planes.blu + dstoff;
+    dstoff = (dstRect.top - dstBounds.top) * dstwid +
+        (dstRect.left - dstBounds.left);
+    dst.red = canvasPlanes.red + dstoff;
+    dst.grn = canvasPlanes.grn + dstoff;
+    dst.blu = canvasPlanes.blu + dstoff;
 
     /* get rid of Text mask mode bit, if (erroneously) set */
     if ((mode & ~64) == 0)
@@ -1555,8 +1609,8 @@ generalBlit(struct Rect       const srcRect,
     else
         trf = transfer(mode & ~64);
 
-    if (!rectsamesize(&clipsrc, &clipdst))
-        doDiffSize(clipsrc, clipdst, pixSize, xsize, ysize,
+    if (!rectsamesize(srcRect, dstRect))
+        doDiffSize(srcRect, dstRect, pixSize, xsize, ysize,
                    trf, color_map, src, srcplane.rowSize, dst, dstwid);
     else {
         if (trf == NULL)
@@ -1575,12 +1629,21 @@ blit(struct Rect       const srcRect,
      struct Rect       const srcBounds, 
      struct raster     const srcplane,
      struct canvas *   const canvasP,
+     blitList *        const blitListP,
      int               const pixSize, 
      struct Rect       const dstRect, 
      struct Rect       const dstBounds, 
      int               const dstwid, 
      struct RGBColor * const color_map, 
      int               const mode) {
+/*----------------------------------------------------------------------------
+   'srcplane' contains the rectangle 'srcBounds' of the image.
+
+   We transfer rectangle 'srcRect' from that.
+
+   if 'blitListP' is non-null, we don't draw anything on 'canvasP'; instead,
+   we add to the list *blitlistP a description of what needs to be drawn.
+-----------------------------------------------------------------------------*/
 
     /* I can't tell what the result value of this function is supposed to mean,
        but I found several return statements that did not set it to anything,
@@ -1595,9 +1658,7 @@ blit(struct Rect       const srcRect,
         retval = 1;
     else {
         /* Almost got it.  Clip source rect with source bounds.
-           clip dest rect with dest bounds.  If source and
-           destination are not the same size, use Pnmscale
-           to get a nicely sized rectangle.
+           clip dest rect with dest bounds.
         */
         struct Rect clipsrc;
         struct Rect clipdst;
@@ -1605,22 +1666,16 @@ blit(struct Rect       const srcRect,
         rectinter(srcBounds, srcRect, &clipsrc);
         rectinter(dstBounds, dstRect, &clipdst);
 
-        if (fullres) {
-            struct blit_info * bi;
-            bi = add_blit_list();
-            bi->srcRect   = clipsrc;
-            bi->srcBounds = srcBounds;
-            bi->srcplane  = srcplane;
-            bi->pixSize   = pixSize;
-            bi->dstRect   = clipdst;
-            bi->color_map = color_map;
-            bi->mode      = mode;
+        if (blitListP) {
+            addBlitList(blitListP,
+                        clipsrc, srcBounds, srcplane, pixSize,
+                        clipdst, color_map, mode);
 
             retval = 0;
         } else {
-            generalBlit(srcRect, srcBounds, srcplane, canvasP->planes, pixSize,
-                        dstRect, dstBounds, dstwid, color_map, mode,
-                        clipsrc, clipdst);
+            doBlit(clipsrc, clipdst,
+                   srcBounds, srcplane, dstBounds, canvasP->planes,
+                   pixSize, dstwid, color_map, mode);
 
             retval = 1;
         }
@@ -1680,9 +1735,31 @@ compact(word const input) {
 
 
 static void
-do_blits(struct canvas * const canvasP) {
+reportBlitList(blitList * const blitListP) {
+
+    if (verbose) {
+        unsigned int count;
+        struct blit_info * biP;
+
+        for (count = 0, biP = blitListP->firstP; biP; biP = biP->next)
+            ++count;
+
+        pm_message("# blits: %u", count);
+    }
+}
+
 
-    struct blit_info* bi;
+
+static void
+doBlitList(struct canvas * const canvasP,
+           blitList *      const blitListP) {
+/*----------------------------------------------------------------------------
+   Do the list of blits *blitListP, drawing on canvas *canvasP.
+
+   We allocate new plane data structures in *canvasP.  We assume it doesn't
+   have them already.
+-----------------------------------------------------------------------------*/
+    struct blit_info * bi;
     int srcwidth, dstwidth, srcheight, dstheight;
     double  scale, scalelow, scalehigh;
     double  xscale = 1.0;
@@ -1690,9 +1767,11 @@ do_blits(struct canvas * const canvasP) {
     double  lowxscale, highxscale, lowyscale, highyscale;
     int     xscalecalc = 0, yscalecalc = 0;
 
+    reportBlitList(blitListP);
+
     fullres = 0;
 
-    for (bi = blit_list; bi; bi = bi->next) {
+    for (bi = blitListP->firstP; bi; bi = bi->next) {
         srcwidth = rectwidth(&bi->srcRect);
         dstwidth = rectwidth(&bi->dstRect);
         srcheight = rectheight(&bi->srcRect);
@@ -1768,11 +1847,12 @@ do_blits(struct canvas * const canvasP) {
     }
 
     if (xscale != 1.0 || yscale != 1.0) {
-        for (bi = blit_list; bi; bi = bi->next)
-            rectscale(&bi->dstRect, xscale, yscale);
+        struct blit_info * biP;
+        
+        for (biP = blitListP->firstP; biP; biP = biP->next)
+            rectscale(&biP->dstRect, xscale, yscale);
 
-        pm_message("Scaling output by %f in X and %f in Y",
-                   xscale, yscale);
+        pm_message("Scaling output by %f in X and %f in Y", xscale, yscale);
         rectscale(&picFrame, xscale, yscale);
     }
 
@@ -1783,12 +1863,10 @@ do_blits(struct canvas * const canvasP) {
 
     clip_rect = picFrame;
 
-    for (bi = blit_list; bi; bi = bi->next) {
-        blit(bi->srcRect, bi->srcBounds, bi->srcplane, canvasP,
-             bi->pixSize,
-             bi->dstRect, picFrame, rowlen,
-             bi->color_map,
-             bi->mode);
+    for (bi = blitListP->firstP; bi; bi = bi->next) {
+        doBlit(bi->srcRect, bi->dstRect,
+               bi->srcBounds, bi->srcplane, picFrame, canvasP->planes,
+               bi->pixSize, rowlen, bi->colorMap, bi->mode);
     }
 }
 
@@ -1856,6 +1934,7 @@ static drawFn Clip;
 
 static void
 Clip(struct canvas * const canvasP,
+     blitList *      const blitListP,
      int             const version) {
 
     word len;
@@ -1878,6 +1957,7 @@ static drawFn OpColor;
 
 static void
 OpColor(struct canvas * const canvasP,
+        blitList *      const blitListP,
         int             const version) {
 
     op_color.red = read_word();
@@ -1967,7 +2047,7 @@ read_color_table(void) {
         color_table[val].blu = read_word();
 
         if (verbose > 1)
-            pm_message("%d: [%d,%d,%d]", val,
+            pm_message("Color %3u: [%u,%u,%u]", val,
                 color_table[val].red,
                 color_table[val].grn,
                 color_table[val].blu);
@@ -2173,6 +2253,42 @@ unpackUncompressedBits(FILE *          const ifP,
 
 
 static void
+reportValidateCompressedLineLen(unsigned int const row,
+                                unsigned int const linelen,
+                                unsigned int const rowSize) {
+/*----------------------------------------------------------------------------
+   'row' is a row number in the raster.
+
+   'linelen' is the number of bytes of PICT that the PICT says hold the
+   compressed version of that row.
+
+   'rowSize' is the number of bytes we expect the uncompressed line to
+   be (includes pad pixels on the right).
+-----------------------------------------------------------------------------*/
+    if (verbose > 1)
+        pm_message("Row %u: %u-byte compressed line", row, linelen);
+
+    /* When the line length value is garbage, it often causes the program to
+       try to read beyond EOF.  To make that failure easier to diagnose,
+       we sanity check the line length now.
+    */
+
+    /* In the worst case, a pixel is represented by two bytes: a one byte
+       repeat count of one followed by a one byte pixel value (the byte could
+       be up to 8 pixels) or a one byte block length of one followed by the
+       pixel value.  So expansion factor two.
+    */
+
+    if (linelen > rowSize * 2)
+        pm_error("Invalid PICT: compressed line of %u bytes for Row %u "
+                 "is too big "
+                 "to represent a %u-byte padded row, even with worse case "
+                 "compression.", linelen, row, rowSize);
+}
+
+
+
+static void
 expandRun(unsigned char * const block,
           unsigned int    const blockLimit,
           unsigned int    const bitsPerPixel,
@@ -2375,7 +2491,7 @@ interpretCompressedLine(unsigned char * const linebuf,
         
         assert(lineCursor <= linelen);
             
-        if (verbose > 1)
+        if (verbose > 2)
             pm_message("At Byte %u of line, Column %u of row",
                        lineCursor, rasterCursor);
 
@@ -2394,6 +2510,32 @@ interpretCompressedLine(unsigned char * const linebuf,
 }
 
 
+/* There is some confusion about when, in PICT, a line length is one byte and
+  when it is two.  An Apple document says it is two bytes when the number of
+  pixels in the row, padded, is > 250.  Ppmtopict generated PICTs that way
+  until January 2009.  Picttoppm assumed something similar until March 2004:
+  It assumed the line length is two bytes when the number of pixels > 250 _or_
+  bits per pixel > 8.  But in March 2004, Steve Summit did a bunch of
+  experiments on existing PICT files and found that they all worked with the
+  rule "pixels per row > 200 => 2 byte line length" and some did not work
+  with the original rule.
+
+  So in March 2004, Picttoppm changed to pixels per row > 200.  Ppmtopict
+  didn't catch up until January 2009.
+
+  http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-460.html#HEADING460-0
+
+  Of course, neither 200 nor 250 make any logical sense.  In the worst case,
+  you can represent 254 pixels of 8 bpp or less in a 255 byte line.
+  In the worst case, you can represent 127 16bpp pixels in a 255 byte line.
+  So with 200 being the cutoff, it's actually impossible to represent some 
+  16 bpp images with 200 pixels per row.
+
+  We have not been able to find an offical spec for PICT.
+
+  Some day, we may have to make a user option for this.
+*/
+
 
 static void
 unpackCompressedBits(FILE *          const ifP,
@@ -2410,14 +2552,13 @@ unpackCompressedBits(FILE *          const ifP,
    "packing" and I don't know what packing is called.  But we don't
    use that confusing terminology in this program, except when talking
    to the user.
-
-   *boundsP describes the rectangle.
 -----------------------------------------------------------------------------*/
     unsigned int const llsize = rowBytes > 200 ? 2 : 1;
         /* Width in bytes of the field at the beginning of a line that tells
-           how long (in bytes) the line is.
+           how long (in bytes) the line is.  See notes above about this
+           computation.
         */
-    unsigned int rowOfRect;
+    unsigned int row;
     unsigned char * linebuf;
     unsigned int linebufSize;
 
@@ -2426,9 +2567,9 @@ unpackCompressedBits(FILE *          const ifP,
     if (linebuf == NULL)
         pm_error("can't allocate memory for line buffer");
 
-    for (rowOfRect = 0; rowOfRect < raster.rowCount; ++rowOfRect) {
+    for (row = 0; row < raster.rowCount; ++row) {
         unsigned char * const rowRaster =
-            &raster.bytes[rowOfRect * raster.rowSize];
+            &raster.bytes[row * raster.rowSize];
         unsigned int linelen;
 
         if (llsize == 2)
@@ -2436,8 +2577,7 @@ unpackCompressedBits(FILE *          const ifP,
         else
             linelen = read_byte();
 
-        if (verbose > 1)
-            pm_message("Row %u: %u-byte line", rowOfRect, linelen);
+        reportValidateCompressedLineLen(row, linelen, raster.rowSize);
 
         if (linelen > linebufSize) {
             linebufSize = linelen;
@@ -2554,6 +2694,7 @@ static drawFn BkPixPat;
 
 static void
 BkPixPat(struct canvas * const canvasP,
+         blitList *      const blitListP,
          int             const version) {
 
     read_pattern();
@@ -2565,6 +2706,7 @@ static drawFn PnPixPat;
 
 static void
 PnPixPat(struct canvas * const canvasP,
+         blitList *      const blitListP,
          int             const version) {
 
     read_pattern();
@@ -2576,6 +2718,7 @@ static drawFn FillPixPat;
 
 static void
 FillPixPat(struct canvas * const canvasP,
+           blitList *      const blitListP,
            int             const version) {
 
     read_pattern();
@@ -2610,6 +2753,7 @@ static drawFn BkPat;
 
 static void 
 BkPat(struct canvas * const canvasP,
+      blitList *      const blitListP,
       int             const version) {
 
     read_8x8_pattern(&bkpat);
@@ -2621,6 +2765,7 @@ static drawFn PnPat;
 
 static void 
 PnPat(struct canvas * const canvasP,
+      blitList *      const blitListP,
       int             const version) {
 
     read_8x8_pattern(&pen_pat);
@@ -2632,6 +2777,7 @@ static drawFn FillPat;
 
 static void 
 FillPat(struct canvas * const canvasP,
+        blitList *      const blitListP,
         int             const version) {
 
     read_8x8_pattern(&fillpat);
@@ -2643,6 +2789,7 @@ static drawFn PnSize;
 
 static void 
 PnSize(struct canvas * const canvasP,
+       blitList *      const blitListP,
        int             const version) {
 
     pen_height = read_word();
@@ -2657,6 +2804,7 @@ static drawFn PnSize;
 
 static void 
 PnMode(struct canvas * const canvasP,
+       blitList *      const blitListP,
        int             const version) {
 
     pen_mode = read_word();
@@ -2685,6 +2833,7 @@ static drawFn RGBFgCol;
 
 static void 
 RGBFgCol(struct canvas * const canvasP,
+         blitList *      const blitListP,
          int             const version) {
 
     read_rgb(&foreground);
@@ -2699,6 +2848,7 @@ static drawFn RGBBkCol;
 
 static void 
 RGBBkCol(struct canvas * const canvasP,
+         blitList *      const blitListP,
          int             const version) {
 
     read_rgb(&background);
@@ -2857,6 +3007,7 @@ static drawFn Line;
 
 static void 
 Line(struct canvas * const canvasP,
+     blitList *      const blitListP,
      int             const version) {
 
   struct Point p1;
@@ -2874,6 +3025,7 @@ static drawFn LineFrom;
 
 static void 
 LineFrom(struct canvas * const canvasP,
+         blitList *      const blitListP,
          int             const version) {
 
     struct Point p1;
@@ -2881,7 +3033,7 @@ LineFrom(struct canvas * const canvasP,
     if (verbose)
         pm_message("(%d,%d) to (%d, %d)", current.x, current.y, p1.x, p1.y);
 
-    if (!fullres)
+    if (!blitListP)
         scan_line(canvasP, current.x, current.y, p1.x, p1.y);
 
     current.x = p1.x;
@@ -2894,6 +3046,7 @@ static drawFn ShortLine;
 
 static void 
 ShortLine(struct canvas * const canvasP,
+          blitList *      const blitListP,
           int             const version) {
 
     struct Point p1;
@@ -2904,7 +3057,7 @@ ShortLine(struct canvas * const canvasP,
     current.x += p1.x;
     current.y += p1.y;
     
-    if (!fullres)
+    if (!blitListP)
         scan_line(canvasP, p1.x, p1.y, current.x, current.y);
 }
 
@@ -2914,6 +3067,7 @@ static drawFn ShortLineFrom;
 
 static void 
 ShortLineFrom(struct canvas * const canvasP,
+              blitList *      const blitListP,
               int             const version) {
 
     struct Point p1;
@@ -2923,7 +3077,7 @@ ShortLineFrom(struct canvas * const canvasP,
                    current.x,current.y,p1.x,p1.y);
     p1.x += current.x;
     p1.y += current.y;
-    if (!fullres)
+    if (!blitListP)
         scan_line(canvasP, current.x, current.y, p1.x, p1.y);
     current.x = p1.x;
     current.y = p1.y;
@@ -2937,9 +3091,6 @@ do_paintRect(struct canvas * const canvasP,
 
     struct Rect rect;
   
-    if (fullres)
-        return;
-
     if (verbose)
         dumpRect("painting", prect);
 
@@ -2954,10 +3105,12 @@ static drawFn paintRect;
 
 static void 
 paintRect(struct canvas * const canvasP,
+          blitList *      const blitListP,
           int             const version) {
 
     read_rect(&cur_rect);
-    do_paintRect(canvasP, cur_rect);
+    if (!blitListP)
+        do_paintRect(canvasP, cur_rect);
 }
 
 
@@ -2966,9 +3119,11 @@ static drawFn paintSameRect;
 
 static void 
 paintSameRect(struct canvas * const canvasP,
+              blitList *      const blitListP,
               int             const version) {
 
-    do_paintRect(canvasP, cur_rect);
+    if (!blitListP)
+        do_paintRect(canvasP, cur_rect);
 }
 
 
@@ -2976,25 +3131,22 @@ paintSameRect(struct canvas * const canvasP,
 static void 
 do_frameRect(struct canvas * const canvasP,
              struct Rect     const rect) {
-    int x, y;
 
-    if (fullres)
-        return;
-  
     if (verbose)
         dumpRect("framing", rect);
 
-    if (pen_width == 0 || pen_height == 0)
-        return;
-
-    for (x = rect.left; x <= rect.right - pen_width; x += pen_width) {
-        draw_pen(canvasP, x, rect.top);
-        draw_pen(canvasP, x, rect.bottom - pen_height);
-    }
+    if (pen_width > 0 && pen_height > 0) {
+        unsigned int x, y;
 
-    for (y = rect.top; y <= rect.bottom - pen_height ; y += pen_height) {
-        draw_pen(canvasP, rect.left, y);
-        draw_pen(canvasP, rect.right - pen_width, y);
+        for (x = rect.left; x <= rect.right - pen_width; x += pen_width) {
+            draw_pen(canvasP, x, rect.top);
+            draw_pen(canvasP, x, rect.bottom - pen_height);
+        }
+        
+        for (y = rect.top; y <= rect.bottom - pen_height ; y += pen_height) {
+            draw_pen(canvasP, rect.left, y);
+            draw_pen(canvasP, rect.right - pen_width, y);
+        }
     }
 }
 
@@ -3004,10 +3156,12 @@ static drawFn frameRect;
 
 static void 
 frameRect(struct canvas * const canvasP,
+          blitList *      const blitListP,
           int             const version) {
 
     read_rect(&cur_rect);
-    do_frameRect(canvasP, cur_rect);
+    if (!blitListP)
+        do_frameRect(canvasP, cur_rect);
 }
 
 
@@ -3016,9 +3170,11 @@ static drawFn frameSameRect;
 
 static void 
 frameSameRect(struct canvas * const canvasP,
+              blitList *      const blitListP,
               int             const version) {
 
-    do_frameRect(canvasP, cur_rect);
+    if (!blitListP)
+        do_frameRect(canvasP, cur_rect);
 }
 
 
@@ -3165,6 +3321,7 @@ static drawFn paintPoly;
   
 static void 
 paintPoly(struct canvas * const canvasP,
+          blitList *      const blitListP,
           int             const version) {
 
   struct Rect bb;
@@ -3176,7 +3333,7 @@ paintPoly(struct canvas * const canvasP,
     read_point(&pts[i]);
 
   /* scan convert poly ... */
-  if (!fullres)
+  if (!blitListP)
       scan_poly(canvasP, np, pts);
 }
 
@@ -3186,6 +3343,7 @@ static drawFn PnLocHFrac;
 
 static void 
 PnLocHFrac(struct canvas * const canvasP,
+           blitList *      const blitListP,
            int             const version) {
 
     word frac = read_word();
@@ -3200,6 +3358,7 @@ static drawFn TxMode;
 
 static void 
 TxMode(struct canvas * const canvasP,
+       blitList *      const blitListP,
        int             const version) {
 
     text_mode = read_word();
@@ -3220,6 +3379,7 @@ static drawFn TxFont;
 
 static void 
 TxFont(struct canvas * const canvasP,
+       blitList *      const blitListP,
        int             const version) {
 
     text_font = read_word();
@@ -3233,6 +3393,7 @@ static drawFn TxFace;
 
 static void 
 TxFace(struct canvas * const canvasP,
+       blitList *      const blitListP,
        int             const version) {
 
     text_face = read_byte();
@@ -3246,6 +3407,7 @@ static drawFn TxSize;
 
 static void 
 TxSize(struct canvas * const canvasP,
+       blitList *      const blitListP,
        int             const version) {
 
     text_size = read_word();
@@ -3256,11 +3418,11 @@ TxSize(struct canvas * const canvasP,
 
 
 static void
-skip_text(void) {
+skip_text(blitList * const blitListP) {
 
-    pm_message("Warning: text is omitted from the output because "
-               "we don't know how to do text with -fullres.");
     skip(read_byte());
+
+    blitListP->unblittableText = true;
 }
 
 
@@ -3279,6 +3441,7 @@ static struct font*
 get_font(int const font, 
          int const size, 
          int const style) {
+
     int closeness, bestcloseness;
     struct fontinfo* fi, *best;
 
@@ -3410,11 +3573,12 @@ do_ps_text(struct canvas * const canvasP,
 
 static void
 do_text(struct canvas *  const canvasP,
+        blitList *       const blitListP,
         word             const startx, 
         word             const starty) {
 
-    if (fullres)
-        skip_text();
+    if (blitListP)
+        skip_text(blitListP);
     else {
         if (!(tfont = get_font(text_font, text_size, text_face)))
             tfont = pbm_defaultfont("bdf");
@@ -3459,13 +3623,14 @@ static drawFn LongText;
 
 static void
 LongText(struct canvas * const canvasP,
+         blitList *      const blitListP,
          int             const version) {
 
     struct Point p;
 
     read_point(&p);
 
-    do_text(canvasP, p.x, p.y);
+    do_text(canvasP, blitListP, p.x, p.y);
 }
 
 
@@ -3474,10 +3639,12 @@ static drawFn DHText;
 
 static void
 DHText(struct canvas * const canvasP,
+       blitList *      const blitListP,
        int             const version) {
 
     current.x += read_byte();
-    do_text(canvasP, current.x, current.y);
+
+    do_text(canvasP, blitListP, current.x, current.y);
 }
 
 
@@ -3486,10 +3653,12 @@ static drawFn DVText;
 
 static void
 DVText(struct canvas * const canvasP,
+       blitList *      const blitListP,
        int             const version) {
 
     current.y += read_byte();
-    do_text(canvasP, current.x, current.y);
+
+    do_text(canvasP, blitListP, current.x, current.y);
 }
 
 
@@ -3498,6 +3667,7 @@ static drawFn DHDVText;
 
 static void
 DHDVText(struct canvas * const canvasP,
+         blitList *      const blitListP,
          int             const version) {
     byte dh, dv;
 
@@ -3509,7 +3679,8 @@ DHDVText(struct canvas * const canvasP,
 
     current.x += dh;
     current.y += dv;
-    do_text(canvasP, current.x, current.y);
+
+    do_text(canvasP, blitListP, current.x, current.y);
 }
 
 
@@ -3520,6 +3691,7 @@ DHDVText(struct canvas * const canvasP,
 
 static void
 directBits(struct canvas * const canvasP,
+           blitList *      const blitListP,
            unsigned int    const pictVersion, 
            bool            const skipRegion) {
 
@@ -3561,11 +3733,11 @@ directBits(struct canvas * const canvasP,
         pm_message("transfer mode = %s", const_name(transfer_name, mode));
 
     if (skipRegion) 
-        skip_poly_or_region(canvasP, pictVersion);
+        skip_poly_or_region(canvasP, blitListP, pictVersion);
 
     unpackbits(ifp, &p.Bounds, 0, p.pixelSize, &raster);
 
-    blit(srcRect, p.Bounds, raster, canvasP, p.pixelSize,
+    blit(srcRect, p.Bounds, raster, canvasP, blitListP, p.pixelSize,
          dstRect, picFrame, rowlen, NULL, mode);
 
     freeRaster(raster);
@@ -3580,9 +3752,10 @@ static drawFn DirectBitsRect;
 
 static void
 DirectBitsRect(struct canvas * const canvasP,
+               blitList *      const blitListP,
                int             const version) {
 
-    directBits(canvasP, version, SKIP_REGION_FALSE);
+    directBits(canvasP, blitListP, version, SKIP_REGION_FALSE);
 }
 
 
@@ -3591,15 +3764,17 @@ static drawFn DirectBitsRgn;
 
 static void
 DirectBitsRgn(struct canvas * const canvasP,
+              blitList *      const blitListP,
               int             const version) {
 
-    directBits(canvasP, version, SKIP_REGION_TRUE);
+    directBits(canvasP, blitListP, version, SKIP_REGION_TRUE);
 }
 
 
 
 static void
 do_pixmap(struct canvas * const canvasP,
+          blitList *      const blitListP,
           int             const version, 
           word            const rowBytes, 
           int             const is_region) {
@@ -3638,13 +3813,13 @@ do_pixmap(struct canvas * const canvasP,
         pm_message("transfer mode = %s", const_name(transfer_name, mode));
 
     if (is_region)
-        skip_poly_or_region(canvasP, version);
+        skip_poly_or_region(canvasP, blitListP, version);
 
     stage = "unpacking rectangle";
 
     unpackbits(ifp, &p.Bounds, rowBytes, p.pixelSize, &raster);
 
-    blit(srcRect, p.Bounds, raster, canvasP, 8,
+    blit(srcRect, p.Bounds, raster, canvasP, blitListP, 8,
          dstRect, picFrame, rowlen, color_table, mode);
 
     free(color_table);
@@ -3656,6 +3831,7 @@ do_pixmap(struct canvas * const canvasP,
 static void
 do_bitmap(FILE *          const ifP,
           struct canvas * const canvasP,
+          blitList *      const blitListP,
           int             const version, 
           int             const rowBytes, 
           int             const is_region) {
@@ -3683,13 +3859,13 @@ do_bitmap(FILE *          const ifP,
         pm_message("transfer mode = %s", const_name(transfer_name, mode));
 
     if (is_region)
-        skip_poly_or_region(canvasP, version);
+        skip_poly_or_region(canvasP, blitListP, version);
 
     stage = "unpacking rectangle";
 
     unpackbits(ifP, &Bounds, rowBytes, 1, &raster);
 
-    blit(srcRect, Bounds, raster, canvasP, 8,
+    blit(srcRect, Bounds, raster, canvasP, blitListP, 8,
          dstRect, picFrame, rowlen, color_table, mode);
 
     freeRaster(raster);
@@ -3701,6 +3877,7 @@ static drawFn BitsRect;
 
 static void
 BitsRect(struct canvas * const canvasP,
+         blitList *      const blitListP,
          int             const version) {
 
     word rowBytesWord;
@@ -3713,9 +3890,9 @@ BitsRect(struct canvas * const canvasP,
     interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes);
 
     if (pixMap)
-        do_pixmap(canvasP, version, rowBytes, 0);
+        do_pixmap(canvasP, blitListP, version, rowBytes, 0);
     else
-        do_bitmap(ifp, canvasP, version, rowBytes, 0);
+        do_bitmap(ifp, canvasP, blitListP, version, rowBytes, 0);
 }
 
 
@@ -3724,6 +3901,7 @@ static drawFn BitsRegion;
 
 static void
 BitsRegion(struct canvas * const canvasP,
+           blitList *      const blitListP,
            int             const version) {
     
     word rowBytesWord;
@@ -3736,9 +3914,9 @@ BitsRegion(struct canvas * const canvasP,
     interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes);
 
     if (pixMap)
-        do_pixmap(canvasP, version, rowBytes, 1);
+        do_pixmap(canvasP, blitListP, version, rowBytes, 1);
     else
-        do_bitmap(ifp, canvasP, version, rowBytes, 1);
+        do_bitmap(ifp, canvasP, blitListP, version, rowBytes, 1);
 }
 
 
@@ -3921,15 +4099,85 @@ static struct opdef const optable[] = {
 
 
 static void
+processOpcode(word const opcode, 
+              struct canvas * const canvasP,
+              blitList *      const blitListP,
+              unsigned int    const version) {
+
+    if (opcode < 0xa2) {
+        stage = optable[opcode].name;
+        if (verbose) {
+            if (streq(stage, "reserved"))
+                pm_message("reserved opcode=0x%x", opcode);
+            else
+                pm_message("Opcode: %s", optable[opcode].name);
+        }
+
+        if (optable[opcode].impl != NULL)
+            (*optable[opcode].impl)(canvasP, blitListP, version);
+        else if (optable[opcode].len >= 0)
+            skip(optable[opcode].len);
+        else {
+            switch (optable[opcode].len) {
+            case WORD_LEN: {
+                word const len = read_word();
+                skip(len);
+                } break;
+            default:
+                pm_error("can't do length %u", optable[opcode].len);
+            }
+        }
+    } else if (opcode == 0xc00) {
+        if (verbose)
+            pm_message("HeaderOp");
+        stage = "HeaderOp";
+        skip(24);
+    } else if (opcode >= 0xa2 && opcode <= 0xaf) {
+        stage = "skipping reserved";
+        if (verbose)
+            pm_message("%s 0x%x", stage, opcode);
+        skip(read_word());
+    } else if (opcode >= 0xb0 && opcode <= 0xcf) {
+        /* just a reserved opcode, no data */
+        if (verbose)
+            pm_message("reserved 0x%x", opcode);
+    } else if (opcode >= 0xd0 && opcode <= 0xfe) {
+        stage = "skipping reserved";
+        if (verbose)
+            pm_message("%s 0x%x", stage, opcode);
+        skip(read_long());
+    } else if (opcode >= 0x100 && opcode <= 0x7fff) {
+        stage = "skipping reserved";
+        if (verbose)
+            pm_message("%s 0x%x", stage, opcode);
+        skip((opcode >> 7) & 255);
+    } else if (opcode >= 0x8000 && opcode <= 0x80ff) {
+        /* just a reserved opcode */
+        if (verbose)
+            pm_message("reserved 0x%x", opcode);
+    } else if (opcode >= 0x8100) {
+        stage = "skipping reserved";
+        if (verbose)
+            pm_message("%s 0x%x", stage, opcode);
+        skip(read_long());
+    } else
+        pm_error("This program does not understand opcode 0x%04x", opcode);
+}
+
+
+
+static void
 interpret_pict(FILE * const ofP) {
 
     byte ch;
     word picSize;
     word opcode;
-    word len;
     unsigned int version;
     int i;
     struct canvas canvas;
+    blitList blitList;
+
+    initBlitList(&blitList);
 
     for (i = 0; i < 64; i++)
         pen_pat.pix[i] = bkpat.pix[i] = fillpat.pix[i] = 1;
@@ -3943,16 +4191,16 @@ interpret_pict(FILE * const ofP) {
     picSize = read_word();
 
     if (verbose)
-        pm_message("picture size = %d (0x%x)", picSize, picSize);
+        pm_message("picture size = %u (0x%x)", picSize, picSize);
 
     stage = "reading picture frame";
     read_rect(&picFrame);
 
     if (verbose) {
         dumpRect("Picture frame:", picFrame);
-        pm_message("Picture size is %d x %d",
-            picFrame.right - picFrame.left,
-            picFrame.bottom - picFrame.top);
+        pm_message("Picture size is %u x %u",
+                   picFrame.right - picFrame.left,
+                   picFrame.bottom - picFrame.top);
     }
 
     if (!fullres) {
@@ -3988,68 +4236,15 @@ interpret_pict(FILE * const ofP) {
     if (verbose)
         pm_message("PICT version %u", version);
 
-    while((opcode = get_op(version)) != 0xff) {
-        if (opcode < 0xa2) {
-            stage = optable[opcode].name;
-            if (verbose) {
-                if (streq(stage, "reserved"))
-                    pm_message("reserved opcode=0x%x", opcode);
-                else
-                    pm_message("Opcode: %s", optable[opcode].name);
-            }
-
-            if (optable[opcode].impl != NULL)
-                (*optable[opcode].impl)(&canvas, version);
-            else if (optable[opcode].len >= 0)
-                skip(optable[opcode].len);
-            else switch (optable[opcode].len) {
-            case WORD_LEN:
-                len = read_word();
-                skip(len);
-                break;
-            default:
-                pm_error("can't do length %u", optable[opcode].len);
-            }
-        } else if (opcode == 0xc00) {
-            if (verbose)
-                pm_message("HeaderOp");
-            stage = "HeaderOp";
-            skip(24);
-        } else if (opcode >= 0xa2 && opcode <= 0xaf) {
-            stage = "skipping reserved";
-            if (verbose)
-                pm_message("%s 0x%x", stage, opcode);
-            skip(read_word());
-        } else if (opcode >= 0xb0 && opcode <= 0xcf) {
-            /* just a reserved opcode, no data */
-            if (verbose)
-                pm_message("reserved 0x%x", opcode);
-        } else if (opcode >= 0xd0 && opcode <= 0xfe) {
-            stage = "skipping reserved";
-            if (verbose)
-                pm_message("%s 0x%x", stage, opcode);
-            skip(read_long());
-        } else if (opcode >= 0x100 && opcode <= 0x7fff) {
-            stage = "skipping reserved";
-            if (verbose)
-                pm_message("%s 0x%x", stage, opcode);
-            skip((opcode >> 7) & 255);
-        } else if (opcode >= 0x8000 && opcode <= 0x80ff) {
-            /* just a reserved opcode */
-            if (verbose)
-                pm_message("reserved 0x%x", opcode);
-        } else if (opcode >= 0x8100) {
-            stage = "skipping reserved";
-            if (verbose)
-                pm_message("%s 0x%x", stage, opcode);
-            skip(read_long());
-        } else
-            pm_error("This program does not understand opcode 0x%04x", opcode);
-    }
+    while((opcode = get_op(version)) != 0xff)
+        processOpcode(opcode, &canvas, fullres ? &blitList : NULL, version);
     
-    if (fullres)
-        do_blits(&canvas);
-
+    if (fullres) {
+        if (blitList.unblittableText)
+            pm_message("Warning: text is omitted from the output because "
+                       "we don't know how to do text with -fullres.");
+        doBlitList(&canvas, &blitList);
+    }
     outputPpm(ofP, canvas.planes);
 
     freePlanes(canvas.planes);
@@ -4123,6 +4318,7 @@ main(int argc, char * argv[]) {
 
     if (header) {
         stage = "Reading 512 byte header";
+        /* Note that the "header" in PICT is entirely comment! */
         skip(512);
     }
 
diff --git a/converter/ppm/ppmtomitsu.c b/converter/ppm/ppmtomitsu.c
index 837d9e2b..e59f09b3 100644
--- a/converter/ppm/ppmtomitsu.c
+++ b/converter/ppm/ppmtomitsu.c
@@ -1,10 +1,10 @@
-/* ppmtomitsu.c - read a portable pixmap and produce output for the
+/* ppmtomitsu.c - read a PPM image and produce output for the
 **                Mitsubishi S340-10 Thermo-Sublimation Printer
 **                (or the S3410-30 parallel interface)
 **
 ** Copyright (C) 1992,93 by S.Petra Zeidler
 ** Minor modifications by Ingo Wilken:
-x**  - mymalloc() and check_and_rotate() functions for often used
+**  - mymalloc() and check_and_rotate() functions for often used
 **    code fragments.  Reduces code size by a few KB.
 **  - use pm_error() instead of fprintf(stderr)
 **  - localized allocation of colorhastable
@@ -271,12 +271,12 @@ frametransferinit(int              const cols,
 
 
 static void
-colorRow(colorhist_vector const table,
-         unsigned int     const colanz,
-         hashinfo *       const colorhashtable) {
+doLookupTableColors(colorhist_vector const table,
+                    unsigned int     const nColor,
+                    hashinfo *       const colorhashtable) {
                 
     unsigned int colval;
-    for (colval = 0; colval < colanz; ++colval) {
+    for (colval = 0; colval < nColor; ++colval) {
         struct hashinfo * const hashchain =
             &colorhashtable[myhash((table[colval]).color)];
 
@@ -308,12 +308,12 @@ colorRow(colorhist_vector const table,
 
 
 static void
-grayRow(colorhist_vector const table,
-        unsigned int     const colanz,
-        hashinfo *       const colorhashtable) {
+doLookupTableGrays(colorhist_vector const table,
+                   unsigned int     const nColor,
+                   hashinfo *       const colorhashtable) {
 
     unsigned int colval;
-    for (colval = 0; colval < colanz; ++colval) {
+    for (colval = 0; colval < nColor; ++colval) {
         struct hashinfo * const hashchain =
             &colorhashtable[myhash((table[colval]).color)];
         struct hashinfo * hashrun;
@@ -329,8 +329,7 @@ grayRow(colorhist_vector const table,
         if (hashrun->flag == -1) {
             hashrun->color = (table[colval]).color;
             hashrun->flag  = colval;
-                    }
-        else {
+        } else {
             while (hashrun->next != NULL)
                 hashrun = hashrun->next;
             MALLOCVAR_NOFAIL(hashrun->next);
@@ -345,20 +344,28 @@ grayRow(colorhist_vector const table,
 
 
 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) {
-
+generateLookupTable(colorhist_vector const table,
+                    unsigned int     const nColor,
+                    unsigned int     const cols,
+                    unsigned int     const rows,
+                    int              const format,
+                    int              const sharpness,
+                    int              const enlarge,
+                    int              const copy,
+                    struct mediasize const medias,
+                    hashinfo **      const colorhashtableP) {
+/*----------------------------------------------------------------------------
+   Write to the output file the palette (color lookup table) indicated by
+   'table' and generate a hash table to use with it: *colorhashtableP.
+
+   Also write the various properties 'sharpness', 'enlarge', 'copy', and
+   'medias' to the output file.
+-----------------------------------------------------------------------------*/
     hashinfo * colorhashtable;
 
-    pm_message("found %u colors - using the lookuptable-method", colanz);
+    lookuptableinit(sharpness, enlarge, copy, medias);
+
+    /* Initialize the hash table to empty */
 
     MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE);
     {
@@ -369,34 +376,75 @@ useLookupTable(pixel **         const pixels,
         }
     }
 
-    lookuptableinit(sharpness, enlarge, copy, medias);
     switch(PPM_FORMAT_TYPE(format)) {
     case PPM_TYPE:
-        colorRow(table, colanz, colorhashtable);
+        doLookupTableColors(table, nColor, colorhashtable);
         break;
     default:
-        grayRow(table, colanz, colorhashtable);
+        doLookupTableGrays(table, nColor, 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;
+
+    *colorhashtableP = colorhashtable;
+}
+
+
+
+static void
+writeColormapRaster(pixel **         const pixels,
+                    unsigned int     const cols,
+                    unsigned int     const rows,
+                    hashinfo *       const colorhashtable) {
+/*----------------------------------------------------------------------------
+   Write a colormapped raster: write the pixels pixels[][] (dimensions cols x
+   rows) as indices into the colormap (palette; lookup table) indicated by
+   'colorhashtable'.
+-----------------------------------------------------------------------------*/
+    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);
+            p = hashchain;
+            while (!PPM_EQUAL((p->color), pixrow[col])) {
+                assert(p->next);
+                p = p->next;
             }
+            datum(p->flag);
         }
     }
+}
+
+
+
+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 nColor) {
+
+    hashinfo * colorhashtable;
+
+    pm_message("found %u colors - using the lookuptable-method", nColor);
+
+    generateLookupTable(table, nColor, cols, rows, format,
+                        sharpness, enlarge, copy, medias,
+                        &colorhashtable);
+
+    writeColormapRaster(pixels, cols, rows, colorhashtable);
+
     free(colorhashtable);
 }
 
@@ -540,7 +588,7 @@ doTiny(FILE *           const ifP,
             data(blurow, cols);
             data(blurow, cols);
             data(blurow, cols);
-            }
+        }
         }
     }
 }
@@ -649,21 +697,21 @@ main(int argc, char * argv[]) {
 
     } else {
         pixel ** pixels;
-        int colanz;
+        int nColor;
         colorhist_vector table;
         unsigned int row;
 
         pixels = ppm_allocarray(cols, rows);
-        for (row = 0; row < rows; row++)
+        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);
+                                     &nColor);
         if (table)
             useLookupTable(pixels, table, sharpness, enlarge, copy, medias,
-                           cols, rows, format, colanz);
+                           cols, rows, format, nColor);
         else
             useNoLookupTable(pixels, sharpness, enlarge, copy, medias,
                              cols, rows, format);
@@ -673,4 +721,3 @@ main(int argc, char * argv[]) {
     pm_close(ifP);
     return 0;
 }
-
diff --git a/converter/ppm/ppmtomitsu.test b/converter/ppm/ppmtomitsu.test
index 1805838a..f574d927 100644
--- a/converter/ppm/ppmtomitsu.test
+++ b/converter/ppm/ppmtomitsu.test
@@ -2,9 +2,9 @@ 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
+echo Test 3.  Should print 3201293405 310
 ./ppmtomitsu ../../testgrid.pbm | cksum 
-echo Test 4.  Should print 629834989 752
+echo Test 4.  Should print 3354679572 752
 ./ppmtomitsu -tiny ../../testgrid.pbm | cksum 
 echo Test 5.  Should print 3999654426 101549
 ./ppmtomitsu -tiny ../../testimg.ppm | cksum 
diff --git a/converter/ppm/ppmtopict.c b/converter/ppm/ppmtopict.c
index 22456857..1b9f2d5c 100644
--- a/converter/ppm/ppmtopict.c
+++ b/converter/ppm/ppmtopict.c
@@ -398,7 +398,7 @@ char *packed;
 		*p++ = counttochar(count);
 
 	packcols = p - packed;		/* how many did we write? */
-	if (cols > 250)
+	if (cols > 200)
 	{
 		putShort(fd, packcols);
 		oc = packcols + 2;
@@ -436,7 +436,7 @@ char *packed;
 	bzero(aux, cols); /* aux?? */
 #endif /*notdef*/
 	bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT;
-	if (bc > 250)
+	if (bc > 200)
 	{
 		putShort(fd, bc);
 		oc = bc + 2;