about summary refs log tree commit diff
path: root/converter
diff options
context:
space:
mode:
Diffstat (limited to 'converter')
-rw-r--r--converter/other/jpeg2000/libjasper/base/jas_image.c33
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_enc.c1377
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_math.c2
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c163
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_util.c71
-rw-r--r--converter/other/jpeg2000/pamtojpeg2k.c11
-rw-r--r--converter/ppm/ppmtompeg/frame.c68
-rw-r--r--converter/ppm/ppmtompeg/readframe.c103
8 files changed, 963 insertions, 865 deletions
diff --git a/converter/other/jpeg2000/libjasper/base/jas_image.c b/converter/other/jpeg2000/libjasper/base/jas_image.c
index 5ee13a0d..c6f984c1 100644
--- a/converter/other/jpeg2000/libjasper/base/jas_image.c
+++ b/converter/other/jpeg2000/libjasper/base/jas_image.c
@@ -675,7 +675,7 @@ int jas_image_fmtfromname(char *name)
 		return -1;
 	}
 	++ext;
-	/* Try to find a format that uses this extension. */	
+	/* Try to find a format that uses this extension. */
 	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i,
 	  ++fmtinfo) {
 		/* Do we have a match? */
@@ -686,25 +686,28 @@ int jas_image_fmtfromname(char *name)
 	return -1;
 }
 
-/******************************************************************************\
+/*****************************************************************************\
 * Miscellaneous operations.
-\******************************************************************************/
+\*****************************************************************************/
 
-uint_fast32_t jas_image_rawsize(jas_image_t *image)
-{
-	uint_fast32_t rawsize;
-	uint_fast32_t cmptno;
-	jas_image_cmpt_t *cmpt;
+uint_fast32_t
+jas_image_rawsize(jas_image_t * const imageP) {
+/*----------------------------------------------------------------------------
+   The raw size of the image, i.e. the number of bytes the raster of the image
+   would take if just represented simply, with no compression.
+-----------------------------------------------------------------------------*/
+    uint_fast32_t rawsize;
+    uint_fast32_t cmptno;
 
-	rawsize = 0;
-	for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
-		cmpt = image->cmpts_[cmptno];
-		rawsize += (cmpt->width_ * cmpt->height_ * cmpt->prec_ +
-		  7) / 8;
-	}
-	return rawsize;
+    for (cmptno = 0, rawsize = 0; cmptno < imageP->numcmpts_; ++cmptno) {
+        jas_image_cmpt_t * const cmptP = imageP->cmpts_[cmptno];
+        rawsize += (cmptP->width_ * cmptP->height_ * cmptP->prec_ + 7) / 8;
+    }
+    return rawsize;
 }
 
