about summary refs log tree commit diff
path: root/converter
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2017-06-30 03:27:10 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2017-06-30 03:27:10 +0000
commit08d938dc6fc6b30e5da6733b52c97169c0d24f8a (patch)
tree92673cd6a5755fc209078cc6b6a42602defc0212 /converter
parente21f4e95d897c93a4779bf78c71f1341d164a222 (diff)
downloadnetpbm-mirror-08d938dc6fc6b30e5da6733b52c97169c0d24f8a.tar.gz
netpbm-mirror-08d938dc6fc6b30e5da6733b52c97169c0d24f8a.tar.xz
netpbm-mirror-08d938dc6fc6b30e5da6733b52c97169c0d24f8a.zip
Copy Development as new Advanced
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@3018 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter')
-rw-r--r--converter/other/bmptopnm.c6
-rw-r--r--converter/other/cameratopam/camera.c6
-rw-r--r--converter/other/cameratopam/foveon.c2
-rw-r--r--converter/other/fiasco/codec/approx.c563
-rw-r--r--converter/other/pamtosvg/vector.c2
-rw-r--r--converter/other/pamtotiff.c81
-rw-r--r--converter/other/svgtopam.c253
-rw-r--r--converter/other/tifftopnm.c2
-rw-r--r--converter/pbm/g3.h297
-rw-r--r--converter/pbm/g3topbm.c96
-rw-r--r--converter/pbm/pbmtog3.c717
-rw-r--r--converter/pbm/pbmtox10bm24
-rw-r--r--converter/ppm/ppmtoarbtxt.c52
-rw-r--r--converter/ppm/ppmtompeg/jrevdct.c44
-rw-r--r--converter/ppm/ppmtompeg/mfwddct.c31
15 files changed, 1375 insertions, 801 deletions
diff --git a/converter/other/bmptopnm.c b/converter/other/bmptopnm.c
index 49e730fd..018b8326 100644
--- a/converter/other/bmptopnm.c
+++ b/converter/other/bmptopnm.c
@@ -1400,8 +1400,8 @@ isValidBmpBpp(unsigned int const cBitCount) {
 static void
 readBmp(FILE *               const ifP, 
         unsigned char ***    const bmpRasterP, 
-        int *                const colsP, 
-        int *                const rowsP,
+        unsigned int *       const colsP, 
+        unsigned int *       const rowsP,
         bool *               const grayPresentP, 
         bool *               const colorPresentP,
         unsigned int *       const cBitCountP, 
@@ -1566,7 +1566,7 @@ main(int argc, const char ** argv) {
            black and white and whether it has colors other than black, white,
            and gray.
         */
-    int cols, rows;
+    unsigned int cols, rows;
     unsigned char ** bmpRaster;
         /* The raster part of the BMP image, as a row x column array, with
            each element being a raw byte from the BMP raster.  Note that
diff --git a/converter/other/cameratopam/camera.c b/converter/other/cameratopam/camera.c
index 503551f1..f6196777 100644
--- a/converter/other/cameratopam/camera.c
+++ b/converter/other/cameratopam/camera.c
@@ -1023,6 +1023,7 @@ static void  sony_decrypt (unsigned *data, int len, int start, int key)
 {
   static uint32_t pad[128];
   unsigned int p;
+  unsigned int i;
 
   if (start) {
     for (p=0; p < 4; p++)
@@ -1047,8 +1048,9 @@ static void  sony_decrypt (unsigned *data, int len, int start, int key)
         pad[p] = u.word;
     }
   }
-  while (len--)
-    *data++ ^= pad[p++ & 0x7f] = pad[(p+1) & 0x7f] ^ pad[(p+65) & 0x7f];
+  for (i = 0, p = 0; i < len; ++i, ++p) {
+    *data++ ^= pad[p & 0x7f] = pad[(p+1) & 0x7f] ^ pad[(p+65) & 0x7f];
+  }
 }
 
 void
diff --git a/converter/other/cameratopam/foveon.c b/converter/other/cameratopam/foveon.c
index a3e5449a..992f3883 100644
--- a/converter/other/cameratopam/foveon.c
+++ b/converter/other/cameratopam/foveon.c
@@ -1,6 +1,6 @@
 /* This code is licensed to the public by its copyright owners under GPL. */
 
-#define _XOPEN_SOURCE   /* get M_PI */
+#define _XOPEN_SOURCE 500  /* get M_PI in math.h */
 
 #include <stdio.h>
 #include <assert.h>
diff --git a/converter/other/fiasco/codec/approx.c b/converter/other/fiasco/codec/approx.c
index d47bac62..d8fefcaa 100644
--- a/converter/other/fiasco/codec/approx.c
+++ b/converter/other/fiasco/codec/approx.c
@@ -294,9 +294,9 @@ static bool_t used [MAXSTATES];
 
 static void 
 matching_pursuit (mp_t *mp, bool_t full_search, real_t price,
-          unsigned max_edges, int y_state, const range_t *range,
-          const domain_pool_t *domain_pool, const coeff_t *coeff,
-          const wfa_t *wfa, const coding_t *c)
+                  unsigned max_edges, int y_state, const range_t *range,
+                  const domain_pool_t *domain_pool, const coeff_t *coeff,
+                  const wfa_t *wfa, const coding_t *c)
 /*
  *  Find an approximation of the current 'range' with a linear
  *  combination of vectors of the 'domain_pool'. The linear
@@ -320,303 +320,310 @@ matching_pursuit (mp_t *mp, bool_t full_search, real_t price,
  *  vectors, factors, rate, distortion and costs are stored in 'mp'
  */
 {
-   unsigned  n;         /* current vector of the OB */
-   int       index;         /* best fitting domain image */
-   unsigned  domain;        /* counter */
-   real_t    norm;          /* norm of range image */
-   real_t    additional_bits;   /* bits for mc, nd, and tree */
-   word_t   *domain_blocks;     /* current set of domain images */
-   const real_t  min_norm = 2e-3;   /* lower bound of norm */
-   unsigned      best_n   = 0;
-   unsigned  size     = size_of_level (range->level);
+    unsigned  n;         /* current vector of the OB */
+    int       index;         /* best fitting domain image */
+    unsigned  domain;        /* counter */
+    real_t    norm;          /* norm of range image */
+    real_t    additional_bits;   /* bits for mc, nd, and tree */
+    word_t   *domain_blocks;     /* current set of domain images */
+    const real_t  min_norm = 2e-3;   /* lower bound of norm */
+    unsigned      best_n   = 0;
+    unsigned  size     = size_of_level (range->level);
  
-   /*
-    *  Initialize domain pool and inner product arrays
-    */
-   domain_blocks = domain_pool->generate (range->level, y_state, wfa,
-                      domain_pool->model);
-   for (domain = 0; domain_blocks [domain] >= 0; domain++)
-   {
-      used [domain] = NO;
-      rem_denominator [domain]      /* norm of domain */
-     = get_ip_state_state (domain_blocks [domain], domain_blocks [domain],
-                   range->level, c);
-      if (rem_denominator [domain] / size < min_norm)
-     used [domain] = YES;       /* don't use domains with small norm */
-      else
-     rem_numerator [domain]     /* inner product <s_domain, b> */
-        = get_ip_image_state (range->image, range->address,
-                  range->level, domain_blocks [domain], c);
-      if (!used [domain] && fabs (rem_numerator [domain]) < min_norm)
-     used [domain] = YES;
-   }
+    /*
+     *  Initialize domain pool and inner product arrays
+     */
+    domain_blocks = domain_pool->generate (range->level, y_state, wfa,
+                                           domain_pool->model);
+    for (domain = 0; domain_blocks [domain] >= 0; domain++)
+    {
+        used [domain] = NO;
+        rem_denominator [domain] =     /* norm of domain */
+            get_ip_state_state (domain_blocks [domain], domain_blocks [domain],
+                                range->level, c);
+        if (rem_denominator [domain] / size < min_norm)
+            used [domain] = YES;       /* don't use domains with small norm */
+        else
+            rem_numerator [domain]     /* inner product <s_domain, b> */
+                = get_ip_image_state (range->image, range->address,
+                                      range->level, domain_blocks [domain], c);
+        if (!used [domain] && fabs (rem_numerator [domain]) < min_norm)
+            used [domain] = YES;
+    }
 
-   /*
-    *  Exclude all domain blocks given in array 'mp->exclude'
-    */
-   for (n = 0; isdomain (mp->exclude [n]); n++)
-      used [mp->exclude [n]] = YES;
+    /*
+     *  Exclude all domain blocks given in array 'mp->exclude'
+     */
+    for (n = 0; isdomain (mp->exclude [n]); n++)
+        used [mp->exclude [n]] = YES;
 
-   /*
-    *  Compute the approximation costs if 'range' is approximated with
-    *  no linear combination, i.e. the error is equal to the square
-    *  of the image norm and the size of the automaton is determined by
-    *  storing only zero elements in the current matrix row
-    */
-   for (norm = 0, n = 0; n < size; n++)
-      norm += square (c->pixels [range->address * size + n]);
-
-   additional_bits = range->tree_bits + range->mv_tree_bits
-             + range->mv_coord_bits + range->nd_tree_bits
-             + range->nd_weights_bits;
-
-   mp->err          = norm;
-   mp->weights_bits = 0;
-   mp->matrix_bits  = domain_pool->bits (domain_blocks, NULL, range->level,
-                     y_state, wfa, domain_pool->model);
-   mp->costs        = (mp->matrix_bits + mp->weights_bits
-               + additional_bits) * price + mp->err;
-
-   n = 0;
-   do 
-   {
-      /*
-       *  Current approximation is: b = d_0 o_0 + ... + d_(n-1) o_(n-1)
-       *  with corresponding costs 'range->err + range->bits * p'.
-       *  For all remaining state images s_i (used[s_i] == NO) set
-       *  o_n : = s_i - \sum(k = 0, ... , n-1) {(<s_i, o_k> / ||o_k||^2) o_k}
-       *  and try to beat current costs.
-       *  Choose that vector for the next orthogonalization step,
-       *  which has minimal costs: s_index.
-       *  (No progress is indicated by index == -1)
-       */
-      
-      real_t min_matrix_bits  = 0;
-      real_t min_weights_bits = 0;
-      real_t min_error        = 0;
-      real_t min_weight [MAXEDGES];
-      real_t min_costs = full_search ? MAXCOSTS : mp->costs;
-      
-      for (index = -1, domain = 0; domain_blocks [domain] >= 0; domain++) 
-     if (!used [domain]) 
-     {
-        real_t    matrix_bits, weights_bits;
+    /*
+     *  Compute the approximation costs if 'range' is approximated with
+     *  no linear combination, i.e. the error is equal to the square
+     *  of the image norm and the size of the automaton is determined by
+     *  storing only zero elements in the current matrix row
+     */
+    for (norm = 0, n = 0; n < size; n++)
+        norm += square (c->pixels [range->address * size + n]);
+
+    additional_bits = range->tree_bits + range->mv_tree_bits
+        + range->mv_coord_bits + range->nd_tree_bits
+        + range->nd_weights_bits;
+
+    mp->err          = norm;
+    mp->weights_bits = 0;
+    mp->matrix_bits  = domain_pool->bits (domain_blocks, NULL, range->level,
+                                          y_state, wfa, domain_pool->model);
+    mp->costs        = (mp->matrix_bits + mp->weights_bits
+                        + additional_bits) * price + mp->err;
+
+    n = 0;
+    do 
+    {
         /*
-         *  To speed up the search through the domain images,
-         *  the costs of using domain image 'domain' as next vector
-         *  can be approximated in a first step:
-         *  improvement of image quality
-         *    <= square (rem_numerator[domain]) / rem_denominator[domain]
+         *  Current approximation is: b = d_0 o_0 + ... + d_(n-1) o_(n-1)
+         *  with corresponding costs 'range->err + range->bits * p'.
+         *  For all remaining state images s_i (used[s_i] == NO) set
+         *  o_n : = s_i - \sum(k = 0, ... , n-1) {(<s_i, o_k> / ||o_k||^2) o_k}
+         *  and try to beat current costs.
+         *  Choose that vector for the next orthogonalization step,
+         *  which has minimal costs: s_index.
+         *  (No progress is indicated by index == -1)
          */
-        {
-          word_t   vectors [MAXEDGES + 1];
-          word_t   states [MAXEDGES + 1];
-          real_t   weights [MAXEDGES + 1];
-          unsigned i, k;
+      
+        real_t min_matrix_bits  = 0;
+        real_t min_weights_bits = 0;
+        real_t min_error        = 0;
+        real_t min_weight [MAXEDGES];
+        real_t min_costs = full_search ? MAXCOSTS : mp->costs;
+      
+        for (index = -1, domain = 0; domain_blocks [domain] >= 0; domain++) 
+            if (!used [domain]) 
+            {
+                real_t    matrix_bits, weights_bits;
+                /*
+                 *  To speed up the search through the domain images,
+                 *  the costs of using domain image 'domain' as next vector
+                 *  can be approximated in a first step:
+                 *  improvement of image quality
+                 *  <= square (rem_numerator[domain]) / rem_denominator[domain]
+                 */
+                {
+                    word_t   vectors [MAXEDGES + 1];
+                    word_t   states [MAXEDGES + 1];
+                    real_t   weights [MAXEDGES + 1];
+                    unsigned i, k;
           
-          for (i = 0, k = 0; k < n; k++)
-             if (mp->weight [k] != 0)
-             {
-            vectors [i] = mp->indices [k];
-            states [i]  = domain_blocks [vectors [i]];
-            weights [i] = mp->weight [k];
-            i++;
-             }
-          vectors [i]     = domain;
-          states [i]      = domain_blocks [domain];
-          weights [i]     = 0.5;
-          vectors [i + 1] = -1;
-          states [i + 1]  = -1;
-
-          weights_bits = coeff->bits (weights, states, range->level,
-                          coeff);
-          matrix_bits = domain_pool->bits (domain_blocks, vectors,
-                           range->level, y_state,
-                           wfa, domain_pool->model);
-        }
-        if (((matrix_bits + weights_bits + additional_bits) * price +
-         mp->err -
-         square (rem_numerator [domain]) / rem_denominator [domain])
-        < min_costs)
-        {
-           /*
-        *  1.) Compute the weights (linear factors) c_i of the
-        *  linear combination
-        *  b = c_0 v_0 + ... + c_(n-1) v_(n-1) + c_n v_'domain'
-        *  Use backward substitution to obtain c_i from the linear
-        *  factors of the lin. comb. b = d_0 o_0 + ... + d_n o_n
-        *  of the corresponding orthogonal vectors {o_0, ..., o_n}.
-        *  Vector o_n of the orthogonal basis is obtained by using
-        *  vector 'v_domain' in step n of the Gram Schmidt
-        *  orthogonalization (see above for definition of o_n).
-        *  Recursive formula for the coefficients c_i:
-        *  c_n := <b, o_n> / ||o_n||^2
-        *  for i = n - 1, ... , 0:
-        *  c_i := <b, o_i> / ||o_i||^2 +
-        *          \sum (k = i + 1, ... , n){ c_k <v_k, o_i>
-        *                   / ||o_i||^2 }
-        *  2.) Because linear factors are stored with reduced precision
-        *  factor c_i is rounded with the given precision in step i
-        *  of the recursive formula. 
-        */
-
-           unsigned k;      /* counter */
-           int      l;      /* counter */
-           real_t   m_bits;     /* number of matrix bits to store */
-           real_t   w_bits;     /* number of weights bits to store */
-           real_t   r [MAXEDGES];   /* rounded linear factors */
-           real_t   f [MAXEDGES];   /* linear factors */
-           int      v [MAXEDGES];   /* mapping of domains to vectors */
-           real_t   costs;      /* current approximation costs */
-           real_t   m_err;      /* current approximation error */
-
-           f [n] = rem_numerator [domain] / rem_denominator [domain];
-           v [n] = domain;      /* corresponding mapping */
-           for (k = 0; k < n; k++)
-           {
-          f [k] = ip_image_ortho_vector [k] / norm_ortho_vector [k];
-          v [k] = mp->indices [k];
-           }
+                    for (i = 0, k = 0; k < n; k++)
+                        if (mp->weight [k] != 0)
+                        {
+                            vectors [i] = mp->indices [k];
+                            states [i]  = domain_blocks [vectors [i]];
+                            weights [i] = mp->weight [k];
+                            i++;
+                        }
+                    vectors [i]     = domain;
+                    states [i]      = domain_blocks [domain];
+                    weights [i]     = 0.5;
+                    vectors [i + 1] = -1;
+                    states [i + 1]  = -1;
+
+                    weights_bits = coeff->bits (weights, states, range->level,
+                                                coeff);
+                    matrix_bits = domain_pool->bits (domain_blocks, vectors,
+                                                     range->level, y_state,
+                                                     wfa, domain_pool->model);
+                }
+                if (((matrix_bits + weights_bits + additional_bits) * price +
+                     mp->err -
+                     square (rem_numerator[domain]) / rem_denominator[domain])
+                    < min_costs)
+                {
+                    /*
+                     *  1.) Compute the weights (linear factors) c_i of the
+                     *  linear combination
+                     *  b = c_0 v_0 + ... + c_(n-1) v_(n-1) + c_n v_'domain'
+                     *  Use backward substitution to obtain c_i from the linear
+                     *  factors of the lin. comb. b = d_0 o_0 + ... + d_n o_n
+                     *  of the corresponding orthogonal vectors {o_0, ..., o_n}.
+                     *  Vector o_n of the orthogonal basis is obtained by using
+                     *  vector 'v_domain' in step n of the Gram Schmidt
+                     *  orthogonalization (see above for definition of o_n).
+                     *  Recursive formula for the coefficients c_i:
+                     *  c_n := <b, o_n> / ||o_n||^2
+                     *  for i = n - 1, ... , 0:
+                     *  c_i := <b, o_i> / ||o_i||^2 +
+                     *          \sum (k = i + 1, ... , n){ c_k <v_k, o_i>
+                     *                   / ||o_i||^2 }
+                     *  2.) Because linear factors are stored with reduced
+                     *  precision factor c_i is rounded with the given
+                     *  precision in step i of the recursive formula.
+                     */
+
+                    unsigned k;      /* counter */
+                    int      l;      /* counter */
+                    real_t   m_bits;     /* number of matrix bits to store */
+                    real_t   w_bits;     /* number of weights bits to store */
+                    real_t   r [MAXEDGES];   /* rounded linear factors */
+                    real_t   f [MAXEDGES];   /* linear factors */
+                    int      v [MAXEDGES];   /* mapping of domains to vectors*/
+                    real_t   costs;      /* current approximation costs */
+                    real_t   m_err;      /* current approximation error */
+
+                    f [n] = rem_numerator [domain] / rem_denominator [domain];
+                    v [n] = domain;      /* corresponding mapping */
+                    for (k = 0; k < n; k++)
+                    {
+                        f[k] = ip_image_ortho_vector[k] / norm_ortho_vector[k];
+                        v [k] = mp->indices [k];
+                    }
         
-           for (l = n; l >= 0; l--) 
-           {
-          rpf_t *rpf = domain_blocks [v [l]]
-                   ? coeff->rpf : coeff->dc_rpf;
+                    for (l = n; l >= 0; --l) {
+                        rpf_t * const rpf = domain_blocks[v[l]]
+                            ? coeff->rpf : coeff->dc_rpf;
+
+                        unsigned int k;
 
-          r [l] = f [l] = btor (rtob (f [l], rpf), rpf);
+                        r[l] = f[l] = btor(rtob(f[l], rpf), rpf);
+
+                        {
+                            real_t const fl = f[l];
              
-          for (k = 0; k < (unsigned) l; k++)
-             f [k] -= f [l] * ip_domain_ortho_vector [v [l]][k]
-                  / norm_ortho_vector [k] ;
-           } 
-
-           /*
-        *  Compute the number of output bits of the linear combination
-        *  and store the weights with reduced precision. The
-        *  resulting linear combination is
-        *  b = r_0 v_0 + ... + r_(n-1) v_(n-1) + r_n v_'domain'
-        */
-           {
-          word_t vectors [MAXEDGES + 1];
-          word_t states [MAXEDGES + 1];
-          real_t weights [MAXEDGES + 1];
-          int    i;
+                            for (k = 0; k < l; ++k) {
+                                f[k] -= fl * ip_domain_ortho_vector[v[l]][k]
+                                    / norm_ortho_vector[k];
+                            }
+                        }
+                    } 
+
+                    /*
+                     *  Compute the number of output bits of the linear
+                     *  combination and store the weights with reduced
+                     *  precision. The resulting linear combination is
+                     *  b = r_0 v_0 + ... + r_(n-1) v_(n-1) + r_n v_'domain'
+                     */
+                    {
+                        word_t vectors [MAXEDGES + 1];
+                        word_t states [MAXEDGES + 1];
+                        real_t weights [MAXEDGES + 1];
+                        int    i;
           
-          for (i = 0, k = 0; k <= n; k++)
-             if (f [k] != 0)
-             {
-            vectors [i] = v [k];
-            states [i]  = domain_blocks [v [k]];
-            weights [i] = f [k];
-            i++;
-             }
-          vectors [i] = -1;
-          states [i]  = -1;
-
-          w_bits = coeff->bits (weights, states, range->level, coeff);
-          m_bits = domain_pool->bits (domain_blocks, vectors,
-                          range->level, y_state,
-                          wfa, domain_pool->model);
-           }
+                        for (i = 0, k = 0; k <= n; k++)
+                            if (f [k] != 0)
+                            {
+                                vectors [i] = v [k];
+                                states [i]  = domain_blocks [v [k]];
+                                weights [i] = f [k];
+                                i++;
+                            }
+                        vectors [i] = -1;
+                        states [i]  = -1;
+
+                        w_bits =
+                            coeff->bits(weights, states, range->level, coeff);
+                        m_bits = domain_pool->bits (domain_blocks, vectors,
+                                                    range->level, y_state,
+                                                    wfa, domain_pool->model);
+                    }
            
-           /*
-        *  To compute the approximation error, the corresponding
-        *  linear factors of the linear combination 
-        *  b = r_0 o_0 + ... + r_(n-1) o_(n-1) + r_n o_'domain'
-        *  with orthogonal vectors must be computed with following
-        *  formula:
-        *  r_i := r_i +
-        *          \sum (k = i + 1, ... , n) { r_k <v_k, o_i>
-        *                   / ||o_i||^2 }
-        */
-           for (l = 0; (unsigned) l <= n; l++)
-           {
-          /*
-           *  compute <v_n, o_n>
-           */
-          real_t a;
-
-          a = get_ip_state_state (domain_blocks [v [l]],
-                      domain_blocks [domain],
-                      range->level, c);
-          for (k = 0; k < n; k++) 
-             a -= ip_domain_ortho_vector [v [l]][k]
-              / norm_ortho_vector [k]
-              * ip_domain_ortho_vector [domain][k];
-          ip_domain_ortho_vector [v [l]][n] = a;
-           }
-           norm_ortho_vector [n]     = rem_denominator [domain];
-           ip_image_ortho_vector [n] = rem_numerator [domain];
+                    /*
+                     *  To compute the approximation error, the corresponding
+                     *  linear factors of the linear combination 
+                     *  b = r_0 o_0 + ... + r_(n-1) o_(n-1) + r_n o_'domain'
+                     *  with orthogonal vectors must be computed with following
+                     *  formula:
+                     *  r_i := r_i +
+                     *          \sum (k = i + 1, ... , n) { r_k <v_k, o_i>
+                     *                   / ||o_i||^2 }
+                     */
+                    for (l = 0; (unsigned) l <= n; l++)
+                    {
+                        /*
+                         *  compute <v_n, o_n>
+                         */
+                        real_t a;
+
+                        a = get_ip_state_state (domain_blocks [v [l]],
+                                                domain_blocks [domain],
+                                                range->level, c);
+                        for (k = 0; k < n; k++) 
+                            a -= ip_domain_ortho_vector [v [l]][k]
+                                / norm_ortho_vector [k]
+                                * ip_domain_ortho_vector [domain][k];
+                        ip_domain_ortho_vector [v [l]][n] = a;
+                    }
+                    norm_ortho_vector [n]     = rem_denominator [domain];
+                    ip_image_ortho_vector [n] = rem_numerator [domain];
         
-           for (k = 0; k <= n; k++)
-          for (l = k + 1; (unsigned) l <= n; l++)
-             r [k] += ip_domain_ortho_vector [v [l]][k] * r [l]
-                  / norm_ortho_vector [k];
-           /*
-        *  Compute approximation error:
-        *  error := ||b||^2 +
-        *  \sum (k = 0, ... , n){r_k^2 ||o_k||^2 - 2 r_k <b, o_k>}
-        */
-           m_err = norm;
-           for (k = 0; k <= n; k++)
-          m_err += square (r [k]) * norm_ortho_vector [k]
-             - 2 * r [k] * ip_image_ortho_vector [k];
-           if (m_err < 0)       /* TODO: return MAXCOSTS */
-          warning ("Negative image norm: %f"
-               " (current domain: %d, level = %d)",
-               (double) m_err, domain, range->level);
-
-           costs = (m_bits + w_bits + additional_bits) * price + m_err;
-           if (costs < min_costs)   /* found a better approximation */
-           {
-          index            = domain;
-          min_costs        = costs;
-          min_matrix_bits  = m_bits;
-          min_weights_bits = w_bits;
-          min_error        = m_err;
-          for (k = 0; k <= n; k++)
-             min_weight [k] = f [k];
-           }
-        }
-     }
+                    for (k = 0; k <= n; k++)
+                        for (l = k + 1; (unsigned) l <= n; l++)
+                            r [k] += ip_domain_ortho_vector [v [l]][k] * r [l]
+                                / norm_ortho_vector [k];
+                    /*
+                     *  Compute approximation error:
+                     *  error := ||b||^2 +
+                     *  \sum (k = 0, ... , n){r_k^2 ||o_k||^2 - 2 r_k <b, o_k>}
+                     */
+                    m_err = norm;
+                    for (k = 0; k <= n; k++)
+                        m_err += square (r [k]) * norm_ortho_vector [k]
+                            - 2 * r [k] * ip_image_ortho_vector [k];
+                    if (m_err < 0)       /* TODO: return MAXCOSTS */
+                        warning ("Negative image norm: %f"
+                                 " (current domain: %d, level = %d)",
+                                 (double) m_err, domain, range->level);
+
+                    costs = (m_bits + w_bits + additional_bits) * price + m_err;
+                    if (costs < min_costs)   /* found a better approximation */
+                    {
+                        index            = domain;
+                        min_costs        = costs;
+                        min_matrix_bits  = m_bits;
+                        min_weights_bits = w_bits;
+                        min_error        = m_err;
+                        for (k = 0; k <= n; k++)
+                            min_weight [k] = f [k];
+                    }
+                }
+            }
       
-      if (index >= 0)           /* found a better approximation */
-      {
-     if (min_costs < mp->costs)
-     {
-        unsigned k;
+        if (index >= 0)           /* found a better approximation */
+        {
+            if (min_costs < mp->costs)
+            {
+                unsigned k;
         
-        mp->costs        = min_costs;
-        mp->err          = min_error;
-        mp->matrix_bits  = min_matrix_bits;
-        mp->weights_bits = min_weights_bits;
+                mp->costs        = min_costs;
+                mp->err          = min_error;
+                mp->matrix_bits  = min_matrix_bits;
+                mp->weights_bits = min_weights_bits;
         
-        for (k = 0; k <= n; k++)
-           mp->weight [k] = min_weight [k];
+                for (k = 0; k <= n; k++)
+                    mp->weight [k] = min_weight [k];
 
-        best_n = n + 1;
-     }
+                best_n = n + 1;
+            }
      
-     mp->indices [n] = index;
-     mp->into [n]    = domain_blocks [index];
+            mp->indices [n] = index;
+            mp->into [n]    = domain_blocks [index];
 
-     used [index] = YES;
+            used [index] = YES;
 
-     /* 
-      *  Gram-Schmidt orthogonalization step n 
-      */
-     orthogonalize (index, n, range->level, min_norm, domain_blocks, c);
-     n++;
-      } 
-   } 
-   while (n < max_edges && index >= 0);
+            /* 
+             *  Gram-Schmidt orthogonalization step n 
+             */
+            orthogonalize (index, n, range->level, min_norm, domain_blocks, c);
+            n++;
+        } 
+    } 
+    while (n < max_edges && index >= 0);
 
-   mp->indices [best_n] = NO_EDGE;
+    mp->indices [best_n] = NO_EDGE;
    
-   mp->costs = (mp->matrix_bits + mp->weights_bits + additional_bits) * price
-           + mp->err;
+    mp->costs = (mp->matrix_bits + mp->weights_bits + additional_bits) * price
+        + mp->err;
 
-   Free (domain_blocks);
+    Free (domain_blocks);
 }
 
 static void
diff --git a/converter/other/pamtosvg/vector.c b/converter/other/pamtosvg/vector.c
index 0a5ef3a9..771e5f27 100644
--- a/converter/other/pamtosvg/vector.c
+++ b/converter/other/pamtosvg/vector.c
@@ -1,6 +1,6 @@
 /* vector.c: vector/point operations. */
 
-#define _XOPEN_SOURCE   /* Make sure M_PI is in <math.h> */
+#define _XOPEN_SOURCE 500  /* get M_PI in math.h */
 #include <math.h>
 #include <errno.h>
 #include <assert.h>
diff --git a/converter/other/pamtotiff.c b/converter/other/pamtotiff.c
index 32057e55..139b1fd7 100644
--- a/converter/other/pamtotiff.c
+++ b/converter/other/pamtotiff.c
@@ -136,6 +136,44 @@ validateTagList(struct optNameValue const taglist[]) {
 
 
 static void
+parseIndexbits(bool          const indexbitsSpec,
+               char **       const indexbits,
+               CmdlineInfo * const cmdlineP) {
+
+    if (indexbitsSpec) {
+        unsigned int i;
+
+        /* Set initial values */
+        cmdlineP->indexsizeAllowed.b1 = FALSE;
+        cmdlineP->indexsizeAllowed.b2 = FALSE;
+        cmdlineP->indexsizeAllowed.b4 = FALSE;
+        cmdlineP->indexsizeAllowed.b8 = FALSE;
+
+        for (i = 0; indexbits[i]; ++i) {
+            const char * const thisItem = indexbits[i];
+            if (streq(thisItem, "1"))
+                cmdlineP->indexsizeAllowed.b1 = TRUE;
+            else if (streq(thisItem, "2"))
+                cmdlineP->indexsizeAllowed.b2 = TRUE;
+            else if (streq(thisItem, "4"))
+                cmdlineP->indexsizeAllowed.b4 = TRUE;
+            else if (streq(thisItem, "8"))
+                cmdlineP->indexsizeAllowed.b8 = TRUE;
+            else
+                pm_error("Invalid item in -indexbits list: '%s'.  "
+                         "We recognize only 1, 2, 4, and 8", thisItem);
+        }           
+    } else {
+        cmdlineP->indexsizeAllowed.b1 = FALSE;
+        cmdlineP->indexsizeAllowed.b2 = FALSE;
+        cmdlineP->indexsizeAllowed.b4 = FALSE;
+        cmdlineP->indexsizeAllowed.b8 = TRUE;
+    }
+}
+
+
+
+static void
 parseCommandLine(int                 argc,
                  const char ** const argv,
                  CmdlineInfo * const cmdlineP) {
@@ -149,7 +187,7 @@ parseCommandLine(int                 argc,
 
     unsigned int none, packbits, lzw, g3, g4, msb2lsb, lsb2msb, opt_2d, fill;
     unsigned int flate, adobeflate;
-    char * indexbits;
+    char ** indexbits;
     char * resolutionunit;
 
     unsigned int appendSpec, outputSpec, predictorSpec, rowsperstripSpec,
@@ -192,7 +230,7 @@ parseCommandLine(int                 argc,
             &yresolutionSpec,  0);
     OPTENT3(0, "resolutionunit", OPT_STRING, &resolutionunit,
             &resolutionunitSpec,    0);
-    OPTENT3(0, "indexbits",    OPT_STRING,   &indexbits,
+    OPTENT3(0, "indexbits",    OPT_STRINGLIST, &indexbits,
             &indexbitsSpec,    0);
     OPTENT3(0, "tag",          OPT_NAMELIST, &cmdlineP->taglist, &tagSpec, 0);
 
@@ -302,35 +340,16 @@ parseCommandLine(int                 argc,
     } else
         cmdlineP->resolutionunit = RESUNIT_INCH;
 
-    if (indexbitsSpec) {
-        if (strstr(indexbits, "1"))
-            cmdlineP->indexsizeAllowed.b1 = TRUE;
-        else
-            cmdlineP->indexsizeAllowed.b1 = FALSE;
-        if (strstr(indexbits, "2"))
-            cmdlineP->indexsizeAllowed.b2 = TRUE;
-        else
-            cmdlineP->indexsizeAllowed.b2 = FALSE;
-        if (strstr(indexbits, "4"))
-            cmdlineP->indexsizeAllowed.b4 = TRUE;
-        else
-            cmdlineP->indexsizeAllowed.b4 = FALSE;
-        if (strstr(indexbits, "8"))
-            cmdlineP->indexsizeAllowed.b8 = TRUE;
-        else
-            cmdlineP->indexsizeAllowed.b8 = FALSE;
-    } else {
-        cmdlineP->indexsizeAllowed.b1 = FALSE;
-        cmdlineP->indexsizeAllowed.b2 = FALSE;
-        cmdlineP->indexsizeAllowed.b4 = FALSE;
-        cmdlineP->indexsizeAllowed.b8 = TRUE;
-    }
+    parseIndexbits(indexbitsSpec, indexbits, cmdlineP);
+
+    if (indexbitsSpec)
+        free(indexbits);
 
     if (tagSpec)
         validateTagList(cmdlineP->taglist);
     else {
         MALLOCARRAY_NOFAIL(cmdlineP->taglist, 1);
-        cmdlineP->taglist[0].name = NULL;
+        cmdlineP->taglist[0].name  = NULL;
         cmdlineP->taglist[0].value = NULL;
     }
 
@@ -346,6 +365,14 @@ parseCommandLine(int                 argc,
 
 
 static void
+freeCmdline(CmdlineInfo const cmdline) {
+
+    pm_optDestroyNameValueList(cmdline.taglist);
+}
+
+
+
+static void
 fillRowOfSubBytePixels(struct pam *    const pamP,
                        const tuple *   const tuplerow,
                        unsigned char * const buf,
@@ -1280,6 +1307,8 @@ main(int argc, const char *argv[]) {
     closeTiffGenerator(cmdline.writeMethod, tifP, ofd);
     pm_close(ifP);
 
+    freeCmdline(cmdline);
+
     return 0;
 }
 
diff --git a/converter/other/svgtopam.c b/converter/other/svgtopam.c
index 09e3a24e..ca6f4dc7 100644
--- a/converter/other/svgtopam.c
+++ b/converter/other/svgtopam.c
@@ -147,36 +147,36 @@ typedef struct {
     unsigned int height;
     pixel ** pixels;
     pixval maxval;
-} canvas;
+} Canvas;
 
 typedef struct {
     pixel fillColor;
-} style;
+} Style;
 
 
 
 typedef struct {
     const char * pathText;
         /* This is e.g. "M0 0 L1 1 L9 8 Z" */
-    style        style;
+    Style        style;
         /* This is the style as given by a 'style' attribute of <path> */
     unsigned int pathTextLength;
         /* This is the length in characters of 'pathText'.  It's redundant
            with 'pathText' and exists for convenience.
         */
-} path;
+} Path;
 
 static void
 createPath(const char * const pathText,
-           style        const style,
-           path **      const pathPP) {
+           Style        const style,
+           Path **      const pathPP) {
 /*----------------------------------------------------------------------------
    Create a path as described by a <path> element whose "style" attribute
    indicates style 'style' and whose "d" attribute indicates path data
    'pathText'.
 -----------------------------------------------------------------------------*/
     bool error;
-    path * pathP;
+    Path * pathP;
     
     MALLOCVAR(pathP);
     if (pathP == NULL)
@@ -204,7 +204,7 @@ createPath(const char * const pathText,
 
 
 static void
-destroyPath(path * const pathP) {
+destroyPath(Path * const pathP) {
     
     assert(pathP->pathTextLength == strlen(pathP->pathText));
 
@@ -218,13 +218,13 @@ destroyPath(path * const pathP) {
 typedef struct {
     unsigned int x;
     unsigned int y;
-} point;
+} Point;
 
-static point
+static Point
 makePoint(unsigned int const x,
           unsigned int const y) {
 
-    point p;
+    Point p;
     
     p.x = x;
     p.y = y;
@@ -233,7 +233,7 @@ makePoint(unsigned int const x,
 }
 
 static ppmd_point
-makePpmdPoint(point const arg) {
+makePpmdPoint(Point const arg) {
 
     ppmd_point p;
 
@@ -248,16 +248,16 @@ typedef enum {
     PATH_LINETO,
     PATH_CLOSEPATH,
     PATH_CUBIC
-} pathCommandVerb;
+} PathCommandVerb;
 
 typedef struct {
-    point dest;
-} pathMovetoArgs;
+    Point dest;
+} PathMovetoArgs;
 
 typedef struct {
     /* Draw a line segment from current point to 'dest' */
-    point dest;
-} pathLinetoArgs;
+    Point dest;
+} PathLinetoArgs;
 
 typedef struct {
     /* Draw a cubic spline from current point to 'dest' with control points
@@ -272,19 +272,19 @@ typedef struct {
        A cubic curve is a plot of a polynomial equation of degree 3
        (or less, for our purposes).
     */
-    point dest;
-    point ctl1;
-    point ctl2;
-} pathCubicArgs;
+    Point dest;
+    Point ctl1;
+    Point ctl2;
+} PathCubicArgs;
 
 typedef struct {
-    pathCommandVerb verb;
+    PathCommandVerb verb;
     union {
-        pathMovetoArgs moveto;
-        pathLinetoArgs lineto;
-        pathCubicArgs  cubic;
+        PathMovetoArgs moveto;
+        PathLinetoArgs lineto;
+        PathCubicArgs  cubic;
     } args;
-} pathCommand;
+} PathCommand;
 
 
 
@@ -292,15 +292,15 @@ typedef struct {
 /*----------------------------------------------------------------------------
    This is an object for reading through a path from beginning to end.
 -----------------------------------------------------------------------------*/
-    path *       pathP;
+    Path *       pathP;
     unsigned int cursor;
-} pathReader;
+} PathReader;
 
 static void
-createPathReader(path *        const pathP,
-                 pathReader ** const pathReaderPP) {
+pathReader_create(Path *        const pathP,
+                  PathReader ** const pathReaderPP) {
 
-    pathReader * pathReaderP;
+    PathReader * pathReaderP;
 
     MALLOCVAR_NOFAIL(pathReaderP);
 
@@ -311,18 +311,31 @@ createPathReader(path *        const pathP,
 }
 
 static void
-destroyPathReader(pathReader * const pathReaderP) {
+pathReader_destroy(PathReader * const pathReaderP) {
     free(pathReaderP);
 }
 
 
 
+static const char *
+pathReader_context(PathReader * const pathReaderP) {
+
+    const char * retval;
+
+    pm_asprintf(&retval, "Character position %u (starting at 0) in '%s'",
+                pathReaderP->cursor, pathReaderP->pathP->pathText);
+
+    return retval;
+}
+
+
+
 static void
-skipWhiteSpace(pathReader * const pathReaderP) {
+pathReader_skipWhiteSpace(PathReader * const pathReaderP) {
 /*----------------------------------------------------------------------------
    Move the cursor over any white space where it now points.
 -----------------------------------------------------------------------------*/
-    const path * const pathP = pathReaderP->pathP;
+    const Path * const pathP = pathReaderP->pathP;
 
     while (isspace(pathP->pathText[pathReaderP->cursor]) &&
            pathReaderP->cursor < pathP->pathTextLength)
@@ -332,10 +345,10 @@ skipWhiteSpace(pathReader * const pathReaderP) {
 
 
 static void
-getNumber(pathReader *   const pathReaderP,
-          unsigned int * const numberP) {
+pathReader_getNumber(PathReader *   const pathReaderP,
+                     unsigned int * const numberP) {
 
-    const path * const pathP          = pathReaderP->pathP;
+    const Path * const pathP          = pathReaderP->pathP;
     const char * const pathText       = pathP->pathText;
     size_t       const pathTextLength = pathP->pathTextLength;
 
@@ -343,7 +356,10 @@ getNumber(pathReader *   const pathReaderP,
 
     if (pathReaderP->cursor >= pathTextLength)
         pm_error("Path description ends where a number was expected.");
-    else {
+    else if (!isdigit(pathText[pathReaderP->cursor])) {
+        pm_error("Character '%c' instead of a digit where number expected",
+                 pathText[pathReaderP->cursor]);
+    } else {
         unsigned int number;
 
         number = 0;  /* initial value */
@@ -353,6 +369,10 @@ getNumber(pathReader *   const pathReaderP,
             number = 10 * number + (pathText[pathReaderP->cursor] - '0');
             ++pathReaderP->cursor;
         }
+        if (pathText[pathReaderP->cursor] == '.')
+            pm_error("Number contains decimal point.  This program does not "
+                     "know how to deal with fractional positions");
+
         *numberP = number;
     }
 }
@@ -360,15 +380,15 @@ getNumber(pathReader *   const pathReaderP,
 
 
 static void
-getNextCommand(pathReader *  const pathReaderP,
-               pathCommand * const pathCommandP,
-               bool *        const endOfPathP) {
+pathReader_getNextCommand(PathReader *  const pathReaderP,
+                          PathCommand * const pathCommandP,
+                          bool *        const endOfPathP) {
 
-    const path * const pathP          = pathReaderP->pathP;
+    const Path * const pathP          = pathReaderP->pathP;
     const char * const pathText       = pathP->pathText;
     size_t       const pathTextLength = pathP->pathTextLength;
 
-    skipWhiteSpace(pathReaderP);
+    pathReader_skipWhiteSpace(pathReaderP);
 
     if (pathReaderP->cursor >= pathTextLength)
         *endOfPathP = true;
@@ -376,67 +396,79 @@ getNextCommand(pathReader *  const pathReaderP,
         switch (pathText[pathReaderP->cursor++]) {
         case 'M':
             pathCommandP->verb = PATH_MOVETO;
-            skipWhiteSpace(pathReaderP);
-            getNumber(pathReaderP, &pathCommandP->args.moveto.dest.x);
-            skipWhiteSpace(pathReaderP);
-            getNumber(pathReaderP, &pathCommandP->args.moveto.dest.y);
+            pathReader_skipWhiteSpace(pathReaderP);
+            pathReader_getNumber(pathReaderP,
+                                 &pathCommandP->args.moveto.dest.x);
+            pathReader_skipWhiteSpace(pathReaderP);
+            pathReader_getNumber(pathReaderP,
+                                 &pathCommandP->args.moveto.dest.y);
             break;
         case 'L':
             pathCommandP->verb = PATH_LINETO;
-            skipWhiteSpace(pathReaderP);
-            getNumber(pathReaderP, &pathCommandP->args.lineto.dest.x);
-            skipWhiteSpace(pathReaderP);
-            getNumber(pathReaderP, &pathCommandP->args.lineto.dest.y);
+            pathReader_skipWhiteSpace(pathReaderP);
+            pathReader_getNumber(pathReaderP,
+                                 &pathCommandP->args.lineto.dest.x);
+            pathReader_skipWhiteSpace(pathReaderP);
+            pathReader_getNumber(pathReaderP,
+                                 &pathCommandP->args.lineto.dest.y);
             break;
         case 'C':
             pathCommandP->verb = PATH_CUBIC;
-            skipWhiteSpace(pathReaderP);
-            getNumber(pathReaderP, &pathCommandP->args.cubic.ctl1.x);
-            skipWhiteSpace(pathReaderP);
-            getNumber(pathReaderP, &pathCommandP->args.cubic.ctl1.y);
-            skipWhiteSpace(pathReaderP);
-            getNumber(pathReaderP, &pathCommandP->args.cubic.ctl2.x);
-            skipWhiteSpace(pathReaderP);
-            getNumber(pathReaderP, &pathCommandP->args.cubic.ctl2.y);
-            skipWhiteSpace(pathReaderP);
-            getNumber(pathReaderP, &pathCommandP->args.cubic.dest.x);
-            skipWhiteSpace(pathReaderP);
-            getNumber(pathReaderP, &pathCommandP->args.cubic.dest.y);
+            pathReader_skipWhiteSpace(pathReaderP);
+            pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.ctl1.x);
+            pathReader_skipWhiteSpace(pathReaderP);
+            pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.ctl1.y);
+            pathReader_skipWhiteSpace(pathReaderP);
+            pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.ctl2.x);
+            pathReader_skipWhiteSpace(pathReaderP);
+            pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.ctl2.y);
+            pathReader_skipWhiteSpace(pathReaderP);
+            pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.dest.x);
+            pathReader_skipWhiteSpace(pathReaderP);
+            pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.dest.y);
             break;
         case 'z':
             pathCommandP->verb = PATH_CLOSEPATH;
             break;
-        default:
-            pm_error("Unrecognized command in <path>: '%c'",
-                     pathText[pathReaderP->cursor++]);
+        default: {
+            const char * const context = pathReader_context(pathReaderP);
+            
+            pm_errormsg("Unrecognized command in <path>: '%c'.  %s",
+                        pathText[pathReaderP->cursor++], context);
+
+            pm_strfree(context);
+
+            pm_longjmp();
+        }
         }
     }
 }
 
 
+
 static void
-outlineObject(path *           const pathP,
+outlineObject(Path *           const pathP,
               struct fillobj * const fillObjP) {
 /*----------------------------------------------------------------------------
   Create a fill object, which contains and outline of the object and
   can be used with ppmd_fill() to fill the figure.  The outline is as
   described by *pathP.
 -----------------------------------------------------------------------------*/
-    pathReader * pathReaderP;
+    PathReader * pathReaderP;
     bool endOfPath;
-    point currentPos;
-    point subpathStart;
+    Point currentPos;
+    Point subpathStart;
         /* Point at which the current subpath starts */
 
     endOfPath = false;
     subpathStart = makePoint(0,0);
     currentPos = subpathStart;
 
-    createPathReader(pathP, &pathReaderP);
+    pathReader_create(pathP, &pathReaderP);
 
     while (!endOfPath) {
-        pathCommand pathCommand;
-        getNextCommand(pathReaderP, &pathCommand, &endOfPath);
+        PathCommand pathCommand;
+        pathReader_getNextCommand(pathReaderP, &pathCommand, &endOfPath);
         if (!endOfPath) {
             switch (pathCommand.verb) {
             case PATH_MOVETO:
@@ -448,7 +480,7 @@ outlineObject(path *           const pathP,
                 currentPos = subpathStart;
                 break;
             case PATH_LINETO: {
-                point const dest = pathCommand.args.lineto.dest;
+                Point const dest = pathCommand.args.lineto.dest;
                 if (traceDraw)
                     pm_message("Lining to (%u, %u)", dest.x, dest.y);
                 ppmd_line(NULL, 0, 0, 0,
@@ -466,12 +498,14 @@ outlineObject(path *           const pathP,
                 currentPos = subpathStart;
                 break;
             case PATH_CUBIC: {
-                point const dest = pathCommand.args.cubic.dest;
-                point const ctl1 = pathCommand.args.cubic.ctl1;
-                point const ctl2 = pathCommand.args.cubic.ctl2;
+                Point const dest = pathCommand.args.cubic.dest;
+                Point const ctl1 = pathCommand.args.cubic.ctl1;
+                Point const ctl2 = pathCommand.args.cubic.ctl2;
                 if (traceDraw)
                     pm_message("Doing cubic spline to (%u, %u)",
                                dest.x, dest.y);
+                pm_error("SVG image contains a cubic spline path.  "
+                         "This program cannot process cubic splines.");
                 /* We need to write ppmd_spline4() */
                 ppmd_spline4p(NULL, 0, 0, 0,
                               makePpmdPoint(currentPos),
@@ -484,14 +518,14 @@ outlineObject(path *           const pathP,
             }
         }
     }
-    destroyPathReader(pathReaderP);
+    pathReader_destroy(pathReaderP);
 }
 
 
 
 static void
-drawPath(canvas * const canvasP,
-         path *   const pathP) {
+drawPath(Canvas * const canvasP,
+         Path *   const pathP) {
 /*----------------------------------------------------------------------------
    Draw the path 'pathP' on the canvas 'canvasP'.
 -----------------------------------------------------------------------------*/
@@ -518,10 +552,10 @@ drawPath(canvas * const canvasP,
 
 
 
-static style
+static Style
 interpretStyle(const char * const styleAttr) {
 
-    style style;
+    Style style;
 
     char * buffer;
 
@@ -582,7 +616,7 @@ interpretStyle(const char * const styleAttr) {
 
 static void
 getPathAttributes(xmlTextReaderPtr const xmlReaderP,
-                  style *          const styleP,
+                  Style *          const styleP,
                   const char **    const pathP) {
 
     const char * const style = getAttribute(xmlReaderP, "style");
@@ -628,11 +662,11 @@ processSubPathNode(xmlTextReaderPtr const xmlReaderP,
 
 static void
 processPathElement(xmlTextReaderPtr const xmlReaderP,
-                   canvas *         const canvasP) {
+                   Canvas *         const canvasP) {
 
-    style style;
+    Style style;
     const char * pathData;
-    path * pathP;
+    Path * pathP;
     bool endOfPath;
 
     assert(xmlTextReaderNodeType(xmlReaderP) == XML_READER_TYPE_ELEMENT);
@@ -670,29 +704,6 @@ processPathElement(xmlTextReaderPtr const xmlReaderP,
 
 
 static void
-stringToUint(const char *   const string,
-             unsigned int * const uintP,
-             const char **  const errorP) {
-
-    /* TODO: move this to nstring.c */
-
-    if (strlen(string) == 0)
-        pm_asprintf(errorP, "Value is a null string");
-    else {
-        char * tailptr;
-
-        *uintP = strtoul(string, &tailptr, 10);
-
-        if (*tailptr != '\0')
-            pm_asprintf(errorP, "Non-numeric crap in string: '%s'", tailptr);
-        else
-            *errorP = NULL;
-    }
-}
-
-
-
-static void
 getSvgAttributes(xmlTextReaderPtr const xmlReaderP,
                  unsigned int *   const colsP,
                  unsigned int *   const rowsP) {
@@ -702,14 +713,16 @@ getSvgAttributes(xmlTextReaderPtr const xmlReaderP,
 
     const char * error;
 
-    stringToUint(width, colsP, &error);
+    pm_string_to_uint(width, colsP, &error);
     if (error) {
-        pm_error("'width' attribute of <svg> has invalid value.  %s", error);
+        pm_error("'width' attribute of <svg> has invalid value '%s'.  %s",
+                 width, error);
         pm_strfree(error);
     }
-    stringToUint(height, rowsP, &error);
+    pm_string_to_uint(height, rowsP, &error);
     if (error) {
-        pm_error("'height' attribute of <svg> has invalid value.  %s", error);
+        pm_error("'height' attribute of <svg> has invalid value '%s'.  %s",
+                 height, error);
         pm_strfree(error);
     }
 }
@@ -718,7 +731,7 @@ getSvgAttributes(xmlTextReaderPtr const xmlReaderP,
 
 static void
 processSubSvgElement(xmlTextReaderPtr const xmlReaderP,
-                     canvas *         const canvasP) {
+                     Canvas *         const canvasP) {
 
     const char * const nodeName = currentNodeName(xmlReaderP);
 
@@ -735,7 +748,7 @@ processSubSvgElement(xmlTextReaderPtr const xmlReaderP,
 
 static void
 processSubSvgNode(xmlTextReaderPtr const xmlReaderP,
-                  canvas *         const canvasP,
+                  Canvas *         const canvasP,
                   bool *           const endOfSvgP) {
 
     xmlReaderTypes const nodeType = xmlTextReaderNodeType(xmlReaderP);
@@ -765,9 +778,9 @@ static void
 createCanvas(unsigned int const width,
              unsigned int const height,
              pixval       const maxval,
-             canvas **    const canvasPP) {
+             Canvas **    const canvasPP) {
 
-    canvas * canvasP;
+    Canvas * canvasP;
 
     MALLOCVAR_NOFAIL(canvasP);
 
@@ -782,7 +795,7 @@ createCanvas(unsigned int const width,
 
 
 static void
-destroyCanvas(canvas * const canvasP) {
+destroyCanvas(Canvas * const canvasP) {
 
     ppm_freearray(canvasP->pixels, canvasP->height);
 
@@ -793,7 +806,7 @@ destroyCanvas(canvas * const canvasP) {
 
 static void
 writePam(FILE *   const ofP,
-         canvas * const canvasP) {
+         Canvas * const canvasP) {
 
     unsigned int row;
     struct pam pam;
@@ -839,7 +852,7 @@ processSvgElement(xmlTextReaderPtr const xmlReaderP,
 
     unsigned int width, height;
     bool endOfSvg;
-    canvas * canvasP;
+    Canvas * canvasP;
 
     assert(xmlTextReaderNodeType(xmlReaderP) == XML_READER_TYPE_ELEMENT);
     assert(streq(currentNodeName(xmlReaderP), "svg"));
diff --git a/converter/other/tifftopnm.c b/converter/other/tifftopnm.c
index e72aff5e..c1e7af85 100644
--- a/converter/other/tifftopnm.c
+++ b/converter/other/tifftopnm.c
@@ -191,7 +191,7 @@ getBps(TIFF *           const tif,
 
     if (bps < 1 || (bps > 8 && bps != 16 && bps != 32))
         pm_error("This program can process Tiff images with only "
-                 "1-8 or 16 bits per sample.  The input Tiff image "
+                 "1-8 or 16 or 32 bits per sample.  The input Tiff image "
                  "has %hu bits per sample.", bps);
     else
         *bpsP = bps;
diff --git a/converter/pbm/g3.h b/converter/pbm/g3.h
index e982f2da..42ba91c5 100644
--- a/converter/pbm/g3.h
+++ b/converter/pbm/g3.h
@@ -24,12 +24,30 @@
    There is also the newer G4.  
 */
 
-typedef struct g3TableEntry {
-    short int code;
-    short int length;
-} g3TableEntry;
+typedef struct G3TableEntry {
+    unsigned short int code;
+    unsigned short int length;
+} G3TableEntry;
 
-static struct g3TableEntry ttable[] = {
+
+struct BitString {
+    /* A string of bits, up to as many fit in 32 bits. */
+    uint32_t     intBuffer;
+        /* The bits are in the 'bitCount' least significant bit positions 
+           of this number.  The rest of the bits of this number are always 
+           zero.
+        */
+    unsigned int bitCount;
+        /* The length of the bit string */
+
+    /* Example:  The bit string 010100 would be represented by
+       bitCount = 6, intBuffer = 20
+       (N.B. 20 = 00000000 00000000 00000000 00010100 in binary)
+    */
+};
+
+
+static struct G3TableEntry ttable[] = {
 /*    TERMWHITE           TERMBLACK   */
     { 0x35, 8 },    { 0x37, 10 },       /* white 0 , black 0 */
     { 0x07, 6 },    { 0x02,  3 },
@@ -143,4 +161,273 @@ static struct g3TableEntry ttable[] = {
 
 #define mtable ((ttable)+64*2)
 
+
+struct PrefabCode {
+    unsigned int leadBits;
+    unsigned int trailBits;
+    struct BitString activeBits;
+};
+
+
+struct PrefabCode const prefabCode[256] =
+{
+{ 0, 8, {   0x0000,   0}},   /* 000 */
+{ 7, 1, {   0x0000,   0}},   /* 001 */
+{ 6, 1, {   0x0002,   3}},   /* 002 */
+{ 6, 2, {   0x0000,   0}},   /* 003 */
+{ 5, 2, {   0x0002,   3}},   /* 004 */
+{ 5, 1, {   0x0087,   9}},   /* 005 */
+{ 5, 1, {   0x0003,   2}},   /* 006 */
+{ 5, 3, {   0x0000,   0}},   /* 007 */
+{ 4, 3, {   0x0002,   3}},   /* 008 */
+{ 4, 1, {   0x0027,   7}},   /* 009 */
+{ 4, 1, {   0x043a,  12}},   /* 010 */
+{ 4, 2, {   0x0087,   9}},   /* 011 */
+{ 4, 2, {   0x0003,   2}},   /* 012 */
+{ 4, 1, {   0x00c7,   8}},   /* 013 */
+{ 4, 1, {   0x0002,   2}},   /* 014 */
+{ 4, 4, {   0x0000,   0}},   /* 015 */
+{ 3, 4, {   0x0002,   3}},   /* 016 */
+{ 3, 1, {   0x0028,   7}},   /* 017 */
+{ 3, 1, {   0x013a,  10}},   /* 018 */
+{ 3, 2, {   0x0027,   7}},   /* 019 */
+{ 3, 2, {   0x043a,  12}},   /* 020 */
+{ 3, 1, {  0x10e87,  18}},   /* 021 */
+{ 3, 1, {   0x021f,  11}},   /* 022 */
+{ 3, 3, {   0x0087,   9}},   /* 023 */
+{ 3, 3, {   0x0003,   2}},   /* 024 */
+{ 3, 1, {   0x0037,   6}},   /* 025 */
+{ 3, 1, {   0x063a,  11}},   /* 026 */
+{ 3, 2, {   0x00c7,   8}},   /* 027 */
+{ 3, 2, {   0x0002,   2}},   /* 028 */
+{ 3, 1, {   0x0087,   8}},   /* 029 */
+{ 3, 1, {   0x0003,   3}},   /* 030 */
+{ 3, 5, {   0x0000,   0}},   /* 031 */
+{ 2, 5, {   0x0002,   3}},   /* 032 */
+{ 2, 1, {   0x002b,   7}},   /* 033 */
+{ 2, 1, {   0x0142,  10}},   /* 034 */
+{ 2, 2, {   0x0028,   7}},   /* 035 */
+{ 2, 2, {   0x013a,  10}},   /* 036 */
+{ 2, 1, {   0x4e87,  16}},   /* 037 */
+{ 2, 1, {   0x009f,   9}},   /* 038 */
+{ 2, 3, {   0x0027,   7}},   /* 039 */
+{ 2, 3, {   0x043a,  12}},   /* 040 */
+{ 2, 1, {   0x43a7,  16}},   /* 041 */
+{ 2, 1, {  0x8743a,  21}},   /* 042 */
+{ 2, 2, {  0x10e87,  18}},   /* 043 */
+{ 2, 2, {   0x021f,  11}},   /* 044 */
+{ 2, 1, {   0x87c7,  17}},   /* 045 */
+{ 2, 1, {   0x021e,  11}},   /* 046 */
+{ 2, 4, {   0x0087,   9}},   /* 047 */
+{ 2, 4, {   0x0003,   2}},   /* 048 */
+{ 2, 1, {   0x0038,   6}},   /* 049 */
+{ 2, 1, {   0x01ba,   9}},   /* 050 */
+{ 2, 2, {   0x0037,   6}},   /* 051 */
+{ 2, 2, {   0x063a,  11}},   /* 052 */
+{ 2, 1, {  0x18e87,  17}},   /* 053 */
+{ 2, 1, {   0x031f,  10}},   /* 054 */
+{ 2, 3, {   0x00c7,   8}},   /* 055 */
+{ 2, 3, {   0x0002,   2}},   /* 056 */
+{ 2, 1, {   0x0027,   6}},   /* 057 */
+{ 2, 1, {   0x043a,  11}},   /* 058 */
+{ 2, 2, {   0x0087,   8}},   /* 059 */
+{ 2, 2, {   0x0003,   3}},   /* 060 */
+{ 2, 1, {   0x00c7,   9}},   /* 061 */
+{ 2, 1, {   0x0003,   4}},   /* 062 */
+{ 2, 6, {   0x0000,   0}},   /* 063 */
+{ 1, 6, {   0x0002,   3}},   /* 064 */
+{ 1, 1, {   0x002c,   7}},   /* 065 */
+{ 1, 1, {   0x015a,  10}},   /* 066 */
+{ 1, 2, {   0x002b,   7}},   /* 067 */
+{ 1, 2, {   0x0142,  10}},   /* 068 */
+{ 1, 1, {   0x5087,  16}},   /* 069 */
+{ 1, 1, {   0x00a3,   9}},   /* 070 */
+{ 1, 3, {   0x0028,   7}},   /* 071 */
+{ 1, 3, {   0x013a,  10}},   /* 072 */
+{ 1, 1, {   0x13a7,  14}},   /* 073 */
+{ 1, 1, {  0x2743a,  19}},   /* 074 */
+{ 1, 2, {   0x4e87,  16}},   /* 075 */
+{ 1, 2, {   0x009f,   9}},   /* 076 */
+{ 1, 1, {   0x27c7,  15}},   /* 077 */
+{ 1, 1, {   0x009e,   9}},   /* 078 */
+{ 1, 4, {   0x0027,   7}},   /* 079 */
+{ 1, 4, {   0x043a,  12}},   /* 080 */
+{ 1, 1, {   0x43a8,  16}},   /* 081 */
+{ 1, 1, {  0x21d3a,  19}},   /* 082 */
+{ 1, 2, {   0x43a7,  16}},   /* 083 */
+{ 1, 2, {  0x8743a,  21}},   /* 084 */
+{ 1, 1, {0x21d0e87,  27}},   /* 085 */
+{ 1, 1, {  0x43a1f,  20}},   /* 086 */
+{ 1, 3, {  0x10e87,  18}},   /* 087 */
+{ 1, 3, {   0x021f,  11}},   /* 088 */
+{ 1, 1, {   0x21f7,  15}},   /* 089 */
+{ 1, 1, {  0x43e3a,  20}},   /* 090 */
+{ 1, 2, {   0x87c7,  17}},   /* 091 */
+{ 1, 2, {   0x021e,  11}},   /* 092 */
+{ 1, 1, {   0x8787,  17}},   /* 093 */
+{ 1, 1, {   0x043b,  12}},   /* 094 */
+{ 1, 5, {   0x0087,   9}},   /* 095 */
+{ 1, 5, {   0x0003,   2}},   /* 096 */
+{ 1, 1, {   0x003b,   6}},   /* 097 */
+{ 1, 1, {   0x01c2,   9}},   /* 098 */
+{ 1, 2, {   0x0038,   6}},   /* 099 */
+{ 1, 2, {   0x01ba,   9}},   /* 100 */
+{ 1, 1, {   0x6e87,  15}},   /* 101 */
+{ 1, 1, {   0x00df,   8}},   /* 102 */
+{ 1, 3, {   0x0037,   6}},   /* 103 */
+{ 1, 3, {   0x063a,  11}},   /* 104 */
+{ 1, 1, {   0x63a7,  15}},   /* 105 */
+{ 1, 1, {  0xc743a,  20}},   /* 106 */
+{ 1, 2, {  0x18e87,  17}},   /* 107 */
+{ 1, 2, {   0x031f,  10}},   /* 108 */
+{ 1, 1, {   0xc7c7,  16}},   /* 109 */
+{ 1, 1, {   0x031e,  10}},   /* 110 */
+{ 1, 4, {   0x00c7,   8}},   /* 111 */
+{ 1, 4, {   0x0002,   2}},   /* 112 */
+{ 1, 1, {   0x0028,   6}},   /* 113 */
+{ 1, 1, {   0x013a,   9}},   /* 114 */
+{ 1, 2, {   0x0027,   6}},   /* 115 */
+{ 1, 2, {   0x043a,  11}},   /* 116 */
+{ 1, 1, {  0x10e87,  17}},   /* 117 */
+{ 1, 1, {   0x021f,  10}},   /* 118 */
+{ 1, 3, {   0x0087,   8}},   /* 119 */
+{ 1, 3, {   0x0003,   3}},   /* 120 */
+{ 1, 1, {   0x0037,   7}},   /* 121 */
+{ 1, 1, {   0x063a,  12}},   /* 122 */
+{ 1, 2, {   0x00c7,   9}},   /* 123 */
+{ 1, 2, {   0x0003,   4}},   /* 124 */
+{ 1, 1, {   0x00c7,  10}},   /* 125 */
+{ 1, 1, {   0x0002,   4}},   /* 126 */
+{ 1, 7, {   0x0000,   0}},   /* 127 */
+{ 1, 7, {   0x0000,   0}},   /* 128 */
+{ 1, 1, {   0x000e,   4}},   /* 129 */
+{ 1, 1, {   0x0062,   7}},   /* 130 */
+{ 1, 2, {   0x000c,   4}},   /* 131 */
+{ 1, 2, {   0x005a,   7}},   /* 132 */
+{ 1, 1, {   0x1687,  13}},   /* 133 */
+{ 1, 1, {   0x002f,   6}},   /* 134 */
+{ 1, 3, {   0x000b,   4}},   /* 135 */
+{ 1, 3, {   0x0042,   7}},   /* 136 */
+{ 1, 1, {   0x0427,  11}},   /* 137 */
+{ 1, 1, {   0x843a,  16}},   /* 138 */
+{ 1, 2, {   0x1087,  13}},   /* 139 */
+{ 1, 2, {   0x0023,   6}},   /* 140 */
+{ 1, 1, {   0x08c7,  12}},   /* 141 */
+{ 1, 1, {   0x0022,   6}},   /* 142 */
+{ 1, 4, {   0x0008,   4}},   /* 143 */
+{ 1, 4, {   0x003a,   7}},   /* 144 */
+{ 1, 1, {   0x03a8,  11}},   /* 145 */
+{ 1, 1, {   0x1d3a,  14}},   /* 146 */
+{ 1, 2, {   0x03a7,  11}},   /* 147 */
+{ 1, 2, {   0x743a,  16}},   /* 148 */
+{ 1, 1, { 0x1d0e87,  22}},   /* 149 */
+{ 1, 1, {   0x3a1f,  15}},   /* 150 */
+{ 1, 3, {   0x0e87,  13}},   /* 151 */
+{ 1, 3, {   0x001f,   6}},   /* 152 */
+{ 1, 1, {   0x01f7,  10}},   /* 153 */
+{ 1, 1, {   0x3e3a,  15}},   /* 154 */
+{ 1, 2, {   0x07c7,  12}},   /* 155 */
+{ 1, 2, {   0x001e,   6}},   /* 156 */
+{ 1, 1, {   0x0787,  12}},   /* 157 */
+{ 1, 1, {   0x003b,   7}},   /* 158 */
+{ 1, 5, {   0x0007,   4}},   /* 159 */
+{ 1, 5, {   0x003a,   9}},   /* 160 */
+{ 1, 1, {   0x03ab,  13}},   /* 161 */
+{ 1, 1, {   0x1d42,  16}},   /* 162 */
+{ 1, 2, {   0x03a8,  13}},   /* 163 */
+{ 1, 2, {   0x1d3a,  16}},   /* 164 */
+{ 1, 1, {  0x74e87,  22}},   /* 165 */
+{ 1, 1, {   0x0e9f,  15}},   /* 166 */
+{ 1, 3, {   0x03a7,  13}},   /* 167 */
+{ 1, 3, {   0x743a,  18}},   /* 168 */
+{ 1, 1, {  0x743a7,  22}},   /* 169 */
+{ 1, 1, { 0xe8743a,  27}},   /* 170 */
+{ 1, 2, { 0x1d0e87,  24}},   /* 171 */
+{ 1, 2, {   0x3a1f,  17}},   /* 172 */
+{ 1, 1, {  0xe87c7,  23}},   /* 173 */
+{ 1, 1, {   0x3a1e,  17}},   /* 174 */
+{ 1, 4, {   0x0e87,  15}},   /* 175 */
+{ 1, 4, {   0x001f,   8}},   /* 176 */
+{ 1, 1, {   0x01f8,  12}},   /* 177 */
+{ 1, 1, {   0x0fba,  15}},   /* 178 */
+{ 1, 2, {   0x01f7,  12}},   /* 179 */
+{ 1, 2, {   0x3e3a,  17}},   /* 180 */
+{ 1, 1, {  0xf8e87,  23}},   /* 181 */
+{ 1, 1, {   0x1f1f,  16}},   /* 182 */
+{ 1, 3, {   0x07c7,  14}},   /* 183 */
+{ 1, 3, {   0x001e,   8}},   /* 184 */
+{ 1, 1, {   0x01e7,  12}},   /* 185 */
+{ 1, 1, {   0x3c3a,  17}},   /* 186 */
+{ 1, 2, {   0x0787,  14}},   /* 187 */
+{ 1, 2, {   0x003b,   9}},   /* 188 */
+{ 1, 1, {   0x0ec7,  15}},   /* 189 */
+{ 1, 1, {   0x0073,  10}},   /* 190 */
+{ 1, 6, {   0x0007,   6}},   /* 191 */
+{ 2, 6, {   0x0000,   0}},   /* 192 */
+{ 2, 1, {   0x000c,   4}},   /* 193 */
+{ 2, 1, {   0x005a,   7}},   /* 194 */
+{ 2, 2, {   0x000b,   4}},   /* 195 */
+{ 2, 2, {   0x0042,   7}},   /* 196 */
+{ 2, 1, {   0x1087,  13}},   /* 197 */
+{ 2, 1, {   0x0023,   6}},   /* 198 */
+{ 2, 3, {   0x0008,   4}},   /* 199 */
+{ 2, 3, {   0x003a,   7}},   /* 200 */
+{ 2, 1, {   0x03a7,  11}},   /* 201 */
+{ 2, 1, {   0x743a,  16}},   /* 202 */
+{ 2, 2, {   0x0e87,  13}},   /* 203 */
+{ 2, 2, {   0x001f,   6}},   /* 204 */
+{ 2, 1, {   0x07c7,  12}},   /* 205 */
+{ 2, 1, {   0x001e,   6}},   /* 206 */
+{ 2, 4, {   0x0007,   4}},   /* 207 */
+{ 2, 4, {   0x003a,   9}},   /* 208 */
+{ 2, 1, {   0x03a8,  13}},   /* 209 */
+{ 2, 1, {   0x1d3a,  16}},   /* 210 */
+{ 2, 2, {   0x03a7,  13}},   /* 211 */
+{ 2, 2, {   0x743a,  18}},   /* 212 */
+{ 2, 1, { 0x1d0e87,  24}},   /* 213 */
+{ 2, 1, {   0x3a1f,  17}},   /* 214 */
+{ 2, 3, {   0x0e87,  15}},   /* 215 */
+{ 2, 3, {   0x001f,   8}},   /* 216 */
+{ 2, 1, {   0x01f7,  12}},   /* 217 */
+{ 2, 1, {   0x3e3a,  17}},   /* 218 */
+{ 2, 2, {   0x07c7,  14}},   /* 219 */
+{ 2, 2, {   0x001e,   8}},   /* 220 */
+{ 2, 1, {   0x0787,  14}},   /* 221 */
+{ 2, 1, {   0x003b,   9}},   /* 222 */
+{ 2, 5, {   0x0007,   6}},   /* 223 */
+{ 3, 5, {   0x0000,   0}},   /* 224 */
+{ 3, 1, {   0x000b,   4}},   /* 225 */
+{ 3, 1, {   0x0042,   7}},   /* 226 */
+{ 3, 2, {   0x0008,   4}},   /* 227 */
+{ 3, 2, {   0x003a,   7}},   /* 228 */
+{ 3, 1, {   0x0e87,  13}},   /* 229 */
+{ 3, 1, {   0x001f,   6}},   /* 230 */
+{ 3, 3, {   0x0007,   4}},   /* 231 */
+{ 3, 3, {   0x003a,   9}},   /* 232 */
+{ 3, 1, {   0x03a7,  13}},   /* 233 */
+{ 3, 1, {   0x743a,  18}},   /* 234 */
+{ 3, 2, {   0x0e87,  15}},   /* 235 */
+{ 3, 2, {   0x001f,   8}},   /* 236 */
+{ 3, 1, {   0x07c7,  14}},   /* 237 */
+{ 3, 1, {   0x001e,   8}},   /* 238 */
+{ 3, 4, {   0x0007,   6}},   /* 239 */
+{ 4, 4, {   0x0000,   0}},   /* 240 */
+{ 4, 1, {   0x0008,   4}},   /* 241 */
+{ 4, 1, {   0x003a,   7}},   /* 242 */
+{ 4, 2, {   0x0007,   4}},   /* 243 */
+{ 4, 2, {   0x003a,   9}},   /* 244 */
+{ 4, 1, {   0x0e87,  15}},   /* 245 */
+{ 4, 1, {   0x001f,   8}},   /* 246 */
+{ 4, 3, {   0x0007,   6}},   /* 247 */
+{ 5, 3, {   0x0000,   0}},   /* 248 */
+{ 5, 1, {   0x0007,   4}},   /* 249 */
+{ 5, 1, {   0x003a,   9}},   /* 250 */
+{ 5, 2, {   0x0007,   6}},   /* 251 */
+{ 6, 2, {   0x0000,   0}},   /* 252 */
+{ 6, 1, {   0x0007,   6}},   /* 253 */
+{ 7, 1, {   0x0000,   0}},   /* 254 */
+{ 0, 8, {   0x0000,   0}},   /* 255 */
+  };
+
 #endif
+
diff --git a/converter/pbm/g3topbm.c b/converter/pbm/g3topbm.c
index 83479b91..2b486324 100644
--- a/converter/pbm/g3topbm.c
+++ b/converter/pbm/g3topbm.c
@@ -44,11 +44,37 @@
 
 #define HASHSIZE 1021
 
-static g3TableEntry * whash[HASHSIZE];
-static g3TableEntry * bhash[HASHSIZE];
+#define MAXFILLBITS (5 * 9600)
 
+/*
+Fill bits are for flow control.  This was important when DRAM was
+expensive and fax machines came with small buffers.
 
-struct cmdlineInfo {
+If data arrives too quickly it may overflow the buffer of the
+receiving device.  On sending devices transmission time of compressed
+data representing a single row can be shorter than the time required
+to scan and encode.  The CCITT standard allows sending devices to
+insert fill bits to put communication on hold in these cases.
+
+By the CCITT standard, the maximum transmission time for one row is:
+
+100 - 400 pixels/inch 13 seconds
+(standard mode: 200 pixels/inch)
+600 pixels/inch 19 seconds
+1200 pixels/inch 37 seconds
+
+If one row is not received within the above limits, the receiving
+machine must disconnect the line.
+
+The receiver may be less patient.  It may opt to disconnect if one row
+is not received within 5 seconds.
+*/
+
+static G3TableEntry * whash[HASHSIZE];
+static G3TableEntry * bhash[HASHSIZE];
+
+
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
@@ -63,8 +89,8 @@ struct cmdlineInfo {
 
 
 static void
-parseCommandLine(int argc, char ** const argv,
-                 struct cmdlineInfo * const cmdlineP) {
+parseCommandLine(int argc, const char ** const argv,
+                 struct CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that the file spec array we return is stored in the storage that
    was passed to us as the argv array.
@@ -98,7 +124,7 @@ parseCommandLine(int argc, char ** const argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We may have parms that are negative numbers */
 
-    pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, (char**)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     if (widthSpec && paper_sizeSpec)
@@ -136,7 +162,7 @@ parseCommandLine(int argc, char ** const argv,
 
 
 
-struct bitStream {
+struct BitStream {
 
     FILE * fileP;
     bool reversebits;
@@ -156,7 +182,7 @@ struct bitStream {
 
 
 static void
-readBit(struct bitStream * const bitStreamP,
+readBit(struct BitStream * const bitStreamP,
         unsigned int *     const bitP,
         const char **      const errorP) {
 /*----------------------------------------------------------------------------
@@ -189,7 +215,7 @@ readBit(struct bitStream * const bitStreamP,
 
 
 static void
-readBitAndDetectEol(struct bitStream * const bitStreamP,
+readBitAndDetectEol(struct BitStream * const bitStreamP,
                     unsigned int *     const bitP,
                     bool *             const eolP,
                     const char **      const errorP) {
@@ -217,7 +243,7 @@ readBitAndDetectEol(struct bitStream * const bitStreamP,
 
 
 static void
-initBitStream(struct bitStream * const bitStreamP,
+initBitStream(struct BitStream * const bitStreamP,
               FILE *             const fileP,
               bool               const reversebits) {
     
@@ -230,7 +256,7 @@ initBitStream(struct bitStream * const bitStreamP,
 
 
 static void
-skipToNextLine(struct bitStream * const bitStreamP) {
+skipToNextLine(struct BitStream * const bitStreamP) {
 
     bool eol;
     const char * error;
@@ -248,8 +274,8 @@ skipToNextLine(struct bitStream * const bitStreamP) {
 
 
 static void
-addtohash(g3TableEntry *     hash[], 
-          g3TableEntry       table[], 
+addtohash(G3TableEntry *     hash[], 
+          G3TableEntry       table[], 
           unsigned int const n, 
           int          const a, 
           int          const b) {
@@ -257,7 +283,7 @@ addtohash(g3TableEntry *     hash[],
     unsigned int i;
 
     for (i = 0; i < n; ++i) {
-        g3TableEntry * const teP = &table[i*2];
+        G3TableEntry * const teP = &table[i*2];
         unsigned int const pos =
             ((teP->length + a) * (teP->code + b)) % HASHSIZE;
         if (hash[pos])
@@ -268,15 +294,15 @@ addtohash(g3TableEntry *     hash[],
 
 
 
-static g3TableEntry *
-hashfind(g3TableEntry *       hash[], 
+static G3TableEntry *
+hashfind(G3TableEntry *       hash[], 
          int            const length, 
          int            const code, 
          int            const a, 
          int            const b) {
 
     unsigned int pos;
-    g3TableEntry * te;
+    G3TableEntry * te;
 
     pos = ((length + a) * (code + b)) % HASHSIZE;
     te = hash[pos];
@@ -286,8 +312,8 @@ hashfind(g3TableEntry *       hash[],
 
 
 static void
-buildHashes(g3TableEntry * (*whashP)[HASHSIZE],
-            g3TableEntry * (*bhashP)[HASHSIZE]) {
+buildHashes(G3TableEntry * (*whashP)[HASHSIZE],
+            G3TableEntry * (*bhashP)[HASHSIZE]) {
 
     unsigned int i;
 
@@ -315,7 +341,7 @@ makeRowWhite(unsigned char * const packedBitrow,
 
 
 
-static g3TableEntry *
+static G3TableEntry *
 g3code(unsigned int const curcode,
        unsigned int const curlen,
        bit          const color) {
@@ -326,7 +352,7 @@ g3code(unsigned int const curcode,
    Note that it is the _position_ in the table that determines the meaning
    of the code.  The contents of the table entry do not.
 -----------------------------------------------------------------------------*/
-    g3TableEntry * retval;
+    G3TableEntry * retval;
 
     switch (color) {
     case PBM_WHITE:
@@ -383,7 +409,7 @@ writeBlackBitSpan(unsigned char * const packedBitrow,
 enum g3tableId {TERMWHITE, TERMBLACK, MKUPWHITE, MKUPBLACK};
 
 static void
-processG3Code(const g3TableEntry * const teP,
+processG3Code(const G3TableEntry * const teP,
               unsigned char *      const packedBitrow,
               unsigned int *       const colP,
               bit *                const colorP,
@@ -452,7 +478,7 @@ formatBadCodeException(const char ** const exceptionP,
 
 
 static void
-readFaxRow(struct bitStream * const bitStreamP,
+readFaxRow(struct BitStream * const bitStreamP,
            unsigned char *    const packedBitrow,
            unsigned int *     const lineLengthP,
            const char **      const exceptionP,
@@ -477,6 +503,8 @@ readFaxRow(struct bitStream * const bitStreamP,
         /* Number of bits we've read so far for the code we're currently 
            reading
         */
+    unsigned int fillbits;
+        /* Number of consecutive 0 bits.  Can precede EOL codes */
     unsigned int curcode; 
         /* What we've assembled so far of the code we're currently reading */
     unsigned int count;
@@ -490,6 +518,7 @@ readFaxRow(struct bitStream * const bitStreamP,
     col = 0;
     curlen = 0;
     curcode = 0;
+    fillbits = 0;
     currentColor = PBM_WHITE;
     count = 0;
     *exceptionP = NULL;
@@ -521,12 +550,17 @@ readFaxRow(struct bitStream * const bitStreamP,
             else {
                 curcode = (curcode << 1) | bit;
                 ++curlen;
-            
-                if (curlen > 13) {
+
+		if (curlen > 11 && curcode == 0x00) {
+		    if (++fillbits > MAXFILLBITS)
+                pm_error("Encountered %u consecutive fill bits.  "
+                       "Aborting", fillbits);
+		}
+		else if (curlen - fillbits > 13) {
                     formatBadCodeException(exceptionP, col, curlen, curcode);
                     done = TRUE;
                 } else if (curcode != 0) {
-                    const g3TableEntry * const teP =
+                    const G3TableEntry * const teP =
                         g3code(curcode, curlen, currentColor);
                         /* Address of structure that describes the 
                            current G3 code.  Null means 'curcode' isn't
@@ -680,7 +714,7 @@ analyzeLineSize(lineSizeAnalyzer * const analyzerP,
 */
 
 static void
-readFax(struct bitStream * const bitStreamP,
+readFax(struct BitStream * const bitStreamP,
         bool               const stretch,
         unsigned int       const expectedLineSize,
         bool               const tolerateErrors,
@@ -747,16 +781,16 @@ readFax(struct bitStream * const bitStreamP,
 
 
 int
-main(int argc, char * argv[]) {
+main(int argc, const char * argv[]) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     FILE * ifP;
-    struct bitStream bitStream;
+    struct BitStream bitStream;
     unsigned int rows, cols;
     unsigned char ** packedBits;
     int row;
 
-    pbm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
diff --git a/converter/pbm/pbmtog3.c b/converter/pbm/pbmtog3.c
index f0fd1252..4a731efd 100644
--- a/converter/pbm/pbmtog3.c
+++ b/converter/pbm/pbmtog3.c
@@ -1,84 +1,52 @@
 /* pbmtog3.c - read a PBM image and produce a Group 3 FAX file
-**
-** Copyright (C) 1989 by Paul Haeberli <paul@manray.sgi.com>.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
-*/
 
-/*
-   For specifications for Group 3 (G3) fax MH coding see ITU-T T.4
-   This program generates only MH.  It is coded with future expansion for
-   MR and MMR in mind.
+   For specifications for Group 3 (G3) fax MH coding see ITU-T T.4:
+   Standardization of Group 3 facsimile terminals for document transmission
+   https://www.itu.int/rec/T-REC-T.4/en
+
+   This program generates only MH.
 */
 
+
 #include <assert.h>
 
 #include "pm_c_util.h"
 #include "shhopt.h"
 #include "mallocvar.h"
 #include "bitreverse.h"
-#include "wordaccess.h"
-#include "wordintclz.h"
+#include "intcode.h"
 #include "g3.h"
 #include "pbm.h"
 
-#define TC_MC 64
-
-static bool const pbmtorl = 
-#ifdef PBMTORL
-    TRUE;
-#else
-    FALSE;
-#endif
-
+enum G3eol {EOL, ALIGN8, ALIGN16, NO_EOL, NO_RTC, NO_EOLRTC};
 
-struct bitString {
-    /* A string of bits, up to as many fit in a word. */
-    unsigned int bitCount;
-        /* The length of the bit string */
-    wordint intBuffer;
-        /* The bits are in the 'bitCount' least significant bit positions 
-           of this number.  The rest of the bits of this number are always 
-           zero.
-        */
+struct OutStream;
 
-    /* Example:  The bit string 010100, on a machine with a 32 bit word,
-       would be represented by bitCount = 6, intBuffer = 20
-       (N.B. 20 = 00000000 00000000 00000000 00010100 in binary)
-    */
+struct OutStream {
+    FILE * fp;
+    struct BitString buffer;
+    bool reverseBits;    /* Reverse bit order */  
+    enum G3eol eolAlign; /* Omit EOL and/or RTC; align EOL to 8/16 bits */ 
+    void * data;         /* Reserved for future expansion */
 };
 
 
 
-struct outStream {
-    struct bitString buffer;
-
-    bool reverseBits;
-};
-
-/* This is a global variable for speed. */
-static struct outStream out;
-
-
 struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
     const char * inputFileName;
     unsigned int reversebits;
-    unsigned int nofixedwidth;
+    enum G3eol   align;
+    unsigned int desiredWidth;
     unsigned int verbose;
 };
 
 
 
 static void
-parseCommandLine(int argc, char ** const argv,
+parseCommandLine(int argc, const char ** const argv,
                  struct CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that the file spec array we return is stored in the storage that
@@ -87,6 +55,8 @@ parseCommandLine(int argc, char ** const argv,
     optEntry * option_def;
         /* Instructions to OptParseOptions2 on how to parse our options.  */
     optStruct3 opt;
+    unsigned int nofixedwidth;
+    unsigned int align8, align16;
 
     unsigned int option_def_index;
 
@@ -95,7 +65,11 @@ parseCommandLine(int argc, char ** const argv,
     option_def_index = 0;   /* incremented by OPTENTRY */
     OPTENT3(0,   "reversebits",      OPT_FLAG,  NULL, &cmdlineP->reversebits,
             0);
-    OPTENT3(0,   "nofixedwidth",     OPT_FLAG,  NULL, &cmdlineP->nofixedwidth,
+    OPTENT3(0,   "nofixedwidth",     OPT_FLAG,  NULL, &nofixedwidth,
+            0);
+    OPTENT3(0,   "align8",           OPT_FLAG,  NULL, &align8,
+            0);
+    OPTENT3(0,   "align16",          OPT_FLAG,  NULL, &align16,
             0);
     OPTENT3(0,   "verbose",          OPT_FLAG,  NULL, &cmdlineP->verbose, 
             0);
@@ -105,14 +79,29 @@ parseCommandLine(int argc, char ** const argv,
     */
 
     opt.opt_table = option_def;
-    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
-    opt.allowNegNum = TRUE;  /* We may have parms that are negative numbers */
+    opt.short_allowed = false;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = true;  /* We may have parms that are negative numbers */
 
-    pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     free(option_def);
 
+    if (align8) {
+        if (align16)
+            pm_error("You can't specify both -align8 and -align16");
+        else
+            cmdlineP->align = ALIGN8;
+    } else if (align16)
+        cmdlineP->align = ALIGN16;
+    else
+        cmdlineP->align = EOL;
+
+    if (nofixedwidth)
+        cmdlineP->desiredWidth = 0;
+    else
+        cmdlineP->desiredWidth = 1728;
+
     if (argc-1 == 0) 
         cmdlineP->inputFileName = "-";
     else if (argc-1 != 1)
@@ -129,27 +118,75 @@ reversebuffer(unsigned char * const p,
               unsigned int    const n) {
 
     unsigned int i;
+
     for (i = 0; i < n; ++i)
         p[i] = bitreverse[p[i]];
 }
 
 
 
-static struct bitString
-makeBs(wordint      const bits, 
-       unsigned int const bitCount) {
+static void
+flushBuffer(struct OutStream * const outP) {
+/*----------------------------------------------------------------------------
+  Flush the contents of the bit buffer 
+-----------------------------------------------------------------------------*/
+    struct BitString const buffer = outP->buffer;
 
-    struct bitString retval;
-    retval.intBuffer = bits;
-    retval.bitCount  = bitCount;
+    assert (buffer.bitCount <= 32);
 
-    return retval;
+    if (buffer.bitCount > 0) {
+        unsigned int const fullBuffer = sizeof(buffer.intBuffer) * 8; 
+        unsigned int const bytesToWrite = (buffer.bitCount+7)/8;
+        bigend32 outbytes;
+        size_t rc;
+
+        outbytes = pm_bigendFromUint32(
+                   buffer.intBuffer << (fullBuffer - buffer.bitCount));
+        if (outP->reverseBits)
+    	reversebuffer((unsigned char *)&outbytes, bytesToWrite);
+        rc = fwrite((unsigned char *)&outbytes, 1, bytesToWrite, outP->fp);
+        if (rc != bytesToWrite)
+            pm_error("Output error");
+    }
 }
 
 
+#if 1==0
+static void
+putbitsDump(struct OutStream * const outP,
+            struct BitString   const newBits) {
+/*----------------------------------------------------------------------------
+  Print the content of the bit put request, in human readable text form
+  For debugging.  Also good for studying how the coding scheme works.
+
+  By default the compiler ignores this function.
+  To turn on, remove the "#if" - "#endif" lines enclosing the function and
+  edit the output function name in putbits().
+-----------------------------------------------------------------------------*/
+    unsigned int const bitCount = newBits.bitCount;
+
+    unsigned int i;
+    char charBuff[128];
+
+    assert (bitCount >= 0 && bitCount < 32);
+    assert (sizeof(newBits.intBuffer) + 2 < 128);
+
+    for (i = 0; i < bitCount; ++i) {
+        unsigned int const n = bitCount - i - 1;
+        charBuff[i] = ((newBits.intBuffer >> n) & 0x01) + '0';
+    }
+
+    charBuff[bitCount]   = '\n';
+    charBuff[bitCount+1] = '\0';
+    fwrite(charBuff, 1, bitCount+1, outP->fp);
+}
+#endif
+
+
 
-static __inline__ void
-putbits(struct bitString const newBits) {
+static void
+putbitsBinary(struct OutStream * const outP,
+              struct BitString   const newBits) {
 /*----------------------------------------------------------------------------
    Push the bits 'newBits' onto the right end of output buffer
    out.buffer (moving the bits already in the buffer left).
@@ -158,334 +195,462 @@ putbits(struct bitString const newBits) {
 
    'newBits' must be shorter than a whole word.
 
-   N.B. the definition of struct bitString requires upper bits to be zero.
+   N.B. the definition of struct BitString requires upper bits to be zero.
 -----------------------------------------------------------------------------*/
-    unsigned int const spaceLeft = 
-        sizeof(out.buffer.intBuffer)*8 - out.buffer.bitCount;
+    unsigned int const fullBuffer = sizeof(outP->buffer.intBuffer) * 8; 
+    unsigned int const spaceLeft = fullBuffer - outP->buffer.bitCount;
         /* Number of bits of unused space (at the high end) in buffer */
 
-    assert(newBits.bitCount < sizeof(out.buffer.intBuffer) * 8);
+    assert(newBits.bitCount < fullBuffer);
     assert(newBits.intBuffer >> newBits.bitCount == 0);
 
     if (spaceLeft > newBits.bitCount) {
         /* New bits fit with bits to spare */
-        out.buffer.intBuffer = 
-            out.buffer.intBuffer << newBits.bitCount | newBits.intBuffer;
-        out.buffer.bitCount += newBits.bitCount;
+        outP->buffer.intBuffer = 
+            outP->buffer.intBuffer << newBits.bitCount | newBits.intBuffer;
+        outP->buffer.bitCount += newBits.bitCount;
     } else { 
         /* New bits fill buffer.  We'll have to flush the buffer to stdout
            and put the rest of the bits in the new buffer.
         */
         unsigned int const nextBufBitCount = newBits.bitCount - spaceLeft;
+        unsigned int const bitMask = ((1<<nextBufBitCount) - 1); 
 
-        wordintBytes outbytes;
-        size_t rc;
-
-        wordintToBytes(&outbytes, 
-                       (out.buffer.intBuffer << spaceLeft) 
-                       | (newBits.intBuffer >> nextBufBitCount));
-        if (out.reverseBits)
-            reversebuffer(outbytes, sizeof(outbytes));
-
-        rc = fwrite(outbytes, 1, sizeof(outbytes), stdout);
-        if (rc != sizeof(outbytes))
-            pm_error("Output error.  Unable to fwrite() to stdout");
+        outP->buffer.intBuffer = ( (outP->buffer.intBuffer << spaceLeft) 
+                                 | (newBits.intBuffer >> nextBufBitCount));
+        outP->buffer.bitCount  = fullBuffer;
+        flushBuffer(outP);
 
-        out.buffer.intBuffer = newBits.intBuffer & ((1<<nextBufBitCount) - 1); 
-        out.buffer.bitCount = nextBufBitCount;
+        outP->buffer.intBuffer = newBits.intBuffer & bitMask;
+        outP->buffer.bitCount = nextBufBitCount;
     }
 }
 
 
 
 static void 
-initOutStream(bool const reverseBits) {
-    out.buffer.intBuffer = 0;
-    out.buffer.bitCount  = 0;
-    out.reverseBits = reverseBits;
+initOutStream(struct OutStream * const outP,
+              bool               const reverseBits,
+              enum G3eol         const eolAlign) {
+
+    outP->buffer.intBuffer = 0;
+    outP->buffer.bitCount  = 0;
+    outP->reverseBits      = reverseBits;
+    outP->fp               = stdout;
+    outP->eolAlign         = eolAlign;
+}
+
+
+
+static struct BitString
+tableEntryToBitString(G3TableEntry const tableEntry) {
+
+    struct BitString retval;
+
+    retval.intBuffer = tableEntry.code;
+    retval.bitCount  = tableEntry.length;
+
+    return retval;
+}
+
+
+
+static void
+putbits(struct OutStream * const outP,
+        struct BitString   const newBits) {
+
+    putbitsBinary(outP, newBits); 
+    /* Change to putbitsDump() for human readable output */
 }
 
 
 
-static __inline__ void
-putcode(unsigned int const clr, 
-        unsigned int const ix) {
+static void
+putcodeShort(struct OutStream * const outP,
+             bit                const color, 
+             unsigned int       const runLength) {
 
     /* Note that this requires ttable to be aligned white entry, black
-       entry, white, black, etc.  
+       entry, white, black, etc.
     */
-    putbits(makeBs(ttable[ix * 2 + clr].code, ttable[ix * 2 + clr].length));
+    unsigned int index = runLength * 2 + color;
+    putbits(outP, tableEntryToBitString(ttable[index]));
 }
 
 
 
-static __inline__ void
-putcode2(int const clr,
-         int const ix) {
+static void
+putcodeLong(struct OutStream * const outP,
+            bit                const color,
+            unsigned int       const runLength) {
 /*----------------------------------------------------------------------------
    Output Make-up code and Terminating code at once.
 
-   For run lengths above TC_MC threshold (usually 64).
+   For run lengths which require both: length 64 and above 
 
    The codes are combined here to avoid calculations in putbits()
-   wordint is usually wide enough, with 32 or 64 bits.
-   Provisions are made for 16 bit wordint (for debugging).
 
    Terminating code is max 12 bits, Make-up code is max 13 bits.
-   (See ttable, mtable entries in pbmtog3.h)
+   (See ttable, mtable entries in pbmtog3.h)  
 
    Also reduces object code size when putcode is compiled inline.
 -----------------------------------------------------------------------------*/
-    unsigned int const loIndex = ix % 64 * 2 + clr;
-    unsigned int const hiIndex = ix / 64 * 2 + clr;
-
-    if (sizeof(wordint) * 8 > 24) {
-        unsigned int const l1 = ttable[loIndex].length;
-
-        putbits(
-            makeBs(mtable[hiIndex].code << l1 | ttable[loIndex].code,
-                   mtable[hiIndex].length + l1)
-            );
-    } else { /* typically 16 bit wordint used for debugging */
-        putbits(makeBs(mtable[hiIndex].code, mtable[hiIndex].length));
-        putbits(makeBs(ttable[loIndex].code, ttable[loIndex].length));
-    }
+    unsigned int const loIndex = runLength % 64 * 2 + color;
+    unsigned int const hiIndex = runLength / 64 * 2 + color;
+    unsigned int const loLength = ttable[loIndex].length;
+    unsigned int const hiLength = mtable[hiIndex].length;
+
+    struct BitString combinedCode;
+
+    combinedCode.intBuffer = mtable[hiIndex].code << loLength |
+                             ttable[loIndex].code;
+    combinedCode.bitCount  = hiLength + loLength;
+
+    putbits(outP, combinedCode);
 }
 
 
 
-static __inline__ void
-putspan_normal(bit          const color, 
-               unsigned int const len) {
+static  void
+putcodeExtra(struct OutStream * const outP,
+             int                const color,
+             int                const runLength) {
+/*----------------------------------------------------------------------------
+   Lengths over 2560.  This is rare.
+   According to the standard, the mark-up code for 2560 can be issued as
+   many times as necessary without terminal codes.  
+   --------------------------------------------------------------------------*/
+    G3TableEntry const markUp2560 = mtable[2560/64*2];
+                              /* Same code for black and white */
 
-    if (len < TC_MC)
-        putcode(color, len);
-    else if (len < 2624)
-        putcode2(color, len);
-    else {  /* len >= 2624 : rare */
-        unsigned int remainingLen;
+    unsigned int remainingLen;
 
-        for (remainingLen = len;
-             remainingLen >= 2624;
-             remainingLen -= 2623) {
+    for (remainingLen = runLength; remainingLen > 2560; remainingLen -= 2560)
+      putbits(outP, tableEntryToBitString(markUp2560));
+    /* after the above: 0 < remainingLen <= 2560 */
 
-            putcode2(color, 2560+63);
-            putcode(!color, 0);
-        }
-        if (remainingLen < TC_MC)
-            putcode(color, remainingLen);
-        else  /* TC_MC <= len < 2624 */
-            putcode2(color, remainingLen);
-    }
+    if (remainingLen >= 64)
+        putcodeLong(outP, color, remainingLen);
+    else
+        putcodeShort(outP, color, remainingLen);
 }
 
 
 
-static __inline__ void
-putspan(bit          const color, 
-        unsigned int const len) {
-/*----------------------------------------------------------------------------
-   Put a span of 'len' pixels of color 'color' in the output.
------------------------------------------------------------------------------*/
-    if (pbmtorl) {
-        if (len > 0) 
-            printf("%c %d\n", color == PBM_WHITE ? 'W' : 'B', len);
-    } else 
-        putspan_normal(color, len);
+static void
+putspan(struct OutStream * const outP,
+        bit                const color, 
+        unsigned int       const runLength) {
+
+    if (runLength < 64)
+        putcodeShort(outP, color, runLength);
+    else if (runLength < 2560)
+        putcodeLong (outP, color, runLength);
+    else  /* runLength > 2560 : rare */
+        putcodeExtra(outP, color, runLength);
 }
 
 
 
 static void
-puteol(void) {
+puteol(struct OutStream * const outP) {
+
+    switch (outP->eolAlign) {
+    case EOL: {
+        struct BitString const eol = { 1, 12 };
+
+        putbits(outP, eol);
+    } break;
+    case ALIGN8:  case ALIGN16: {
+        unsigned int const bitCount = outP->buffer.bitCount;
+        unsigned int const fillbits =
+            (outP->eolAlign == ALIGN8) ? (44 - bitCount) % 8
+            : (52 - bitCount) % 16;
+
+        struct BitString eol;
+
+        eol.bitCount = 12 + fillbits;     eol.intBuffer = 1;
+        putbits(outP, eol);
+    } break;
+    case NO_EOL: case NO_EOLRTC:
+        break;
+    case NO_RTC:
+        pm_error("INTERNAL ERROR: no-RTC EOL treatment not implemented");
+        break;
+    }
+}
+
 
-    if (pbmtorl)
-        puts("EOL");
-    else {
-        struct bitString const eol = {12, 1};
 
-        putbits(eol);
+static void
+putrtc(struct OutStream * const outP) {
+
+    switch (outP->eolAlign) {
+    case NO_RTC: case NO_EOLRTC:
+        break;
+    default:
+        puteol(outP);    puteol(outP);    puteol(outP);
+        puteol(outP);    puteol(outP);    puteol(outP);
     }
 }
 
 
 
-/*
-  PBM raw bitrow to inflection point array
+static void
+readOffSideMargins(unsigned char * const bitrow,
+                   unsigned int    const colChars,
+                   unsigned int  * const firstNonWhiteCharP, 
+                   unsigned int  * const lastNonWhiteCharP,
+                   bool          * const blankRowP) {
+/*----------------------------------------------------------------------------
+  Determine the white margins on the left and right side of a row.
+  This is an enhancement: convertRowToG3() works without this.
+-----------------------------------------------------------------------------*/
+    unsigned int charCnt;
+    unsigned int firstChar;
+    unsigned int lastChar;
+    bool         blankRow;
 
-  Write inflection (=color change) points into array milepost[].  
-  It is easy to calculate run length from this.
+    assert(colChars > 0);
 
-  In milepost, a white-to-black (black-to-white) inflection point
-  always has an even (odd) index.  A line starting with black is
-  indicated by bitrow[0] == 0.
+    for (charCnt = 0; charCnt < colChars && bitrow[charCnt] == 0; ++charCnt);
 
-  WWWWWWWBBWWWWWWW ... = 7,2,7, ...
-  BBBBBWBBBBBWBBBB ... = 0,5,1,5,1,4, ...
+    if (charCnt >= colChars) {
+        /* Reached end of bitrow with no black pixels encountered */
+        firstChar = lastChar = 0;
+        blankRow  = true;
+    } else {
+        /* There is at least one black pixel in the row */
+        firstChar = charCnt;
+        blankRow = false;
 
-  Return the number of milepost elements written.
-  Note that max number of entries into milepost = cols+1 .
+        charCnt = colChars - 1;
 
-  The inflection points are calculated like this:
+        while (bitrow[charCnt--] == 0x00)
+            ;
+        lastChar = charCnt + 1;
+    }
+
+    *firstNonWhiteCharP = firstChar;
+    *lastNonWhiteCharP  = lastChar;
+    *blankRowP          = blankRow;
+}
 
-   r1: 00000000000111111110011111000000
-   r2: c0000000000011111111001111100000 0->carry
-  xor: ?0000000000100000001010000100000
 
-  The 1 bits in the xor above are the inflection points.
-*/
 
-static __inline__ void
-convertRowToRunLengths(unsigned char * const bitrow, 
-                       int             const cols, 
-                       unsigned int *  const milepost,
-                       unsigned int *  const lengthP) {
-
-    unsigned int   const bitsPerWord  = sizeof(wordint) * 8;
-    wordint      * const bitrowByWord = (wordint *) bitrow;
-    int            const wordCount    = (cols + bitsPerWord - 1)/bitsPerWord; 
-        /* Number of full and partial words in the row */
-
-
-    if (cols % bitsPerWord != 0) {
-        /* Clean final word in row.  For loop simplicity */
-        wordint r1;
-        r1 = bytesToWordint((unsigned char *)&bitrowByWord[wordCount - 1]);
-        r1 >>= bitsPerWord - cols % bitsPerWord;
-        r1 <<= bitsPerWord - cols % bitsPerWord;
-        wordintToBytes((wordintBytes *)&bitrowByWord[wordCount - 1], r1);
+static void
+setBlockBitsInFinalChar(unsigned char * const finalByteP,
+                        unsigned int    const cols) {
+/*----------------------------------------------------------------------------
+   If the char in the row is fractional, set it up so that the don't care
+   bits are the opposite color of the last valid pixel.
+----------------------------------------------------------------------------*/
+    unsigned char const finalByte  = *finalByteP;
+    unsigned int const silentBitCnt = 8 - cols % 8;
+    bit const rowEndColor = (finalByte >> silentBitCnt) & 0x01;
+
+    if (rowEndColor == PBM_WHITE) {
+        unsigned char const blackMask = (0x01 << silentBitCnt) - 1;
+
+        *finalByteP = finalByte | blackMask;
     }
-    {
-
-        wordint carry;
-        wordint r1, r2;
-        unsigned int n;
-        int i,c,k;
-
-        for (i = carry = n = 0; i < wordCount; ++i) {
-            r1 = r2 = bytesToWordint((unsigned char *)&bitrowByWord[i]);
-            r2 = r1 ^ (carry << (bitsPerWord-1) | r2 >> 1);
-            carry = r1 & 0x1;  k = 0;
-            while (r2 != 0) {
-                /* wordintClz(r2) reports most significant "1" bit of r2
-                   counting from MSB = position 0.
-                */
-                c = wordintClz(r2);
-                milepost[n++] = i * bitsPerWord + k + c;
-                r2 <<= c++; r2 <<= 1;  k += c; 
-            } 
+    /* No adjustment required if the row ends with a black pixel.
+       pbm_cleanrowend_packed() takes care of this.
+    */
+}
+
+
+
+static void
+trimFinalChar(struct OutStream * const outP,
+              bit                const color,
+              int                const carryLength, 
+              int                const existingCols,
+              int                const desiredWidth) {
+/*---------------------------------------------------------------------------
+   If the carry value from the last char in the row represents a valid
+   sequence, output it.
+
+   (1) If input row width is not a whole multiple of 8 and -nofixwidth
+       was specified, the final carry value represents inactive bits
+       at the row end.  Emit no code.  See setBlockBitsInFinalChar().
+
+   (2) If there is white margin on the right side, the final carry value
+       is valid.  We add to it the margin width.  Right-side margin may
+       be added in main() to a narrow input image, detected in the
+       input row by readOffSideMargins() or both.  The same treatment
+       applies regardless of the nature of the right-side margin.  
+----------------------------------------------------------------------------*/
+    if (existingCols == desiredWidth) {
+        if (existingCols % 8 == 0)
+            putspan(outP, color, carryLength);  /* Code up to byte boundary */
+        /* Emit nothing if existingCols is not a whole multiple of 8 */
+    } else if (existingCols < desiredWidth) {
+        if (color == 0) {       /* Last bit sequence in final char: white */
+            unsigned int const totalLength =
+                carryLength + (desiredWidth - existingCols);
+            putspan(outP, 0, totalLength);
+        } else {                 /* Black */
+            unsigned int const padLength = desiredWidth - existingCols;
+            putspan(outP, 1, carryLength);
+            putspan(outP, 0, padLength);
         }
-        if (n == 0 || milepost[n - 1] != cols) 
-            milepost[n++] = cols;
-        *lengthP = n;
     }
 }
 
 
 
 static void
-padToDesiredWidth(unsigned int * const milepost,
-                  unsigned int * const nRunP,
-                  int            const existingCols,
-                  int            const desiredCols) {
-
-    if (existingCols < desiredCols) {
-        /* adjustment for narrow input in fixed width mode
-           nRun % 2 == 1 (0) means last (=rightmost) pixel is white (black)
-           if white, extend the last span to outwidth
-           if black, fill with a white span len (outwidth - readcols)
-        */
-        if (*nRunP % 2 == 0)
-            ++*nRunP;
-        milepost[*nRunP - 1] = desiredCols;
+convertRowToG3(struct OutStream * const outP,
+               unsigned char    * const bitrow, 
+               unsigned int       const existingCols,
+               unsigned int       const desiredWidth) {
+/*----------------------------------------------------------------------------
+   Table based Huffman coding
+  
+   Normally Huffman code encoders count sequences of ones and zeros
+   and convert them to binary codes as they terminate.  This program
+   recognizes chains of pixels and converts them directly, reading
+   prefabricated code chains from an indexed table.
+
+   For example the 8-bit sequence 01100110 translates to
+   Huffman code: 000111 11 0111 11 000111.
+
+   In reality things are more complicated.  The leftmost 0 (MSB) may be
+   part of a longer sequence starting in the adjacent byte or perhaps
+   spanning several bytes.  Likewise for the rightmost 0.
+
+   So we first remove the sequence on the left side and compare its
+   color with the leftmost pixel of the adjacent byte and emit either
+   one code for a single sequence if they agree or two if they disagree. 
+   Next the composite code for the central part (in the above example
+   110011 -> 11 0111 11) is emitted.  Finally we save the length and
+   color of the sequence on the right end as carry-over for the next
+   byte cycle.  Some 8-bit input sequences (00000000, 01111111,
+   00111111, etc.) have no central part: these are special cases.  
+---------------------------------------------------------------------------*/
+    unsigned int const colChars = pbm_packed_bytes(existingCols);
+
+    unsigned int charCnt;
+    unsigned int firstActiveChar;
+    unsigned int lastActiveChar;
+    bool         blankRow;
+    bit          borderColor;
+
+    borderColor = PBM_WHITE; /* initial value */ 
+
+    if (existingCols == desiredWidth && (desiredWidth % 8) > 0)
+        setBlockBitsInFinalChar(&bitrow[colChars-1], desiredWidth);
+
+    readOffSideMargins(bitrow, colChars,
+                       &firstActiveChar, &lastActiveChar, &blankRow);
+
+    if (blankRow)
+        putspan(outP, PBM_WHITE, desiredWidth);
+    else {
+        unsigned int carryLength;
+
+        for (charCnt = firstActiveChar, carryLength = firstActiveChar * 8;
+             charCnt <=lastActiveChar;
+             ++charCnt) {
+
+            unsigned char const byte = bitrow[charCnt];
+            bit const rColor = !borderColor;
+
+            if (byte == borderColor * 0xFF) {
+                carryLength += 8;
+            } else if (byte == (unsigned char) ~(borderColor * 0xFF)) {
+                putspan(outP, borderColor, carryLength);
+                carryLength = 8;
+                borderColor = rColor;
+            } else {
+                struct PrefabCode const code = prefabCode[byte];
+                unsigned int const activeLength =
+                    8 - code.leadBits - code.trailBits; 
+
+                if (borderColor == (byte >> 7)) {
+                    putspan(outP, borderColor, carryLength + code.leadBits);
+                } else {
+                    putspan(outP, borderColor, carryLength);
+                    putcodeShort(outP, rColor, code.leadBits);
+                }
+                if (activeLength > 0)
+                    putbits(outP, code.activeBits);
+
+                borderColor = byte & 0x01;
+                carryLength = code.trailBits;
+            }
+        }
+        trimFinalChar(outP, borderColor, carryLength,
+                      (lastActiveChar + 1) * 8, desiredWidth);
     }
+    puteol(outP);
 }
 
 
 
 int
-main(int    argc,
-     char * argv[]) {
+main(int          argc,
+     const char * argv[]) {
 
     struct CmdlineInfo cmdline;
     FILE * ifP;
     unsigned char * bitrow;
        /* This is the bits of the current row, as read from the input and
-           modified various ways at various points in the program.  It has
-           a word of zero padding on the high (right) end for the convenience
-           of code that accesses this buffer in word-size bites.
+          modified various ways at various points in the program.  It has
+          a word of zero padding on the high (right) end for the convenience
+          of code that accesses this buffer in word-size bites.
         */
 
     int rows;
     int cols;
-    int readcols;
-    int outwidth;
     int format;
-    int row;
-    unsigned int * milepost;
+    unsigned int existingCols;
+    unsigned int desiredWidth;
+    unsigned int row;
+    struct OutStream out;
 
-    pbm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
     ifP = pm_openr(cmdline.inputFileName);
 
     pbm_readpbminit(ifP, &cols, &rows, &format);
-    if (cmdline.nofixedwidth)
-        readcols = outwidth = cols;
+
+    if (cmdline.desiredWidth == 0)
+        desiredWidth = existingCols = cols;
     else {
-        readcols = MIN(cols, 1728);
-        outwidth = 1728;
+        if (cmdline.desiredWidth < cols)
+            existingCols = desiredWidth = cmdline.desiredWidth;
+        else {
+            existingCols = pbm_packed_bytes(cols) * 8;
+            desiredWidth = cmdline.desiredWidth;
+        }
     }
 
-    MALLOCARRAY_NOFAIL(bitrow, pbm_packed_bytes(cols) + sizeof(wordint));
+    MALLOCARRAY(bitrow, pbm_packed_bytes(cols) + sizeof(uint32_t));
 
-    MALLOCARRAY_NOFAIL(milepost, readcols + 2);
+    if (!bitrow)
+        pm_error("Failed to allocate a row buffer for %u columns", cols);
 
-    initOutStream(cmdline.reversebits);
-    puteol();
+    initOutStream(&out, cmdline.reversebits, cmdline.align);
+    
+    puteol(&out);
 
     for (row = 0; row < rows; ++row) {
-        unsigned int nRun;  /* Number of runs in milepost[] */
-        unsigned int p;
-        unsigned int i;
-
         pbm_readpbmrow_packed(ifP, bitrow, cols, format);
-
-        convertRowToRunLengths(bitrow, readcols, milepost, &nRun);
-
-        padToDesiredWidth(milepost, &nRun, readcols, outwidth);
-
-        for (i = p = 0; i < nRun; p = milepost[i++])
-            putspan(i%2 == 0 ? PBM_WHITE : PBM_BLACK, milepost[i] - p);
-        /* TODO 2-dimensional coding MR, MMR */
-        puteol();
+        pbm_cleanrowend_packed(bitrow, cols);
+        convertRowToG3(&out, bitrow, existingCols, desiredWidth);
     }
 
-    free(milepost);
     pbm_freerow_packed(bitrow);
-
-    {
-        unsigned int i;  
-        for( i = 0; i < 6; ++i)
-            puteol();
-    }
-    if (out.buffer.bitCount > 0) {
-        /* flush final partial buffer */
-        unsigned int const bytesToWrite = (out.buffer.bitCount+7)/8;
-
-        unsigned char outbytes[sizeof(wordint)];
-        size_t rc;
-        wordintToBytes(&outbytes, 
-                       out.buffer.intBuffer << (sizeof(out.buffer.intBuffer)*8 
-                                                - out.buffer.bitCount));
-        if (out.reverseBits)
-            reversebuffer(outbytes, bytesToWrite);
-        rc = fwrite(outbytes, 1, bytesToWrite, stdout);
-        if (rc != bytesToWrite)
-            pm_error("Output error");
-    }
+    putrtc(&out);
+    flushBuffer(&out);
     pm_close(ifP);
 
     return 0;
 }
+
+
+
diff --git a/converter/pbm/pbmtox10bm b/converter/pbm/pbmtox10bm
index 6e1a12a2..deb3aeab 100644
--- a/converter/pbm/pbmtox10bm
+++ b/converter/pbm/pbmtox10bm
@@ -1,3 +1,27 @@
+#!/bin/sh
+
+##############################################################################
+# This is essentially a Perl program.  We exec the Perl interpreter specifying
+# this same file as the Perl program and use the -x option to cause the Perl
+# interpreter to skip down to the Perl code.  The reason we do this instead of
+# just making /usr/bin/perl the script interpreter (instead of /bin/sh) is
+# that the user may have multiple Perl interpreters and the one he wants to
+# use is properly located in the PATH.  The user's choice of Perl interpreter
+# may be crucial, such as when the user also has a PERL5LIB environment
+# variable and it selects modules that work with only a certain main
+# interpreter program.
+#
+# An alternative some people use is to have /usr/bin/env as the script
+# interpreter.  We don't do that because we think the existence and
+# compatibility of /bin/sh is more reliable.
+#
+# Note that we aren't concerned about efficiency because the user who needs
+# high efficiency can use directly the programs that this program invokes.
+#
+##############################################################################
+
+exec perl -w -x -S -- "$0" "$@"
+
 #! /usr/bin/perl
 
 #============================================================================
diff --git a/converter/ppm/ppmtoarbtxt.c b/converter/ppm/ppmtoarbtxt.c
index fc8927ce..6d4ed04e 100644
--- a/converter/ppm/ppmtoarbtxt.c
+++ b/converter/ppm/ppmtoarbtxt.c
@@ -734,15 +734,20 @@ interpretObjType(const char * const typstr) {
 
 
 static SkeletonObject *
-newIcSkelFromReplString(const char *       const objstr,
+newIcSkelFromReplString(const char *       const icolorObjstr,
                         SkeletonObjectType const objType) {
-
+/*----------------------------------------------------------------------------
+  A new skeleton for an integer color substitution specifier (class
+  OBJTYP_ICOLOR) whose replacement string (the stuff between the parentheses
+  in #(...)) says substitution type 'objType' and the rest of the
+  replacement string is 'icolorObjstr'.
+-----------------------------------------------------------------------------*/
     SkeletonObject * retval;
     unsigned int icolmin, icolmax;
     char formstr[MAX_OBJ_BUF];
-    unsigned int nOdata;
+    int nOdata;
 
-    nOdata = sscanf(objstr, "%*s%s%u%u", formstr, &icolmin, &icolmax);
+    nOdata = sscanf(icolorObjstr, "%s%u%u", formstr, &icolmin, &icolmax);
 
     if (nOdata == 3)
         retval = newIcolDataObj(objType, formstr, icolmin, icolmax);
@@ -758,16 +763,20 @@ newIcSkelFromReplString(const char *       const objstr,
 
 
 static SkeletonObject *
-newFcSkelFromReplString(const char *       const objstr,
+newFcSkelFromReplString(const char *       const fcolorObjstr,
                         SkeletonObjectType const objType) {
-
+/*----------------------------------------------------------------------------
+  A new skeleton for a floating point color substitution specifier (class
+  OBJTYP_FCOLOR) whose replacement string (the stuff between the parentheses
+  in #(...)) says substitution type 'objType' and the rest of the
+  replacement string is 'fcolorObjstr'.
+-----------------------------------------------------------------------------*/
     SkeletonObject * retval;
     double fcolmin, fcolmax;
     char formstr[MAX_OBJ_BUF];
-    unsigned int nOdata;
+    int nOdata;
 
-    nOdata = sscanf(objstr, "%*s%s%lf%lf", formstr,
-                    &fcolmin, &fcolmax);
+    nOdata = sscanf(fcolorObjstr, "%s%lf%lf", formstr, &fcolmin, &fcolmax);
 
     if (nOdata == 3)
         retval = newFcolDataObj(objType, formstr, fcolmin, fcolmax);
@@ -783,12 +792,19 @@ newFcSkelFromReplString(const char *       const objstr,
 
 
 static SkeletonObject *
-newISkelFromReplString(const char *       const objstr,
+newISkelFromReplString(const char *       const intObjstr,
                        SkeletonObjectType const objType) {
-
+/*----------------------------------------------------------------------------
+  A new skeleton for an integer substitution specifier (class OBJTYP_INT)
+  whose replacement string (the stuff between the parentheses in #(...))
+  says substitution type 'objType' and the rest of the replacement string is
+  'intObjstr'.
+-----------------------------------------------------------------------------*/
     SkeletonObject * retval;
     char formstr[MAX_OBJ_BUF];
-    unsigned int const nOdata = sscanf(objstr, "%*s%s", formstr);
+    int nOdata;
+
+    nOdata = sscanf(intObjstr, "%s", formstr);
     
     if (nOdata == 1)
         retval = newIdataObj(objType, formstr);
@@ -806,7 +822,7 @@ newISkelFromReplString(const char *       const objstr,
 static SkeletonObject *
 newSkeletonFromReplString(const char * const objstr) {
 /*----------------------------------------------------------------------------
-  Create a skeleton from the replacement string 'objstr' (the stuff
+  A new skeleton created from the replacement string 'objstr' (the stuff
   between the parentheses in #(...) ).
 
   Return NULL if it isn't a valid replacement string.
@@ -821,6 +837,7 @@ newSkeletonFromReplString(const char * const objstr) {
 
     SkeletonObject * retval;
     char typstr[MAX_OBJ_BUF];
+    int typlen;
     SkeletonObjectType objType;
     int conversionCt;
     char s1[MAX_OBJ_BUF];    /* Dry read. */
@@ -829,7 +846,8 @@ newSkeletonFromReplString(const char * const objstr) {
 
     typstr[0] = '\0';  /* initial value */
 
-    conversionCt = sscanf(objstr, "%s%s%f%f%s", typstr, s1, &f1, &f2, s2);
+    conversionCt = sscanf(objstr, "%s%n%s%f%f%s",
+                          typstr, &typlen, s1, &f1, &f2, s2);
     switch (conversionCt) {
     case 1: case 2: case 4:
         objType = interpretObjType(typstr);
@@ -840,13 +858,13 @@ newSkeletonFromReplString(const char * const objstr) {
 
     switch (objClass(objType)) {
     case OBJTYP_ICOLOR:
-        retval = newIcSkelFromReplString(objstr, objType);
+        retval = newIcSkelFromReplString(&objstr[typlen], objType);
         break;
     case OBJTYP_FCOLOR:
-        retval = newFcSkelFromReplString(objstr, objType);
+        retval = newFcSkelFromReplString(&objstr[typlen], objType);
         break;
     case OBJTYP_INT:
-        retval = newISkelFromReplString(objstr, objType);
+        retval = newISkelFromReplString(&objstr[typlen], objType);
         break;
     case OBJTYP_BDATA:
         retval = NULL;
diff --git a/converter/ppm/ppmtompeg/jrevdct.c b/converter/ppm/ppmtompeg/jrevdct.c
index bf9196c4..dd1f9fff 100644
--- a/converter/ppm/ppmtompeg/jrevdct.c
+++ b/converter/ppm/ppmtompeg/jrevdct.c
@@ -26,7 +26,11 @@
  * matrix, perhaps with the difference cases encoded.
  */
 
+#define _XOPEN_SOURCE 500  /* get M_PI in math.h */
+
 #include <memory.h>
+#include <math.h>
+
 #include "all.h"
 #include "dct.h"
 
@@ -1211,35 +1215,29 @@ mpeg_jrevdct_quick(data)
 */
 
 
-/* Here we use math.h to generate constants.  Compiler results may
-   vary a little */
-
-#ifndef PI
-#ifdef M_PI
-#define PI M_PI
-#else
-#define PI 3.14159265358979323846
-#endif
-#endif
-
 /* cosine transform matrix for 8x1 IDCT */
 static double itrans_coef[8][8];
 
-/* initialize DCT coefficient matrix */
 
-void init_idctref()
-{
-  int freq, time;
-  double scale;
-
-  for (freq=0; freq < 8; freq++)
-  {
-    scale = (freq == 0) ? sqrt(0.125) : 0.5;
-    for (time=0; time<8; time++)
-      itrans_coef[freq][time] = scale*cos((PI/8.0)*freq*(time + 0.5));
-  }
+
+void init_idctref() {
+/*----------------------------------------------------------------------------
+   initialize DCT coefficient matrix 
+-----------------------------------------------------------------------------*/
+    unsigned int freq;
+
+    for (freq=0; freq < 8; ++freq) {
+        double const scale = (freq == 0) ? sqrt(0.125) : 0.5;
+
+        unsigned int time;
+
+        for (time = 0; time < 8; ++time)
+            itrans_coef[freq][time] = scale*cos((M_PI/8.0)*freq*(time + 0.5));
+    }
 }
 
+
+
 /* perform IDCT matrix multiply for 8x8 coefficient block */
 
 void reference_rev_dct(block)
diff --git a/converter/ppm/ppmtompeg/mfwddct.c b/converter/ppm/ppmtompeg/mfwddct.c
index 75c3a718..9381e51c 100644
--- a/converter/ppm/ppmtompeg/mfwddct.c
+++ b/converter/ppm/ppmtompeg/mfwddct.c
@@ -15,6 +15,10 @@
  * instead of floating point.
  */
 
+#define _XOPEN_SOURCE 500  /* get M_PI in math.h */
+
+#include <math.h>
+
 #include "all.h"
 
 #include "dct.h"
@@ -375,26 +379,19 @@ mp_fwd_dct_block2(data, dest)
  *
  */
 
-#ifndef PI
-#ifdef M_PI
-#define PI M_PI
-#else
-#define PI 3.14159265358979323846
-#endif
-#endif
 
-void init_fdct()
-{
-  int i, j;
-  double s;
+void init_fdct() {
 
-  for (i=0; i<8; i++)
-  {
-    s = (i==0) ? sqrt(0.125) : 0.5;
+    unsigned int i;
 
-    for (j=0; j<8; j++)
-      trans_coef[i][j] = s * cos((PI/8.0)*i*(j+0.5));
-  }
+    for (i = 0; i < 8; ++i) {
+        double const s = i == 0 ? sqrt(0.125) : 0.5;
+
+        unsigned int j;
+
+        for (j = 0; j < 8; ++j)
+            trans_coef[i][j] = s * cos((M_PI/8.0) * i * (j+0.5));
+    }
 }