+
+
 void jas_image_delcmpt(jas_image_t *image, uint_fast16_t cmptno)
 {
 	if (cmptno >= image->numcmpts_) {
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c
index 9db41ca2..0c77a94e 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c
@@ -69,7 +69,6 @@ static void prc_destroy(jpc_enc_prc_t *prcs);
 static jpc_enc_cblk_t *cblk_create(jpc_enc_cblk_t *cblk, jpc_enc_cp_t *cp,
   jpc_enc_prc_t *prc);
 static void cblk_destroy(jpc_enc_cblk_t *cblks);
-int ratestrtosize(const char *s, uint_fast32_t rawsize, uint_fast32_t *size);
 static void pass_destroy(jpc_enc_pass_t *pass);
 void jpc_enc_dump(jpc_enc_t *enc);
 
@@ -78,17 +77,8 @@ void jpc_enc_dump(jpc_enc_t *enc);
 \*****************************************************************************/
 
 void quantize(jas_matrix_t *data, jpc_fix_t stepsize);
-static int jpc_enc_encodemainhdr(jpc_enc_t *enc);
-static int jpc_enc_encodemainbody(jpc_enc_t *enc);
-int jpc_enc_encodetiledata(jpc_enc_t *enc);
 jpc_enc_t *jpc_enc_create(jpc_enc_cp_t *cp, jas_stream_t *out, jas_image_t *image);
 void jpc_enc_destroy(jpc_enc_t *enc);
-static int jpc_enc_encodemainhdr(jpc_enc_t *enc);
-static int jpc_enc_encodemainbody(jpc_enc_t *enc);
-int jpc_enc_encodetiledata(jpc_enc_t *enc);
-int setins(int numvalues, jpc_flt_t *values, jpc_flt_t value);
-static jpc_enc_cp_t *cp_create(char *optstr, jas_image_t *image);
-void jpc_enc_cp_destroy(jpc_enc_cp_t *cp);
 
 
 
@@ -143,7 +133,6 @@ typedef enum {
     OPT_NUMGBITS,
     OPT_RATE,
     OPT_ILYRRATES,
-    OPT_JP2OVERHEAD
 } optid_t;
 
 jas_taginfo_t encopts[] = {
@@ -173,7 +162,6 @@ jas_taginfo_t encopts[] = {
     {OPT_NUMGBITS, "numgbits"},
     {OPT_RATE, "rate"},
     {OPT_ILYRRATES, "ilyrrates"},
-    {OPT_JP2OVERHEAD, "_jp2overhead"},
     {-1, 0}
 };
 
@@ -230,72 +218,46 @@ trace(const char * const fmt, ...) {
 
 
 
-int
-jpc_encode(jas_image_t *image, jas_stream_t *out, char *optstr) {
-
-    jpc_enc_t *enc;
-    jpc_enc_cp_t *cp;
-
-    enc = 0;
-    cp = 0;
-
-    jpc_initluts();
-
-    if (!(cp = cp_create(optstr, image))) {
-        fprintf(stderr, "invalid JP encoder options\n");
-        goto error;
-    }
-
-    if (!(enc = jpc_enc_create(cp, out, image))) {
-        goto error;
-    }
-    cp = 0;
+/*****************************************************************************\
+* Option parsing code.
+\*****************************************************************************/
 
-    /* Encode the main header. */
-    if (jpc_enc_encodemainhdr(enc)) {
-        goto error;
-    }
+static void
+ratestrtosize(const char *    const s,
+              uint_fast32_t   const rawsize,
+              uint_fast32_t * const sizeP) {
 
-    /* Encode the main body.  This constitutes most of the encoding work. */
-    if (jpc_enc_encodemainbody(enc)) {
-        goto error;
-    }
+    if (strchr(s, 'B')) {
+        *sizeP = atoi(s);
+    } else {
+        jpc_flt_t const f = atof(s);
 
-    /* Write EOC marker segment. */
-    if (!(enc->mrk = jpc_ms_create(JPC_MS_EOC))) {
-        goto error;
-    }
-    if (jpc_putms(enc->out, enc->cstate, enc->mrk)) {
-        fprintf(stderr, "cannot write EOI marker\n");
-        goto error;
+        if (f < 0) {
+            *sizeP = 0;
+        } else if (f > 1.0) {
+            *sizeP = rawsize + 1;
+        } else {
+            *sizeP = f * rawsize;
+        }
     }
-    jpc_ms_destroy(enc->mrk);
-    enc->mrk = 0;
+}
 
-    if (jas_stream_flush(enc->out)) {
-        goto error;
-    }
 
-    jpc_enc_destroy(enc);
 
-    return 0;
+static void
+cp_destroy(jpc_enc_cp_t *cp) {
 
-error:
-    if (cp) {
-        jpc_enc_cp_destroy(cp);
-    }
-    if (enc) {
-        jpc_enc_destroy(enc);
+    if (cp->ccps) {
+        if (cp->tcp.ilyrrates) {
+            jas_free(cp->tcp.ilyrrates);
+        }
+        jas_free(cp->ccps);
     }
-    return -1;
+    jas_free(cp);
 }
 
 
 
-/*****************************************************************************\
-* Option parsing code.
-\*****************************************************************************/
-
 static jpc_enc_cp_t *
 cp_create(char *optstr, jas_image_t *image) {
 
@@ -314,7 +276,6 @@ cp_create(char *optstr, jas_image_t *image) {
     uint_fast16_t prcwidthexpn;
     uint_fast16_t prcheightexpn;
     bool enablemct;
-    uint_fast32_t jp2overhead;
     uint_fast16_t lyrno;
     uint_fast32_t hsteplcm;
     uint_fast32_t vsteplcm;
@@ -332,7 +293,6 @@ cp_create(char *optstr, jas_image_t *image) {
     prcwidthexpn = 15;
     prcheightexpn = 15;
     enablemct = true;
-    jp2overhead = 0;
 
     cp->ccps = 0;
     cp->debug = 0;
@@ -380,6 +340,10 @@ cp_create(char *optstr, jas_image_t *image) {
 
     cp->rawsize = jas_image_rawsize(image);
     cp->totalsize = UINT_FAST32_MAX;
+        /* Set default value, the special value that means size is unlimited
+           (so lossless coding is called for).  To be overridden if user
+           specified
+        */
 
     tcp = &cp->tcp;
     tcp->csty = 0;
@@ -492,12 +456,8 @@ cp_create(char *optstr, jas_image_t *image) {
             cp->tccp.numgbits = atoi(jas_tvparser_getval(tvp));
             break;
         case OPT_RATE:
-            if (ratestrtosize(jas_tvparser_getval(tvp), cp->rawsize,
-              &cp->totalsize)) {
-                fprintf(stderr,
-                  "ignoring bad rate specifier %s\n",
-                  jas_tvparser_getval(tvp));
-            }
+            ratestrtosize(jas_tvparser_getval(tvp), cp->rawsize,
+                          &cp->totalsize);
             break;
         case OPT_ILYRRATES:
             if (jpc_atoaf(jas_tvparser_getval(tvp), &numilyrrates,
@@ -505,13 +465,10 @@ cp_create(char *optstr, jas_image_t *image) {
                 fprintf(stderr,
                         "warning: invalid intermediate layer rates specifier "
                         "ignored (%s)\n",
-                  jas_tvparser_getval(tvp));
+                        jas_tvparser_getval(tvp));
             }
             break;
 
-        case OPT_JP2OVERHEAD:
-            jp2overhead = atoi(jas_tvparser_getval(tvp));
-            break;
         default:
             fprintf(stderr, "warning: ignoring invalid option %s\n",
              jas_tvparser_gettag(tvp));
@@ -522,11 +479,6 @@ cp_create(char *optstr, jas_image_t *image) {
     jas_tvparser_destroy(tvp);
     tvp = 0;
 
-    if (cp->totalsize != UINT_FAST32_MAX) {
-        cp->totalsize = (cp->totalsize > jp2overhead) ?
-          (cp->totalsize - jp2overhead) : 0;
-    }
-
     if (cp->imgareatlx == UINT_FAST32_MAX) {
         cp->imgareatlx = 0;
     } else {
@@ -697,20 +649,28 @@ cp_create(char *optstr, jas_image_t *image) {
         /* The intermediate layers rates must increase monotonically. */
         for (lyrno = 0; lyrno + 2 < tcp->numlyrs; ++lyrno) {
             if (tcp->ilyrrates[lyrno] >= tcp->ilyrrates[lyrno + 1]) {
-                fprintf(stderr,
-                        "intermediate layer rates must increase "
-                        "monotonically\n");
+                pm_message("Compression rate for Layer %u (%f) "
+                           "is not greater than that for Layer %u (%f).  "
+                           "Rates must increase at every layer",
+                           (unsigned)(lyrno+1),
+                           jpc_fixtodbl(tcp->ilyrrates[lyrno + 1]),
+                           (unsigned)lyrno,
+                           jpc_fixtodbl(tcp->ilyrrates[lyrno]));
                 goto error;
             }
         }
         /* The intermediate layer rates must be less than the overall rate. */
         if (cp->totalsize != UINT_FAST32_MAX) {
             for (lyrno = 0; lyrno < tcp->numlyrs - 1; ++lyrno) {
-                if (jpc_fixtodbl(tcp->ilyrrates[lyrno]) >
-                    ((double) cp->totalsize) / cp->rawsize) {
-                    fprintf(stderr,
-                            "warning: intermediate layer rates must be "
-                            "less than overall rate\n");
+                double const thisLyrRate = jpc_fixtodbl(tcp->ilyrrates[lyrno]);
+                double const completeRate =
+                    ((double) cp->totalsize) / cp->rawsize;
+                if (thisLyrRate > completeRate) {
+                    pm_message(
+                        "Compression rate for Layer %u is %f, "
+                        "which is greater than the rate for the complete "
+                        "image (%f)",
+                        (unsigned)lyrno, thisLyrRate, completeRate);
                     goto error;
                 }
             }
@@ -732,118 +692,17 @@ error:
         jas_tvparser_destroy(tvp);
     }
     if (cp) {
-        jpc_enc_cp_destroy(cp);
-    }
-    return 0;
-}
-
-
-
-void
-jpc_enc_cp_destroy(jpc_enc_cp_t *cp) {
-
-    if (cp->ccps) {
-        if (cp->tcp.ilyrrates) {
-            jas_free(cp->tcp.ilyrrates);
-        }
-        jas_free(cp->ccps);
-    }
-    jas_free(cp);
-}
-
-
-
-int
-ratestrtosize(const char *s, uint_fast32_t rawsize, uint_fast32_t *size) {
-
-    char *cp;
-    jpc_flt_t f;
-
-    /* Note: This function must not modify output size on failure. */
-    if ((cp = strchr(s, 'B'))) {
-        *size = atoi(s);
-    } else {
-        f = atof(s);
-        if (f < 0) {
-            *size = 0;
-        } else if (f > 1.0) {
-            *size = rawsize + 1;
-        } else {
-            *size = f * rawsize;
-        }
-    }
-    return 0;
-}
-
-/*****************************************************************************\
-* Encoder constructor and destructor.
-\*****************************************************************************/
-
-jpc_enc_t *
-jpc_enc_create(jpc_enc_cp_t *cp, jas_stream_t *out, jas_image_t *image) {
-
-    jpc_enc_t *enc;
-
-    enc = 0;
-
-    if (!(enc = jas_malloc(sizeof(jpc_enc_t)))) {
-        goto error;
-    }
-
-    enc->image = image;
-    enc->out = out;
-    enc->cp = cp;
-    enc->cstate = 0;
-    enc->tmpstream = 0;
-    enc->mrk = 0;
-    enc->curtile = 0;
-
-    if (!(enc->cstate = jpc_cstate_create())) {
-        goto error;
-    }
-    enc->len = 0;
-    enc->mainbodysize = 0;
-
-    return enc;
-
-error:
-
-    if (enc) {
-        jpc_enc_destroy(enc);
+        cp_destroy(cp);
     }
     return 0;
 }
 
 
 
-void
-jpc_enc_destroy(jpc_enc_t *enc) {
-
-    /* The image object (i.e., enc->image) and output stream object
-       (i.e., enc->out) are created outside of the encoder.
-       Therefore, they must not be destroyed here.
-    */
-
-    if (enc->curtile) {
-        jpc_enc_tile_destroy(enc->curtile);
-    }
-    if (enc->cp) {
-        jpc_enc_cp_destroy(enc->cp);
-    }
-    if (enc->cstate) {
-        jpc_cstate_destroy(enc->cstate);
-    }
-    if (enc->tmpstream) {
-        jas_stream_close(enc->tmpstream);
-    }
-
-    jas_free(enc);
-}
-
-
-
 static int
-jpc_enc_encodemainhdr(jpc_enc_t *enc) {
+encodemainhdr(jpc_enc_t *enc) {
+
+    uint_fast32_t const maintlrlen = 2;
 
     jpc_siz_t *siz;
     jpc_cod_t *cod;
@@ -961,7 +820,7 @@ jpc_enc_encodemainhdr(jpc_enc_t *enc) {
                   (analgain + 1)), bandinfo->synenergywt);
             } else {
                 absstepsize = jpc_inttofix(1);
-            }   
+            }
             cp->ccps[cmptno].stepsizes[bandno] =
               jpc_abstorelstepsize(absstepsize,
               cp->ccps[cmptno].prec + analgain);
@@ -1038,61 +897,32 @@ jpc_enc_encodemainhdr(jpc_enc_t *enc) {
         enc->mrk = 0;
     }
 
-#define MAINTLRLEN  2
     mainhdrlen = jas_stream_getrwcount(enc->out) - startoff;
     enc->len += mainhdrlen;
     if (enc->cp->totalsize != UINT_FAST32_MAX) {
-        uint_fast32_t overhead;
-        overhead = mainhdrlen + MAINTLRLEN;
-        enc->mainbodysize = (enc->cp->totalsize >= overhead) ?
-          (enc->cp->totalsize - overhead) : 0;
-    } else {
-        enc->mainbodysize = UINT_FAST32_MAX;
-    }
-
-    return 0;
-}
-
-
-
-int
-jpc_enc_encodetiledata(jpc_enc_t *enc) {
-
-    assert(enc->tmpstream);
-    if (jpc_enc_encpkts(enc, enc->tmpstream)) {
-        return -1;
-    }
-    return 0;
-}
-
-
-
-void
-quantize(jas_matrix_t *data, jpc_fix_t stepsize) {
+        uint_fast32_t const overhead = mainhdrlen + maintlrlen;
 
-    int i;
-    int j;
-    jpc_fix_t t;
-
-    if (stepsize == jpc_inttofix(1)) {
-        return;
-    }
-
-    for (i = 0; i < jas_matrix_numrows(data); ++i) {
-        for (j = 0; j < jas_matrix_numcols(data); ++j) {
-            t = jas_matrix_get(data, i, j);
+        if (overhead > enc->cp->totalsize) {
+            pm_message("Requested limit on image size of %u bytes "
+                       "is not possible because it is less than "
+                       "the image metadata size (%u bytes)",
+                       (unsigned)enc->cp->totalsize, (unsigned)overhead);
+            return -1;
+        }
+        enc->mainbodysize = enc->cp->totalsize - overhead;
+        /* This has never actually worked.  'totalsize' is supposed to be
+           the total all-in, so if you request total size 200, you should
+           get an output file 200 bytes or smaller; but we see 209 bytes.
+           Furthermore, at 194 bytes, we get a warning that an empty layer
+           is generated, which probably is actually an error.
 
-{
-    if (t < 0) {
-        t = jpc_fix_neg(jpc_fix_div(jpc_fix_neg(t), stepsize));
+           We should fix this some day.
+        */
     } else {
-        t = jpc_fix_div(t, stepsize);
+        enc->mainbodysize = UINT_FAST32_MAX;
     }
-}
 
-            jas_matrix_set(data, i, j, t);
-        }
-    }
+    return 0;
 }
 
 
@@ -1166,12 +996,12 @@ calcrdslopes(jpc_enc_cblk_t *cblk) {
 
 static void
 traceLayerSizes(const uint_fast32_t * const lyrSizes,
-                unsigned int          const layerCt) {
+                uint_fast32_t         const layerCt) {
 
     if (jas_getdbglevel() > 0) {
-        unsigned int i;
+        uint_fast32_t i;
         for (i = 0; i < layerCt; ++i) {
-            fprintf(stderr, "Layer %u size = ", i);
+            fprintf(stderr, "Layer %u size = ", (unsigned)i);
 
             if (lyrSizes[i] == UINT_FAST32_MAX)
                 fprintf(stderr, "Unlimited");
@@ -1189,48 +1019,28 @@ computeLayerSizes(jpc_enc_t *      const encP,
                   jpc_enc_tile_t * const tileP,
                   jpc_enc_cp_t *   const cpP,
                   double           const rho,
-                  long             const tilehdrlen,
-                  const char **    const errorP) {
+                  long             const tilehdrlen) {
 
     /* Note that in allowed sizes, UINT_FAST32_MAX is a special value meaning
        "unlimited".
     */
 
-    unsigned int const lastLyrno = tileP->numlyrs - 1;
+    uint_fast32_t const lastLyrno = tileP->numlyrs - 1;
 
-    unsigned int lyrno;
+    uint_fast32_t lyrno;
 
     assert(tileP->numlyrs > 0);
 
     for (lyrno = 0; lyrno < lastLyrno; ++lyrno) {
-        tileP->lyrsizes[lyrno] = tileP->rawsize * jpc_fixtodbl(
-            cpP->tcp.ilyrrates[lyrno]);
+        tileP->lyrsizes[lyrno] =
+            MAX(tileP->rawsize *
+                jpc_fixtodbl(cpP->tcp.ilyrrates[lyrno]),
+                tilehdrlen + 1) - tilehdrlen;
     }
 
     tileP->lyrsizes[lastLyrno] =
-        (cpP->totalsize != UINT_FAST32_MAX) ?
-        (rho * encP->mainbodysize) : UINT_FAST32_MAX;
-
-
-    /* Subtract 'tilehdrlen' from every layer. */
-
-    for (lyrno = 0; lyrno < tileP->numlyrs; ++lyrno) {
-        if (tileP->lyrsizes[lyrno] != UINT_FAST32_MAX) {
-            if (tilehdrlen <= tileP->lyrsizes[lyrno]) {
-                tileP->lyrsizes[lyrno] -= tilehdrlen;
-            } else {
-                tileP->lyrsizes[lyrno] = 0;
-            }
-        }
-    }
-
-    if (tileP->lyrsizes[lastLyrno] < 1)
-        pm_asprintf(errorP, "Cannot make image that small (%u bytes).  "
-                    "Even with pixels compressed as far as possible, metadata "
-                    "would exceed the limit",
-                    (unsigned)cpP->totalsize);
-    else
-        *errorP = NULL;
+        (cpP->totalsize == UINT_FAST32_MAX) ?
+        UINT_FAST32_MAX : (rho * encP->mainbodysize);
 
     traceLayerSizes(tileP->lyrsizes, tileP->numlyrs);
 }
@@ -1313,8 +1123,8 @@ trace_layeringinfo(jpc_enc_t * const encP) {
 
 static void
 validateCumlensIncreases(const uint_fast32_t * const cumlens,
-                         unsigned int          const numlyrs) {
-    unsigned int lyrno;
+                         uint_fast32_t          const numlyrs) {
+    uint_fast32_t lyrno;
 
     for (lyrno = 1; lyrno < numlyrs - 1; ++lyrno) {
         if (cumlens[lyrno - 1] > cumlens[lyrno]) {
@@ -1404,7 +1214,7 @@ findMinMaxRDSlopeValues(jpc_enc_tile_t * const tileP,
 static void
 performTier2CodingOneLayer(jpc_enc_t *      const encP,
                            jpc_enc_tile_t * const tileP,
-                           unsigned int     const lyrno,
+                           uint_fast32_t     const lyrno,
                            jas_stream_t *   const outP,
                            const char **    const errorP) {
 /*----------------------------------------------------------------------------
@@ -1444,9 +1254,9 @@ performTier2CodingOneLayer(jpc_enc_t *      const encP,
 static void
 assignHighSlopePassesToLayer(jpc_enc_t *      const encP,
                              jpc_enc_tile_t * const tileP,
-                             unsigned int     const lyrno,
-                             bool             const haveThresh,
-                             jpc_flt_t        const thresh) {
+                             uint_fast32_t     const lyrno,
+                             bool              const haveThresh,
+                             jpc_flt_t         const thresh) {
 /*----------------------------------------------------------------------------
   Assign all passes with R-D slopes greater than or equal to 'thresh' to layer
   'lyrno' and the rest to no layer.
@@ -1505,8 +1315,7 @@ assignHighSlopePassesToLayer(jpc_enc_t *      const encP,
                                         for (; passP != endpassesP; ++passP) {
                                             passP->lyrno = -1;
                                         }
-                                    
-                                    }   
+                                    }
                                 }
                             }
                         }
@@ -1522,7 +1331,7 @@ assignHighSlopePassesToLayer(jpc_enc_t *      const encP,
 static void
 doLayer(jpc_enc_t *      const encP,
         jpc_enc_tile_t * const tileP,
-        unsigned int     const lyrno,
+        uint_fast32_t    const lyrno,
         uint_fast32_t    const allowedSize,
         jpc_flt_t        const mnrdslope,
         jpc_flt_t        const mxrdslope,
@@ -1550,7 +1359,7 @@ doLayer(jpc_enc_t *      const encP,
         long pos;
         jpc_flt_t lo;
         jpc_flt_t hi;
-        unsigned int numiters;
+        uint_fast32_t numiters;
 
         lo = mnrdslope;  /* initial value */
         hi = mxrdslope;  /* initial value */
@@ -1559,52 +1368,46 @@ doLayer(jpc_enc_t *      const encP,
         goodThresh = 0;     /* initial value */
 
         do {
-            if (allowedSize == UINT_FAST32_MAX) {
-                /* There's no rate constraint (This can be true of the last
-                   layer, e.g. for lossless coding). */
-                goodThresh = -1;
-                haveGoodThresh = true;
-            } else {
-                jpc_flt_t const thresh = (lo + hi) / 2;
-
-                int rc;
-                long oldpos;
-
-                /* Save the tier 2 coding state. */
-                jpc_save_t2state(encP);
-                oldpos = jas_stream_tell(outP);
-                assert(oldpos >= 0);
-
-                assignHighSlopePassesToLayer(encP, tileP, lyrno, true, thresh);
-
-                performTier2CodingOneLayer(encP, tileP, lyrno, outP, errorP);
-
-                if (!*errorP) {
-                    pos = jas_stream_tell(outP);
-
-                    /* Check the rate constraint. */
-                    assert(pos >= 0);
-                    if (pos > allowedSize) {
-                        /* The rate is too high. */
-                        lo = thresh;
-                    } else if (pos <= allowedSize) {
-                        /* The rate is low enough, so try higher. */
-                        hi = thresh;
-                        if (!haveGoodThresh || thresh < goodThresh) {
-                            goodThresh = thresh;
-                            haveGoodThresh = true;
-                        }
+            jpc_flt_t const thresh = (lo + hi) / 2;
+
+            int rc;
+            long oldpos;
+
+            /* Save the tier 2 coding state. */
+            jpc_save_t2state(encP);
+            oldpos = jas_stream_tell(outP);
+            assert(oldpos >= 0);
+
+            assignHighSlopePassesToLayer(encP, tileP, lyrno, true, thresh);
+
+            performTier2CodingOneLayer(encP, tileP, lyrno, outP, errorP);
+
+            if (!*errorP) {
+                pos = jas_stream_tell(outP);
+
+                /* Check the rate constraint. */
+                assert(pos >= 0);
+                if (pos > allowedSize) {
+                    /* The rate is too high. */
+                    lo = thresh;
+                } else if (pos <= allowedSize) {
+                    /* The rate is low enough, so try higher. */
+                    hi = thresh;
+                    if (!haveGoodThresh || thresh < goodThresh) {
+                        goodThresh = thresh;
+                        haveGoodThresh = true;
                     }
                 }
-                /* Restore the tier 2 coding state. */
-                jpc_restore_t2state(encP);
-                rc = jas_stream_seek(outP, oldpos, SEEK_SET);
-                if (rc < 0)
-                    abort();
-
-                trace("iter %u: allowedlen=%08ld actuallen=%08ld thresh=%f",
-                      numiters, allowedSize, pos, thresh);
             }
+            /* Restore the tier 2 coding state. */
+            jpc_restore_t2state(encP);
+            rc = jas_stream_seek(outP, oldpos, SEEK_SET);
+            if (rc < 0)
+                abort();
+
+            trace("iter %u: allowedlen=%08ld actuallen=%08ld thresh=%f",
+                  numiters, allowedSize, pos, thresh);
+
             ++numiters;
         } while (lo < hi - 1e-3 && numiters < 32 && !*errorP);
     }
@@ -1625,10 +1428,10 @@ doLayer(jpc_enc_t *      const encP,
 
 
 static void
-performTier2Coding(jpc_enc_t *     const encP,
-                   unsigned int    const numlyrs,
-                   uint_fast32_t * const cumlens,
-                   const char **   const errorP) {
+performTier2Coding(jpc_enc_t *      const encP,
+                   uint_fast32_t    const numlyrs,
+                   uint_fast32_t *  const cumlens,
+                   const char **    const errorP) {
 /*----------------------------------------------------------------------------
    Encode in 'numlyrs' layers, such that at each layer L, the size is
    cumlens[L].
@@ -1636,7 +1439,7 @@ performTier2Coding(jpc_enc_t *     const encP,
     jpc_enc_tile_t * const tileP = encP->curtile;
 
     jas_stream_t * outP;
-    unsigned int lyrno;
+    uint_fast32_t lyrno;
     jpc_flt_t mnrdslope;
     jpc_flt_t mxrdslope;
 
@@ -1669,6 +1472,562 @@ performTier2Coding(jpc_enc_t *     const encP,
 
 
 
+
+
+static void
+encodeTileBody(jpc_enc_t *   const encoderP,
+               long          const tilehdrlen,
+               const char ** const errorP) {
+/*----------------------------------------------------------------------------
+   Encode the body of encoder *encoderP's current tile, writing the encoded
+   result to the encoder's output stream.
+
+   Assume the tile header is already in that stream, and its length is
+   'tilehdrlen'.
+-----------------------------------------------------------------------------*/
+    jpc_enc_tile_t * const tileP = encoderP->curtile;
+    jpc_enc_cp_t *   const cp    = encoderP->cp;
+
+    int rc;
+
+    rc = jpc_enc_enccblks(encoderP);
+    if (rc != 0)
+        pm_asprintf(errorP, "jpc_enc_enccblks() failed");
+    else {
+        double const rho =
+            (double) (tileP->brx - tileP->tlx) * (tileP->bry - tileP->tly) /
+            ((cp->refgrdwidth - cp->imgareatlx) * (cp->refgrdheight -
+                                                   cp->imgareatly));
+        const char * error;
+
+        tileP->rawsize = cp->rawsize * rho;
+
+        computeLayerSizes(encoderP, tileP, cp, rho, tilehdrlen);
+
+        performTier2Coding(encoderP, tileP->numlyrs, tileP->lyrsizes, &error);
+
+        if (error) {
+            pm_asprintf(errorP, "Tier 2 coding failed.  %s", error);
+            pm_strfree(error);
+        } else {
+            int rc;
+
+            rc = jpc_enc_encpkts(encoderP, encoderP->tmpstream);
+            if (rc != 0)
+                pm_asprintf(errorP, "jpc_enc_encpkts() failed\n");
+            else
+                *errorP = NULL;
+        }
+    }
+}
+
+
+
+static void
+quantizeBand(jpc_enc_band_t * const bandP,
+             jpc_enc_tile_t * const tileP,
+             jpc_enc_cp_t *   const cp,
+             int              const prec,
+             int              const tccp_numgbits,
+             int *            const numgbitsP) {
+
+    if (bandP->data) {
+        int actualnumbps;
+        uint_fast32_t y;
+        jpc_fix_t mxmag;
+
+        for (y = 0, actualnumbps = 0, mxmag = 0;
+             y < jas_matrix_numrows(bandP->data);
+             ++y) {
+            uint_fast32_t x;
+
+            for (x = 0; x < jas_matrix_numcols(bandP->data); ++x)
+                mxmag = MAX(mxmag, abs(jas_matrix_get(bandP->data, y, x)));
+        }
+        if (tileP->intmode)
+            actualnumbps = jpc_firstone(mxmag) + 1;
+        else
+            actualnumbps = jpc_firstone(mxmag) + 1 - JPC_FIX_FRACBITS;
+
+        *numgbitsP = actualnumbps - (prec - 1 + bandP->analgain);
+
+        if (!tileP->intmode) {
+            bandP->absstepsize =
+                jpc_fix_div(
+                    jpc_inttofix(1 << (bandP->analgain + 1)),
+                    bandP->synweight);
+        } else {
+            bandP->absstepsize = jpc_inttofix(1);
+        }
+        bandP->stepsize = jpc_abstorelstepsize(
+            bandP->absstepsize, prec + bandP->analgain);
+        /* I couldn't figure out what the calculation with tccp_numgbits and
+           stepsize does (or even what a step size is), but there is an
+           assertion elsewhere than the number here is at least at large as
+           the 'numbps' value for every code block, which means
+           'actualnumbps'.  In practice, we saw that not be true, so we added
+           the code to make 'actualnumbps' the floor here in hopes that would
+           fix the problem.  But with the change, the image that caused the
+           assertion failure produces incorrect output.  22.11.07
+        */
+        bandP->numbps =
+            MAX(actualnumbps,
+                tccp_numgbits + JPC_QCX_GETEXPN(bandP->stepsize) - 1);
+
+        if (!tileP->intmode && bandP->data)
+            quantize(bandP->data, bandP->absstepsize);
+    } else
+        *numgbitsP = 0;
+}
+
+
+
+static int
+encodemainbody(jpc_enc_t *enc) {
+
+    int tileno;
+    int i;
+    jpc_sot_t *sot;
+    int rlvlno;
+    jpc_qcc_t *qcc;
+    jpc_cod_t *cod;
+    int adjust;
+    int j;
+    int absbandno;
+    long tilehdrlen;
+    long tilelen;
+    jpc_enc_tile_t *tile;
+    jpc_enc_cp_t *cp;
+    int samestepsizes;
+    jpc_enc_ccp_t *ccps;
+    jpc_enc_tccp_t *tccp;
+    int mingbits; /* Minimum number of guard bits needed */
+    const char * error;
+
+    cp = enc->cp;
+
+    for (tileno = 0; tileno < cp->numtiles; ++tileno) {
+        uint_fast16_t cmptno;
+
+        enc->curtile = jpc_enc_tile_create(enc->cp, enc->image, tileno);
+        if (!enc->curtile)
+            abort();
+
+        tile = enc->curtile;
+
+        if (jas_getdbglevel() >= 10) {
+            jpc_enc_dump(enc);
+        }
+
+        for (cmptno = 0; cmptno < tile->numtcmpts; ++cmptno) {
+
+            jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno];
+
+            if (!cp->ccps[cmptno].sgnd) {
+                adjust = 1 << (cp->ccps[cmptno].prec - 1);
+                for (i = 0; i < jas_matrix_numrows(comp->data); ++i) {
+                    for (j = 0; j < jas_matrix_numcols(comp->data); ++j) {
+                        *jas_matrix_getref(comp->data, i, j) -= adjust;
+                    }
+                }
+            }
+        }
+
+        if (!tile->intmode) {
+            uint_fast16_t cmptno;
+            for (cmptno = 0; cmptno < tile->numtcmpts; ++cmptno) {
+                jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno];
+                jas_matrix_asl(comp->data, JPC_FIX_FRACBITS);
+            }
+        }
+
+        switch (tile->mctid) {
+        case JPC_MCT_RCT:
+            assert(jas_image_numcmpts(enc->image) == 3);
+            jpc_rct(tile->tcmpts[0].data, tile->tcmpts[1].data,
+                    tile->tcmpts[2].data);
+            break;
+        case JPC_MCT_ICT:
+            assert(jas_image_numcmpts(enc->image) == 3);
+            jpc_ict(tile->tcmpts[0].data, tile->tcmpts[1].data,
+                    tile->tcmpts[2].data);
+            break;
+        default:
+            break;
+        }
+
+        for (i = 0; i < jas_image_numcmpts(enc->image); ++i) {
+            jpc_enc_tcmpt_t * const comp = &tile->tcmpts[i];
+            jpc_tsfb_analyze(comp->tsfb,
+                             ((comp->qmfbid == JPC_COX_RFT) ?
+                              JPC_TSFB_RITIMODE : 0), comp->data);
+
+        }
+
+        for (cmptno = 0; cmptno < tile->numtcmpts; ++cmptno) {
+
+            jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno];
+
+            mingbits = 0;
+            absbandno = 0;
+            /* All bands must have a corresponding quantizer step size,
+               even if they contain no samples and are never coded. */
+            /* Some bands may not be hit by the loop below, so we must
+               initialize all of the step sizes to a sane value. */
+            memset(comp->stepsizes, 0, sizeof(comp->stepsizes));
+            for (rlvlno = 0; rlvlno < comp->numrlvls; ++rlvlno) {
+                jpc_enc_rlvl_t * const lvl = &comp->rlvls[rlvlno];
+
+                unsigned int bandno;
+
+                if (!lvl->bands) {
+                    absbandno += rlvlno ? 3 : 1;
+                    continue;
+                }
+                for (bandno = 0; bandno < lvl->numbands; ++bandno) {
+                    jpc_enc_band_t * const band = &lvl->bands[bandno];
+
+                    int numgbits;
+
+                    quantizeBand(band, tile, cp,
+                                 cp->ccps[cmptno].prec,
+                                 cp->tccp.numgbits,
+                                 &numgbits);
+
+                    mingbits = MAX(mingbits, numgbits);
+
+                    comp->stepsizes[absbandno] = band->stepsize;
+
+                    ++absbandno;
+                }
+            }
+
+            assert(JPC_FIX_FRACBITS >= JPC_NUMEXTRABITS);
+            if (!tile->intmode) {
+                jas_matrix_divpow2(comp->data,
+                                   JPC_FIX_FRACBITS - JPC_NUMEXTRABITS);
+            } else {
+                jas_matrix_asl(comp->data, JPC_NUMEXTRABITS);
+            }
+        }
+
+        if (mingbits > cp->tccp.numgbits) {
+            fprintf(stderr, "error: too few guard bits (need at least %d)\n",
+                    mingbits);
+            return -1;
+        }
+
+        enc->tmpstream = jas_stream_memopen(0, 0);
+        if (!enc->tmpstream) {
+            fprintf(stderr, "cannot open tmp file\n");
+            return -1;
+        }
+
+        /* Write the tile header. */
+        enc->mrk = jpc_ms_create(JPC_MS_SOT);
+        if (!enc->mrk)
+            return -1;
+        sot = &enc->mrk->parms.sot;
+        sot->len = 0;
+        sot->tileno = tileno;
+        sot->partno = 0;
+        sot->numparts = 1;
+        if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) {
+            fprintf(stderr, "cannot write SOT marker\n");
+            return -1;
+        }
+        jpc_ms_destroy(enc->mrk);
+        enc->mrk = 0;
+
+/************************************************************************/
+/************************************************************************/
+/************************************************************************/
+
+        tccp = &cp->tccp;
+        for (cmptno = 0; cmptno < cp->numcmpts; ++cmptno) {
+            jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno];
+            jpc_enc_tcmpt_t * const comp0 = &tile->tcmpts[0];
+
+            if (comp->numrlvls != tccp->maxrlvls) {
+                if (!(enc->mrk = jpc_ms_create(JPC_MS_COD))) {
+                    return -1;
+                }
+                /* XXX = this is not really correct. we are using comp #0's
+                   precint sizes and other characteristics */
+                cod = &enc->mrk->parms.cod;
+                cod->compparms.csty = 0;
+                cod->compparms.numdlvls = comp0->numrlvls - 1;
+                cod->prg = tile->prg;
+                cod->numlyrs = tile->numlyrs;
+                cod->compparms.cblkwidthval =
+                    JPC_COX_CBLKSIZEEXPN(comp0->cblkwidthexpn);
+                cod->compparms.cblkheightval =
+                    JPC_COX_CBLKSIZEEXPN(comp0->cblkheightexpn);
+                cod->compparms.cblksty = comp0->cblksty;
+                cod->compparms.qmfbid = comp0->qmfbid;
+                cod->mctrans = (tile->mctid != JPC_MCT_NONE);
+                for (i = 0; i < comp0->numrlvls; ++i) {
+                    cod->compparms.rlvls[i].parwidthval =
+                        comp0->rlvls[i].prcwidthexpn;
+                    cod->compparms.rlvls[i].parheightval =
+                        comp0->rlvls[i].prcheightexpn;
+                }
+                if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) {
+                    return -1;
+                }
+                jpc_ms_destroy(enc->mrk);
+                enc->mrk = 0;
+            }
+        }
+
+        for (cmptno = 0; cmptno < cp->numcmpts; ++cmptno) {
+            jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno];
+
+            ccps = &cp->ccps[cmptno];
+            if (ccps->numstepsizes == comp->numstepsizes) {
+                unsigned int bandno;
+                samestepsizes = 1;
+                for (bandno = 0; bandno < ccps->numstepsizes; ++bandno) {
+                    if (ccps->stepsizes[bandno] != comp->stepsizes[bandno]) {
+                        samestepsizes = 0;
+                        break;
+                    }
+                }
+            } else {
+                samestepsizes = 0;
+            }
+            if (!samestepsizes) {
+                if (!(enc->mrk = jpc_ms_create(JPC_MS_QCC))) {
+                    return -1;
+                }
+                qcc = &enc->mrk->parms.qcc;
+                qcc->compno = cmptno;
+                qcc->compparms.numguard = cp->tccp.numgbits;
+                qcc->compparms.qntsty = (comp->qmfbid == JPC_COX_INS) ?
+                    JPC_QCX_SEQNT : JPC_QCX_NOQNT;
+                qcc->compparms.numstepsizes = comp->numstepsizes;
+                qcc->compparms.stepsizes = comp->stepsizes;
+                if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) {
+                    return -1;
+                }
+                qcc->compparms.stepsizes = 0;
+                jpc_ms_destroy(enc->mrk);
+                enc->mrk = 0;
+            }
+        }
+
+        /* Write a SOD marker to indicate the end of the tile header. */
+        if (!(enc->mrk = jpc_ms_create(JPC_MS_SOD))) {
+            return -1;
+        }
+        if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) {
+            fprintf(stderr, "cannot write SOD marker\n");
+            return -1;
+        }
+        jpc_ms_destroy(enc->mrk);
+        enc->mrk = 0;
+        tilehdrlen = jas_stream_getrwcount(enc->tmpstream);
+
+/************************************************************************/
+/************************************************************************/
+/************************************************************************/
+
+        encodeTileBody(enc, tilehdrlen, &error);
+            /* Encodes current tile; writes to output file */
+
+        if (error) {
+            fprintf(stderr, "Failed to encode body of tile %u.  %s\n",
+                    tileno, error);
+            pm_strfree(error);
+            return -1;
+        }
+        tilelen = jas_stream_tell(enc->tmpstream);
+
+        if (jas_stream_seek(enc->tmpstream, 6, SEEK_SET) < 0) {
+            return -1;
+        }
+        jpc_putuint32(enc->tmpstream, tilelen);
+
+        if (jas_stream_seek(enc->tmpstream, 0, SEEK_SET) < 0) {
+            return -1;
+        }
+        if (jpc_putdata(enc->out, enc->tmpstream, -1)) {
+            return -1;
+        }
+        enc->len += tilelen;
+
+        jas_stream_close(enc->tmpstream);
+        enc->tmpstream = 0;
+
+        jpc_enc_tile_destroy(enc->curtile);
+        enc->curtile = 0;
+
+    }
+
+    return 0;
+}
+
+
+
+int
+jpc_encode(jas_image_t *image, jas_stream_t *out, char *optstr) {
+
+    jpc_enc_t *enc;
+    jpc_enc_cp_t *cp;
+
+    enc = 0;
+    cp = 0;
+
+    jpc_initluts();
+
+    if (!(cp = cp_create(optstr, image))) {
+        fprintf(stderr, "invalid JP encoder options\n");
+        goto error;
+    }
+
+    if (!(enc = jpc_enc_create(cp, out, image))) {
+        goto error;
+    }
+    cp = 0;
+
+    /* Encode the main header. */
+    if (encodemainhdr(enc)) {
+        goto error;
+    }
+
+    /* Encode the main body.  This constitutes most of the encoding work. */
+    if (encodemainbody(enc)) {
+        goto error;
+    }
+
+    /* Write EOC marker segment. */
+    if (!(enc->mrk = jpc_ms_create(JPC_MS_EOC))) {
+        goto error;
+    }
+    if (jpc_putms(enc->out, enc->cstate, enc->mrk)) {
+        fprintf(stderr, "cannot write EOI marker\n");
+        goto error;
+    }
+    jpc_ms_destroy(enc->mrk);
+    enc->mrk = 0;
+
+    if (jas_stream_flush(enc->out)) {
+        goto error;
+    }
+
+    jpc_enc_destroy(enc);
+
+    return 0;
+
+error:
+    if (cp) {
+        cp_destroy(cp);
+    }
+    if (enc) {
+        jpc_enc_destroy(enc);
+    }
+    return -1;
+}
+
+
+
+/*****************************************************************************\
+* Encoder constructor and destructor.
+\*****************************************************************************/
+
+jpc_enc_t *
+jpc_enc_create(jpc_enc_cp_t *cp, jas_stream_t *out, jas_image_t *image) {
+
+    jpc_enc_t *enc;
+
+    enc = 0;
+
+    if (!(enc = jas_malloc(sizeof(jpc_enc_t)))) {
+        goto error;
+    }
+
+    enc->image = image;
+    enc->out = out;
+    enc->cp = cp;
+    enc->cstate = 0;
+    enc->tmpstream = 0;
+    enc->mrk = 0;
+    enc->curtile = 0;
+
+    if (!(enc->cstate = jpc_cstate_create())) {
+        goto error;
+    }
+    enc->len = 0;
+    enc->mainbodysize = 0;
+
+    return enc;
+
+error:
+
+    if (enc) {
+        jpc_enc_destroy(enc);
+    }
+    return 0;
+}
+
+
+
+void
+jpc_enc_destroy(jpc_enc_t *enc) {
+
+    /* The image object (i.e., enc->image) and output stream object
+       (i.e., enc->out) are created outside of the encoder.
+       Therefore, they must not be destroyed here.
+    */
+
+    if (enc->curtile) {
+        jpc_enc_tile_destroy(enc->curtile);
+    }
+    if (enc->cp) {
+        cp_destroy(enc->cp);
+    }
+    if (enc->cstate) {
+        jpc_cstate_destroy(enc->cstate);
+    }
+    if (enc->tmpstream) {
+        jas_stream_close(enc->tmpstream);
+    }
+
+    jas_free(enc);
+}
+
+
+
+void
+quantize(jas_matrix_t *data, jpc_fix_t stepsize) {
+
+    int i;
+    int j;
+    jpc_fix_t t;
+
+    if (stepsize == jpc_inttofix(1)) {
+        return;
+    }
+
+    for (i = 0; i < jas_matrix_numrows(data); ++i) {
+        for (j = 0; j < jas_matrix_numcols(data); ++j) {
+            t = jas_matrix_get(data, i, j);
+
+{
+    if (t < 0) {
+        t = jpc_fix_neg(jpc_fix_div(jpc_fix_neg(t), stepsize));
+    } else {
+        t = jpc_fix_div(t, stepsize);
+    }
+}
+
+            jas_matrix_set(data, i, j, t);
+        }
+    }
+}
+
+
+
 /*****************************************************************************\
 * Tile constructors and destructors.
 \*****************************************************************************/
@@ -2227,7 +2586,7 @@ prc_create(jpc_enc_prc_t *prc, jpc_enc_cp_t *cp, jpc_enc_band_t *band) {
         }
 
         prc->cblks = jas_malloc(prc->numcblks * sizeof(jpc_enc_cblk_t));
-        
+
         if (!prc->cblks)
             goto error;
         for (cblkno = 0, cblk = prc->cblks;
@@ -2445,9 +2804,9 @@ jpc_enc_dump(jpc_enc_t *enc) {
                      prcno < rlvl->numprcs;
                      ++prcno, ++prc) {
                     fprintf(stderr, "        prc %5d %5d %5d %5d (%5d %5d)\n",
-                            (int)prc->tlx, (int)prc->tly, 
+                            (int)prc->tlx, (int)prc->tly,
                             (int)prc->brx, (int)prc->bry,
-                            (int)(prc->brx - prc->tlx), 
+                            (int)(prc->brx - prc->tlx),
                             (int)(prc->bry - prc->tly));
                     if (!prc->cblks) {
                         continue;
@@ -2468,352 +2827,6 @@ jpc_enc_dump(jpc_enc_t *enc) {
 
 
 
-static int
-jpc_enc_encodemainbody(jpc_enc_t *enc) {
-
-    int tileno;
-    int i;
-    jpc_sot_t *sot;
-    jpc_enc_tcmpt_t *comp;
-    jpc_enc_tcmpt_t *endcomps;
-    jpc_enc_band_t *band;
-    jpc_enc_band_t *endbands;
-    jpc_enc_rlvl_t *lvl;
-    int rlvlno;
-    jpc_qcc_t *qcc;
-    jpc_cod_t *cod;
-    int adjust;
-    int j;
-    int absbandno;
-    long tilehdrlen;
-    long tilelen;
-    jpc_enc_tile_t *tile;
-    jpc_enc_cp_t *cp;
-    double rho;
-    uint_fast16_t cmptno;
-    int samestepsizes;
-    jpc_enc_ccp_t *ccps;
-    jpc_enc_tccp_t *tccp;
-    int bandno;
-    uint_fast32_t x;
-    uint_fast32_t y;
-    int mingbits;
-    int actualnumbps;
-    jpc_fix_t mxmag;
-    jpc_fix_t mag;
-    int numgbits;
-    const char * error;
-
-    cp = enc->cp;
-
-    for (tileno = 0; tileno < cp->numtiles; ++tileno) {
-        enc->curtile = jpc_enc_tile_create(enc->cp, enc->image, tileno);
-        if (!enc->curtile)
-            abort();
-
-        tile = enc->curtile;
-
-        if (jas_getdbglevel() >= 10) {
-            jpc_enc_dump(enc);
-        }
-
-        endcomps = &tile->tcmpts[tile->numtcmpts];
-        for (cmptno = 0, comp = tile->tcmpts;
-             cmptno < tile->numtcmpts;
-             ++cmptno, ++comp) {
-            if (!cp->ccps[cmptno].sgnd) {
-                adjust = 1 << (cp->ccps[cmptno].prec - 1);
-                for (i = 0; i < jas_matrix_numrows(comp->data); ++i) {
-                    for (j = 0; j < jas_matrix_numcols(comp->data); ++j) {
-                        *jas_matrix_getref(comp->data, i, j) -= adjust;
-                    }
-                }
-            }
-        }
-
-        if (!tile->intmode) {
-            endcomps = &tile->tcmpts[tile->numtcmpts];
-            for (comp = tile->tcmpts; comp != endcomps; ++comp) {
-                jas_matrix_asl(comp->data, JPC_FIX_FRACBITS);
-            }
-        }
-
-        switch (tile->mctid) {
-        case JPC_MCT_RCT:
-            assert(jas_image_numcmpts(enc->image) == 3);
-            jpc_rct(tile->tcmpts[0].data, tile->tcmpts[1].data,
-                    tile->tcmpts[2].data);
-            break;
-        case JPC_MCT_ICT:
-            assert(jas_image_numcmpts(enc->image) == 3);
-            jpc_ict(tile->tcmpts[0].data, tile->tcmpts[1].data,
-                    tile->tcmpts[2].data);
-            break;
-        default:
-            break;
-        }
-
-        for (i = 0; i < jas_image_numcmpts(enc->image); ++i) {
-            comp = &tile->tcmpts[i];
-            jpc_tsfb_analyze(comp->tsfb,
-                             ((comp->qmfbid == JPC_COX_RFT) ?
-                              JPC_TSFB_RITIMODE : 0), comp->data);
-
-        }
-
-        endcomps = &tile->tcmpts[tile->numtcmpts];
-        for (cmptno = 0, comp = tile->tcmpts;
-             comp != endcomps;
-             ++cmptno, ++comp) {
-            mingbits = 0;
-            absbandno = 0;
-            /* All bands must have a corresponding quantizer step size,
-               even if they contain no samples and are never coded. */
-            /* Some bands may not be hit by the loop below, so we must
-               initialize all of the step sizes to a sane value. */
-            memset(comp->stepsizes, 0, sizeof(comp->stepsizes));
-            for (rlvlno = 0, lvl = comp->rlvls;
-                 rlvlno < comp->numrlvls;
-                 ++rlvlno, ++lvl) {
-                if (!lvl->bands) {
-                    absbandno += rlvlno ? 3 : 1;
-                    continue;
-                }
-                endbands = &lvl->bands[lvl->numbands];
-                for (band = lvl->bands; band != endbands; ++band) {
-                    if (!band->data) {
-                        ++absbandno;
-                        continue;
-                    }
-                    actualnumbps = 0;
-                    mxmag = 0;
-                    for (y = 0; y < jas_matrix_numrows(band->data); ++y) {
-                        for (x = 0; x < jas_matrix_numcols(band->data); ++x) {
-                            mag = abs(jas_matrix_get(band->data, y, x));
-                            if (mag > mxmag) {
-                                mxmag = mag;
-                            }
-                        }
-                    }
-                    if (tile->intmode) {
-                        actualnumbps =
-                            jpc_firstone(mxmag) + 1;
-                    } else {
-                        actualnumbps =
-                            jpc_firstone(mxmag) + 1 - JPC_FIX_FRACBITS;
-                    }
-                    numgbits = actualnumbps - (cp->ccps[cmptno].prec - 1 +
-                                               band->analgain);
-                    if (numgbits > mingbits) {
-                        mingbits = numgbits;
-                    }
-                    if (!tile->intmode) {
-                        band->absstepsize =
-                            jpc_fix_div(
-                                jpc_inttofix(1 << (band->analgain + 1)),
-                                band->synweight);
-                    } else {
-                        band->absstepsize = jpc_inttofix(1);
-                    }
-                    band->stepsize = jpc_abstorelstepsize(
-                        band->absstepsize, cp->ccps[cmptno].prec +
-                        band->analgain);
-                    band->numbps = cp->tccp.numgbits +
-                        JPC_QCX_GETEXPN(band->stepsize) - 1;
-
-                    if ((!tile->intmode) && band->data) {
-                        quantize(band->data, band->absstepsize);
-                    }
-
-                    comp->stepsizes[absbandno] = band->stepsize;
-                    ++absbandno;
-                }
-            }
-
-            assert(JPC_FIX_FRACBITS >= JPC_NUMEXTRABITS);
-            if (!tile->intmode) {
-                jas_matrix_divpow2(comp->data,
-                                   JPC_FIX_FRACBITS - JPC_NUMEXTRABITS);
-            } else {
-                jas_matrix_asl(comp->data, JPC_NUMEXTRABITS);
-            }
-        }
-
-        if (mingbits > cp->tccp.numgbits) {
-            fprintf(stderr, "error: too few guard bits (need at least %d)\n",
-                    mingbits);
-            return -1;
-        }
-
-        enc->tmpstream = jas_stream_memopen(0, 0);
-        if (!enc->tmpstream) {
-            fprintf(stderr, "cannot open tmp file\n");
-            return -1;
-        }
-
-        /* Write the tile header. */
-        enc->mrk = jpc_ms_create(JPC_MS_SOT);
-        if (!enc->mrk)
-            return -1;
-        sot = &enc->mrk->parms.sot;
-        sot->len = 0;
-        sot->tileno = tileno;
-        sot->partno = 0;
-        sot->numparts = 1;
-        if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) {
-            fprintf(stderr, "cannot write SOT marker\n");
-            return -1;
-        }
-        jpc_ms_destroy(enc->mrk);
-        enc->mrk = 0;
-
-/************************************************************************/
-/************************************************************************/
-/************************************************************************/
-
-        tccp = &cp->tccp;
-        for (cmptno = 0; cmptno < cp->numcmpts; ++cmptno) {
-            comp = &tile->tcmpts[cmptno];
-            if (comp->numrlvls != tccp->maxrlvls) {
-                if (!(enc->mrk = jpc_ms_create(JPC_MS_COD))) {
-                    return -1;
-                }
-                /* XXX = this is not really correct. we are using comp #0's
-                   precint sizes and other characteristics */
-                comp = &tile->tcmpts[0];
-                cod = &enc->mrk->parms.cod;
-                cod->compparms.csty = 0;
-                cod->compparms.numdlvls = comp->numrlvls - 1;
-                cod->prg = tile->prg;
-                cod->numlyrs = tile->numlyrs;
-                cod->compparms.cblkwidthval =
-                    JPC_COX_CBLKSIZEEXPN(comp->cblkwidthexpn);
-                cod->compparms.cblkheightval =
-                    JPC_COX_CBLKSIZEEXPN(comp->cblkheightexpn);
-                cod->compparms.cblksty = comp->cblksty;
-                cod->compparms.qmfbid = comp->qmfbid;
-                cod->mctrans = (tile->mctid != JPC_MCT_NONE);
-                for (i = 0; i < comp->numrlvls; ++i) {
-                    cod->compparms.rlvls[i].parwidthval =
-                        comp->rlvls[i].prcwidthexpn;
-                    cod->compparms.rlvls[i].parheightval =
-                        comp->rlvls[i].prcheightexpn;
-                }
-                if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) {
-                    return -1;
-                }
-                jpc_ms_destroy(enc->mrk);
-                enc->mrk = 0;
-            }
-        }
-
-        for (cmptno = 0, comp = tile->tcmpts;
-             cmptno < cp->numcmpts;
-             ++cmptno, ++comp) {
-            ccps = &cp->ccps[cmptno];
-            if (ccps->numstepsizes == comp->numstepsizes) {
-                samestepsizes = 1;
-                for (bandno = 0; bandno < ccps->numstepsizes; ++bandno) {
-                    if (ccps->stepsizes[bandno] != comp->stepsizes[bandno]) {
-                        samestepsizes = 0;
-                        break;
-                    }
-                }
-            } else {
-                samestepsizes = 0;
-            }
-            if (!samestepsizes) {
-                if (!(enc->mrk = jpc_ms_create(JPC_MS_QCC))) {
-                    return -1;
-                }
-                qcc = &enc->mrk->parms.qcc;
-                qcc->compno = cmptno;
-                qcc->compparms.numguard = cp->tccp.numgbits;
-                qcc->compparms.qntsty = (comp->qmfbid == JPC_COX_INS) ?
-                    JPC_QCX_SEQNT : JPC_QCX_NOQNT;
-                qcc->compparms.numstepsizes = comp->numstepsizes;
-                qcc->compparms.stepsizes = comp->stepsizes;
-                if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) {
-                    return -1;
-                }
-                qcc->compparms.stepsizes = 0;
-                jpc_ms_destroy(enc->mrk);
-                enc->mrk = 0;
-            }
-        }
-
-        /* Write a SOD marker to indicate the end of the tile header. */
-        if (!(enc->mrk = jpc_ms_create(JPC_MS_SOD))) {
-            return -1;
-        }
-        if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) {
-            fprintf(stderr, "cannot write SOD marker\n");
-            return -1;
-        }
-        jpc_ms_destroy(enc->mrk);
-        enc->mrk = 0;
-        tilehdrlen = jas_stream_getrwcount(enc->tmpstream);
-
-/************************************************************************/
-/************************************************************************/
-/************************************************************************/
-
-        if (jpc_enc_enccblks(enc)) {
-            abort();
-            return -1;
-        }
-
-        cp = enc->cp;
-        rho = (double) (tile->brx - tile->tlx) * (tile->bry - tile->tly) /
-            ((cp->refgrdwidth - cp->imgareatlx) * (cp->refgrdheight -
-                                                   cp->imgareatly));
-        tile->rawsize = cp->rawsize * rho;
-
-        computeLayerSizes(enc, tile, cp, rho, tilehdrlen, &error);
-        
-        if (!error) {
-            int rc;
-            performTier2Coding(enc, tile->numlyrs, tile->lyrsizes, &error);
-
-            rc =  jpc_enc_encodetiledata(enc);
-            if (rc != 0)
-                pm_asprintf(&error, "jpc_enc_encodetiledata() failed\n");
-        }
-
-        if (error) {
-            fprintf(stderr, "%s\n", error);
-            pm_strfree(error);
-            return -1;
-        }
-
-        tilelen = jas_stream_tell(enc->tmpstream);
-
-        if (jas_stream_seek(enc->tmpstream, 6, SEEK_SET) < 0) {
-            return -1;
-        }
-        jpc_putuint32(enc->tmpstream, tilelen);
-
-        if (jas_stream_seek(enc->tmpstream, 0, SEEK_SET) < 0) {
-            return -1;
-        }
-        if (jpc_putdata(enc->out, enc->tmpstream, -1)) {
-            return -1;
-        }
-        enc->len += tilelen;
-
-        jas_stream_close(enc->tmpstream);
-        enc->tmpstream = 0;
-
-        jpc_enc_tile_destroy(enc->curtile);
-        enc->curtile = 0;
-
-    }
-
-    return 0;
-}
-
-
-
 /*
  * Copyright (c) 1999-2000 Image Power, Inc. and the University of
  *   British Columbia.
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_math.c b/converter/other/jpeg2000/libjasper/jpc/jpc_math.c
index 01e3611e..a884ed4d 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_math.c
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_math.c
@@ -50,6 +50,8 @@ jpc_firstone(int_fast32_t const arg) {
 /*---------------------------------------------------------------------------- 
   Calculate the bit position of the first leading one in a nonnegative
   integer.
+
+  LSB is bit position 0.  Iff there are no ones, return -1.
 -----------------------------------------------------------------------------*/
 	int n;
     int x;
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c b/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c
index e1af0f61..34b9738c 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c
@@ -124,6 +124,8 @@
 #include <stdlib.h>
 #include <assert.h>
 
+#include "netpbm/nstring.h"
+
 #include "jasper/jas_fix.h"
 #include "jasper/jas_malloc.h"
 #include "jasper/jas_math.h"
@@ -149,74 +151,111 @@ static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, int,
 static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, int,
   jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
 
-/******************************************************************************\
+/*****************************************************************************\
 * Code for encoding code blocks.
-\******************************************************************************/
+\*****************************************************************************/
 
-/* Encode all of the code blocks associated with the current tile. */
-int jpc_enc_enccblks(jpc_enc_t *enc)
-{
-    jpc_enc_tcmpt_t *tcmpt;
-    jpc_enc_tcmpt_t *endcomps;
-    jpc_enc_rlvl_t *lvl;
-    jpc_enc_rlvl_t *endlvls;
-    jpc_enc_band_t *band;
-    jpc_enc_band_t *endbands;
-    jpc_enc_cblk_t *cblk;
-    jpc_enc_cblk_t *endcblks;
-    int i;
-    int j;
-    int mx;
-    int bmx;
-    int v;
-    jpc_enc_tile_t *tile;
-    uint_fast32_t prcno;
-    jpc_enc_prc_t *prc;
+static void
+encodeBlocksOfPrecinct(jpc_enc_prc_t *   const prcP,
+                       jpc_enc_band_t *  const bandP,
+                       jpc_enc_tcmpt_t * const tcmptP,
+                       jpc_enc_t *       const encoderP,
+                       const char **     const errorP) {
 
-    tile = enc->curtile;
+    if (prcP->cblks) {
+        int bmx;
+        uint_fast32_t cblkno;
 
-    endcomps = &tile->tcmpts[tile->numtcmpts];
-    for (tcmpt = tile->tcmpts; tcmpt != endcomps; ++tcmpt) {
-        endlvls = &tcmpt->rlvls[tcmpt->numrlvls];
-        for (lvl = tcmpt->rlvls; lvl != endlvls; ++lvl) {
-            if (!lvl->bands) {
-                continue;
-            }
-            endbands = &lvl->bands[lvl->numbands];
-            for (band = lvl->bands; band != endbands; ++band) {
-                if (!band->data) {
-                    continue;
+        for (cblkno = 0, bmx = 0; cblkno < prcP->numcblks; ++ cblkno) {
+            jpc_enc_cblk_t * const cblkP = &prcP->cblks[cblkno];
+
+            int mx;
+            uint_fast32_t row;
+
+            for (row = 0, mx = 0;
+                 row < jas_matrix_numrows(cblkP->data);
+                 ++row) {
+
+                uint_fast32_t col;
+
+                for (col = 0; col < jas_matrix_numcols(cblkP->data); ++col) {
+                    int const v = abs(jas_matrix_get(cblkP->data, row, col));
+                    if (v > mx)
+                        mx = v;
                 }
-                for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) {
-                    if (!prc->cblks) {
-                        continue;
-                    }
-                    bmx = 0;
-                    endcblks = &prc->cblks[prc->numcblks];
-                    for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
-                        mx = 0;
-                        for (i = 0; i < jas_matrix_numrows(cblk->data); ++i) {
-                            for (j = 0; j < jas_matrix_numcols(cblk->data); ++j) {
-                                v = abs(jas_matrix_get(cblk->data, i, j));
-                                if (v > mx) {
-                                    mx = v;
-                                }
-                            }
-                        }
-                        if (mx > bmx) {
-                            bmx = mx;
-                        }
-                        cblk->numbps = JAS_MAX(jpc_firstone(mx) + 1 - JPC_NUMEXTRABITS, 0);
-                    }
+            }
+            if (mx > bmx)
+                bmx = mx;
 
-                    for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
-                        cblk->numimsbs = band->numbps - cblk->numbps;
-                        assert(cblk->numimsbs >= 0);
-                    }
+            cblkP->numbps = MAX(jpc_firstone(mx) + 1 - JPC_NUMEXTRABITS, 0);
+        }
+
+        for (cblkno = 0; cblkno < prcP->numcblks; ++ cblkno) {
+            jpc_enc_cblk_t * const cblkP = &prcP->cblks[cblkno];
 
-                    for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
-                        if (jpc_enc_enccblk(enc, cblk->stream, tcmpt, band, cblk)) {
-                            return -1;
+            assert(cblkP->numbps <= bandP->numbps);
+        }
+
+        for (cblkno = 0, *errorP = NULL;
+             cblkno < prcP->numcblks && !*errorP;
+             ++ cblkno) {
+
+            jpc_enc_cblk_t * const cblkP = &prcP->cblks[cblkno];
+
+            int rc;
+
+            rc = jpc_enc_enccblk(encoderP,
+                                 cblkP->stream, tcmptP, bandP, cblkP);
+            if (rc != 0)
+                pm_asprintf(errorP, "Encoding failed on code block %u "
+                            "of %u", (unsigned)cblkno,
+                            (unsigned)prcP->numcblks);
+        }
+    } else
+        *errorP = NULL;
+}
+
+
+
+int
+jpc_enc_enccblks(jpc_enc_t * const encoderP) {
+/*----------------------------------------------------------------------------
+  Encode all of the code blocks associated with the current tile.
+-----------------------------------------------------------------------------*/
+    jpc_enc_tile_t * const tileP = encoderP->curtile;
+
+    uint_fast32_t cmptno;
+
+    for (cmptno = 0; cmptno < tileP->numtcmpts; ++cmptno) {
+        jpc_enc_tcmpt_t * const tcmptP = &tileP->tcmpts[cmptno];
+
+        unsigned int lvlno;
+        for (lvlno = 0; lvlno < tcmptP->numrlvls; ++ lvlno) {
+            jpc_enc_rlvl_t * const lvlP = &tcmptP->rlvls[lvlno];
+
+            if (lvlP->bands) {
+                uint_fast32_t bandno;
+
+                for (bandno = 0; bandno < lvlP->numbands; ++bandno) {
+                    jpc_enc_band_t * const bandP = &lvlP->bands[bandno];
+
+                    if (bandP->data) {
+                        uint_fast32_t prcno;
+
+                        for (prcno = 0; prcno < lvlP->numprcs; ++prcno) {
+
+                            const char * error;
+
+                            encodeBlocksOfPrecinct(&bandP->prcs[prcno],
+                                                   bandP,
+                                                   tcmptP,
+                                                   encoderP,
+                                                   &error);
+
+                            if (error) {
+                                pm_strfree(error);
+                                return -1;
+                            }
                         }
                     }
                 }
@@ -226,6 +265,8 @@ int jpc_enc_enccblks(jpc_enc_t *enc)
     return 0;
 }
 
+
+
 static int getthebyte(jas_stream_t *in, long off)
 {
     int c;
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_util.c b/converter/other/jpeg2000/libjasper/jpc/jpc_util.c
index fede2bef..e6e3942a 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_util.c
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_util.c
@@ -114,9 +114,9 @@
  * $Id$
  */
 
-/******************************************************************************\
+/*****************************************************************************\
 * Includes
-\******************************************************************************/
+\*****************************************************************************/
 
 #include <assert.h>
 #include <stdio.h>
@@ -133,21 +133,21 @@
 #include "jpc_flt.h"
 #include "jpc_util.h"
 
-/******************************************************************************\
+/*****************************************************************************\
 * Miscellaneous Functions
-\******************************************************************************/
+\*****************************************************************************/
 
-int jpc_atoaf(const char *s, int *numvalues, double **values)
-{
-	static char delim[] = ", \t\n";
+static unsigned int
+countOfTokens(const char * const s,
+			  const char * const delim) {
+
+	unsigned int n;
 	char buf[4096];
-	int n;
-	double *vs;
-	char *cp;
+	const char * cp;
 
 	strncpy(buf, s, sizeof(buf));
 	buf[sizeof(buf) - 1] = '\0';
-	n = 0;
+	n = 0;  /* initial value */
 	if ((cp = strtok(buf, delim))) {
 		++n;
 		while ((cp = strtok(0, delim))) {
@@ -156,32 +156,57 @@ int jpc_atoaf(const char *s, int *numvalues, double **values)
 			}
 		}
 	}
+	return n;
+}
+
+
+
+int
+jpc_atoaf(const char * const s,
+		  int *        const numvaluesP,
+		  double **    const valuesP) {
+/*----------------------------------------------------------------------------
+   Parse a string like "3.2,9,-5".  Return as *numvaluesP the number of
+   values in the string and as *valuesP a malloced array of the values.
 
-	if (n) {
-		if (!(vs = jas_malloc(n * sizeof(double)))) {
+   But if the string is empty (*numvaluesP is zero), return *valuesP NULL.
+
+   Delimiters can be comma as in the example or space, tab, or newline.
+-----------------------------------------------------------------------------*/
+	char const delim[] = ", \t\n";
+
+	unsigned int const valueCt = countOfTokens(s, delim);
+
+	if (valueCt > 0) {
+		unsigned int i;
+		double * vs;
+		const char * cp;
+		char buf[4096];
+
+		if (!(vs = jas_malloc(valueCt * sizeof(double)))) {
 			return -1;
 		}
 
 		strncpy(buf, s, sizeof(buf));
 		buf[sizeof(buf) - 1] = '\0';
-		n = 0;
+		i = 0;
 		if ((cp = strtok(buf, delim))) {
-			vs[n] = atof(cp);
-			++n;
+			vs[i] = atof(cp);
+			++i;
 			while ((cp = strtok(0, delim))) {
 				if (cp[0] != '\0') {
-					vs[n] = atof(cp);
-					++n;
+					vs[i] = atof(cp);
+					++i;
 				}
 			}
 		}
+		assert(i == valueCt);
+		*numvaluesP = valueCt;
+		*valuesP    = vs;
 	} else {
-		vs = 0;
+		*valuesP    = NULL;
+		*numvaluesP = 0;
 	}
-
-	*numvalues = n;
-	*values = vs;
-
 	return 0;
 }
 
diff --git a/converter/other/jpeg2000/pamtojpeg2k.c b/converter/other/jpeg2000/pamtojpeg2k.c
index ee5189ce..8f7409c0 100644
--- a/converter/other/jpeg2000/pamtojpeg2k.c
+++ b/converter/other/jpeg2000/pamtojpeg2k.c
@@ -53,6 +53,8 @@ struct CmdlineInfo {
     enum compmode compmode;
     unsigned int compressionSpec;
     float        compression;
+    unsigned int size;
+    unsigned int sizeSpec;
     char *       ilyrrates;
     enum progression progression;
     unsigned int numrlvls;
@@ -76,7 +78,7 @@ parseCommandLine(int argc, char ** argv,
                  struct CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that many of the strings that this function returns in the
-   *cmdline_p structure are actually in the supplied argv array.  And
+   *cmdlineP structure are actually in the supplied argv array.  And
    sometimes, one of these strings is actually just a suffix of an entry
    in argv!
 -----------------------------------------------------------------------------*/
@@ -126,6 +128,8 @@ parseCommandLine(int argc, char ** argv,
             &modeSpec,           0);
     OPTENT3(0, "compression",  OPT_FLOAT,  &cmdlineP->compression,
             &cmdlineP->compressionSpec,    0);
+    OPTENT3(0, "size",         OPT_UINT,   &cmdlineP->size,
+            &cmdlineP->sizeSpec,           0);
     OPTENT3(0, "ilyrrates",    OPT_STRING, &cmdlineP->ilyrrates,
             &ilyrratesSpec,      0);
     OPTENT3(0, "progression",  OPT_STRING, &progressionOpt,
@@ -219,6 +223,9 @@ parseCommandLine(int argc, char ** argv,
     if (!debuglevelSpec)
         cmdlineP->debuglevel = 0;
 
+    if (cmdlineP->compressionSpec && cmdlineP->sizeSpec)
+        pm_error("You cannot specify by -compression and -size");
+
     if (argc - 1 == 0)
         cmdlineP->inputFilename = strdup("-");  /* he wants stdin */
     else if (argc - 1 == 1)
@@ -405,6 +412,8 @@ writeJpc(jas_image_t *      const jasperP,
 
     if (cmdline.compressionSpec)
         sprintf(rateOpt, "rate=%1.9f", 1.0/cmdline.compression);
+    else if (cmdline.sizeSpec)
+        sprintf(rateOpt, "rate=%uB", cmdline.size);
     else {
         /* No 'rate' option.  This means there is no constraint on the image
            size, so the encoder will compress losslessly.  Note that the
diff --git a/converter/ppm/ppmtompeg/frame.c b/converter/ppm/ppmtompeg/frame.c
index f5a0d39d..09e35410 100644
--- a/converter/ppm/ppmtompeg/frame.c
+++ b/converter/ppm/ppmtompeg/frame.c
@@ -12,7 +12,7 @@
  *  Frame_AllocYCC                               *
  *  Frame_AllocDecoded                           *
  *  Frame_AllocHalf                                  *
- *  Frame_Resize                                     * 
+ *  Frame_Resize                                     *
  *                                       *
  *===========================================================================*/
 
@@ -52,7 +52,7 @@
  *===========*/
 
 /* The maximum number of B-Frames allowed between reference frames. */
-#define  B_FRAME_RUN  16    
+#define  B_FRAME_RUN  16
 
 /*==================*
  * GLOBAL VARIABLES *
@@ -64,13 +64,13 @@ static unsigned int numOfFrames;
 
 /*====================================================
 * Resize_Array_Width
-*    
+*
 *   This function will resize any array width up
 * or down in size.  The algorithm is based on the
 * least common multiple approach more commonly
 * used in audio frequency adjustments.
 *=====================================================*/
-static void 
+static void
 Resize_Array_Width(uint8 ** const inarray,
                    int      const in_x,
                    int      const in_y,
@@ -86,7 +86,7 @@ Resize_Array_Width(uint8 ** const inarray,
     uint8 pointA,pointB;
     double slope,diff;
 #endif
-    
+
     for (i = 0; i < in_y; ++i) {     /* For each row */
         unsigned int j;
         inptr = &inarray[i][0];
@@ -106,7 +106,7 @@ Resize_Array_Width(uint8 ** const inarray,
                     in_total = in_total - out_x;
                     --inptr;
                 }
-            } else {  
+            } else {
 #ifdef DOING_INTERPOLATION
                 pointA = *inptr;
 #endif
@@ -124,10 +124,10 @@ Resize_Array_Width(uint8 ** const inarray,
                 } else {
                     *outptr = (pointB -
                                (uint8)(slope*(((float)(out_x)) - diff)));
-                } 
+                }
 #endif
                 /* Non-Interpolative solution */
-                *outptr = *inptr;  
+                *outptr = *inptr;
 
                 ++outptr;
                 out_total = out_total + in_x;
@@ -153,7 +153,7 @@ Resize_Array_Width(uint8 ** const inarray,
 * Same as Resize_array_Width except pointer
 * manipulation must change.
 *===============================*/
-static void 
+static void
 Resize_Array_Height(uint8 ** const inarray,
                     int      const in_x,
                     int      const in_y,
@@ -176,7 +176,7 @@ Resize_Array_Height(uint8 ** const inarray,
         out_total = 0;
         k = 0;
         for(j=0; j < out_y; ++j){  /* for each output value */
-            if (in_total == out_total) {  
+            if (in_total == out_total) {
                 outarray[j][i] = inarray[k][i];
                 out_total=out_total+in_y;
                 while(in_total < out_total){
@@ -187,7 +187,7 @@ Resize_Array_Height(uint8 ** const inarray,
                     in_total = in_total - out_y;
                     --k;
                 }
-            } else {  
+            } else {
 #ifdef DOING_INTERPOLATION
                 pointA = inarray[k][i];
                 if (k != (in_y - 1)) {
@@ -210,7 +210,7 @@ Resize_Array_Height(uint8 ** const inarray,
                     in_total = in_total - out_y;
                     --k;
                 }
-            } 
+            }
         }
     }
 }
@@ -220,7 +220,7 @@ Resize_Array_Height(uint8 ** const inarray,
 /*========================================================
 * Resize_Width
 *======================================================*/
-static void  
+static void
 Resize_Width(MpegFrame * const omfrw,
              MpegFrame * const mfrw,
              int         const in_x,
@@ -274,12 +274,12 @@ Resize_Width(MpegFrame * const omfrw,
             free(mfrw->orig_y[i]);
         }
         free(mfrw->orig_y);
-        
+
         for (i = 0; i < in_y / 2; ++i) {
             free(mfrw->orig_cr[i]);
         }
         free(mfrw->orig_cr);
-        
+
         for (i = 0; i < in_y / 2; ++i) {
             free(mfrw->orig_cb[i]);
         }
@@ -300,9 +300,9 @@ Resize_Height(MpegFrame * const omfrh,
               int         const in_x,
               int         const in_y,
               int         const out_y) {
-    
-    unsigned int y; 
-    
+
+    unsigned int y;
+
     Fsize_y = out_y;
 
     /* Allocate new frame memory */
@@ -347,12 +347,12 @@ Resize_Height(MpegFrame * const omfrh,
             free(mfrh->orig_y[i]);
         }
         free(mfrh->orig_y);
-        
+
     for (i = 0; i < in_y / 2; ++i) {
         free(mfrh->orig_cr[i]);
     }
     free(mfrh->orig_cr);
-    
+
     for (i = 0; i < in_y / 2; ++i) {
         free(mfrh->orig_cb[i]);
     }
@@ -386,8 +386,8 @@ Frame_Init(unsigned int const numOfFramesRequested) {
     for (idx = 0; idx < numOfFrames; ++idx) {
         MALLOCVAR(frameMemory[idx]);
         frameMemory[idx]->inUse = FALSE;
-        frameMemory[idx]->orig_y = NULL;    
-        frameMemory[idx]->y_blocks = NULL; 
+        frameMemory[idx]->orig_y = NULL;
+        frameMemory[idx]->y_blocks = NULL;
         frameMemory[idx]->decoded_y = NULL;
         frameMemory[idx]->halfX = NULL;
         frameMemory[idx]->next = NULL;
@@ -458,11 +458,11 @@ FreeFrame(MpegFrame * const frameP) {
             for ( i = 0; i < Fsize_y; ++i )
                 free(frameP->halfX[i]);
             free(frameP->halfX);
-            
+
             for (i = 0; i < Fsize_y-1; ++i)
                 free(frameP->halfY[i]);
             free(frameP->halfY);
-            
+
             for (i = 0; i < Fsize_y-1; ++i)
                 free(frameP->halfBoth[i]);
             free(frameP->halfBoth);
@@ -542,7 +542,7 @@ GetUnusedFrame() {
                 "See the man page for help.\n");
         exit(1);
     }
-    return frameMemory[idx]; 
+    return frameMemory[idx];
 }
 
 
@@ -638,7 +638,7 @@ Frame_AllocBlocks(MpegFrame * const frameP) {
             MALLOCARRAY(frameP->y_blocks[i], dctx);
             ERRCHK(frameP->y_blocks[i], "malloc");
         }
-    
+
         MALLOCARRAY(frameP->cr_blocks, dcty / 2);
         ERRCHK(frameP->cr_blocks, "malloc");
         MALLOCARRAY(frameP->cb_blocks, dcty / 2);
@@ -672,7 +672,7 @@ Frame_AllocYCC(MpegFrame * const frameP) {
         /* already allocated */
     } else {
         unsigned int y;
-    
+
         DBG_PRINT(("ycc_calc:\n"));
         /*
          * first, allocate tons of memory
@@ -755,7 +755,7 @@ Frame_AllocHalf(MpegFrame * const frameP) {
  *
  *  allocate memory for decoded frame for the given frame, if required
  *  if makeReference == TRUE, then makes it reference frame
- * 
+ *
  * RETURNS: nothing
  *
  * SIDE EFFECTS:    none
@@ -781,14 +781,14 @@ Frame_AllocDecoded(MpegFrame * const frameP,
             MALLOCARRAY(frameP->decoded_y[y], Fsize_x);
             ERRCHK(frameP->decoded_y[y], "malloc");
         }
-        
+
         MALLOCARRAY(frameP->decoded_cr, Fsize_y / 2);
         ERRCHK(frameP->decoded_cr, "malloc");
         for (y = 0; y < (Fsize_y / 2); ++y) {
             MALLOCARRAY(frameP->decoded_cr[y], Fsize_x / 2);
             ERRCHK(frameP->decoded_cr[y], "malloc");
         }
-        
+
         MALLOCARRAY(frameP->decoded_cb, Fsize_y / 2);
         ERRCHK(frameP->decoded_cb, "malloc");
         for (y = 0; y < (Fsize_y / 2); ++y) {
@@ -810,7 +810,7 @@ Frame_AllocDecoded(MpegFrame * const frameP,
  *
  * Frame_Resize                  by James Boucher
  *                Boston University Multimedia Communications Lab
- *  
+ *
  *     This function takes the mf input frame, read in READFrame(),
  * and resizes all the input component arrays to the output
  * dimensions specified in the parameter file as OUT_SIZE.
@@ -828,11 +828,11 @@ Frame_Resize(MpegFrame * const omf,
     MpegFrame * frameAP;  /* intermediate frame */
 
     MALLOCVAR_NOFAIL(frameAP);
-    
+
     if (insize_x != outsize_x && insize_y != outsize_y) {
         Resize_Width(frameAP, mf, insize_x, insize_y, outsize_x);
         Resize_Height(omf, frameAP, outsize_x, insize_y, outsize_y);
-    } else 
+    } else
         if (insize_x ==outsize_x && insize_y != outsize_y) {
             Resize_Height(omf, mf, insize_x, insize_y, outsize_y);
         } else
@@ -843,3 +843,5 @@ Frame_Resize(MpegFrame * const omf,
 
     free(frameAP);
 }
+
+
diff --git a/converter/ppm/ppmtompeg/readframe.c b/converter/ppm/ppmtompeg/readframe.c
index 2a359b2f..dcc02052 100644
--- a/converter/ppm/ppmtompeg/readframe.c
+++ b/converter/ppm/ppmtompeg/readframe.c
@@ -1,13 +1,13 @@
 /*===========================================================================*
- * readframe.c                    
- *                                
- *  procedures to read in frames  
- *                                
- * EXPORTED PROCEDURES:           
- *  ReadFrame                     
- *  SetFileType                   
- *  SetFileFormat                 
- *                                
+ * readframe.c
+ *
+ *  procedures to read in frames
+ *
+ * EXPORTED PROCEDURES:
+ *  ReadFrame
+ *  SetFileType
+ *  SetFileFormat
+ *
  *===========================================================================*/
 
 /* COPYRIGHT INFORMATION IS AT THE END OF THIS FILE */
@@ -62,7 +62,7 @@ struct YuvLine {
 #ifdef __OS2__
   #define popen _popen
 #endif
-   
+
 
 /*==================*
  * Global VARIABLES *
@@ -100,7 +100,7 @@ static void DoKillDim (MpegFrame *mf, int w, int h);
 
 
 
-void    
+void
 SetResize(bool const set) {
     resizeFrame = set;
 }
@@ -134,7 +134,7 @@ ReadPNM(MpegFrame * const mpegFrameP,
 static void
 openFile(struct inputSource * const inputSourceP,
          unsigned int         const frameNumber,
-         const char *         const conversion, 
+         const char *         const conversion,
          FILE **              const ifPP) {
 
     if (inputSourceP->stdinUsed) {
@@ -145,24 +145,24 @@ openFile(struct inputSource * const inputSourceP,
                 "INPUT_CONVERTER * in the parameter file or supply the "
                 "frames in files by specifying a directory with "
                 "INPUT_DIRECTORY in the parameter file.");
-        
+
         *ifPP = stdin;
     } else {
         const char * fileName;
         const char * fullFileName;
-        
+
         GetNthInputFileName(inputSourceP, frameNumber, &fileName);
-        
+
         pm_asprintf(&fullFileName, "%s/%s", currentPath, fileName);
-        
+
         CurrFile = fullFileName;
-        
+
         if (fileType == ANY_FILE_TYPE) {
             char command[1024];
             const char * convertPtr;
             char * commandPtr;
             const char * charPtr;
-            
+
             /* replace every occurrence of '*' with fullFileName */
             convertPtr = conversion;
             commandPtr = command;
@@ -172,7 +172,7 @@ openFile(struct inputSource * const inputSourceP,
                     ++commandPtr;
                     ++convertPtr;
                 }
-                
+
                 if (*convertPtr == '*') {
                     /* copy fullFileName */
                     charPtr = fullFileName;
@@ -185,7 +185,7 @@ openFile(struct inputSource * const inputSourceP,
                 }
             }
             *commandPtr = '\0';
-            
+
             *ifPP = popen(command, "r");
             if (*ifPP == NULL) {
                 pm_message(
@@ -201,7 +201,7 @@ openFile(struct inputSource * const inputSourceP,
             *ifPP = fopen(fullFileName, "rb");
             if (*ifPP == NULL)
                 pm_error("Couldn't open input file '%s'", fullFileName);
-            
+
             if (baseFormat == JMOVIE_FILE_TYPE)
                 unlink(fullFileName);
         }
@@ -238,7 +238,7 @@ fileIsAtEnd(FILE * const ifP) {
 
     c = getc(ifP);
     if (c == EOF) {
-        if (feof(ifP)) 
+        if (feof(ifP))
             eof = TRUE;
         else
             pm_error("File error on getc() to position to image");
@@ -248,7 +248,7 @@ fileIsAtEnd(FILE * const ifP) {
         eof = FALSE;
 
         rc = ungetc(c, ifP);
-        if (rc == EOF) 
+        if (rc == EOF)
             pm_error("File error doing ungetc() to position to image.");
     }
     return eof;
@@ -262,14 +262,11 @@ ReadFrameFile(MpegFrame *  const frameP,
               const char * const conversion,
               bool *       const eofP) {
 /*----------------------------------------------------------------------------
-   Read a frame from the file 'ifP'.
+   Read a frame from the file 'ifP', doing adjustments as indicated.
 
    Return *eofP == TRUE iff we encounter EOF before we can get the
    frame.
 -----------------------------------------------------------------------------*/
-    MpegFrame   tempFrame;
-    MpegFrame * framePtr;
-
     /* To make this code fit Netpbm properly, we should remove handling
        of all types except PNM and use pm_nextimage() to handle sensing
        of end of stream.
@@ -278,53 +275,59 @@ ReadFrameFile(MpegFrame *  const frameP,
     if (fileIsAtEnd(ifP))
         *eofP = TRUE;
     else {
+        MpegFrame   preResizeFrame;
+            /* The frame object that holds the frame before resizing */
+        MpegFrame * rawFrameP;
+            /* The frame object with which we read in the raw frame */
+
         *eofP = FALSE;
 
         if (resizeFrame) {
-            tempFrame.inUse = FALSE;
-            tempFrame.orig_y = NULL;
-            tempFrame.y_blocks = NULL;
-            tempFrame.decoded_y = NULL;
-            tempFrame.halfX = NULL;
-            framePtr = &tempFrame;
+            preResizeFrame.inUse = FALSE;
+            preResizeFrame.orig_y = NULL;
+            preResizeFrame.y_blocks = NULL;
+            preResizeFrame.decoded_y = NULL;
+            preResizeFrame.halfX = NULL;
+            rawFrameP = &preResizeFrame;
         } else
-            framePtr = frameP;
+            rawFrameP = frameP;
 
         switch(baseFormat) {
         case YUV_FILE_TYPE:
 
             /* Encoder YUV */
             if ((strncmp (yuvConversion, "EYUV", 4) == 0) ||
-                (strncmp (yuvConversion, "UCB", 3) == 0)) 
+                (strncmp (yuvConversion, "UCB", 3) == 0))
 
-                ReadEYUV(framePtr, ifP, realWidth, realHeight);
+                ReadEYUV(rawFrameP, ifP, realWidth, realHeight);
 
             else
                 /* Abekas-type (interlaced) YUV */
-                ReadAYUV(framePtr, ifP, realWidth, realHeight);
+                ReadAYUV(rawFrameP, ifP, realWidth, realHeight);
 
             break;
         case Y_FILE_TYPE:
-            ReadY(framePtr, ifP, realWidth, realHeight);
+            ReadY(rawFrameP, ifP, realWidth, realHeight);
             break;
         case PNM_FILE_TYPE:
-            ReadPNM(framePtr, ifP);
+            ReadPNM(rawFrameP, ifP);
             break;
         case SUB4_FILE_TYPE:
-            ReadSub4(framePtr, ifP, yuvWidth, yuvHeight);
+            ReadSub4(rawFrameP, ifP, yuvWidth, yuvHeight);
             break;
         case JPEG_FILE_TYPE:
         case JMOVIE_FILE_TYPE:
-            ReadJPEG(framePtr, ifP);
+            ReadJPEG(rawFrameP, ifP);
             break;
         default:
             break;
         }
 
-        if (resizeFrame)
-            Frame_Resize(frameP, &tempFrame, Fsize_x, Fsize_y, 
+        if (resizeFrame) {
+            assert(rawFrameP == &preResizeFrame);
+            Frame_Resize(frameP, &preResizeFrame, Fsize_x, Fsize_y,
                          outputWidth, outputHeight);
-    
+        }
         if (GammaCorrection)
             DoGamma(frameP, Fsize_x, Fsize_y);
 
@@ -338,7 +341,7 @@ ReadFrameFile(MpegFrame *  const frameP,
 
 
 void
-ReadFrame(MpegFrame *          const frameP, 
+ReadFrame(MpegFrame *          const frameP,
           struct inputSource * const inputSourceP,
           unsigned int         const frameNumber,
           const char *         const conversion,
@@ -693,7 +696,7 @@ SeparateLine(fpointer, lineptr, width)
         fprintf(stderr, "       or any even-length string consisting of the letters U, V, and Y.\n");
             exit(1);
         }
-    
+
     }
 
 }
@@ -738,7 +741,7 @@ ReadY(mf, fpointer, width, height)
     for (y = Fsize_y; y < height; y++) {
     safe_fread(junk, 1, width, fpointer);
     }
-    
+
     for (y = 0 ; y < (Fsize_y >> 1); y++) {
       memset(mf->orig_cb[y], 128, (Fsize_x>>1));
       memset(mf->orig_cr[y], 128, (Fsize_x>>1));
@@ -830,7 +833,7 @@ int w,h;
   int i,j;
 
   if (!init_done) {
-    for(i=0; i<256; i++) 
+    for(i=0; i<256; i++)
       GammaVal[i]=(unsigned char) (pow(((double) i)/255.0,GammaValue)*255.0+0.5);
     init_done=TRUE;
   }
@@ -871,7 +874,7 @@ int w,h;
                         ^ kill_dim_break
                              ^kill_dim_end
               kill_dim_slope gives the slope (y = kill_dim_slope * x +0)
-              from 0 to kill_dim_break                      
+              from 0 to kill_dim_break
  *
  *===========================================================================*/
 
@@ -930,7 +933,7 @@ int w,h;
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  */
 
-/*  
+/*
  *  $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/readframe.c,v 1.27 1995/08/14 22:31:40 smoot Exp $
  *  $Log: readframe.c,v $
  *  Revision 1.27  1995/08/14 22:31:40  smoot